UNPKG

897 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 moduleNamespace = 'module-' + namespace,
44
45 $document = $(document),
46 $module = $document,
47 element = this,
48 instance = $module.data(moduleNamespace),
49
50 module,
51 returnedValue
52 ;
53 module = {
54
55 initialize: function() {
56 module.instantiate();
57 },
58
59 instantiate: function() {
60 module.verbose('Storing instance of site', module);
61 instance = module;
62 $module
63 .data(moduleNamespace, module)
64 ;
65 },
66
67 normalize: function() {
68 module.fix.console();
69 module.fix.requestAnimationFrame();
70 },
71
72 fix: {
73 console: function() {
74 module.debug('Normalizing window.console');
75 if (console === undefined || console.log === undefined) {
76 module.verbose('Console not available, normalizing events');
77 module.disable.console();
78 }
79 if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
80 module.verbose('Console group not available, normalizing events');
81 window.console.group = function() {};
82 window.console.groupEnd = function() {};
83 window.console.groupCollapsed = function() {};
84 }
85 if (typeof console.markTimeline == 'undefined') {
86 module.verbose('Mark timeline not available, normalizing events');
87 window.console.markTimeline = function() {};
88 }
89 },
90 consoleClear: function() {
91 module.debug('Disabling programmatic console clearing');
92 window.console.clear = function() {};
93 },
94 requestAnimationFrame: function() {
95 module.debug('Normalizing requestAnimationFrame');
96 if(window.requestAnimationFrame === undefined) {
97 module.debug('RequestAnimationFrame not available, normalizing event');
98 window.requestAnimationFrame = window.requestAnimationFrame
99 || window.mozRequestAnimationFrame
100 || window.webkitRequestAnimationFrame
101 || window.msRequestAnimationFrame
102 || function(callback) { setTimeout(callback, 0); }
103 ;
104 }
105 }
106 },
107
108 moduleExists: function(name) {
109 return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
110 },
111
112 enabled: {
113 modules: function(modules) {
114 var
115 enabledModules = []
116 ;
117 modules = modules || settings.modules;
118 $.each(modules, function(index, name) {
119 if(module.moduleExists(name)) {
120 enabledModules.push(name);
121 }
122 });
123 return enabledModules;
124 }
125 },
126
127 disabled: {
128 modules: function(modules) {
129 var
130 disabledModules = []
131 ;
132 modules = modules || settings.modules;
133 $.each(modules, function(index, name) {
134 if(!module.moduleExists(name)) {
135 disabledModules.push(name);
136 }
137 });
138 return disabledModules;
139 }
140 },
141
142 change: {
143 setting: function(setting, value, modules, modifyExisting) {
144 modules = (typeof modules === 'string')
145 ? (modules === 'all')
146 ? settings.modules
147 : [modules]
148 : modules || settings.modules
149 ;
150 modifyExisting = (modifyExisting !== undefined)
151 ? modifyExisting
152 : true
153 ;
154 $.each(modules, function(index, name) {
155 var
156 namespace = (module.moduleExists(name))
157 ? $.fn[name].settings.namespace || false
158 : true,
159 $existingModules
160 ;
161 if(module.moduleExists(name)) {
162 module.verbose('Changing default setting', setting, value, name);
163 $.fn[name].settings[setting] = value;
164 if(modifyExisting && namespace) {
165 $existingModules = $(':data(module-' + namespace + ')');
166 if($existingModules.length > 0) {
167 module.verbose('Modifying existing settings', $existingModules);
168 $existingModules[name]('setting', setting, value);
169 }
170 }
171 }
172 });
173 },
174 settings: function(newSettings, modules, modifyExisting) {
175 modules = (typeof modules === 'string')
176 ? [modules]
177 : modules || settings.modules
178 ;
179 modifyExisting = (modifyExisting !== undefined)
180 ? modifyExisting
181 : true
182 ;
183 $.each(modules, function(index, name) {
184 var
185 $existingModules
186 ;
187 if(module.moduleExists(name)) {
188 module.verbose('Changing default setting', newSettings, name);
189 $.extend(true, $.fn[name].settings, newSettings);
190 if(modifyExisting && namespace) {
191 $existingModules = $(':data(module-' + namespace + ')');
192 if($existingModules.length > 0) {
193 module.verbose('Modifying existing settings', $existingModules);
194 $existingModules[name]('setting', newSettings);
195 }
196 }
197 }
198 });
199 }
200 },
201
202 enable: {
203 console: function() {
204 module.console(true);
205 },
206 debug: function(modules, modifyExisting) {
207 modules = modules || settings.modules;
208 module.debug('Enabling debug for modules', modules);
209 module.change.setting('debug', true, modules, modifyExisting);
210 },
211 verbose: function(modules, modifyExisting) {
212 modules = modules || settings.modules;
213 module.debug('Enabling verbose debug for modules', modules);
214 module.change.setting('verbose', true, modules, modifyExisting);
215 }
216 },
217 disable: {
218 console: function() {
219 module.console(false);
220 },
221 debug: function(modules, modifyExisting) {
222 modules = modules || settings.modules;
223 module.debug('Disabling debug for modules', modules);
224 module.change.setting('debug', false, modules, modifyExisting);
225 },
226 verbose: function(modules, modifyExisting) {
227 modules = modules || settings.modules;
228 module.debug('Disabling verbose debug for modules', modules);
229 module.change.setting('verbose', false, modules, modifyExisting);
230 }
231 },
232
233 console: function(enable) {
234 if(enable) {
235 if(instance.cache.console === undefined) {
236 module.error(error.console);
237 return;
238 }
239 module.debug('Restoring console function');
240 window.console = instance.cache.console;
241 }
242 else {
243 module.debug('Disabling console function');
244 instance.cache.console = window.console;
245 window.console = {
246 clear : function(){},
247 error : function(){},
248 group : function(){},
249 groupCollapsed : function(){},
250 groupEnd : function(){},
251 info : function(){},
252 log : function(){},
253 markTimeline : function(){},
254 warn : function(){}
255 };
256 }
257 },
258
259 destroy: function() {
260 module.verbose('Destroying previous site for', $module);
261 $module
262 .removeData(moduleNamespace)
263 ;
264 },
265
266 cache: {},
267
268 setting: function(name, value) {
269 if( $.isPlainObject(name) ) {
270 $.extend(true, settings, name);
271 }
272 else if(value !== undefined) {
273 settings[name] = value;
274 }
275 else {
276 return settings[name];
277 }
278 },
279 internal: function(name, value) {
280 if( $.isPlainObject(name) ) {
281 $.extend(true, module, name);
282 }
283 else if(value !== undefined) {
284 module[name] = value;
285 }
286 else {
287 return module[name];
288 }
289 },
290 debug: function() {
291 if(settings.debug) {
292 if(settings.performance) {
293 module.performance.log(arguments);
294 }
295 else {
296 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
297 module.debug.apply(console, arguments);
298 }
299 }
300 },
301 verbose: function() {
302 if(settings.verbose && settings.debug) {
303 if(settings.performance) {
304 module.performance.log(arguments);
305 }
306 else {
307 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
308 module.verbose.apply(console, arguments);
309 }
310 }
311 },
312 error: function() {
313 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
314 module.error.apply(console, arguments);
315 },
316 performance: {
317 log: function(message) {
318 var
319 currentTime,
320 executionTime,
321 previousTime
322 ;
323 if(settings.performance) {
324 currentTime = new Date().getTime();
325 previousTime = time || currentTime;
326 executionTime = currentTime - previousTime;
327 time = currentTime;
328 performance.push({
329 'Element' : element,
330 'Name' : message[0],
331 'Arguments' : [].slice.call(message, 1) || '',
332 'Execution Time' : executionTime
333 });
334 }
335 clearTimeout(module.performance.timer);
336 module.performance.timer = setTimeout(module.performance.display, 500);
337 },
338 display: function() {
339 var
340 title = settings.name + ':',
341 totalTime = 0
342 ;
343 time = false;
344 clearTimeout(module.performance.timer);
345 $.each(performance, function(index, data) {
346 totalTime += data['Execution Time'];
347 });
348 title += ' ' + totalTime + 'ms';
349 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
350 console.groupCollapsed(title);
351 if(console.table) {
352 console.table(performance);
353 }
354 else {
355 $.each(performance, function(index, data) {
356 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
357 });
358 }
359 console.groupEnd();
360 }
361 performance = [];
362 }
363 },
364 invoke: function(query, passedArguments, context) {
365 var
366 object = instance,
367 maxDepth,
368 found,
369 response
370 ;
371 passedArguments = passedArguments || queryArguments;
372 context = element || context;
373 if(typeof query == 'string' && object !== undefined) {
374 query = query.split(/[\. ]/);
375 maxDepth = query.length - 1;
376 $.each(query, function(depth, value) {
377 var camelCaseValue = (depth != maxDepth)
378 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
379 : query
380 ;
381 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
382 object = object[camelCaseValue];
383 }
384 else if( object[camelCaseValue] !== undefined ) {
385 found = object[camelCaseValue];
386 return false;
387 }
388 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
389 object = object[value];
390 }
391 else if( object[value] !== undefined ) {
392 found = object[value];
393 return false;
394 }
395 else {
396 module.error(error.method, query);
397 return false;
398 }
399 });
400 }
401 if ( $.isFunction( found ) ) {
402 response = found.apply(context, passedArguments);
403 }
404 else if(found !== undefined) {
405 response = found;
406 }
407 if(Array.isArray(returnedValue)) {
408 returnedValue.push(response);
409 }
410 else if(returnedValue !== undefined) {
411 returnedValue = [returnedValue, response];
412 }
413 else if(response !== undefined) {
414 returnedValue = response;
415 }
416 return found;
417 }
418 };
419
420 if(methodInvoked) {
421 if(instance === undefined) {
422 module.initialize();
423 }
424 module.invoke(query);
425 }
426 else {
427 if(instance !== undefined) {
428 module.destroy();
429 }
430 module.initialize();
431 }
432 return (returnedValue !== undefined)
433 ? returnedValue
434 : this
435 ;
436};
437
438$.site.settings = {
439
440 name : 'Site',
441 namespace : 'site',
442
443 error : {
444 console : 'Console cannot be restored, most likely it was overwritten outside of module',
445 method : 'The method you called is not defined.'
446 },
447
448 debug : false,
449 verbose : false,
450 performance : true,
451
452 modules: [
453 'accordion',
454 'api',
455 'calendar',
456 'checkbox',
457 'dimmer',
458 'dropdown',
459 'embed',
460 'form',
461 'modal',
462 'nag',
463 'popup',
464 'slider',
465 'rating',
466 'shape',
467 'sidebar',
468 'state',
469 'sticky',
470 'tab',
471 'toast',
472 'transition',
473 'visibility',
474 'visit'
475 ],
476
477 siteNamespace : 'site',
478 namespaceStub : {
479 cache : {},
480 config : {},
481 sections : {},
482 section : {},
483 utilities : {}
484 }
485
486};
487
488// allows for selection of elements with data attributes
489$.extend($.expr[ ":" ], {
490 data: ($.expr.createPseudo)
491 ? $.expr.createPseudo(function(dataName) {
492 return function(elem) {
493 return !!$.data(elem, dataName);
494 };
495 })
496 : function(elem, i, match) {
497 // support: jQuery < 1.8
498 return !!$.data(elem, match[ 3 ]);
499 }
500});
501
502
503})( jQuery, window, document );
504
505/*!
506 * # Semantic UI 2.7.2 - Form Validation
507 * http://github.com/semantic-org/semantic-ui/
508 *
509 *
510 * Released under the MIT license
511 * http://opensource.org/licenses/MIT
512 *
513 */
514
515;(function ($, window, document, undefined) {
516
517'use strict';
518
519$.isFunction = $.isFunction || function(obj) {
520 return typeof obj === "function" && typeof obj.nodeType !== "number";
521};
522
523window = (typeof window != 'undefined' && window.Math == Math)
524 ? window
525 : (typeof self != 'undefined' && self.Math == Math)
526 ? self
527 : Function('return this')()
528;
529
530$.fn.form = function(parameters) {
531 var
532 $allModules = $(this),
533 moduleSelector = $allModules.selector || '',
534
535 time = new Date().getTime(),
536 performance = [],
537
538 query = arguments[0],
539 legacyParameters = arguments[1],
540 methodInvoked = (typeof query == 'string'),
541 queryArguments = [].slice.call(arguments, 1),
542 returnedValue
543 ;
544 $allModules
545 .each(function() {
546 var
547 $module = $(this),
548 element = this,
549
550 formErrors = [],
551 keyHeldDown = false,
552
553 // set at run-time
554 $field,
555 $group,
556 $message,
557 $prompt,
558 $submit,
559 $clear,
560 $reset,
561
562 settings,
563 validation,
564
565 metadata,
566 selector,
567 className,
568 regExp,
569 error,
570
571 namespace,
572 moduleNamespace,
573 eventNamespace,
574
575 instance,
576 module
577 ;
578
579 module = {
580
581 initialize: function() {
582
583 // settings grabbed at run time
584 module.get.settings();
585 if(methodInvoked) {
586 if(instance === undefined) {
587 module.instantiate();
588 }
589 module.invoke(query);
590 }
591 else {
592 if(instance !== undefined) {
593 instance.invoke('destroy');
594 }
595 module.verbose('Initializing form validation', $module, settings);
596 module.bindEvents();
597 module.set.defaults();
598 module.instantiate();
599 }
600 },
601
602 instantiate: function() {
603 module.verbose('Storing instance of module', module);
604 instance = module;
605 $module
606 .data(moduleNamespace, module)
607 ;
608 },
609
610 destroy: function() {
611 module.verbose('Destroying previous module', instance);
612 module.removeEvents();
613 $module
614 .removeData(moduleNamespace)
615 ;
616 },
617
618 refresh: function() {
619 module.verbose('Refreshing selector cache');
620 $field = $module.find(selector.field);
621 $group = $module.find(selector.group);
622 $message = $module.find(selector.message);
623 $prompt = $module.find(selector.prompt);
624
625 $submit = $module.find(selector.submit);
626 $clear = $module.find(selector.clear);
627 $reset = $module.find(selector.reset);
628 },
629
630 submit: function() {
631 module.verbose('Submitting form', $module);
632 $module
633 .submit()
634 ;
635 },
636
637 attachEvents: function(selector, action) {
638 action = action || 'submit';
639 $(selector)
640 .on('click' + eventNamespace, function(event) {
641 module[action]();
642 event.preventDefault();
643 })
644 ;
645 },
646
647 bindEvents: function() {
648 module.verbose('Attaching form events');
649 $module
650 .on('submit' + eventNamespace, module.validate.form)
651 .on('blur' + eventNamespace, selector.field, module.event.field.blur)
652 .on('click' + eventNamespace, selector.submit, module.submit)
653 .on('click' + eventNamespace, selector.reset, module.reset)
654 .on('click' + eventNamespace, selector.clear, module.clear)
655 ;
656 if(settings.keyboardShortcuts) {
657 $module
658 .on('keydown' + eventNamespace, selector.field, module.event.field.keydown)
659 ;
660 }
661 $field
662 .each(function() {
663 var
664 $input = $(this),
665 type = $input.prop('type'),
666 inputEvent = module.get.changeEvent(type, $input)
667 ;
668 $(this)
669 .on(inputEvent + eventNamespace, module.event.field.change)
670 ;
671 })
672 ;
673 },
674
675 clear: function() {
676 $field
677 .each(function () {
678 var
679 $field = $(this),
680 $element = $field.parent(),
681 $fieldGroup = $field.closest($group),
682 $prompt = $fieldGroup.find(selector.prompt),
683 defaultValue = $field.data(metadata.defaultValue) || '',
684 isCheckbox = $element.is(selector.uiCheckbox),
685 isDropdown = $element.is(selector.uiDropdown),
686 isErrored = $fieldGroup.hasClass(className.error)
687 ;
688 if(isErrored) {
689 module.verbose('Resetting error on field', $fieldGroup);
690 $fieldGroup.removeClass(className.error);
691 $prompt.remove();
692 }
693 if(isDropdown) {
694 module.verbose('Resetting dropdown value', $element, defaultValue);
695 $element.dropdown('clear');
696 }
697 else if(isCheckbox) {
698 $field.prop('checked', false);
699 }
700 else {
701 module.verbose('Resetting field value', $field, defaultValue);
702 $field.val('');
703 }
704 })
705 ;
706 },
707
708 reset: function() {
709 $field
710 .each(function () {
711 var
712 $field = $(this),
713 $element = $field.parent(),
714 $fieldGroup = $field.closest($group),
715 $prompt = $fieldGroup.find(selector.prompt),
716 defaultValue = $field.data(metadata.defaultValue),
717 isCheckbox = $element.is(selector.uiCheckbox),
718 isDropdown = $element.is(selector.uiDropdown),
719 isErrored = $fieldGroup.hasClass(className.error)
720 ;
721 if(defaultValue === undefined) {
722 return;
723 }
724 if(isErrored) {
725 module.verbose('Resetting error on field', $fieldGroup);
726 $fieldGroup.removeClass(className.error);
727 $prompt.remove();
728 }
729 if(isDropdown) {
730 module.verbose('Resetting dropdown value', $element, defaultValue);
731 $element.dropdown('restore defaults');
732 }
733 else if(isCheckbox) {
734 module.verbose('Resetting checkbox value', $element, defaultValue);
735 $field.prop('checked', defaultValue);
736 }
737 else {
738 module.verbose('Resetting field value', $field, defaultValue);
739 $field.val(defaultValue);
740 }
741 })
742 ;
743 },
744
745 determine: {
746 isValid: function() {
747 var
748 allValid = true
749 ;
750 $.each(validation, function(fieldName, field) {
751 if( !( module.validate.field(field, fieldName, true) ) ) {
752 allValid = false;
753 }
754 });
755 return allValid;
756 }
757 },
758
759 is: {
760 bracketedRule: function(rule) {
761 return (rule.type && rule.type.match(settings.regExp.bracket));
762 },
763 shorthandFields: function(fields) {
764 var
765 fieldKeys = Object.keys(fields),
766 firstRule = fields[fieldKeys[0]]
767 ;
768 return module.is.shorthandRules(firstRule);
769 },
770 // duck type rule test
771 shorthandRules: function(rules) {
772 return (typeof rules == 'string' || Array.isArray(rules));
773 },
774 empty: function($field) {
775 if(!$field || $field.length === 0) {
776 return true;
777 }
778 else if($field.is(selector.checkbox)) {
779 return !$field.is(':checked');
780 }
781 else {
782 return module.is.blank($field);
783 }
784 },
785 blank: function($field) {
786 return $.trim($field.val()) === '';
787 },
788 valid: function(field) {
789 var
790 allValid = true
791 ;
792 if(field) {
793 module.verbose('Checking if field is valid', field);
794 return module.validate.field(validation[field], field, false);
795 }
796 else {
797 module.verbose('Checking if form is valid');
798 $.each(validation, function(fieldName, field) {
799 if( !module.is.valid(fieldName) ) {
800 allValid = false;
801 }
802 });
803 return allValid;
804 }
805 }
806 },
807
808 removeEvents: function() {
809 $module
810 .off(eventNamespace)
811 ;
812 $field
813 .off(eventNamespace)
814 ;
815 $submit
816 .off(eventNamespace)
817 ;
818 $field
819 .off(eventNamespace)
820 ;
821 },
822
823 event: {
824 field: {
825 keydown: function(event) {
826 var
827 $field = $(this),
828 key = event.which,
829 isInput = $field.is(selector.input),
830 isCheckbox = $field.is(selector.checkbox),
831 isInDropdown = ($field.closest(selector.uiDropdown).length > 0),
832 keyCode = {
833 enter : 13,
834 escape : 27
835 }
836 ;
837 if( key == keyCode.escape) {
838 module.verbose('Escape key pressed blurring field');
839 $field
840 .blur()
841 ;
842 }
843 if(!event.ctrlKey && key == keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
844 if(!keyHeldDown) {
845 $field
846 .one('keyup' + eventNamespace, module.event.field.keyup)
847 ;
848 module.submit();
849 module.debug('Enter pressed on input submitting form');
850 }
851 keyHeldDown = true;
852 }
853 },
854 keyup: function() {
855 keyHeldDown = false;
856 },
857 blur: function(event) {
858 var
859 $field = $(this),
860 $fieldGroup = $field.closest($group),
861 validationRules = module.get.validation($field)
862 ;
863 if( $fieldGroup.hasClass(className.error) ) {
864 module.debug('Revalidating field', $field, validationRules);
865 if(validationRules) {
866 module.validate.field( validationRules );
867 }
868 }
869 else if(settings.on == 'blur') {
870 if(validationRules) {
871 module.validate.field( validationRules );
872 }
873 }
874 },
875 change: function(event) {
876 var
877 $field = $(this),
878 $fieldGroup = $field.closest($group),
879 validationRules = module.get.validation($field)
880 ;
881 if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
882 clearTimeout(module.timer);
883 module.timer = setTimeout(function() {
884 module.debug('Revalidating field', $field, module.get.validation($field));
885 module.validate.field( validationRules );
886 }, settings.delay);
887 }
888 }
889 }
890
891 },
892
893 get: {
894 ancillaryValue: function(rule) {
895 if(!rule.type || (!rule.value && !module.is.bracketedRule(rule))) {
896 return false;
897 }
898 return (rule.value !== undefined)
899 ? rule.value
900 : rule.type.match(settings.regExp.bracket)[1] + ''
901 ;
902 },
903 ruleName: function(rule) {
904 if( module.is.bracketedRule(rule) ) {
905 return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
906 }
907 return rule.type;
908 },
909 changeEvent: function(type, $input) {
910 if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
911 return 'change';
912 }
913 else {
914 return module.get.inputEvent();
915 }
916 },
917 inputEvent: function() {
918 return (document.createElement('input').oninput !== undefined)
919 ? 'input'
920 : (document.createElement('input').onpropertychange !== undefined)
921 ? 'propertychange'
922 : 'keyup'
923 ;
924 },
925 fieldsFromShorthand: function(fields) {
926 var
927 fullFields = {}
928 ;
929 $.each(fields, function(name, rules) {
930 if(typeof rules == 'string') {
931 rules = [rules];
932 }
933 fullFields[name] = {
934 rules: []
935 };
936 $.each(rules, function(index, rule) {
937 fullFields[name].rules.push({ type: rule });
938 });
939 });
940 return fullFields;
941 },
942 prompt: function(rule, field) {
943 var
944 ruleName = module.get.ruleName(rule),
945 ancillary = module.get.ancillaryValue(rule),
946 $field = module.get.field(field.identifier),
947 value = $field.val(),
948 prompt = $.isFunction(rule.prompt)
949 ? rule.prompt(value)
950 : rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
951 requiresValue = (prompt.search('{value}') !== -1),
952 requiresName = (prompt.search('{name}') !== -1),
953 $label,
954 name
955 ;
956 if(requiresValue) {
957 prompt = prompt.replace('{value}', $field.val());
958 }
959 if(requiresName) {
960 $label = $field.closest(selector.group).find('label').eq(0);
961 name = ($label.length == 1)
962 ? $label.text()
963 : $field.prop('placeholder') || settings.text.unspecifiedField
964 ;
965 prompt = prompt.replace('{name}', name);
966 }
967 prompt = prompt.replace('{identifier}', field.identifier);
968 prompt = prompt.replace('{ruleValue}', ancillary);
969 if(!rule.prompt) {
970 module.verbose('Using default validation prompt for type', prompt, ruleName);
971 }
972 return prompt;
973 },
974 settings: function() {
975 if($.isPlainObject(parameters)) {
976 var
977 keys = Object.keys(parameters),
978 isLegacySettings = (keys.length > 0)
979 ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
980 : false
981 ;
982 if(isLegacySettings) {
983 // 1.x (ducktyped)
984 settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
985 validation = $.extend({}, $.fn.form.settings.defaults, parameters);
986 module.error(settings.error.oldSyntax, element);
987 module.verbose('Extending settings from legacy parameters', validation, settings);
988 }
989 else {
990 // 2.x
991 if(parameters.fields && module.is.shorthandFields(parameters.fields)) {
992 parameters.fields = module.get.fieldsFromShorthand(parameters.fields);
993 }
994 settings = $.extend(true, {}, $.fn.form.settings, parameters);
995 validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
996 module.verbose('Extending settings', validation, settings);
997 }
998 }
999 else {
1000 settings = $.fn.form.settings;
1001 validation = $.fn.form.settings.defaults;
1002 module.verbose('Using default form validation', validation, settings);
1003 }
1004
1005 // shorthand
1006 namespace = settings.namespace;
1007 metadata = settings.metadata;
1008 selector = settings.selector;
1009 className = settings.className;
1010 regExp = settings.regExp;
1011 error = settings.error;
1012 moduleNamespace = 'module-' + namespace;
1013 eventNamespace = '.' + namespace;
1014
1015 // grab instance
1016 instance = $module.data(moduleNamespace);
1017
1018 // refresh selector cache
1019 module.refresh();
1020 },
1021 field: function(identifier) {
1022 module.verbose('Finding field with identifier', identifier);
1023 identifier = module.escape.string(identifier);
1024 var t;
1025 if((t=$field.filter('#' + identifier)).length > 0 ) {
1026 return t;
1027 }
1028 if((t=$field.filter('[name="' + identifier +'"]')).length > 0 ) {
1029 return t;
1030 }
1031 if((t=$field.filter('[name="' + identifier +'[]"]')).length > 0 ) {
1032 return t;
1033 }
1034 if((t=$field.filter('[data-' + metadata.validate + '="'+ identifier +'"]')).length > 0 ) {
1035 return t;
1036 }
1037 return $('<input/>');
1038 },
1039 fields: function(fields) {
1040 var
1041 $fields = $()
1042 ;
1043 $.each(fields, function(index, name) {
1044 $fields = $fields.add( module.get.field(name) );
1045 });
1046 return $fields;
1047 },
1048 validation: function($field) {
1049 var
1050 fieldValidation,
1051 identifier
1052 ;
1053 if(!validation) {
1054 return false;
1055 }
1056 $.each(validation, function(fieldName, field) {
1057 identifier = field.identifier || fieldName;
1058 $.each(module.get.field(identifier), function(index, groupField) {
1059 if(groupField == $field[0]) {
1060 field.identifier = identifier;
1061 fieldValidation = field;
1062 return false;
1063 }
1064 });
1065 });
1066 return fieldValidation || false;
1067 },
1068 value: function (field) {
1069 var
1070 fields = [],
1071 results
1072 ;
1073 fields.push(field);
1074 results = module.get.values.call(element, fields);
1075 return results[field];
1076 },
1077 values: function (fields) {
1078 var
1079 $fields = Array.isArray(fields)
1080 ? module.get.fields(fields)
1081 : $field,
1082 values = {}
1083 ;
1084 $fields.each(function(index, field) {
1085 var
1086 $field = $(field),
1087 name = $field.prop('name'),
1088 value = $field.val(),
1089 isCheckbox = $field.is(selector.checkbox),
1090 isRadio = $field.is(selector.radio),
1091 isMultiple = (name.indexOf('[]') !== -1),
1092 isChecked = (isCheckbox)
1093 ? $field.is(':checked')
1094 : false
1095 ;
1096 if(name) {
1097 if(isMultiple) {
1098 name = name.replace('[]', '');
1099 if(!values[name]) {
1100 values[name] = [];
1101 }
1102 if(isCheckbox) {
1103 if(isChecked) {
1104 values[name].push(value || true);
1105 }
1106 else {
1107 values[name].push(false);
1108 }
1109 }
1110 else {
1111 values[name].push(value);
1112 }
1113 }
1114 else {
1115 if(isRadio) {
1116 if(values[name] === undefined || values[name] == false) {
1117 values[name] = (isChecked)
1118 ? value || true
1119 : false
1120 ;
1121 }
1122 }
1123 else if(isCheckbox) {
1124 if(isChecked) {
1125 values[name] = value || true;
1126 }
1127 else {
1128 values[name] = false;
1129 }
1130 }
1131 else {
1132 values[name] = value;
1133 }
1134 }
1135 }
1136 });
1137 return values;
1138 }
1139 },
1140
1141 has: {
1142
1143 field: function(identifier) {
1144 module.verbose('Checking for existence of a field with identifier', identifier);
1145 identifier = module.escape.string(identifier);
1146 if(typeof identifier !== 'string') {
1147 module.error(error.identifier, identifier);
1148 }
1149 if($field.filter('#' + identifier).length > 0 ) {
1150 return true;
1151 }
1152 else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
1153 return true;
1154 }
1155 else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
1156 return true;
1157 }
1158 return false;
1159 }
1160
1161 },
1162
1163 escape: {
1164 string: function(text) {
1165 text = String(text);
1166 return text.replace(regExp.escape, '\\$&');
1167 }
1168 },
1169
1170 add: {
1171 // alias
1172 rule: function(name, rules) {
1173 module.add.field(name, rules);
1174 },
1175 field: function(name, rules) {
1176 var
1177 newValidation = {}
1178 ;
1179 if(module.is.shorthandRules(rules)) {
1180 rules = Array.isArray(rules)
1181 ? rules
1182 : [rules]
1183 ;
1184 newValidation[name] = {
1185 rules: []
1186 };
1187 $.each(rules, function(index, rule) {
1188 newValidation[name].rules.push({ type: rule });
1189 });
1190 }
1191 else {
1192 newValidation[name] = rules;
1193 }
1194 validation = $.extend({}, validation, newValidation);
1195 module.debug('Adding rules', newValidation, validation);
1196 },
1197 fields: function(fields) {
1198 var
1199 newValidation
1200 ;
1201 if(fields && module.is.shorthandFields(fields)) {
1202 newValidation = module.get.fieldsFromShorthand(fields);
1203 }
1204 else {
1205 newValidation = fields;
1206 }
1207 validation = $.extend({}, validation, newValidation);
1208 },
1209 prompt: function(identifier, errors, internal) {
1210 var
1211 $field = module.get.field(identifier),
1212 $fieldGroup = $field.closest($group),
1213 $prompt = $fieldGroup.children(selector.prompt),
1214 promptExists = ($prompt.length !== 0)
1215 ;
1216 errors = (typeof errors == 'string')
1217 ? [errors]
1218 : errors
1219 ;
1220 module.verbose('Adding field error state', identifier);
1221 if(!internal) {
1222 $fieldGroup
1223 .addClass(className.error)
1224 ;
1225 }
1226 if(settings.inline) {
1227 if(!promptExists) {
1228 $prompt = settings.templates.prompt(errors);
1229 $prompt
1230 .appendTo($fieldGroup)
1231 ;
1232 }
1233 $prompt
1234 .html(errors[0])
1235 ;
1236 if(!promptExists) {
1237 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
1238 module.verbose('Displaying error with css transition', settings.transition);
1239 $prompt.transition(settings.transition + ' in', settings.duration);
1240 }
1241 else {
1242 module.verbose('Displaying error with fallback javascript animation');
1243 $prompt
1244 .fadeIn(settings.duration)
1245 ;
1246 }
1247 }
1248 else {
1249 module.verbose('Inline errors are disabled, no inline error added', identifier);
1250 }
1251 }
1252 },
1253 errors: function(errors) {
1254 module.debug('Adding form error messages', errors);
1255 module.set.error();
1256 $message
1257 .html( settings.templates.error(errors) )
1258 ;
1259 }
1260 },
1261
1262 remove: {
1263 rule: function(field, rule) {
1264 var
1265 rules = Array.isArray(rule)
1266 ? rule
1267 : [rule]
1268 ;
1269 if(validation[field] === undefined || !Array.isArray(validation[field].rules)) {
1270 return;
1271 }
1272 if(rule === undefined) {
1273 module.debug('Removed all rules');
1274 validation[field].rules = [];
1275 return;
1276 }
1277 $.each(validation[field].rules, function(index, rule) {
1278 if(rules.indexOf(rule.type) !== -1) {
1279 module.debug('Removed rule', rule.type);
1280 validation[field].rules.splice(index, 1);
1281 }
1282 });
1283 },
1284 field: function(field) {
1285 var
1286 fields = Array.isArray(field)
1287 ? field
1288 : [field]
1289 ;
1290 $.each(fields, function(index, field) {
1291 module.remove.rule(field);
1292 });
1293 },
1294 // alias
1295 rules: function(field, rules) {
1296 if(Array.isArray(field)) {
1297 $.each(field, function(index, field) {
1298 module.remove.rule(field, rules);
1299 });
1300 }
1301 else {
1302 module.remove.rule(field, rules);
1303 }
1304 },
1305 fields: function(fields) {
1306 module.remove.field(fields);
1307 },
1308 prompt: function(identifier) {
1309 var
1310 $field = module.get.field(identifier),
1311 $fieldGroup = $field.closest($group),
1312 $prompt = $fieldGroup.children(selector.prompt)
1313 ;
1314 $fieldGroup
1315 .removeClass(className.error)
1316 ;
1317 if(settings.inline && $prompt.is(':visible')) {
1318 module.verbose('Removing prompt for field', identifier);
1319 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
1320 $prompt.transition(settings.transition + ' out', settings.duration, function() {
1321 $prompt.remove();
1322 });
1323 }
1324 else {
1325 $prompt
1326 .fadeOut(settings.duration, function(){
1327 $prompt.remove();
1328 })
1329 ;
1330 }
1331 }
1332 }
1333 },
1334
1335 set: {
1336 success: function() {
1337 $module
1338 .removeClass(className.error)
1339 .addClass(className.success)
1340 ;
1341 },
1342 defaults: function () {
1343 $field
1344 .each(function () {
1345 var
1346 $field = $(this),
1347 isCheckbox = ($field.filter(selector.checkbox).length > 0),
1348 value = (isCheckbox)
1349 ? $field.is(':checked')
1350 : $field.val()
1351 ;
1352 $field.data(metadata.defaultValue, value);
1353 })
1354 ;
1355 },
1356 error: function() {
1357 $module
1358 .removeClass(className.success)
1359 .addClass(className.error)
1360 ;
1361 },
1362 value: function (field, value) {
1363 var
1364 fields = {}
1365 ;
1366 fields[field] = value;
1367 return module.set.values.call(element, fields);
1368 },
1369 values: function (fields) {
1370 if($.isEmptyObject(fields)) {
1371 return;
1372 }
1373 $.each(fields, function(key, value) {
1374 var
1375 $field = module.get.field(key),
1376 $element = $field.parent(),
1377 isMultiple = Array.isArray(value),
1378 isCheckbox = $element.is(selector.uiCheckbox),
1379 isDropdown = $element.is(selector.uiDropdown),
1380 isRadio = ($field.is(selector.radio) && isCheckbox),
1381 fieldExists = ($field.length > 0),
1382 $multipleField
1383 ;
1384 if(fieldExists) {
1385 if(isMultiple && isCheckbox) {
1386 module.verbose('Selecting multiple', value, $field);
1387 $element.checkbox('uncheck');
1388 $.each(value, function(index, value) {
1389 $multipleField = $field.filter('[value="' + value + '"]');
1390 $element = $multipleField.parent();
1391 if($multipleField.length > 0) {
1392 $element.checkbox('check');
1393 }
1394 });
1395 }
1396 else if(isRadio) {
1397 module.verbose('Selecting radio value', value, $field);
1398 $field.filter('[value="' + value + '"]')
1399 .parent(selector.uiCheckbox)
1400 .checkbox('check')
1401 ;
1402 }
1403 else if(isCheckbox) {
1404 module.verbose('Setting checkbox value', value, $element);
1405 if(value === true) {
1406 $element.checkbox('check');
1407 }
1408 else {
1409 $element.checkbox('uncheck');
1410 }
1411 }
1412 else if(isDropdown) {
1413 module.verbose('Setting dropdown value', value, $element);
1414 $element.dropdown('set selected', value);
1415 }
1416 else {
1417 module.verbose('Setting field value', value, $field);
1418 $field.val(value);
1419 }
1420 }
1421 });
1422 }
1423 },
1424
1425 validate: {
1426
1427 form: function(event, ignoreCallbacks) {
1428 var
1429 values = module.get.values()
1430 ;
1431
1432 // input keydown event will fire submit repeatedly by browser default
1433 if(keyHeldDown) {
1434 return false;
1435 }
1436
1437 // reset errors
1438 formErrors = [];
1439 if( module.determine.isValid() ) {
1440 module.debug('Form has no validation errors, submitting');
1441 module.set.success();
1442 if(ignoreCallbacks !== true) {
1443 return settings.onSuccess.call(element, event, values);
1444 }
1445 }
1446 else {
1447 module.debug('Form has errors');
1448 module.set.error();
1449 if(!settings.inline) {
1450 module.add.errors(formErrors);
1451 }
1452 // prevent ajax submit
1453 if($module.data('moduleApi') !== undefined) {
1454 event.stopImmediatePropagation();
1455 }
1456 if(ignoreCallbacks !== true) {
1457 return settings.onFailure.call(element, formErrors, values);
1458 }
1459 }
1460 },
1461
1462 // takes a validation object and returns whether field passes validation
1463 field: function(field, fieldName, showErrors) {
1464 showErrors = (showErrors !== undefined)
1465 ? showErrors
1466 : true
1467 ;
1468 if(typeof field == 'string') {
1469 module.verbose('Validating field', field);
1470 fieldName = field;
1471 field = validation[field];
1472 }
1473 var
1474 identifier = field.identifier || fieldName,
1475 $field = module.get.field(identifier),
1476 $dependsField = (field.depends)
1477 ? module.get.field(field.depends)
1478 : false,
1479 fieldValid = true,
1480 fieldErrors = []
1481 ;
1482 if(!field.identifier) {
1483 module.debug('Using field name as identifier', identifier);
1484 field.identifier = identifier;
1485 }
1486 var isDisabled = true;
1487 $.each($field, function(){
1488 if(!$(this).prop('disabled')) {
1489 isDisabled = false;
1490 return false;
1491 }
1492 });
1493 if(isDisabled) {
1494 module.debug('Field is disabled. Skipping', identifier);
1495 }
1496 else if(field.optional && module.is.blank($field)){
1497 module.debug('Field is optional and blank. Skipping', identifier);
1498 }
1499 else if(field.depends && module.is.empty($dependsField)) {
1500 module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
1501 }
1502 else if(field.rules !== undefined) {
1503 $field.closest($group).removeClass(className.error);
1504 $.each(field.rules, function(index, rule) {
1505 if( module.has.field(identifier)) {
1506 var invalidFields = module.validate.rule(field, rule,true) || [];
1507 if (invalidFields.length>0){
1508 module.debug('Field is invalid', identifier, rule.type);
1509 fieldErrors.push(module.get.prompt(rule, field));
1510 fieldValid = false;
1511 if(showErrors){
1512 $(invalidFields).closest($group).addClass(className.error);
1513 }
1514 }
1515 }
1516 });
1517 }
1518 if(fieldValid) {
1519 if(showErrors) {
1520 module.remove.prompt(identifier, fieldErrors);
1521 settings.onValid.call($field);
1522 }
1523 }
1524 else {
1525 if(showErrors) {
1526 formErrors = formErrors.concat(fieldErrors);
1527 module.add.prompt(identifier, fieldErrors, true);
1528 settings.onInvalid.call($field, fieldErrors);
1529 }
1530 return false;
1531 }
1532 return true;
1533 },
1534
1535 // takes validation rule and returns whether field passes rule
1536 rule: function(field, rule, internal) {
1537 var
1538 $field = module.get.field(field.identifier),
1539 ancillary = module.get.ancillaryValue(rule),
1540 ruleName = module.get.ruleName(rule),
1541 ruleFunction = settings.rules[ruleName],
1542 invalidFields = [],
1543 isCheckbox = $field.is(selector.checkbox),
1544 isValid = function(field){
1545 var value = (isCheckbox ? $(field).filter(':checked').val() : $(field).val());
1546 // cast to string avoiding encoding special values
1547 value = (value === undefined || value === '' || value === null)
1548 ? ''
1549 : (settings.shouldTrim) ? $.trim(value + '') : String(value + '')
1550 ;
1551 return ruleFunction.call(field, value, ancillary);
1552 }
1553 ;
1554 if( !$.isFunction(ruleFunction) ) {
1555 module.error(error.noRule, ruleName);
1556 return;
1557 }
1558 if(isCheckbox) {
1559 if (!isValid($field)) {
1560 invalidFields = $field;
1561 }
1562 } else {
1563 $.each($field, function (index, field) {
1564 if (!isValid(field)) {
1565 invalidFields.push(field);
1566 }
1567 });
1568 }
1569 return internal ? invalidFields : !(invalidFields.length>0);
1570 }
1571 },
1572
1573 setting: function(name, value) {
1574 if( $.isPlainObject(name) ) {
1575 $.extend(true, settings, name);
1576 }
1577 else if(value !== undefined) {
1578 settings[name] = value;
1579 }
1580 else {
1581 return settings[name];
1582 }
1583 },
1584 internal: function(name, value) {
1585 if( $.isPlainObject(name) ) {
1586 $.extend(true, module, name);
1587 }
1588 else if(value !== undefined) {
1589 module[name] = value;
1590 }
1591 else {
1592 return module[name];
1593 }
1594 },
1595 debug: function() {
1596 if(!settings.silent && settings.debug) {
1597 if(settings.performance) {
1598 module.performance.log(arguments);
1599 }
1600 else {
1601 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
1602 module.debug.apply(console, arguments);
1603 }
1604 }
1605 },
1606 verbose: function() {
1607 if(!settings.silent && settings.verbose && settings.debug) {
1608 if(settings.performance) {
1609 module.performance.log(arguments);
1610 }
1611 else {
1612 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
1613 module.verbose.apply(console, arguments);
1614 }
1615 }
1616 },
1617 error: function() {
1618 if(!settings.silent) {
1619 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
1620 module.error.apply(console, arguments);
1621 }
1622 },
1623 performance: {
1624 log: function(message) {
1625 var
1626 currentTime,
1627 executionTime,
1628 previousTime
1629 ;
1630 if(settings.performance) {
1631 currentTime = new Date().getTime();
1632 previousTime = time || currentTime;
1633 executionTime = currentTime - previousTime;
1634 time = currentTime;
1635 performance.push({
1636 'Name' : message[0],
1637 'Arguments' : [].slice.call(message, 1) || '',
1638 'Element' : element,
1639 'Execution Time' : executionTime
1640 });
1641 }
1642 clearTimeout(module.performance.timer);
1643 module.performance.timer = setTimeout(module.performance.display, 500);
1644 },
1645 display: function() {
1646 var
1647 title = settings.name + ':',
1648 totalTime = 0
1649 ;
1650 time = false;
1651 clearTimeout(module.performance.timer);
1652 $.each(performance, function(index, data) {
1653 totalTime += data['Execution Time'];
1654 });
1655 title += ' ' + totalTime + 'ms';
1656 if(moduleSelector) {
1657 title += ' \'' + moduleSelector + '\'';
1658 }
1659 if($allModules.length > 1) {
1660 title += ' ' + '(' + $allModules.length + ')';
1661 }
1662 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
1663 console.groupCollapsed(title);
1664 if(console.table) {
1665 console.table(performance);
1666 }
1667 else {
1668 $.each(performance, function(index, data) {
1669 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
1670 });
1671 }
1672 console.groupEnd();
1673 }
1674 performance = [];
1675 }
1676 },
1677 invoke: function(query, passedArguments, context) {
1678 var
1679 object = instance,
1680 maxDepth,
1681 found,
1682 response
1683 ;
1684 passedArguments = passedArguments || queryArguments;
1685 context = element || context;
1686 if(typeof query == 'string' && object !== undefined) {
1687 query = query.split(/[\. ]/);
1688 maxDepth = query.length - 1;
1689 $.each(query, function(depth, value) {
1690 var camelCaseValue = (depth != maxDepth)
1691 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1692 : query
1693 ;
1694 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
1695 object = object[camelCaseValue];
1696 }
1697 else if( object[camelCaseValue] !== undefined ) {
1698 found = object[camelCaseValue];
1699 return false;
1700 }
1701 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
1702 object = object[value];
1703 }
1704 else if( object[value] !== undefined ) {
1705 found = object[value];
1706 return false;
1707 }
1708 else {
1709 return false;
1710 }
1711 });
1712 }
1713 if( $.isFunction( found ) ) {
1714 response = found.apply(context, passedArguments);
1715 }
1716 else if(found !== undefined) {
1717 response = found;
1718 }
1719 if(Array.isArray(returnedValue)) {
1720 returnedValue.push(response);
1721 }
1722 else if(returnedValue !== undefined) {
1723 returnedValue = [returnedValue, response];
1724 }
1725 else if(response !== undefined) {
1726 returnedValue = response;
1727 }
1728 return found;
1729 }
1730 };
1731 module.initialize();
1732 })
1733 ;
1734
1735 return (returnedValue !== undefined)
1736 ? returnedValue
1737 : this
1738 ;
1739};
1740
1741$.fn.form.settings = {
1742
1743 name : 'Form',
1744 namespace : 'form',
1745
1746 debug : false,
1747 verbose : false,
1748 performance : true,
1749
1750 fields : false,
1751
1752 keyboardShortcuts : true,
1753 on : 'submit',
1754 inline : false,
1755
1756 delay : 200,
1757 revalidate : true,
1758 shouldTrim : true,
1759
1760 transition : 'scale',
1761 duration : 200,
1762
1763 onValid : function() {},
1764 onInvalid : function() {},
1765 onSuccess : function() { return true; },
1766 onFailure : function() { return false; },
1767
1768 metadata : {
1769 defaultValue : 'default',
1770 validate : 'validate'
1771 },
1772
1773 regExp: {
1774 htmlID : /^[a-zA-Z][\w:.-]*$/g,
1775 bracket : /\[(.*)\]/i,
1776 decimal : /^\d+\.?\d*$/,
1777 email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
1778 escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|:,=@]/g,
1779 flags : /^\/(.*)\/(.*)?/,
1780 integer : /^\-?\d+$/,
1781 number : /^\-?\d*(\.\d+)?$/,
1782 url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
1783 },
1784
1785 text: {
1786 unspecifiedRule : 'Please enter a valid value',
1787 unspecifiedField : 'This field'
1788 },
1789
1790 prompt: {
1791 empty : '{name} must have a value',
1792 checked : '{name} must be checked',
1793 email : '{name} must be a valid e-mail',
1794 url : '{name} must be a valid url',
1795 regExp : '{name} is not formatted correctly',
1796 integer : '{name} must be an integer',
1797 decimal : '{name} must be a decimal number',
1798 number : '{name} must be set to a number',
1799 is : '{name} must be "{ruleValue}"',
1800 isExactly : '{name} must be exactly "{ruleValue}"',
1801 not : '{name} cannot be set to "{ruleValue}"',
1802 notExactly : '{name} cannot be set to exactly "{ruleValue}"',
1803 contain : '{name} must contain "{ruleValue}"',
1804 containExactly : '{name} must contain exactly "{ruleValue}"',
1805 doesntContain : '{name} cannot contain "{ruleValue}"',
1806 doesntContainExactly : '{name} cannot contain exactly "{ruleValue}"',
1807 minLength : '{name} must be at least {ruleValue} characters',
1808 length : '{name} must be at least {ruleValue} characters',
1809 exactLength : '{name} must be exactly {ruleValue} characters',
1810 maxLength : '{name} cannot be longer than {ruleValue} characters',
1811 match : '{name} must match {ruleValue} field',
1812 different : '{name} must have a different value than {ruleValue} field',
1813 creditCard : '{name} must be a valid credit card number',
1814 minCount : '{name} must have at least {ruleValue} choices',
1815 exactCount : '{name} must have exactly {ruleValue} choices',
1816 maxCount : '{name} must have {ruleValue} or less choices'
1817 },
1818
1819 selector : {
1820 checkbox : 'input[type="checkbox"], input[type="radio"]',
1821 clear : '.clear',
1822 field : 'input, textarea, select',
1823 group : '.field',
1824 input : 'input',
1825 message : '.error.message',
1826 prompt : '.prompt.label',
1827 radio : 'input[type="radio"]',
1828 reset : '.reset:not([type="reset"])',
1829 submit : '.submit:not([type="submit"])',
1830 uiCheckbox : '.ui.checkbox',
1831 uiDropdown : '.ui.dropdown'
1832 },
1833
1834 className : {
1835 error : 'error',
1836 label : 'ui prompt label',
1837 pressed : 'down',
1838 success : 'success'
1839 },
1840
1841 error: {
1842 identifier : 'You must specify a string identifier for each field',
1843 method : 'The method you called is not defined.',
1844 noRule : 'There is no rule matching the one you specified',
1845 oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.'
1846 },
1847
1848 templates: {
1849
1850 // template that produces error message
1851 error: function(errors) {
1852 var
1853 html = '<ul class="list">'
1854 ;
1855 $.each(errors, function(index, value) {
1856 html += '<li>' + value + '</li>';
1857 });
1858 html += '</ul>';
1859 return $(html);
1860 },
1861
1862 // template that produces label
1863 prompt: function(errors) {
1864 return $('<div/>')
1865 .addClass('ui basic red pointing prompt label')
1866 .html(errors[0])
1867 ;
1868 }
1869 },
1870
1871 rules: {
1872
1873 // is not empty or blank string
1874 empty: function(value) {
1875 return !(value === undefined || '' === value || Array.isArray(value) && value.length === 0);
1876 },
1877
1878 // checkbox checked
1879 checked: function() {
1880 return ($(this).filter(':checked').length > 0);
1881 },
1882
1883 // is most likely an email
1884 email: function(value){
1885 return $.fn.form.settings.regExp.email.test(value);
1886 },
1887
1888 // value is most likely url
1889 url: function(value) {
1890 return $.fn.form.settings.regExp.url.test(value);
1891 },
1892
1893 // matches specified regExp
1894 regExp: function(value, regExp) {
1895 if(regExp instanceof RegExp) {
1896 return value.match(regExp);
1897 }
1898 var
1899 regExpParts = regExp.match($.fn.form.settings.regExp.flags),
1900 flags
1901 ;
1902 // regular expression specified as /baz/gi (flags)
1903 if(regExpParts) {
1904 regExp = (regExpParts.length >= 2)
1905 ? regExpParts[1]
1906 : regExp
1907 ;
1908 flags = (regExpParts.length >= 3)
1909 ? regExpParts[2]
1910 : ''
1911 ;
1912 }
1913 return value.match( new RegExp(regExp, flags) );
1914 },
1915
1916 // is valid integer or matches range
1917 integer: function(value, range) {
1918 var
1919 intRegExp = $.fn.form.settings.regExp.integer,
1920 min,
1921 max,
1922 parts
1923 ;
1924 if( !range || ['', '..'].indexOf(range) !== -1) {
1925 // do nothing
1926 }
1927 else if(range.indexOf('..') == -1) {
1928 if(intRegExp.test(range)) {
1929 min = max = range - 0;
1930 }
1931 }
1932 else {
1933 parts = range.split('..', 2);
1934 if(intRegExp.test(parts[0])) {
1935 min = parts[0] - 0;
1936 }
1937 if(intRegExp.test(parts[1])) {
1938 max = parts[1] - 0;
1939 }
1940 }
1941 return (
1942 intRegExp.test(value) &&
1943 (min === undefined || value >= min) &&
1944 (max === undefined || value <= max)
1945 );
1946 },
1947
1948 // is valid number (with decimal)
1949 decimal: function(value) {
1950 return $.fn.form.settings.regExp.decimal.test(value);
1951 },
1952
1953 // is valid number
1954 number: function(value) {
1955 return $.fn.form.settings.regExp.number.test(value);
1956 },
1957
1958 // is value (case insensitive)
1959 is: function(value, text) {
1960 text = (typeof text == 'string')
1961 ? text.toLowerCase()
1962 : text
1963 ;
1964 value = (typeof value == 'string')
1965 ? value.toLowerCase()
1966 : value
1967 ;
1968 return (value == text);
1969 },
1970
1971 // is value
1972 isExactly: function(value, text) {
1973 return (value == text);
1974 },
1975
1976 // value is not another value (case insensitive)
1977 not: function(value, notValue) {
1978 value = (typeof value == 'string')
1979 ? value.toLowerCase()
1980 : value
1981 ;
1982 notValue = (typeof notValue == 'string')
1983 ? notValue.toLowerCase()
1984 : notValue
1985 ;
1986 return (value != notValue);
1987 },
1988
1989 // value is not another value (case sensitive)
1990 notExactly: function(value, notValue) {
1991 return (value != notValue);
1992 },
1993
1994 // value contains text (insensitive)
1995 contains: function(value, text) {
1996 // escape regex characters
1997 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
1998 return (value.search( new RegExp(text, 'i') ) !== -1);
1999 },
2000
2001 // value contains text (case sensitive)
2002 containsExactly: function(value, text) {
2003 // escape regex characters
2004 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
2005 return (value.search( new RegExp(text) ) !== -1);
2006 },
2007
2008 // value contains text (insensitive)
2009 doesntContain: function(value, text) {
2010 // escape regex characters
2011 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
2012 return (value.search( new RegExp(text, 'i') ) === -1);
2013 },
2014
2015 // value contains text (case sensitive)
2016 doesntContainExactly: function(value, text) {
2017 // escape regex characters
2018 text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
2019 return (value.search( new RegExp(text) ) === -1);
2020 },
2021
2022 // is at least string length
2023 minLength: function(value, requiredLength) {
2024 return (value !== undefined)
2025 ? (value.length >= requiredLength)
2026 : false
2027 ;
2028 },
2029
2030 // see rls notes for 2.0.6 (this is a duplicate of minLength)
2031 length: function(value, requiredLength) {
2032 return (value !== undefined)
2033 ? (value.length >= requiredLength)
2034 : false
2035 ;
2036 },
2037
2038 // is exactly length
2039 exactLength: function(value, requiredLength) {
2040 return (value !== undefined)
2041 ? (value.length == requiredLength)
2042 : false
2043 ;
2044 },
2045
2046 // is less than length
2047 maxLength: function(value, maxLength) {
2048 return (value !== undefined)
2049 ? (value.length <= maxLength)
2050 : false
2051 ;
2052 },
2053
2054 // matches another field
2055 match: function(value, identifier) {
2056 var
2057 matchingValue
2058 ;
2059 if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
2060 matchingValue = $('[data-validate="'+ identifier +'"]').val();
2061 }
2062 else if($('#' + identifier).length > 0) {
2063 matchingValue = $('#' + identifier).val();
2064 }
2065 else if($('[name="' + identifier +'"]').length > 0) {
2066 matchingValue = $('[name="' + identifier + '"]').val();
2067 }
2068 else if( $('[name="' + identifier +'[]"]').length > 0 ) {
2069 matchingValue = $('[name="' + identifier +'[]"]');
2070 }
2071 return (matchingValue !== undefined)
2072 ? ( value.toString() == matchingValue.toString() )
2073 : false
2074 ;
2075 },
2076
2077 // different than another field
2078 different: function(value, identifier) {
2079 // use either id or name of field
2080 var
2081 matchingValue
2082 ;
2083 if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
2084 matchingValue = $('[data-validate="'+ identifier +'"]').val();
2085 }
2086 else if($('#' + identifier).length > 0) {
2087 matchingValue = $('#' + identifier).val();
2088 }
2089 else if($('[name="' + identifier +'"]').length > 0) {
2090 matchingValue = $('[name="' + identifier + '"]').val();
2091 }
2092 else if( $('[name="' + identifier +'[]"]').length > 0 ) {
2093 matchingValue = $('[name="' + identifier +'[]"]');
2094 }
2095 return (matchingValue !== undefined)
2096 ? ( value.toString() !== matchingValue.toString() )
2097 : false
2098 ;
2099 },
2100
2101 creditCard: function(cardNumber, cardTypes) {
2102 var
2103 cards = {
2104 visa: {
2105 pattern : /^4/,
2106 length : [16]
2107 },
2108 amex: {
2109 pattern : /^3[47]/,
2110 length : [15]
2111 },
2112 mastercard: {
2113 pattern : /^5[1-5]/,
2114 length : [16]
2115 },
2116 discover: {
2117 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)/,
2118 length : [16]
2119 },
2120 unionPay: {
2121 pattern : /^(62|88)/,
2122 length : [16, 17, 18, 19]
2123 },
2124 jcb: {
2125 pattern : /^35(2[89]|[3-8][0-9])/,
2126 length : [16]
2127 },
2128 maestro: {
2129 pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
2130 length : [12, 13, 14, 15, 16, 17, 18, 19]
2131 },
2132 dinersClub: {
2133 pattern : /^(30[0-5]|^36)/,
2134 length : [14]
2135 },
2136 laser: {
2137 pattern : /^(6304|670[69]|6771)/,
2138 length : [16, 17, 18, 19]
2139 },
2140 visaElectron: {
2141 pattern : /^(4026|417500|4508|4844|491(3|7))/,
2142 length : [16]
2143 }
2144 },
2145 valid = {},
2146 validCard = false,
2147 requiredTypes = (typeof cardTypes == 'string')
2148 ? cardTypes.split(',')
2149 : false,
2150 unionPay,
2151 validation
2152 ;
2153
2154 if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
2155 return;
2156 }
2157
2158 // allow dashes in card
2159 cardNumber = cardNumber.replace(/[\-]/g, '');
2160
2161 // verify card types
2162 if(requiredTypes) {
2163 $.each(requiredTypes, function(index, type){
2164 // verify each card type
2165 validation = cards[type];
2166 if(validation) {
2167 valid = {
2168 length : ($.inArray(cardNumber.length, validation.length) !== -1),
2169 pattern : (cardNumber.search(validation.pattern) !== -1)
2170 };
2171 if(valid.length && valid.pattern) {
2172 validCard = true;
2173 }
2174 }
2175 });
2176
2177 if(!validCard) {
2178 return false;
2179 }
2180 }
2181
2182 // skip luhn for UnionPay
2183 unionPay = {
2184 number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
2185 pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
2186 };
2187 if(unionPay.number && unionPay.pattern) {
2188 return true;
2189 }
2190
2191 // verify luhn, adapted from <https://gist.github.com/2134376>
2192 var
2193 length = cardNumber.length,
2194 multiple = 0,
2195 producedValue = [
2196 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
2197 [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
2198 ],
2199 sum = 0
2200 ;
2201 while (length--) {
2202 sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
2203 multiple ^= 1;
2204 }
2205 return (sum % 10 === 0 && sum > 0);
2206 },
2207
2208 minCount: function(value, minCount) {
2209 if(minCount == 0) {
2210 return true;
2211 }
2212 if(minCount == 1) {
2213 return (value !== '');
2214 }
2215 return (value.split(',').length >= minCount);
2216 },
2217
2218 exactCount: function(value, exactCount) {
2219 if(exactCount == 0) {
2220 return (value === '');
2221 }
2222 if(exactCount == 1) {
2223 return (value !== '' && value.search(',') === -1);
2224 }
2225 return (value.split(',').length == exactCount);
2226 },
2227
2228 maxCount: function(value, maxCount) {
2229 if(maxCount == 0) {
2230 return false;
2231 }
2232 if(maxCount == 1) {
2233 return (value.search(',') === -1);
2234 }
2235 return (value.split(',').length <= maxCount);
2236 }
2237 }
2238
2239};
2240
2241})( jQuery, window, document );
2242
2243/*!
2244 * # Semantic UI 2.7.2 - Accordion
2245 * http://github.com/semantic-org/semantic-ui/
2246 *
2247 *
2248 * Released under the MIT license
2249 * http://opensource.org/licenses/MIT
2250 *
2251 */
2252
2253;(function ($, window, document, undefined) {
2254
2255'use strict';
2256
2257$.isFunction = $.isFunction || function(obj) {
2258 return typeof obj === "function" && typeof obj.nodeType !== "number";
2259};
2260
2261window = (typeof window != 'undefined' && window.Math == Math)
2262 ? window
2263 : (typeof self != 'undefined' && self.Math == Math)
2264 ? self
2265 : Function('return this')()
2266;
2267
2268$.fn.accordion = function(parameters) {
2269 var
2270 $allModules = $(this),
2271
2272 time = new Date().getTime(),
2273 performance = [],
2274
2275 query = arguments[0],
2276 methodInvoked = (typeof query == 'string'),
2277 queryArguments = [].slice.call(arguments, 1),
2278
2279 returnedValue
2280 ;
2281 $allModules
2282 .each(function() {
2283 var
2284 settings = ( $.isPlainObject(parameters) )
2285 ? $.extend(true, {}, $.fn.accordion.settings, parameters)
2286 : $.extend({}, $.fn.accordion.settings),
2287
2288 className = settings.className,
2289 namespace = settings.namespace,
2290 selector = settings.selector,
2291 error = settings.error,
2292
2293 eventNamespace = '.' + namespace,
2294 moduleNamespace = 'module-' + namespace,
2295 moduleSelector = $allModules.selector || '',
2296
2297 $module = $(this),
2298 $title = $module.find(selector.title),
2299 $content = $module.find(selector.content),
2300
2301 element = this,
2302 instance = $module.data(moduleNamespace),
2303 observer,
2304 module
2305 ;
2306
2307 module = {
2308
2309 initialize: function() {
2310 module.debug('Initializing', $module);
2311 module.bind.events();
2312 if(settings.observeChanges) {
2313 module.observeChanges();
2314 }
2315 module.instantiate();
2316 },
2317
2318 instantiate: function() {
2319 instance = module;
2320 $module
2321 .data(moduleNamespace, module)
2322 ;
2323 },
2324
2325 destroy: function() {
2326 module.debug('Destroying previous instance', $module);
2327 $module
2328 .off(eventNamespace)
2329 .removeData(moduleNamespace)
2330 ;
2331 },
2332
2333 refresh: function() {
2334 $title = $module.find(selector.title);
2335 $content = $module.find(selector.content);
2336 },
2337
2338 observeChanges: function() {
2339 if('MutationObserver' in window) {
2340 observer = new MutationObserver(function(mutations) {
2341 module.debug('DOM tree modified, updating selector cache');
2342 module.refresh();
2343 });
2344 observer.observe(element, {
2345 childList : true,
2346 subtree : true
2347 });
2348 module.debug('Setting up mutation observer', observer);
2349 }
2350 },
2351
2352 bind: {
2353 events: function() {
2354 module.debug('Binding delegated events');
2355 $module
2356 .on(settings.on + eventNamespace, selector.trigger, module.event.click)
2357 ;
2358 }
2359 },
2360
2361 event: {
2362 click: function() {
2363 module.toggle.call(this);
2364 }
2365 },
2366
2367 toggle: function(query) {
2368 var
2369 $activeTitle = (query !== undefined)
2370 ? (typeof query === 'number')
2371 ? $title.eq(query)
2372 : $(query).closest(selector.title)
2373 : $(this).closest(selector.title),
2374 $activeContent = $activeTitle.next($content),
2375 isAnimating = $activeContent.hasClass(className.animating),
2376 isActive = $activeContent.hasClass(className.active),
2377 isOpen = (isActive && !isAnimating),
2378 isOpening = (!isActive && isAnimating)
2379 ;
2380 module.debug('Toggling visibility of content', $activeTitle);
2381 if(isOpen || isOpening) {
2382 if(settings.collapsible) {
2383 module.close.call($activeTitle);
2384 }
2385 else {
2386 module.debug('Cannot close accordion content collapsing is disabled');
2387 }
2388 }
2389 else {
2390 module.open.call($activeTitle);
2391 }
2392 },
2393
2394 open: function(query) {
2395 var
2396 $activeTitle = (query !== undefined)
2397 ? (typeof query === 'number')
2398 ? $title.eq(query)
2399 : $(query).closest(selector.title)
2400 : $(this).closest(selector.title),
2401 $activeContent = $activeTitle.next($content),
2402 isAnimating = $activeContent.hasClass(className.animating),
2403 isActive = $activeContent.hasClass(className.active),
2404 isOpen = (isActive || isAnimating)
2405 ;
2406 if(isOpen) {
2407 module.debug('Accordion already open, skipping', $activeContent);
2408 return;
2409 }
2410 module.debug('Opening accordion content', $activeTitle);
2411 settings.onOpening.call($activeContent);
2412 settings.onChanging.call($activeContent);
2413 if(settings.exclusive) {
2414 module.closeOthers.call($activeTitle);
2415 }
2416 $activeTitle
2417 .addClass(className.active)
2418 ;
2419 $activeContent
2420 .stop(true, true)
2421 .addClass(className.animating)
2422 ;
2423 if(settings.animateChildren) {
2424 if($.fn.transition !== undefined && $module.transition('is supported')) {
2425 $activeContent
2426 .children()
2427 .transition({
2428 animation : 'fade in',
2429 queue : false,
2430 useFailSafe : true,
2431 debug : settings.debug,
2432 verbose : settings.verbose,
2433 duration : settings.duration,
2434 skipInlineHidden : true
2435 })
2436 ;
2437 }
2438 else {
2439 $activeContent
2440 .children()
2441 .stop(true, true)
2442 .animate({
2443 opacity: 1
2444 }, settings.duration, module.resetOpacity)
2445 ;
2446 }
2447 }
2448 $activeContent
2449 .slideDown(settings.duration, settings.easing, function() {
2450 $activeContent
2451 .removeClass(className.animating)
2452 .addClass(className.active)
2453 ;
2454 module.reset.display.call(this);
2455 settings.onOpen.call(this);
2456 settings.onChange.call(this);
2457 })
2458 ;
2459 },
2460
2461 close: function(query) {
2462 var
2463 $activeTitle = (query !== undefined)
2464 ? (typeof query === 'number')
2465 ? $title.eq(query)
2466 : $(query).closest(selector.title)
2467 : $(this).closest(selector.title),
2468 $activeContent = $activeTitle.next($content),
2469 isAnimating = $activeContent.hasClass(className.animating),
2470 isActive = $activeContent.hasClass(className.active),
2471 isOpening = (!isActive && isAnimating),
2472 isClosing = (isActive && isAnimating)
2473 ;
2474 if((isActive || isOpening) && !isClosing) {
2475 module.debug('Closing accordion content', $activeContent);
2476 settings.onClosing.call($activeContent);
2477 settings.onChanging.call($activeContent);
2478 $activeTitle
2479 .removeClass(className.active)
2480 ;
2481 $activeContent
2482 .stop(true, true)
2483 .addClass(className.animating)
2484 ;
2485 if(settings.animateChildren) {
2486 if($.fn.transition !== undefined && $module.transition('is supported')) {
2487 $activeContent
2488 .children()
2489 .transition({
2490 animation : 'fade out',
2491 queue : false,
2492 useFailSafe : true,
2493 debug : settings.debug,
2494 verbose : settings.verbose,
2495 duration : settings.duration,
2496 skipInlineHidden : true
2497 })
2498 ;
2499 }
2500 else {
2501 $activeContent
2502 .children()
2503 .stop(true, true)
2504 .animate({
2505 opacity: 0
2506 }, settings.duration, module.resetOpacity)
2507 ;
2508 }
2509 }
2510 $activeContent
2511 .slideUp(settings.duration, settings.easing, function() {
2512 $activeContent
2513 .removeClass(className.animating)
2514 .removeClass(className.active)
2515 ;
2516 module.reset.display.call(this);
2517 settings.onClose.call(this);
2518 settings.onChange.call(this);
2519 })
2520 ;
2521 }
2522 },
2523
2524 closeOthers: function(index) {
2525 var
2526 $activeTitle = (index !== undefined)
2527 ? $title.eq(index)
2528 : $(this).closest(selector.title),
2529 $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
2530 $activeAccordion = $activeTitle.closest(selector.accordion),
2531 activeSelector = selector.title + '.' + className.active + ':visible',
2532 activeContent = selector.content + '.' + className.active + ':visible',
2533 $openTitles,
2534 $nestedTitles,
2535 $openContents
2536 ;
2537 if(settings.closeNested) {
2538 $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
2539 $openContents = $openTitles.next($content);
2540 }
2541 else {
2542 $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
2543 $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
2544 $openTitles = $openTitles.not($nestedTitles);
2545 $openContents = $openTitles.next($content);
2546 }
2547 if( ($openTitles.length > 0) ) {
2548 module.debug('Exclusive enabled, closing other content', $openTitles);
2549 $openTitles
2550 .removeClass(className.active)
2551 ;
2552 $openContents
2553 .removeClass(className.animating)
2554 .stop(true, true)
2555 ;
2556 if(settings.animateChildren) {
2557 if($.fn.transition !== undefined && $module.transition('is supported')) {
2558 $openContents
2559 .children()
2560 .transition({
2561 animation : 'fade out',
2562 useFailSafe : true,
2563 debug : settings.debug,
2564 verbose : settings.verbose,
2565 duration : settings.duration,
2566 skipInlineHidden : true
2567 })
2568 ;
2569 }
2570 else {
2571 $openContents
2572 .children()
2573 .stop(true, true)
2574 .animate({
2575 opacity: 0
2576 }, settings.duration, module.resetOpacity)
2577 ;
2578 }
2579 }
2580 $openContents
2581 .slideUp(settings.duration , settings.easing, function() {
2582 $(this).removeClass(className.active);
2583 module.reset.display.call(this);
2584 })
2585 ;
2586 }
2587 },
2588
2589 reset: {
2590
2591 display: function() {
2592 module.verbose('Removing inline display from element', this);
2593 $(this).css('display', '');
2594 if( $(this).attr('style') === '') {
2595 $(this)
2596 .attr('style', '')
2597 .removeAttr('style')
2598 ;
2599 }
2600 },
2601
2602 opacity: function() {
2603 module.verbose('Removing inline opacity from element', this);
2604 $(this).css('opacity', '');
2605 if( $(this).attr('style') === '') {
2606 $(this)
2607 .attr('style', '')
2608 .removeAttr('style')
2609 ;
2610 }
2611 },
2612
2613 },
2614
2615 setting: function(name, value) {
2616 module.debug('Changing setting', name, value);
2617 if( $.isPlainObject(name) ) {
2618 $.extend(true, settings, name);
2619 }
2620 else if(value !== undefined) {
2621 if($.isPlainObject(settings[name])) {
2622 $.extend(true, settings[name], value);
2623 }
2624 else {
2625 settings[name] = value;
2626 }
2627 }
2628 else {
2629 return settings[name];
2630 }
2631 },
2632 internal: function(name, value) {
2633 module.debug('Changing internal', name, value);
2634 if(value !== undefined) {
2635 if( $.isPlainObject(name) ) {
2636 $.extend(true, module, name);
2637 }
2638 else {
2639 module[name] = value;
2640 }
2641 }
2642 else {
2643 return module[name];
2644 }
2645 },
2646 debug: function() {
2647 if(!settings.silent && settings.debug) {
2648 if(settings.performance) {
2649 module.performance.log(arguments);
2650 }
2651 else {
2652 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
2653 module.debug.apply(console, arguments);
2654 }
2655 }
2656 },
2657 verbose: function() {
2658 if(!settings.silent && settings.verbose && settings.debug) {
2659 if(settings.performance) {
2660 module.performance.log(arguments);
2661 }
2662 else {
2663 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
2664 module.verbose.apply(console, arguments);
2665 }
2666 }
2667 },
2668 error: function() {
2669 if(!settings.silent) {
2670 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
2671 module.error.apply(console, arguments);
2672 }
2673 },
2674 performance: {
2675 log: function(message) {
2676 var
2677 currentTime,
2678 executionTime,
2679 previousTime
2680 ;
2681 if(settings.performance) {
2682 currentTime = new Date().getTime();
2683 previousTime = time || currentTime;
2684 executionTime = currentTime - previousTime;
2685 time = currentTime;
2686 performance.push({
2687 'Name' : message[0],
2688 'Arguments' : [].slice.call(message, 1) || '',
2689 'Element' : element,
2690 'Execution Time' : executionTime
2691 });
2692 }
2693 clearTimeout(module.performance.timer);
2694 module.performance.timer = setTimeout(module.performance.display, 500);
2695 },
2696 display: function() {
2697 var
2698 title = settings.name + ':',
2699 totalTime = 0
2700 ;
2701 time = false;
2702 clearTimeout(module.performance.timer);
2703 $.each(performance, function(index, data) {
2704 totalTime += data['Execution Time'];
2705 });
2706 title += ' ' + totalTime + 'ms';
2707 if(moduleSelector) {
2708 title += ' \'' + moduleSelector + '\'';
2709 }
2710 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
2711 console.groupCollapsed(title);
2712 if(console.table) {
2713 console.table(performance);
2714 }
2715 else {
2716 $.each(performance, function(index, data) {
2717 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
2718 });
2719 }
2720 console.groupEnd();
2721 }
2722 performance = [];
2723 }
2724 },
2725 invoke: function(query, passedArguments, context) {
2726 var
2727 object = instance,
2728 maxDepth,
2729 found,
2730 response
2731 ;
2732 passedArguments = passedArguments || queryArguments;
2733 context = element || context;
2734 if(typeof query == 'string' && object !== undefined) {
2735 query = query.split(/[\. ]/);
2736 maxDepth = query.length - 1;
2737 $.each(query, function(depth, value) {
2738 var camelCaseValue = (depth != maxDepth)
2739 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
2740 : query
2741 ;
2742 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
2743 object = object[camelCaseValue];
2744 }
2745 else if( object[camelCaseValue] !== undefined ) {
2746 found = object[camelCaseValue];
2747 return false;
2748 }
2749 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
2750 object = object[value];
2751 }
2752 else if( object[value] !== undefined ) {
2753 found = object[value];
2754 return false;
2755 }
2756 else {
2757 module.error(error.method, query);
2758 return false;
2759 }
2760 });
2761 }
2762 if ( $.isFunction( found ) ) {
2763 response = found.apply(context, passedArguments);
2764 }
2765 else if(found !== undefined) {
2766 response = found;
2767 }
2768 if(Array.isArray(returnedValue)) {
2769 returnedValue.push(response);
2770 }
2771 else if(returnedValue !== undefined) {
2772 returnedValue = [returnedValue, response];
2773 }
2774 else if(response !== undefined) {
2775 returnedValue = response;
2776 }
2777 return found;
2778 }
2779 };
2780 if(methodInvoked) {
2781 if(instance === undefined) {
2782 module.initialize();
2783 }
2784 module.invoke(query);
2785 }
2786 else {
2787 if(instance !== undefined) {
2788 instance.invoke('destroy');
2789 }
2790 module.initialize();
2791 }
2792 })
2793 ;
2794 return (returnedValue !== undefined)
2795 ? returnedValue
2796 : this
2797 ;
2798};
2799
2800$.fn.accordion.settings = {
2801
2802 name : 'Accordion',
2803 namespace : 'accordion',
2804
2805 silent : false,
2806 debug : false,
2807 verbose : false,
2808 performance : true,
2809
2810 on : 'click', // event on title that opens accordion
2811
2812 observeChanges : true, // whether accordion should automatically refresh on DOM insertion
2813
2814 exclusive : true, // whether a single accordion content panel should be open at once
2815 collapsible : true, // whether accordion content can be closed
2816 closeNested : false, // whether nested content should be closed when a panel is closed
2817 animateChildren : true, // whether children opacity should be animated
2818
2819 duration : 350, // duration of animation
2820 easing : 'easeOutQuad', // easing equation for animation
2821
2822 onOpening : function(){}, // callback before open animation
2823 onClosing : function(){}, // callback before closing animation
2824 onChanging : function(){}, // callback before closing or opening animation
2825
2826 onOpen : function(){}, // callback after open animation
2827 onClose : function(){}, // callback after closing animation
2828 onChange : function(){}, // callback after closing or opening animation
2829
2830 error: {
2831 method : 'The method you called is not defined'
2832 },
2833
2834 className : {
2835 active : 'active',
2836 animating : 'animating'
2837 },
2838
2839 selector : {
2840 accordion : '.accordion',
2841 title : '.title',
2842 trigger : '.title',
2843 content : '.content'
2844 }
2845
2846};
2847
2848// Adds easing
2849$.extend( $.easing, {
2850 easeOutQuad: function (x, t, b, c, d) {
2851 return -c *(t/=d)*(t-2) + b;
2852 }
2853});
2854
2855})( jQuery, window, document );
2856
2857
2858/*!
2859 * # Semantic UI 2.7.2 - Calendar
2860 * http://github.com/semantic-org/semantic-ui/
2861 *
2862 *
2863 * Released under the MIT license
2864 * http://opensource.org/licenses/MIT
2865 *
2866 */
2867
2868;(function ($, window, document, undefined) {
2869
2870'use strict';
2871
2872$.isFunction = $.isFunction || function(obj) {
2873 return typeof obj === "function" && typeof obj.nodeType !== "number";
2874};
2875
2876window = (typeof window != 'undefined' && window.Math == Math)
2877 ? window
2878 : (typeof self != 'undefined' && self.Math == Math)
2879 ? self
2880 : Function('return this')()
2881;
2882
2883$.fn.calendar = function(parameters) {
2884 var
2885 $allModules = $(this),
2886
2887 moduleSelector = $allModules.selector || '',
2888
2889 time = new Date().getTime(),
2890 performance = [],
2891
2892 query = arguments[0],
2893 methodInvoked = (typeof query == 'string'),
2894 queryArguments = [].slice.call(arguments, 1),
2895 returnedValue,
2896 timeGapTable = {
2897 '5': {'row': 4, 'column': 3 },
2898 '10': {'row': 3, 'column': 2 },
2899 '15': {'row': 2, 'column': 2 },
2900 '20': {'row': 3, 'column': 1 },
2901 '30': {'row': 2, 'column': 1 }
2902 }
2903 ;
2904
2905 $allModules
2906 .each(function () {
2907 var
2908 settings = ( $.isPlainObject(parameters) )
2909 ? $.extend(true, {}, $.fn.calendar.settings, parameters)
2910 : $.extend({}, $.fn.calendar.settings),
2911
2912 className = settings.className,
2913 namespace = settings.namespace,
2914 selector = settings.selector,
2915 formatter = settings.formatter,
2916 parser = settings.parser,
2917 metadata = settings.metadata,
2918 timeGap = timeGapTable[settings.minTimeGap],
2919 error = settings.error,
2920
2921 eventNamespace = '.' + namespace,
2922 moduleNamespace = 'module-' + namespace,
2923
2924 $module = $(this),
2925 $input = $module.find(selector.input),
2926 $container = $module.find(selector.popup),
2927 $activator = $module.find(selector.activator),
2928
2929 element = this,
2930 instance = $module.data(moduleNamespace),
2931
2932 isTouch,
2933 isTouchDown = false,
2934 focusDateUsedForRange = false,
2935 module
2936 ;
2937
2938 module = {
2939
2940 initialize: function () {
2941 module.debug('Initializing calendar for', element, $module);
2942
2943 isTouch = module.get.isTouch();
2944 module.setup.config();
2945 module.setup.popup();
2946 module.setup.inline();
2947 module.setup.input();
2948 module.setup.date();
2949 module.create.calendar();
2950
2951 module.bind.events();
2952 module.instantiate();
2953 },
2954
2955 instantiate: function () {
2956 module.verbose('Storing instance of calendar');
2957 instance = module;
2958 $module.data(moduleNamespace, instance);
2959 },
2960
2961 destroy: function () {
2962 module.verbose('Destroying previous calendar for', element);
2963 $module.removeData(moduleNamespace);
2964 module.unbind.events();
2965 },
2966
2967 setup: {
2968 config: function () {
2969 if (module.get.minDate() !== null) {
2970 module.set.minDate($module.data(metadata.minDate));
2971 }
2972 if (module.get.maxDate() !== null) {
2973 module.set.maxDate($module.data(metadata.maxDate));
2974 }
2975 },
2976 popup: function () {
2977 if (settings.inline) {
2978 return;
2979 }
2980 if (!$activator.length) {
2981 $activator = $module.children().first();
2982 if (!$activator.length) {
2983 return;
2984 }
2985 }
2986 if ($.fn.popup === undefined) {
2987 module.error(error.popup);
2988 return;
2989 }
2990 if (!$container.length) {
2991 //prepend the popup element to the activator's parent so that it has less chance of messing with
2992 //the styling (eg input action button needs to be the last child to have correct border radius)
2993 $container = $('<div/>').addClass(className.popup).prependTo($activator.parent());
2994 }
2995 $container.addClass(className.calendar);
2996 var onVisible = settings.onVisible;
2997 var onHidden = settings.onHidden;
2998 if (!$input.length) {
2999 //no input, $container has to handle focus/blur
3000 $container.attr('tabindex', '0');
3001 onVisible = function () {
3002 module.focus();
3003 return settings.onVisible.apply($container, arguments);
3004 };
3005 onHidden = function () {
3006 module.blur();
3007 return settings.onHidden.apply($container, arguments);
3008 };
3009 }
3010 var onShow = function () {
3011 //reset the focus date onShow
3012 module.set.focusDate(module.get.date());
3013 module.set.mode(settings.startMode);
3014 return settings.onShow.apply($container, arguments);
3015 };
3016 var on = settings.on || ($input.length ? 'focus' : 'click');
3017 var options = $.extend({}, settings.popupOptions, {
3018 popup: $container,
3019 on: on,
3020 hoverable: on === 'hover',
3021 onShow: onShow,
3022 onVisible: onVisible,
3023 onHide: settings.onHide,
3024 onHidden: onHidden
3025 });
3026 module.popup(options);
3027 },
3028 inline: function () {
3029 if ($activator.length && !settings.inline) {
3030 return;
3031 }
3032 $container = $('<div/>').addClass(className.calendar).appendTo($module);
3033 if (!$input.length) {
3034 $container.attr('tabindex', '0');
3035 }
3036 },
3037 input: function () {
3038 if (settings.touchReadonly && $input.length && isTouch) {
3039 $input.prop('readonly', true);
3040 }
3041 },
3042 date: function () {
3043 if (settings.initialDate) {
3044 var date = parser.date(settings.initialDate, settings);
3045 module.set.date(date, settings.formatInput, false);
3046 } else if ($module.data(metadata.date) !== undefined) {
3047 var date = parser.date($module.data(metadata.date), settings);
3048 module.set.date(date, settings.formatInput, false);
3049 } else if ($input.length) {
3050 var val = $input.val();
3051 var date = parser.date(val, settings);
3052 module.set.date(date, settings.formatInput, false);
3053 }
3054 }
3055 },
3056
3057 create: {
3058 calendar: function () {
3059 var i, r, c, p, row, cell, pageGrid;
3060
3061 var mode = module.get.mode();
3062 var today = new Date();
3063 var date = module.get.date();
3064 var focusDate = module.get.focusDate();
3065 var display = focusDate || date || settings.initialDate || today;
3066 display = module.helper.dateInRange(display);
3067
3068 if (!focusDate) {
3069 focusDate = display;
3070 module.set.focusDate(focusDate, false, false);
3071 }
3072
3073 var isYear = mode === 'year';
3074 var isMonth = mode === 'month';
3075 var isDay = mode === 'day';
3076 var isHour = mode === 'hour';
3077 var isMinute = mode === 'minute';
3078 var isTimeOnly = settings.type === 'time';
3079
3080 var multiMonth = Math.max(settings.multiMonth, 1);
3081 var monthOffset = !isDay ? 0 : module.get.monthOffset();
3082
3083 var minute = display.getMinutes();
3084 var hour = display.getHours();
3085 var day = display.getDate();
3086 var startMonth = display.getMonth() + monthOffset;
3087 var year = display.getFullYear();
3088
3089 var columns = isDay ? settings.showWeekNumbers ? 8 : 7 : isHour ? 4 : timeGap['column'];
3090 var rows = isDay || isHour ? 6 : timeGap['row'];
3091 var pages = isDay ? multiMonth : 1;
3092
3093 var container = $container;
3094 var tooltipPosition = container.hasClass("left") ? "right center" : "left center";
3095 container.empty();
3096 if (pages > 1) {
3097 pageGrid = $('<div/>').addClass(className.grid).appendTo(container);
3098 }
3099
3100 for (p = 0; p < pages; p++) {
3101 if (pages > 1) {
3102 var pageColumn = $('<div/>').addClass(className.column).appendTo(pageGrid);
3103 container = pageColumn;
3104 }
3105
3106 var month = startMonth + p;
3107 var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
3108 if (!settings.constantHeight && isDay) {
3109 var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
3110 rows = Math.ceil(requiredCells / 7);
3111 }
3112
3113 var yearChange = isYear ? 10 : isMonth ? 1 : 0;
3114 var monthChange = isDay ? 1 : 0;
3115 var dayChange = isHour || isMinute ? 1 : 0;
3116 var prevNextDay = isHour || isMinute ? day : 1;
3117 var prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour);
3118 var nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour);
3119
3120 var prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) :
3121 isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1);
3122 var nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) :
3123 isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1);
3124
3125 var tempMode = mode;
3126 if (isDay && settings.showWeekNumbers){
3127 tempMode += ' andweek';
3128 }
3129 var table = $('<table/>').addClass(className.table).addClass(tempMode).appendTo(container);
3130 var textColumns = columns;
3131 //no header for time-only mode
3132 if (!isTimeOnly) {
3133 var thead = $('<thead/>').appendTo(table);
3134
3135 row = $('<tr/>').appendTo(thead);
3136 cell = $('<th/>').attr('colspan', '' + columns).appendTo(row);
3137
3138 var headerDate = isYear || isMonth ? new Date(year, 0, 1) :
3139 isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute);
3140 var headerText = $('<span/>').addClass(className.link).appendTo(cell);
3141 headerText.text(formatter.header(headerDate, mode, settings));
3142 var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') :
3143 isDay ? (settings.disableMonth ? 'year' : 'month') : 'day';
3144 headerText.data(metadata.mode, newMode);
3145
3146 if (p === 0) {
3147 var prev = $('<span/>').addClass(className.prev).appendTo(cell);
3148 prev.data(metadata.focusDate, prevDate);
3149 prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
3150 $('<i/>').addClass(className.prevIcon).appendTo(prev);
3151 }
3152
3153 if (p === pages - 1) {
3154 var next = $('<span/>').addClass(className.next).appendTo(cell);
3155 next.data(metadata.focusDate, nextDate);
3156 next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
3157 $('<i/>').addClass(className.nextIcon).appendTo(next);
3158 }
3159 if (isDay) {
3160 row = $('<tr/>').appendTo(thead);
3161 if(settings.showWeekNumbers) {
3162 cell = $('<th/>').appendTo(row);
3163 cell.text(settings.text.weekNo);
3164 cell.addClass(className.weekCell);
3165 textColumns--;
3166 }
3167 for (i = 0; i < textColumns; i++) {
3168 cell = $('<th/>').appendTo(row);
3169 cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
3170 }
3171 }
3172 }
3173
3174 var tbody = $('<tbody/>').appendTo(table);
3175 i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
3176 for (r = 0; r < rows; r++) {
3177 row = $('<tr/>').appendTo(tbody);
3178 if(isDay && settings.showWeekNumbers){
3179 cell = $('<th/>').appendTo(row);
3180 cell.text(module.get.weekOfYear(year,month,i+1-settings.firstDayOfWeek));
3181 cell.addClass(className.weekCell);
3182 }
3183 for (c = 0; c < textColumns; c++, i++) {
3184 var cellDate = isYear ? new Date(i, month, 1, hour, minute) :
3185 isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) :
3186 isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * settings.minTimeGap);
3187 var cellText = isYear ? i :
3188 isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() :
3189 formatter.time(cellDate, settings, true);
3190 cell = $('<td/>').addClass(className.cell).appendTo(row);
3191 cell.text(cellText);
3192 cell.data(metadata.date, cellDate);
3193 var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
3194 var disabled = (!settings.selectAdjacentDays && adjacent) || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode) || module.helper.isDisabled(cellDate, mode) || !module.helper.isEnabled(cellDate, mode);
3195 if (disabled) {
3196 var disabledReason = module.helper.disabledReason(cellDate, mode);
3197 if (disabledReason !== null) {
3198 cell.attr("data-tooltip", disabledReason[metadata.message]);
3199 cell.attr("data-position", tooltipPosition);
3200 }
3201 }
3202 var active = module.helper.dateEqual(cellDate, date, mode);
3203 var isToday = module.helper.dateEqual(cellDate, today, mode);
3204 cell.toggleClass(className.adjacentCell, adjacent);
3205 cell.toggleClass(className.disabledCell, disabled);
3206 cell.toggleClass(className.activeCell, active && !adjacent);
3207 if (!isHour && !isMinute) {
3208 cell.toggleClass(className.todayCell, !adjacent && isToday);
3209 }
3210
3211 // Allow for external modifications of each cell
3212 var cellOptions = {
3213 mode: mode,
3214 adjacent: adjacent,
3215 disabled: disabled,
3216 active: active,
3217 today: isToday
3218 };
3219 formatter.cell(cell, cellDate, cellOptions);
3220
3221 if (module.helper.dateEqual(cellDate, focusDate, mode)) {
3222 //ensure that the focus date is exactly equal to the cell date
3223 //so that, if selected, the correct value is set
3224 module.set.focusDate(cellDate, false, false);
3225 }
3226 }
3227 }
3228
3229 if (settings.today) {
3230 var todayRow = $('<tr/>').appendTo(tbody);
3231 var todayButton = $('<td/>').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
3232 todayButton.text(formatter.today(settings));
3233 todayButton.data(metadata.date, today);
3234 }
3235
3236 module.update.focus(false, table);
3237 }
3238 }
3239 },
3240
3241 update: {
3242 focus: function (updateRange, container) {
3243 container = container || $container;
3244 var mode = module.get.mode();
3245 var date = module.get.date();
3246 var focusDate = module.get.focusDate();
3247 var startDate = module.get.startDate();
3248 var endDate = module.get.endDate();
3249 var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
3250
3251 container.find('td').each(function () {
3252 var cell = $(this);
3253 var cellDate = cell.data(metadata.date);
3254 if (!cellDate) {
3255 return;
3256 }
3257 var disabled = cell.hasClass(className.disabledCell);
3258 var active = cell.hasClass(className.activeCell);
3259 var adjacent = cell.hasClass(className.adjacentCell);
3260 var focused = module.helper.dateEqual(cellDate, focusDate, mode);
3261 var inRange = !rangeDate ? false :
3262 ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) ||
3263 (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
3264 cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && (!adjacent || (settings.selectAdjacentDays && adjacent)) && !disabled);
3265 cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
3266 });
3267 }
3268 },
3269
3270 refresh: function () {
3271 module.create.calendar();
3272 },
3273
3274 bind: {
3275 events: function () {
3276 module.debug('Binding events');
3277 $container.on('mousedown' + eventNamespace, module.event.mousedown);
3278 $container.on('touchstart' + eventNamespace, module.event.mousedown);
3279 $container.on('mouseup' + eventNamespace, module.event.mouseup);
3280 $container.on('touchend' + eventNamespace, module.event.mouseup);
3281 $container.on('mouseover' + eventNamespace, module.event.mouseover);
3282 if ($input.length) {
3283 $input.on('input' + eventNamespace, module.event.inputChange);
3284 $input.on('focus' + eventNamespace, module.event.inputFocus);
3285 $input.on('blur' + eventNamespace, module.event.inputBlur);
3286 $input.on('click' + eventNamespace, module.event.inputClick);
3287 $input.on('keydown' + eventNamespace, module.event.keydown);
3288 } else {
3289 $container.on('keydown' + eventNamespace, module.event.keydown);
3290 }
3291 }
3292 },
3293
3294 unbind: {
3295 events: function () {
3296 module.debug('Unbinding events');
3297 $container.off(eventNamespace);
3298 if ($input.length) {
3299 $input.off(eventNamespace);
3300 }
3301 }
3302 },
3303
3304 event: {
3305 mouseover: function (event) {
3306 var target = $(event.target);
3307 var date = target.data(metadata.date);
3308 var mousedown = event.buttons === 1;
3309 if (date) {
3310 module.set.focusDate(date, false, true, mousedown);
3311 }
3312 },
3313 mousedown: function (event) {
3314 if ($input.length) {
3315 //prevent the mousedown on the calendar causing the input to lose focus
3316 event.preventDefault();
3317 }
3318 isTouchDown = event.type.indexOf('touch') >= 0;
3319 var target = $(event.target);
3320 var date = target.data(metadata.date);
3321 if (date) {
3322 module.set.focusDate(date, false, true, true);
3323 }
3324 },
3325 mouseup: function (event) {
3326 //ensure input has focus so that it receives keydown events for calendar navigation
3327 module.focus();
3328 event.preventDefault();
3329 event.stopPropagation();
3330 isTouchDown = false;
3331 var target = $(event.target);
3332 if (target.hasClass("disabled")) {
3333 return;
3334 }
3335 var parent = target.parent();
3336 if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
3337 //clicked on a child element, switch to parent (used when clicking directly on prev/next <i> icon element)
3338 target = parent;
3339 }
3340 var date = target.data(metadata.date);
3341 var focusDate = target.data(metadata.focusDate);
3342 var mode = target.data(metadata.mode);
3343 if (date) {
3344 var forceSet = target.hasClass(className.today);
3345 module.selectDate(date, forceSet);
3346 }
3347 else if (focusDate) {
3348 module.set.focusDate(focusDate);
3349 }
3350 else if (mode) {
3351 module.set.mode(mode);
3352 }
3353 },
3354 keydown: function (event) {
3355 if (event.keyCode === 27 || event.keyCode === 9) {
3356 //esc || tab
3357 module.popup('hide');
3358 }
3359
3360 if (module.popup('is visible')) {
3361 if (event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40) {
3362 //arrow keys
3363 var mode = module.get.mode();
3364 var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : mode === 'minute' ? timeGap['column'] : 3;
3365 var increment = event.keyCode === 37 ? -1 : event.keyCode === 38 ? -bigIncrement : event.keyCode == 39 ? 1 : bigIncrement;
3366 increment *= mode === 'minute' ? settings.minTimeGap : 1;
3367 var focusDate = module.get.focusDate() || module.get.date() || new Date();
3368 var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
3369 var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
3370 var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
3371 var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
3372 var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
3373 var newFocusDate = new Date(year, month, day, hour, minute);
3374 if (settings.type === 'time') {
3375 newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
3376 }
3377 if (module.helper.isDateInRange(newFocusDate, mode)) {
3378 module.set.focusDate(newFocusDate);
3379 }
3380 } else if (event.keyCode === 13) {
3381 //enter
3382 var mode = module.get.mode();
3383 var date = module.get.focusDate();
3384 if (date && !settings.isDisabled(date, mode) && !module.helper.isDisabled(date, mode) && module.helper.isEnabled(date, mode)) {
3385 module.selectDate(date);
3386 }
3387 //disable form submission:
3388 event.preventDefault();
3389 event.stopPropagation();
3390 }
3391 }
3392
3393 if (event.keyCode === 38 || event.keyCode === 40) {
3394 //arrow-up || arrow-down
3395 event.preventDefault(); //don't scroll
3396 module.popup('show');
3397 }
3398 },
3399 inputChange: function () {
3400 var val = $input.val();
3401 var date = parser.date(val, settings);
3402 module.set.date(date, false);
3403 },
3404 inputFocus: function () {
3405 $container.addClass(className.active);
3406 },
3407 inputBlur: function () {
3408 $container.removeClass(className.active);
3409 if (settings.formatInput) {
3410 var date = module.get.date();
3411 var text = formatter.datetime(date, settings);
3412 $input.val(text);
3413 }
3414 },
3415 inputClick: function () {
3416 module.popup('show');
3417 }
3418 },
3419
3420 get: {
3421 weekOfYear: function(weekYear,weekMonth,weekDay) {
3422 // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
3423 var ms1d = 864e5, // milliseconds in a day
3424 ms7d = 7 * ms1d; // milliseconds in a week
3425
3426 return function() { // return a closure so constants get calculated only once
3427 var DC3 = Date.UTC(weekYear, weekMonth, weekDay + 3) / ms1d, // an Absolute Day Number
3428 AWN = Math.floor(DC3 / 7), // an Absolute Week Number
3429 Wyr = new Date(AWN * ms7d).getUTCFullYear();
3430
3431 return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
3432 }();
3433 },
3434 date: function () {
3435 return module.helper.sanitiseDate($module.data(metadata.date)) || null;
3436 },
3437 focusDate: function () {
3438 return $module.data(metadata.focusDate) || null;
3439 },
3440 startDate: function () {
3441 var startModule = module.get.calendarModule(settings.startCalendar);
3442 return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
3443 },
3444 endDate: function () {
3445 var endModule = module.get.calendarModule(settings.endCalendar);
3446 return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
3447 },
3448 minDate: function() {
3449 return $module.data(metadata.minDate) || null;
3450 },
3451 maxDate: function() {
3452 return $module.data(metadata.maxDate) || null;
3453 },
3454 monthOffset: function () {
3455 return $module.data(metadata.monthOffset) || 0;
3456 },
3457 mode: function () {
3458 //only returns valid modes for the current settings
3459 var mode = $module.data(metadata.mode) || settings.startMode;
3460 var validModes = module.get.validModes();
3461 if ($.inArray(mode, validModes) >= 0) {
3462 return mode;
3463 }
3464 return settings.type === 'time' ? 'hour' :
3465 settings.type === 'month' ? 'month' :
3466 settings.type === 'year' ? 'year' : 'day';
3467 },
3468 validModes: function () {
3469 var validModes = [];
3470 if (settings.type !== 'time') {
3471 if (!settings.disableYear || settings.type === 'year') {
3472 validModes.push('year');
3473 }
3474 if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
3475 validModes.push('month');
3476 }
3477 if (settings.type.indexOf('date') >= 0) {
3478 validModes.push('day');
3479 }
3480 }
3481 if (settings.type.indexOf('time') >= 0) {
3482 validModes.push('hour');
3483 if (!settings.disableMinute) {
3484 validModes.push('minute');
3485 }
3486 }
3487 return validModes;
3488 },
3489 isTouch: function () {
3490 try {
3491 document.createEvent('TouchEvent');
3492 return true;
3493 }
3494 catch (e) {
3495 return false;
3496 }
3497 },
3498 calendarModule: function (selector) {
3499 if (!selector) {
3500 return null;
3501 }
3502 if (!(selector instanceof $)) {
3503 selector = $module.parent().children(selector).first();
3504 }
3505 //assume range related calendars are using the same namespace
3506 return selector.data(moduleNamespace);
3507 }
3508 },
3509
3510 set: {
3511 date: function (date, updateInput, fireChange) {
3512 updateInput = updateInput !== false;
3513 fireChange = fireChange !== false;
3514 date = module.helper.sanitiseDate(date);
3515 date = module.helper.dateInRange(date);
3516
3517 var mode = module.get.mode();
3518 var text = formatter.datetime(date, settings);
3519 if (fireChange && settings.onChange.call(element, date, text, mode) === false) {
3520 return false;
3521 }
3522
3523 module.set.focusDate(date);
3524
3525 if (settings.isDisabled(date, mode)) {
3526 return false;
3527 }
3528
3529 var endDate = module.get.endDate();
3530 if (!!endDate && !!date && date > endDate) {
3531 //selected date is greater than end date in range, so clear end date
3532 module.set.endDate(undefined);
3533 }
3534 module.set.dataKeyValue(metadata.date, date);
3535
3536 if (updateInput && $input.length) {
3537 $input.val(text);
3538 }
3539 },
3540 startDate: function (date, refreshCalendar) {
3541 date = module.helper.sanitiseDate(date);
3542 var startModule = module.get.calendarModule(settings.startCalendar);
3543 if (startModule) {
3544 startModule.set.date(date);
3545 }
3546 module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
3547 },
3548 endDate: function (date, refreshCalendar) {
3549 date = module.helper.sanitiseDate(date);
3550 var endModule = module.get.calendarModule(settings.endCalendar);
3551 if (endModule) {
3552 endModule.set.date(date);
3553 }
3554 module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
3555 },
3556 focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
3557 date = module.helper.sanitiseDate(date);
3558 date = module.helper.dateInRange(date);
3559 var isDay = module.get.mode() === 'day';
3560 var oldFocusDate = module.get.focusDate();
3561 if (isDay && date && oldFocusDate) {
3562 var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
3563 var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
3564 if (monthDelta) {
3565 var monthOffset = module.get.monthOffset() - monthDelta;
3566 module.set.monthOffset(monthOffset, false);
3567 }
3568 }
3569 var changed = module.set.dataKeyValue(metadata.focusDate, date, refreshCalendar);
3570 updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
3571 focusDateUsedForRange = updateRange;
3572 if (updateFocus) {
3573 module.update.focus(updateRange);
3574 }
3575 },
3576 minDate: function (date) {
3577 date = module.helper.sanitiseDate(date);
3578 if (settings.maxDate !== null && settings.maxDate <= date) {
3579 module.verbose('Unable to set minDate variable bigger that maxDate variable', date, settings.maxDate);
3580 } else {
3581 module.setting('minDate', date);
3582 module.set.dataKeyValue(metadata.minDate, date);
3583 }
3584 },
3585 maxDate: function (date) {
3586 date = module.helper.sanitiseDate(date);
3587 if (settings.minDate !== null && settings.minDate >= date) {
3588 module.verbose('Unable to set maxDate variable lower that minDate variable', date, settings.minDate);
3589 } else {
3590 module.setting('maxDate', date);
3591 module.set.dataKeyValue(metadata.maxDate, date);
3592 }
3593 },
3594 monthOffset: function (monthOffset, refreshCalendar) {
3595 var multiMonth = Math.max(settings.multiMonth, 1);
3596 monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
3597 module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
3598 },
3599 mode: function (mode, refreshCalendar) {
3600 module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
3601 },
3602 dataKeyValue: function (key, value, refreshCalendar) {
3603 var oldValue = $module.data(key);
3604 var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects
3605 if (value) {
3606 $module.data(key, value);
3607 } else {
3608 $module.removeData(key);
3609 }
3610 refreshCalendar = refreshCalendar !== false && !equal;
3611 if (refreshCalendar) {
3612 module.refresh();
3613 }
3614 return !equal;
3615 }
3616 },
3617
3618 selectDate: function (date, forceSet) {
3619 module.verbose('New date selection', date)
3620 var mode = module.get.mode();
3621 var complete = forceSet || mode === 'minute' ||
3622 (settings.disableMinute && mode === 'hour') ||
3623 (settings.type === 'date' && mode === 'day') ||
3624 (settings.type === 'month' && mode === 'month') ||
3625 (settings.type === 'year' && mode === 'year');
3626 if (complete) {
3627 var canceled = module.set.date(date) === false;
3628 if (!canceled && settings.closable) {
3629 module.popup('hide');
3630 //if this is a range calendar, show the end date calendar popup and focus the input
3631 var endModule = module.get.calendarModule(settings.endCalendar);
3632 if (endModule) {
3633 endModule.popup('show');
3634 endModule.focus();
3635 }
3636 }
3637 } else {
3638 var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') :
3639 mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute';
3640 module.set.mode(newMode);
3641 if (mode === 'hour' || (mode === 'day' && module.get.date())) {
3642 //the user has chosen enough to consider a valid date/time has been chosen
3643 module.set.date(date);
3644 } else {
3645 module.set.focusDate(date);
3646 }
3647 }
3648 },
3649
3650 changeDate: function (date) {
3651 module.set.date(date);
3652 },
3653
3654 clear: function () {
3655 module.set.date(undefined);
3656 },
3657
3658 popup: function () {
3659 return $activator.popup.apply($activator, arguments);
3660 },
3661
3662 focus: function () {
3663 if ($input.length) {
3664 $input.focus();
3665 } else {
3666 $container.focus();
3667 }
3668 },
3669 blur: function () {
3670 if ($input.length) {
3671 $input.blur();
3672 } else {
3673 $container.blur();
3674 }
3675 },
3676
3677 helper: {
3678 isDisabled: function(date, mode) {
3679 return mode === 'day' && ((settings.disabledDaysOfWeek.indexOf(date.getDay()) !== -1) || settings.disabledDates.some(function(d){
3680 if (d instanceof Date) {
3681 return module.helper.dateEqual(date, d, mode);
3682 }
3683 if (d !== null && typeof d === 'object') {
3684 return module.helper.dateEqual(date, d[metadata.date], mode);
3685 }
3686 }));
3687 },
3688 isEnabled: function(date, mode) {
3689 if (mode === 'day') {
3690 return settings.enabledDates.length == 0 || settings.enabledDates.some(function(d){
3691 if (d instanceof Date) {
3692 return module.helper.dateEqual(date, d, mode);
3693 }
3694 if (d !== null && typeof d === 'object') {
3695 return module.helper.dateEqual(date, d[metadata.date], mode);
3696 }
3697 });
3698 } else {
3699 return true;
3700 }
3701 },
3702 disabledReason: function(date, mode) {
3703 if (mode === 'day') {
3704 for (var i = 0; i < settings.disabledDates.length; i++) {
3705 var d = settings.disabledDates[i];
3706 if (d !== null && typeof d === 'object' && module.helper.dateEqual(date, d[metadata.date], mode)) {
3707 var reason = {};
3708 reason[metadata.message] = d[metadata.message];
3709 return reason;
3710 }
3711 }
3712 }
3713 return null;
3714 },
3715 sanitiseDate: function (date) {
3716 if (!date) {
3717 return undefined;
3718 }
3719 if (!(date instanceof Date)) {
3720 date = parser.date('' + date, settings);
3721 }
3722 if (isNaN(date.getTime())) {
3723 return undefined;
3724 }
3725 return date;
3726 },
3727 dateDiff: function (date1, date2, mode) {
3728 mode = mode || 'day';
3729 var isTimeOnly = settings.type === 'time';
3730 var isYear = mode === 'year';
3731 var isYearOrMonth = isYear || mode === 'month';
3732 var isMinute = mode === 'minute';
3733 var isHourOrMinute = isMinute || mode === 'hour';
3734 //only care about a minute accuracy of settings.minTimeGap
3735 date1 = new Date(
3736 isTimeOnly ? 2000 : date1.getFullYear(),
3737 isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
3738 isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
3739 !isHourOrMinute ? 0 : date1.getHours(),
3740 !isMinute ? 0 : settings.minTimeGap * Math.floor(date1.getMinutes() / settings.minTimeGap));
3741 date2 = new Date(
3742 isTimeOnly ? 2000 : date2.getFullYear(),
3743 isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
3744 isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
3745 !isHourOrMinute ? 0 : date2.getHours(),
3746 !isMinute ? 0 : settings.minTimeGap * Math.floor(date2.getMinutes() / settings.minTimeGap));
3747 return date2.getTime() - date1.getTime();
3748 },
3749 dateEqual: function (date1, date2, mode) {
3750 return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
3751 },
3752 isDateInRange: function (date, mode, minDate, maxDate) {
3753 if (!minDate && !maxDate) {
3754 var startDate = module.get.startDate();
3755 minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
3756 maxDate = settings.maxDate;
3757 }
3758 minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
3759 return !(!date ||
3760 (minDate && module.helper.dateDiff(date, minDate, mode) > 0) ||
3761 (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
3762 },
3763 dateInRange: function (date, minDate, maxDate) {
3764 if (!minDate && !maxDate) {
3765 var startDate = module.get.startDate();
3766 minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
3767 maxDate = settings.maxDate;
3768 }
3769 minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
3770 var isTimeOnly = settings.type === 'time';
3771 return !date ? date :
3772 (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ?
3773 (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) :
3774 (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ?
3775 (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) :
3776 date;
3777 },
3778 mergeDateTime: function (date, time) {
3779 return (!date || !time) ? time :
3780 new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
3781 }
3782 },
3783
3784 setting: function (name, value) {
3785 module.debug('Changing setting', name, value);
3786 if ($.isPlainObject(name)) {
3787 $.extend(true, settings, name);
3788 }
3789 else if (value !== undefined) {
3790 if ($.isPlainObject(settings[name])) {
3791 $.extend(true, settings[name], value);
3792 }
3793 else {
3794 settings[name] = value;
3795 }
3796 }
3797 else {
3798 return settings[name];
3799 }
3800 },
3801 internal: function (name, value) {
3802 if( $.isPlainObject(name) ) {
3803 $.extend(true, module, name);
3804 }
3805 else if(value !== undefined) {
3806 module[name] = value;
3807 }
3808 else {
3809 return module[name];
3810 }
3811 },
3812 debug: function () {
3813 if (!settings.silent && settings.debug) {
3814 if (settings.performance) {
3815 module.performance.log(arguments);
3816 }
3817 else {
3818 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
3819 module.debug.apply(console, arguments);
3820 }
3821 }
3822 },
3823 verbose: function () {
3824 if (!settings.silent && settings.verbose && settings.debug) {
3825 if (settings.performance) {
3826 module.performance.log(arguments);
3827 }
3828 else {
3829 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
3830 module.verbose.apply(console, arguments);
3831 }
3832 }
3833 },
3834 error: function () {
3835 if (!settings.silent) {
3836 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
3837 module.error.apply(console, arguments);
3838 }
3839 },
3840 performance: {
3841 log: function (message) {
3842 var
3843 currentTime,
3844 executionTime,
3845 previousTime
3846 ;
3847 if (settings.performance) {
3848 currentTime = new Date().getTime();
3849 previousTime = time || currentTime;
3850 executionTime = currentTime - previousTime;
3851 time = currentTime;
3852 performance.push({
3853 'Name': message[0],
3854 'Arguments': [].slice.call(message, 1) || '',
3855 'Element': element,
3856 'Execution Time': executionTime
3857 });
3858 }
3859 clearTimeout(module.performance.timer);
3860 module.performance.timer = setTimeout(module.performance.display, 500);
3861 },
3862 display: function () {
3863 var
3864 title = settings.name + ':',
3865 totalTime = 0
3866 ;
3867 time = false;
3868 clearTimeout(module.performance.timer);
3869 $.each(performance, function (index, data) {
3870 totalTime += data['Execution Time'];
3871 });
3872 title += ' ' + totalTime + 'ms';
3873 if (moduleSelector) {
3874 title += ' \'' + moduleSelector + '\'';
3875 }
3876 if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
3877 console.groupCollapsed(title);
3878 if (console.table) {
3879 console.table(performance);
3880 }
3881 else {
3882 $.each(performance, function (index, data) {
3883 console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
3884 });
3885 }
3886 console.groupEnd();
3887 }
3888 performance = [];
3889 }
3890 },
3891 invoke: function (query, passedArguments, context) {
3892 var
3893 object = instance,
3894 maxDepth,
3895 found,
3896 response
3897 ;
3898 passedArguments = passedArguments || queryArguments;
3899 context = element || context;
3900 if (typeof query == 'string' && object !== undefined) {
3901 query = query.split(/[\. ]/);
3902 maxDepth = query.length - 1;
3903 $.each(query, function (depth, value) {
3904 var camelCaseValue = (depth != maxDepth)
3905 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
3906 : query
3907 ;
3908 if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
3909 object = object[camelCaseValue];
3910 }
3911 else if (object[camelCaseValue] !== undefined) {
3912 found = object[camelCaseValue];
3913 return false;
3914 }
3915 else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
3916 object = object[value];
3917 }
3918 else if (object[value] !== undefined) {
3919 found = object[value];
3920 return false;
3921 }
3922 else {
3923 module.error(error.method, query);
3924 return false;
3925 }
3926 });
3927 }
3928 if ($.isFunction(found)) {
3929 response = found.apply(context, passedArguments);
3930 }
3931 else if (found !== undefined) {
3932 response = found;
3933 }
3934 if (Array.isArray(returnedValue)) {
3935 returnedValue.push(response);
3936 }
3937 else if (returnedValue !== undefined) {
3938 returnedValue = [returnedValue, response];
3939 }
3940 else if (response !== undefined) {
3941 returnedValue = response;
3942 }
3943 return found;
3944 }
3945 };
3946
3947 if (methodInvoked) {
3948 if (instance === undefined) {
3949 module.initialize();
3950 }
3951 module.invoke(query);
3952 }
3953 else {
3954 if (instance !== undefined) {
3955 instance.invoke('destroy');
3956 }
3957 module.initialize();
3958 }
3959 })
3960 ;
3961 return (returnedValue !== undefined)
3962 ? returnedValue
3963 : this
3964 ;
3965};
3966
3967$.fn.calendar.settings = {
3968
3969 name : 'Calendar',
3970 namespace : 'calendar',
3971
3972 silent: false,
3973 debug: false,
3974 verbose: false,
3975 performance: false,
3976
3977 type : 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
3978 firstDayOfWeek : 0, // day for first day column (0 = Sunday)
3979 constantHeight : true, // add rows to shorter months to keep day calendar height consistent (6 rows)
3980 today : false, // show a 'today/now' button at the bottom of the calendar
3981 closable : true, // close the popup after selecting a date/time
3982 monthFirst : true, // month before day when parsing/converting date from/to text
3983 touchReadonly : true, // set input to readonly on touch devices
3984 inline : false, // create the calendar inline instead of inside a popup
3985 on : null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
3986 initialDate : null, // date to display initially when no date is selected (null = now)
3987 startMode : false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
3988 minDate : null, // minimum date/time that can be selected, dates/times before are disabled
3989 maxDate : null, // maximum date/time that can be selected, dates/times after are disabled
3990 ampm : true, // show am/pm in time mode
3991 disableYear : false, // disable year selection mode
3992 disableMonth : false, // disable month selection mode
3993 disableMinute : false, // disable minute selection mode
3994 formatInput : true, // format the input text upon input blur and module creation
3995 startCalendar : null, // jquery object or selector for another calendar that represents the start date of a date range
3996 endCalendar : null, // jquery object or selector for another calendar that represents the end date of a date range
3997 multiMonth : 1, // show multiple months when in 'day' mode
3998 minTimeGap : 5,
3999 showWeekNumbers : null, // show Number of Week at the very first column of a dayView
4000 disabledDates : [], // specific day(s) which won't be selectable and contain additional information.
4001 disabledDaysOfWeek : [], // day(s) which won't be selectable(s) (0 = Sunday)
4002 enabledDates : [], // specific day(s) which will be selectable, all other days will be disabled
4003 centuryBreak : 60, // starting short year until 99 where it will be assumed to belong to the last century
4004 currentCentury : 2000, // century to be added to 2-digit years (00 to {centuryBreak}-1)
4005 selectAdjacentDays : false, // The calendar can show dates from adjacent month. These adjacent month dates can also be made selectable.
4006 // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
4007 popupOptions: {
4008 position: 'bottom left',
4009 lastResort: 'bottom left',
4010 prefer: 'opposite',
4011 hideOnScroll: false
4012 },
4013
4014 text: {
4015 days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
4016 months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
4017 monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
4018 today: 'Today',
4019 now: 'Now',
4020 am: 'AM',
4021 pm: 'PM',
4022 weekNo: 'Week'
4023 },
4024
4025 formatter: {
4026 header: function (date, mode, settings) {
4027 return mode === 'year' ? settings.formatter.yearHeader(date, settings) :
4028 mode === 'month' ? settings.formatter.monthHeader(date, settings) :
4029 mode === 'day' ? settings.formatter.dayHeader(date, settings) :
4030 mode === 'hour' ? settings.formatter.hourHeader(date, settings) :
4031 settings.formatter.minuteHeader(date, settings);
4032 },
4033 yearHeader: function (date, settings) {
4034 var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
4035 return (decadeYear - 9) + ' - ' + (decadeYear + 2);
4036 },
4037 monthHeader: function (date, settings) {
4038 return date.getFullYear();
4039 },
4040 dayHeader: function (date, settings) {
4041 var month = settings.text.months[date.getMonth()];
4042 var year = date.getFullYear();
4043 return month + ' ' + year;
4044 },
4045 hourHeader: function (date, settings) {
4046 return settings.formatter.date(date, settings);
4047 },
4048 minuteHeader: function (date, settings) {
4049 return settings.formatter.date(date, settings);
4050 },
4051 dayColumnHeader: function (day, settings) {
4052 return settings.text.days[day];
4053 },
4054 datetime: function (date, settings) {
4055 if (!date) {
4056 return '';
4057 }
4058 var day = settings.type === 'time' ? '' : settings.formatter.date(date, settings);
4059 var time = settings.type.indexOf('time') < 0 ? '' : settings.formatter.time(date, settings, false);
4060 var separator = settings.type === 'datetime' ? ' ' : '';
4061 return day + separator + time;
4062 },
4063 date: function (date, settings) {
4064 if (!date) {
4065 return '';
4066 }
4067 var day = date.getDate();
4068 var month = settings.text.months[date.getMonth()];
4069 var year = date.getFullYear();
4070 return settings.type === 'year' ? year :
4071 settings.type === 'month' ? month + ' ' + year :
4072 (settings.monthFirst ? month + ' ' + day : day + ' ' + month) + ', ' + year;
4073 },
4074 time: function (date, settings, forCalendar) {
4075 if (!date) {
4076 return '';
4077 }
4078 var hour = date.getHours();
4079 var minute = date.getMinutes();
4080 var ampm = '';
4081 if (settings.ampm) {
4082 ampm = ' ' + (hour < 12 ? settings.text.am : settings.text.pm);
4083 hour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
4084 }
4085 return hour + ':' + (minute < 10 ? '0' : '') + minute + ampm;
4086 },
4087 today: function (settings) {
4088 return settings.type === 'date' ? settings.text.today : settings.text.now;
4089 },
4090 cell: function (cell, date, cellOptions) {
4091 }
4092 },
4093
4094 parser: {
4095 date: function (text, settings) {
4096 if (!text) {
4097 return null;
4098 }
4099 text = ('' + text).trim().toLowerCase();
4100 if (text.length === 0) {
4101 return null;
4102 }
4103
4104 var i, j, k;
4105 var minute = -1, hour = -1, day = -1, month = -1, year = -1;
4106 var isAm = undefined;
4107
4108 var isTimeOnly = settings.type === 'time';
4109 var isDateOnly = settings.type.indexOf('time') < 0;
4110
4111 var words = text.split(settings.regExp.dateWords);
4112 var numbers = text.split(settings.regExp.dateNumbers);
4113
4114 if (!isDateOnly) {
4115 //am/pm
4116 isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true :
4117 $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
4118
4119 //time with ':'
4120 for (i = 0; i < numbers.length; i++) {
4121 var number = numbers[i];
4122 if (number.indexOf(':') >= 0) {
4123 if (hour < 0 || minute < 0) {
4124 var parts = number.split(':');
4125 for (k = 0; k < Math.min(2, parts.length); k++) {
4126 j = parseInt(parts[k]);
4127 if (isNaN(j)) {
4128 j = 0;
4129 }
4130 if (k === 0) {
4131 hour = j % 24;
4132 } else {
4133 minute = j % 60;
4134 }
4135 }
4136 }
4137 numbers.splice(i, 1);
4138 }
4139 }
4140 }
4141
4142 if (!isTimeOnly) {
4143 //textual month
4144 for (i = 0; i < words.length; i++) {
4145 var word = words[i];
4146 if (word.length <= 0) {
4147 continue;
4148 }
4149 word = word.substring(0, Math.min(word.length, 3));
4150 for (j = 0; j < settings.text.months.length; j++) {
4151 var monthString = settings.text.months[j];
4152 monthString = monthString.substring(0, Math.min(word.length, Math.min(monthString.length, 3))).toLowerCase();
4153 if (monthString === word) {
4154 month = j + 1;
4155 break;
4156 }
4157 }
4158 if (month >= 0) {
4159 break;
4160 }
4161 }
4162
4163 //year > settings.centuryBreak
4164 for (i = 0; i < numbers.length; i++) {
4165 j = parseInt(numbers[i]);
4166 if (isNaN(j)) {
4167 continue;
4168 }
4169 if (j >= settings.centuryBreak && i === numbers.length-1) {
4170 if (j <= 99) {
4171 j += settings.currentCentury - 100;
4172 }
4173 year = j;
4174 numbers.splice(i, 1);
4175 break;
4176 }
4177 }
4178
4179 //numeric month
4180 if (month < 0) {
4181 for (i = 0; i < numbers.length; i++) {
4182 k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
4183 j = parseInt(numbers[k]);
4184 if (isNaN(j)) {
4185 continue;
4186 }
4187 if (1 <= j && j <= 12) {
4188 month = j;
4189 numbers.splice(k, 1);
4190 break;
4191 }
4192 }
4193 }
4194
4195 //day
4196 for (i = 0; i < numbers.length; i++) {
4197 j = parseInt(numbers[i]);
4198 if (isNaN(j)) {
4199 continue;
4200 }
4201 if (1 <= j && j <= 31) {
4202 day = j;
4203 numbers.splice(i, 1);
4204 break;
4205 }
4206 }
4207
4208 //year <= settings.centuryBreak
4209 if (year < 0) {
4210 for (i = numbers.length - 1; i >= 0; i--) {
4211 j = parseInt(numbers[i]);
4212 if (isNaN(j)) {
4213 continue;
4214 }
4215 if (j <= 99) {
4216 j += settings.currentCentury;
4217 }
4218 year = j;
4219 numbers.splice(i, 1);
4220 break;
4221 }
4222 }
4223 }
4224
4225 if (!isDateOnly) {
4226 //hour
4227 if (hour < 0) {
4228 for (i = 0; i < numbers.length; i++) {
4229 j = parseInt(numbers[i]);
4230 if (isNaN(j)) {
4231 continue;
4232 }
4233 if (0 <= j && j <= 23) {
4234 hour = j;
4235 numbers.splice(i, 1);
4236 break;
4237 }
4238 }
4239 }
4240
4241 //minute
4242 if (minute < 0) {
4243 for (i = 0; i < numbers.length; i++) {
4244 j = parseInt(numbers[i]);
4245 if (isNaN(j)) {
4246 continue;
4247 }
4248 if (0 <= j && j <= 59) {
4249 minute = j;
4250 numbers.splice(i, 1);
4251 break;
4252 }
4253 }
4254 }
4255 }
4256
4257 if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
4258 return null;
4259 }
4260
4261 if (minute < 0) {
4262 minute = 0;
4263 }
4264 if (hour < 0) {
4265 hour = 0;
4266 }
4267 if (day < 0) {
4268 day = 1;
4269 }
4270 if (month < 0) {
4271 month = 1;
4272 }
4273 if (year < 0) {
4274 year = new Date().getFullYear();
4275 }
4276
4277 if (isAm !== undefined) {
4278 if (isAm) {
4279 if (hour === 12) {
4280 hour = 0;
4281 }
4282 } else if (hour < 12) {
4283 hour += 12;
4284 }
4285 }
4286
4287 var date = new Date(year, month - 1, day, hour, minute);
4288 if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
4289 //month or year don't match up, switch to last day of the month
4290 date = new Date(year, month, 0, hour, minute);
4291 }
4292 return isNaN(date.getTime()) ? null : date;
4293 }
4294 },
4295
4296 // callback when date changes, return false to cancel the change
4297 onChange: function (date, text, mode) {
4298 return true;
4299 },
4300
4301 // callback before show animation, return false to prevent show
4302 onShow: function () {
4303 },
4304
4305 // callback after show animation
4306 onVisible: function () {
4307 },
4308
4309 // callback before hide animation, return false to prevent hide
4310 onHide: function () {
4311 },
4312
4313 // callback after hide animation
4314 onHidden: function () {
4315 },
4316
4317 // is the given date disabled?
4318 isDisabled: function (date, mode) {
4319 return false;
4320 },
4321
4322 selector: {
4323 popup: '.ui.popup',
4324 input: 'input',
4325 activator: 'input'
4326 },
4327
4328 regExp: {
4329 dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
4330 dateNumbers: /[^\d:]+/g
4331 },
4332
4333 error: {
4334 popup: 'UI Popup, a required component is not included in this page',
4335 method: 'The method you called is not defined.'
4336 },
4337
4338 className: {
4339 calendar: 'calendar',
4340 active: 'active',
4341 popup: 'ui popup',
4342 grid: 'ui equal width grid',
4343 column: 'column',
4344 table: 'ui celled center aligned unstackable table',
4345 prev: 'prev link',
4346 next: 'next link',
4347 prevIcon: 'chevron left icon',
4348 nextIcon: 'chevron right icon',
4349 link: 'link',
4350 cell: 'link',
4351 disabledCell: 'disabled',
4352 weekCell: 'disabled',
4353 adjacentCell: 'adjacent',
4354 activeCell: 'active',
4355 rangeCell: 'range',
4356 focusCell: 'focus',
4357 todayCell: 'today',
4358 today: 'today link'
4359 },
4360
4361 metadata: {
4362 date: 'date',
4363 focusDate: 'focusDate',
4364 startDate: 'startDate',
4365 endDate: 'endDate',
4366 minDate: 'minDate',
4367 maxDate: 'maxDate',
4368 mode: 'mode',
4369 monthOffset: 'monthOffset',
4370 message: 'message'
4371 }
4372};
4373
4374})(jQuery, window, document);
4375
4376/*!
4377 * # Semantic UI 2.7.2 - Checkbox
4378 * http://github.com/semantic-org/semantic-ui/
4379 *
4380 *
4381 * Released under the MIT license
4382 * http://opensource.org/licenses/MIT
4383 *
4384 */
4385
4386;(function ($, window, document, undefined) {
4387
4388'use strict';
4389
4390$.isFunction = $.isFunction || function(obj) {
4391 return typeof obj === "function" && typeof obj.nodeType !== "number";
4392};
4393
4394window = (typeof window != 'undefined' && window.Math == Math)
4395 ? window
4396 : (typeof self != 'undefined' && self.Math == Math)
4397 ? self
4398 : Function('return this')()
4399;
4400
4401$.fn.checkbox = function(parameters) {
4402 var
4403 $allModules = $(this),
4404 moduleSelector = $allModules.selector || '',
4405
4406 time = new Date().getTime(),
4407 performance = [],
4408
4409 query = arguments[0],
4410 methodInvoked = (typeof query == 'string'),
4411 queryArguments = [].slice.call(arguments, 1),
4412 returnedValue
4413 ;
4414
4415 $allModules
4416 .each(function() {
4417 var
4418 settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
4419
4420 className = settings.className,
4421 namespace = settings.namespace,
4422 selector = settings.selector,
4423 error = settings.error,
4424
4425 eventNamespace = '.' + namespace,
4426 moduleNamespace = 'module-' + namespace,
4427
4428 $module = $(this),
4429 $label = $(this).children(selector.label),
4430 $input = $(this).children(selector.input),
4431 input = $input[0],
4432
4433 initialLoad = false,
4434 shortcutPressed = false,
4435 instance = $module.data(moduleNamespace),
4436
4437 observer,
4438 element = this,
4439 module
4440 ;
4441
4442 module = {
4443
4444 initialize: function() {
4445 module.verbose('Initializing checkbox', settings);
4446
4447 module.create.label();
4448 module.bind.events();
4449
4450 module.set.tabbable();
4451 module.hide.input();
4452
4453 module.observeChanges();
4454 module.instantiate();
4455 module.setup();
4456 },
4457
4458 instantiate: function() {
4459 module.verbose('Storing instance of module', module);
4460 instance = module;
4461 $module
4462 .data(moduleNamespace, module)
4463 ;
4464 },
4465
4466 destroy: function() {
4467 module.verbose('Destroying module');
4468 module.unbind.events();
4469 module.show.input();
4470 $module.removeData(moduleNamespace);
4471 },
4472
4473 fix: {
4474 reference: function() {
4475 if( $module.is(selector.input) ) {
4476 module.debug('Behavior called on <input> adjusting invoked element');
4477 $module = $module.closest(selector.checkbox);
4478 module.refresh();
4479 }
4480 }
4481 },
4482
4483 setup: function() {
4484 module.set.initialLoad();
4485 if( module.is.indeterminate() ) {
4486 module.debug('Initial value is indeterminate');
4487 module.indeterminate();
4488 }
4489 else if( module.is.checked() ) {
4490 module.debug('Initial value is checked');
4491 module.check();
4492 }
4493 else {
4494 module.debug('Initial value is unchecked');
4495 module.uncheck();
4496 }
4497 module.remove.initialLoad();
4498 },
4499
4500 refresh: function() {
4501 $label = $module.children(selector.label);
4502 $input = $module.children(selector.input);
4503 input = $input[0];
4504 },
4505
4506 hide: {
4507 input: function() {
4508 module.verbose('Modifying <input> z-index to be unselectable');
4509 $input.addClass(className.hidden);
4510 }
4511 },
4512 show: {
4513 input: function() {
4514 module.verbose('Modifying <input> z-index to be selectable');
4515 $input.removeClass(className.hidden);
4516 }
4517 },
4518
4519 observeChanges: function() {
4520 if('MutationObserver' in window) {
4521 observer = new MutationObserver(function(mutations) {
4522 module.debug('DOM tree modified, updating selector cache');
4523 module.refresh();
4524 });
4525 observer.observe(element, {
4526 childList : true,
4527 subtree : true
4528 });
4529 module.debug('Setting up mutation observer', observer);
4530 }
4531 },
4532
4533 attachEvents: function(selector, event) {
4534 var
4535 $element = $(selector)
4536 ;
4537 event = $.isFunction(module[event])
4538 ? module[event]
4539 : module.toggle
4540 ;
4541 if($element.length > 0) {
4542 module.debug('Attaching checkbox events to element', selector, event);
4543 $element
4544 .on('click' + eventNamespace, event)
4545 ;
4546 }
4547 else {
4548 module.error(error.notFound);
4549 }
4550 },
4551
4552 preventDefaultOnInputTarget: function() {
4553 if(typeof event !== 'undefined' && $(event.target).is(selector.input)) {
4554 module.verbose('Preventing default check action after manual check action');
4555 event.preventDefault();
4556 }
4557 },
4558
4559 event: {
4560 change: function(event) {
4561 if( !module.should.ignoreCallbacks() ) {
4562 settings.onChange.call(input);
4563 }
4564 },
4565 click: function(event) {
4566 var
4567 $target = $(event.target)
4568 ;
4569 if( $target.is(selector.input) ) {
4570 module.verbose('Using default check action on initialized checkbox');
4571 return;
4572 }
4573 if( $target.is(selector.link) ) {
4574 module.debug('Clicking link inside checkbox, skipping toggle');
4575 return;
4576 }
4577 module.toggle();
4578 $input.focus();
4579 event.preventDefault();
4580 },
4581 keydown: function(event) {
4582 var
4583 key = event.which,
4584 keyCode = {
4585 enter : 13,
4586 space : 32,
4587 escape : 27,
4588 left : 37,
4589 up : 38,
4590 right : 39,
4591 down : 40
4592 }
4593 ;
4594
4595 var r = module.get.radios(),
4596 rIndex = r.index($module),
4597 rLen = r.length,
4598 checkIndex = false;
4599
4600 if(key == keyCode.left || key == keyCode.up) {
4601 checkIndex = (rIndex === 0 ? rLen : rIndex) - 1;
4602 } else if(key == keyCode.right || key == keyCode.down) {
4603 checkIndex = rIndex === rLen-1 ? 0 : rIndex+1;
4604 }
4605
4606 if (!module.should.ignoreCallbacks() && checkIndex !== false) {
4607 if(settings.beforeUnchecked.apply(input)===false) {
4608 module.verbose('Option not allowed to be unchecked, cancelling key navigation');
4609 return false;
4610 }
4611 if (settings.beforeChecked.apply($(r[checkIndex]).children(selector.input)[0])===false) {
4612 module.verbose('Next option should not allow check, cancelling key navigation');
4613 return false;
4614 }
4615 }
4616
4617 if(key == keyCode.escape) {
4618 module.verbose('Escape key pressed blurring field');
4619 $input.blur();
4620 shortcutPressed = true;
4621 }
4622 else if(!event.ctrlKey && ( key == keyCode.space || key == keyCode.enter) ) {
4623 module.verbose('Enter/space key pressed, toggling checkbox');
4624 module.toggle();
4625 shortcutPressed = true;
4626 }
4627 else {
4628 shortcutPressed = false;
4629 }
4630 },
4631 keyup: function(event) {
4632 if(shortcutPressed) {
4633 event.preventDefault();
4634 }
4635 }
4636 },
4637
4638 check: function() {
4639 if( !module.should.allowCheck() ) {
4640 return;
4641 }
4642 module.debug('Checking checkbox', $input);
4643 module.set.checked();
4644 if( !module.should.ignoreCallbacks() ) {
4645 settings.onChecked.call(input);
4646 module.trigger.change();
4647 }
4648 module.preventDefaultOnInputTarget();
4649 },
4650
4651 uncheck: function() {
4652 if( !module.should.allowUncheck() ) {
4653 return;
4654 }
4655 module.debug('Unchecking checkbox');
4656 module.set.unchecked();
4657 if( !module.should.ignoreCallbacks() ) {
4658 settings.onUnchecked.call(input);
4659 module.trigger.change();
4660 }
4661 module.preventDefaultOnInputTarget();
4662 },
4663
4664 indeterminate: function() {
4665 if( module.should.allowIndeterminate() ) {
4666 module.debug('Checkbox is already indeterminate');
4667 return;
4668 }
4669 module.debug('Making checkbox indeterminate');
4670 module.set.indeterminate();
4671 if( !module.should.ignoreCallbacks() ) {
4672 settings.onIndeterminate.call(input);
4673 module.trigger.change();
4674 }
4675 },
4676
4677 determinate: function() {
4678 if( module.should.allowDeterminate() ) {
4679 module.debug('Checkbox is already determinate');
4680 return;
4681 }
4682 module.debug('Making checkbox determinate');
4683 module.set.determinate();
4684 if( !module.should.ignoreCallbacks() ) {
4685 settings.onDeterminate.call(input);
4686 module.trigger.change();
4687 }
4688 },
4689
4690 enable: function() {
4691 if( module.is.enabled() ) {
4692 module.debug('Checkbox is already enabled');
4693 return;
4694 }
4695 module.debug('Enabling checkbox');
4696 module.set.enabled();
4697 if( !module.should.ignoreCallbacks() ) {
4698 settings.onEnable.call(input);
4699 // preserve legacy callbacks
4700 settings.onEnabled.call(input);
4701 module.trigger.change();
4702 }
4703 },
4704
4705 disable: function() {
4706 if( module.is.disabled() ) {
4707 module.debug('Checkbox is already disabled');
4708 return;
4709 }
4710 module.debug('Disabling checkbox');
4711 module.set.disabled();
4712 if( !module.should.ignoreCallbacks() ) {
4713 settings.onDisable.call(input);
4714 // preserve legacy callbacks
4715 settings.onDisabled.call(input);
4716 module.trigger.change();
4717 }
4718 },
4719
4720 get: {
4721 radios: function() {
4722 var
4723 name = module.get.name()
4724 ;
4725 return $('input[name="' + name + '"]').closest(selector.checkbox);
4726 },
4727 otherRadios: function() {
4728 return module.get.radios().not($module);
4729 },
4730 name: function() {
4731 return $input.attr('name');
4732 }
4733 },
4734
4735 is: {
4736 initialLoad: function() {
4737 return initialLoad;
4738 },
4739 radio: function() {
4740 return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
4741 },
4742 indeterminate: function() {
4743 return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
4744 },
4745 checked: function() {
4746 return $input.prop('checked') !== undefined && $input.prop('checked');
4747 },
4748 disabled: function() {
4749 return $input.prop('disabled') !== undefined && $input.prop('disabled');
4750 },
4751 enabled: function() {
4752 return !module.is.disabled();
4753 },
4754 determinate: function() {
4755 return !module.is.indeterminate();
4756 },
4757 unchecked: function() {
4758 return !module.is.checked();
4759 }
4760 },
4761
4762 should: {
4763 allowCheck: function() {
4764 if(module.is.determinate() && module.is.checked() && !module.is.initialLoad() ) {
4765 module.debug('Should not allow check, checkbox is already checked');
4766 return false;
4767 }
4768 if(!module.should.ignoreCallbacks() && settings.beforeChecked.apply(input) === false) {
4769 module.debug('Should not allow check, beforeChecked cancelled');
4770 return false;
4771 }
4772 return true;
4773 },
4774 allowUncheck: function() {
4775 if(module.is.determinate() && module.is.unchecked() && !module.is.initialLoad() ) {
4776 module.debug('Should not allow uncheck, checkbox is already unchecked');
4777 return false;
4778 }
4779 if(!module.should.ignoreCallbacks() && settings.beforeUnchecked.apply(input) === false) {
4780 module.debug('Should not allow uncheck, beforeUnchecked cancelled');
4781 return false;
4782 }
4783 return true;
4784 },
4785 allowIndeterminate: function() {
4786 if(module.is.indeterminate() && !module.is.initialLoad() ) {
4787 module.debug('Should not allow indeterminate, checkbox is already indeterminate');
4788 return false;
4789 }
4790 if(!module.should.ignoreCallbacks() && settings.beforeIndeterminate.apply(input) === false) {
4791 module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
4792 return false;
4793 }
4794 return true;
4795 },
4796 allowDeterminate: function() {
4797 if(module.is.determinate() && !module.is.initialLoad() ) {
4798 module.debug('Should not allow determinate, checkbox is already determinate');
4799 return false;
4800 }
4801 if(!module.should.ignoreCallbacks() && settings.beforeDeterminate.apply(input) === false) {
4802 module.debug('Should not allow determinate, beforeDeterminate cancelled');
4803 return false;
4804 }
4805 return true;
4806 },
4807 ignoreCallbacks: function() {
4808 return (initialLoad && !settings.fireOnInit);
4809 }
4810 },
4811
4812 can: {
4813 change: function() {
4814 return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
4815 },
4816 uncheck: function() {
4817 return (typeof settings.uncheckable === 'boolean')
4818 ? settings.uncheckable
4819 : !module.is.radio()
4820 ;
4821 }
4822 },
4823
4824 set: {
4825 initialLoad: function() {
4826 initialLoad = true;
4827 },
4828 checked: function() {
4829 module.verbose('Setting class to checked');
4830 $module
4831 .removeClass(className.indeterminate)
4832 .addClass(className.checked)
4833 ;
4834 if( module.is.radio() ) {
4835 module.uncheckOthers();
4836 }
4837 if(!module.is.indeterminate() && module.is.checked()) {
4838 module.debug('Input is already checked, skipping input property change');
4839 return;
4840 }
4841 module.verbose('Setting state to checked', input);
4842 $input
4843 .prop('indeterminate', false)
4844 .prop('checked', true)
4845 ;
4846 },
4847 unchecked: function() {
4848 module.verbose('Removing checked class');
4849 $module
4850 .removeClass(className.indeterminate)
4851 .removeClass(className.checked)
4852 ;
4853 if(!module.is.indeterminate() && module.is.unchecked() ) {
4854 module.debug('Input is already unchecked');
4855 return;
4856 }
4857 module.debug('Setting state to unchecked');
4858 $input
4859 .prop('indeterminate', false)
4860 .prop('checked', false)
4861 ;
4862 },
4863 indeterminate: function() {
4864 module.verbose('Setting class to indeterminate');
4865 $module
4866 .addClass(className.indeterminate)
4867 ;
4868 if( module.is.indeterminate() ) {
4869 module.debug('Input is already indeterminate, skipping input property change');
4870 return;
4871 }
4872 module.debug('Setting state to indeterminate');
4873 $input
4874 .prop('indeterminate', true)
4875 ;
4876 },
4877 determinate: function() {
4878 module.verbose('Removing indeterminate class');
4879 $module
4880 .removeClass(className.indeterminate)
4881 ;
4882 if( module.is.determinate() ) {
4883 module.debug('Input is already determinate, skipping input property change');
4884 return;
4885 }
4886 module.debug('Setting state to determinate');
4887 $input
4888 .prop('indeterminate', false)
4889 ;
4890 },
4891 disabled: function() {
4892 module.verbose('Setting class to disabled');
4893 $module
4894 .addClass(className.disabled)
4895 ;
4896 if( module.is.disabled() ) {
4897 module.debug('Input is already disabled, skipping input property change');
4898 return;
4899 }
4900 module.debug('Setting state to disabled');
4901 $input
4902 .prop('disabled', 'disabled')
4903 ;
4904 },
4905 enabled: function() {
4906 module.verbose('Removing disabled class');
4907 $module.removeClass(className.disabled);
4908 if( module.is.enabled() ) {
4909 module.debug('Input is already enabled, skipping input property change');
4910 return;
4911 }
4912 module.debug('Setting state to enabled');
4913 $input
4914 .prop('disabled', false)
4915 ;
4916 },
4917 tabbable: function() {
4918 module.verbose('Adding tabindex to checkbox');
4919 if( $input.attr('tabindex') === undefined) {
4920 $input.attr('tabindex', 0);
4921 }
4922 }
4923 },
4924
4925 remove: {
4926 initialLoad: function() {
4927 initialLoad = false;
4928 }
4929 },
4930
4931 trigger: {
4932 change: function() {
4933 var
4934 events = document.createEvent('HTMLEvents'),
4935 inputElement = $input[0]
4936 ;
4937 if(inputElement) {
4938 module.verbose('Triggering native change event');
4939 events.initEvent('change', true, false);
4940 inputElement.dispatchEvent(events);
4941 }
4942 }
4943 },
4944
4945
4946 create: {
4947 label: function() {
4948 if($input.prevAll(selector.label).length > 0) {
4949 $input.prev(selector.label).detach().insertAfter($input);
4950 module.debug('Moving existing label', $label);
4951 }
4952 else if( !module.has.label() ) {
4953 $label = $('<label>').insertAfter($input);
4954 module.debug('Creating label', $label);
4955 }
4956 }
4957 },
4958
4959 has: {
4960 label: function() {
4961 return ($label.length > 0);
4962 }
4963 },
4964
4965 bind: {
4966 events: function() {
4967 module.verbose('Attaching checkbox events');
4968 $module
4969 .on('click' + eventNamespace, module.event.click)
4970 .on('change' + eventNamespace, module.event.change)
4971 .on('keydown' + eventNamespace, selector.input, module.event.keydown)
4972 .on('keyup' + eventNamespace, selector.input, module.event.keyup)
4973 ;
4974 }
4975 },
4976
4977 unbind: {
4978 events: function() {
4979 module.debug('Removing events');
4980 $module
4981 .off(eventNamespace)
4982 ;
4983 }
4984 },
4985
4986 uncheckOthers: function() {
4987 var
4988 $radios = module.get.otherRadios()
4989 ;
4990 module.debug('Unchecking other radios', $radios);
4991 $radios.removeClass(className.checked);
4992 },
4993
4994 toggle: function() {
4995 if( !module.can.change() ) {
4996 if(!module.is.radio()) {
4997 module.debug('Checkbox is read-only or disabled, ignoring toggle');
4998 }
4999 return;
5000 }
5001 if( module.is.indeterminate() || module.is.unchecked() ) {
5002 module.debug('Currently unchecked');
5003 module.check();
5004 }
5005 else if( module.is.checked() && module.can.uncheck() ) {
5006 module.debug('Currently checked');
5007 module.uncheck();
5008 }
5009 },
5010 setting: function(name, value) {
5011 module.debug('Changing setting', name, value);
5012 if( $.isPlainObject(name) ) {
5013 $.extend(true, settings, name);
5014 }
5015 else if(value !== undefined) {
5016 if($.isPlainObject(settings[name])) {
5017 $.extend(true, settings[name], value);
5018 }
5019 else {
5020 settings[name] = value;
5021 }
5022 }
5023 else {
5024 return settings[name];
5025 }
5026 },
5027 internal: function(name, value) {
5028 if( $.isPlainObject(name) ) {
5029 $.extend(true, module, name);
5030 }
5031 else if(value !== undefined) {
5032 module[name] = value;
5033 }
5034 else {
5035 return module[name];
5036 }
5037 },
5038 debug: function() {
5039 if(!settings.silent && settings.debug) {
5040 if(settings.performance) {
5041 module.performance.log(arguments);
5042 }
5043 else {
5044 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
5045 module.debug.apply(console, arguments);
5046 }
5047 }
5048 },
5049 verbose: function() {
5050 if(!settings.silent && settings.verbose && settings.debug) {
5051 if(settings.performance) {
5052 module.performance.log(arguments);
5053 }
5054 else {
5055 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
5056 module.verbose.apply(console, arguments);
5057 }
5058 }
5059 },
5060 error: function() {
5061 if(!settings.silent) {
5062 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
5063 module.error.apply(console, arguments);
5064 }
5065 },
5066 performance: {
5067 log: function(message) {
5068 var
5069 currentTime,
5070 executionTime,
5071 previousTime
5072 ;
5073 if(settings.performance) {
5074 currentTime = new Date().getTime();
5075 previousTime = time || currentTime;
5076 executionTime = currentTime - previousTime;
5077 time = currentTime;
5078 performance.push({
5079 'Name' : message[0],
5080 'Arguments' : [].slice.call(message, 1) || '',
5081 'Element' : element,
5082 'Execution Time' : executionTime
5083 });
5084 }
5085 clearTimeout(module.performance.timer);
5086 module.performance.timer = setTimeout(module.performance.display, 500);
5087 },
5088 display: function() {
5089 var
5090 title = settings.name + ':',
5091 totalTime = 0
5092 ;
5093 time = false;
5094 clearTimeout(module.performance.timer);
5095 $.each(performance, function(index, data) {
5096 totalTime += data['Execution Time'];
5097 });
5098 title += ' ' + totalTime + 'ms';
5099 if(moduleSelector) {
5100 title += ' \'' + moduleSelector + '\'';
5101 }
5102 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
5103 console.groupCollapsed(title);
5104 if(console.table) {
5105 console.table(performance);
5106 }
5107 else {
5108 $.each(performance, function(index, data) {
5109 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
5110 });
5111 }
5112 console.groupEnd();
5113 }
5114 performance = [];
5115 }
5116 },
5117 invoke: function(query, passedArguments, context) {
5118 var
5119 object = instance,
5120 maxDepth,
5121 found,
5122 response
5123 ;
5124 passedArguments = passedArguments || queryArguments;
5125 context = element || context;
5126 if(typeof query == 'string' && object !== undefined) {
5127 query = query.split(/[\. ]/);
5128 maxDepth = query.length - 1;
5129 $.each(query, function(depth, value) {
5130 var camelCaseValue = (depth != maxDepth)
5131 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
5132 : query
5133 ;
5134 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
5135 object = object[camelCaseValue];
5136 }
5137 else if( object[camelCaseValue] !== undefined ) {
5138 found = object[camelCaseValue];
5139 return false;
5140 }
5141 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
5142 object = object[value];
5143 }
5144 else if( object[value] !== undefined ) {
5145 found = object[value];
5146 return false;
5147 }
5148 else {
5149 module.error(error.method, query);
5150 return false;
5151 }
5152 });
5153 }
5154 if ( $.isFunction( found ) ) {
5155 response = found.apply(context, passedArguments);
5156 }
5157 else if(found !== undefined) {
5158 response = found;
5159 }
5160 if(Array.isArray(returnedValue)) {
5161 returnedValue.push(response);
5162 }
5163 else if(returnedValue !== undefined) {
5164 returnedValue = [returnedValue, response];
5165 }
5166 else if(response !== undefined) {
5167 returnedValue = response;
5168 }
5169 return found;
5170 }
5171 };
5172
5173 if(methodInvoked) {
5174 if(instance === undefined) {
5175 module.initialize();
5176 }
5177 module.invoke(query);
5178 }
5179 else {
5180 if(instance !== undefined) {
5181 instance.invoke('destroy');
5182 }
5183 module.initialize();
5184 }
5185 })
5186 ;
5187
5188 return (returnedValue !== undefined)
5189 ? returnedValue
5190 : this
5191 ;
5192};
5193
5194$.fn.checkbox.settings = {
5195
5196 name : 'Checkbox',
5197 namespace : 'checkbox',
5198
5199 silent : false,
5200 debug : false,
5201 verbose : true,
5202 performance : true,
5203
5204 // delegated event context
5205 uncheckable : 'auto',
5206 fireOnInit : false,
5207
5208 onChange : function(){},
5209
5210 beforeChecked : function(){},
5211 beforeUnchecked : function(){},
5212 beforeDeterminate : function(){},
5213 beforeIndeterminate : function(){},
5214
5215 onChecked : function(){},
5216 onUnchecked : function(){},
5217
5218 onDeterminate : function() {},
5219 onIndeterminate : function() {},
5220
5221 onEnable : function(){},
5222 onDisable : function(){},
5223
5224 // preserve misspelled callbacks (will be removed in 3.0)
5225 onEnabled : function(){},
5226 onDisabled : function(){},
5227
5228 className : {
5229 checked : 'checked',
5230 indeterminate : 'indeterminate',
5231 disabled : 'disabled',
5232 hidden : 'hidden',
5233 radio : 'radio',
5234 readOnly : 'read-only'
5235 },
5236
5237 error : {
5238 method : 'The method you called is not defined'
5239 },
5240
5241 selector : {
5242 checkbox : '.ui.checkbox',
5243 label : 'label, .box',
5244 input : 'input[type="checkbox"], input[type="radio"]',
5245 link : 'a[href]'
5246 }
5247
5248};
5249
5250})( jQuery, window, document );
5251
5252/*!
5253 * # Semantic UI 2.7.2 - Dimmer
5254 * http://github.com/semantic-org/semantic-ui/
5255 *
5256 *
5257 * Released under the MIT license
5258 * http://opensource.org/licenses/MIT
5259 *
5260 */
5261
5262;(function ($, window, document, undefined) {
5263
5264'use strict';
5265
5266$.isFunction = $.isFunction || function(obj) {
5267 return typeof obj === "function" && typeof obj.nodeType !== "number";
5268};
5269
5270window = (typeof window != 'undefined' && window.Math == Math)
5271 ? window
5272 : (typeof self != 'undefined' && self.Math == Math)
5273 ? self
5274 : Function('return this')()
5275;
5276
5277$.fn.dimmer = function(parameters) {
5278 var
5279 $allModules = $(this),
5280
5281 time = new Date().getTime(),
5282 performance = [],
5283
5284 query = arguments[0],
5285 methodInvoked = (typeof query == 'string'),
5286 queryArguments = [].slice.call(arguments, 1),
5287
5288 returnedValue
5289 ;
5290
5291 $allModules
5292 .each(function() {
5293 var
5294 settings = ( $.isPlainObject(parameters) )
5295 ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
5296 : $.extend({}, $.fn.dimmer.settings),
5297
5298 selector = settings.selector,
5299 namespace = settings.namespace,
5300 className = settings.className,
5301 error = settings.error,
5302
5303 eventNamespace = '.' + namespace,
5304 moduleNamespace = 'module-' + namespace,
5305 moduleSelector = $allModules.selector || '',
5306
5307 clickEvent = ('ontouchstart' in document.documentElement)
5308 ? 'touchstart'
5309 : 'click',
5310
5311 $module = $(this),
5312 $dimmer,
5313 $dimmable,
5314
5315 element = this,
5316 instance = $module.data(moduleNamespace),
5317 module
5318 ;
5319
5320 module = {
5321
5322 preinitialize: function() {
5323 if( module.is.dimmer() ) {
5324
5325 $dimmable = $module.parent();
5326 $dimmer = $module;
5327 }
5328 else {
5329 $dimmable = $module;
5330 if( module.has.dimmer() ) {
5331 if(settings.dimmerName) {
5332 $dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
5333 }
5334 else {
5335 $dimmer = $dimmable.find(selector.dimmer);
5336 }
5337 }
5338 else {
5339 $dimmer = module.create();
5340 }
5341 }
5342 },
5343
5344 initialize: function() {
5345 module.debug('Initializing dimmer', settings);
5346
5347 module.bind.events();
5348 module.set.dimmable();
5349 module.instantiate();
5350 },
5351
5352 instantiate: function() {
5353 module.verbose('Storing instance of module', module);
5354 instance = module;
5355 $module
5356 .data(moduleNamespace, instance)
5357 ;
5358 },
5359
5360 destroy: function() {
5361 module.verbose('Destroying previous module', $dimmer);
5362 module.unbind.events();
5363 module.remove.variation();
5364 $dimmable
5365 .off(eventNamespace)
5366 ;
5367 },
5368
5369 bind: {
5370 events: function() {
5371 if(settings.on == 'hover') {
5372 $dimmable
5373 .on('mouseenter' + eventNamespace, module.show)
5374 .on('mouseleave' + eventNamespace, module.hide)
5375 ;
5376 }
5377 else if(settings.on == 'click') {
5378 $dimmable
5379 .on(clickEvent + eventNamespace, module.toggle)
5380 ;
5381 }
5382 if( module.is.page() ) {
5383 module.debug('Setting as a page dimmer', $dimmable);
5384 module.set.pageDimmer();
5385 }
5386
5387 if( module.is.closable() ) {
5388 module.verbose('Adding dimmer close event', $dimmer);
5389 $dimmable
5390 .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
5391 ;
5392 }
5393 }
5394 },
5395
5396 unbind: {
5397 events: function() {
5398 $module
5399 .removeData(moduleNamespace)
5400 ;
5401 $dimmable
5402 .off(eventNamespace)
5403 ;
5404 }
5405 },
5406
5407 event: {
5408 click: function(event) {
5409 module.verbose('Determining if event occured on dimmer', event);
5410 if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
5411 module.hide();
5412 event.stopImmediatePropagation();
5413 }
5414 }
5415 },
5416
5417 addContent: function(element) {
5418 var
5419 $content = $(element)
5420 ;
5421 module.debug('Add content to dimmer', $content);
5422 if($content.parent()[0] !== $dimmer[0]) {
5423 $content.detach().appendTo($dimmer);
5424 }
5425 },
5426
5427 create: function() {
5428 var
5429 $element = $( settings.template.dimmer(settings) )
5430 ;
5431 if(settings.dimmerName) {
5432 module.debug('Creating named dimmer', settings.dimmerName);
5433 $element.addClass(settings.dimmerName);
5434 }
5435 $element
5436 .appendTo($dimmable)
5437 ;
5438 return $element;
5439 },
5440
5441 show: function(callback) {
5442 callback = $.isFunction(callback)
5443 ? callback
5444 : function(){}
5445 ;
5446 module.debug('Showing dimmer', $dimmer, settings);
5447 module.set.variation();
5448 if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
5449 module.animate.show(callback);
5450 settings.onShow.call(element);
5451 settings.onChange.call(element);
5452 }
5453 else {
5454 module.debug('Dimmer is already shown or disabled');
5455 }
5456 },
5457
5458 hide: function(callback) {
5459 callback = $.isFunction(callback)
5460 ? callback
5461 : function(){}
5462 ;
5463 if( module.is.dimmed() || module.is.animating() ) {
5464 module.debug('Hiding dimmer', $dimmer);
5465 module.animate.hide(callback);
5466 settings.onHide.call(element);
5467 settings.onChange.call(element);
5468 }
5469 else {
5470 module.debug('Dimmer is not visible');
5471 }
5472 },
5473
5474 toggle: function() {
5475 module.verbose('Toggling dimmer visibility', $dimmer);
5476 if( !module.is.dimmed() ) {
5477 module.show();
5478 }
5479 else {
5480 if ( module.is.closable() ) {
5481 module.hide();
5482 }
5483 }
5484 },
5485
5486 animate: {
5487 show: function(callback) {
5488 callback = $.isFunction(callback)
5489 ? callback
5490 : function(){}
5491 ;
5492 if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
5493 if(settings.useFlex) {
5494 module.debug('Using flex dimmer');
5495 module.remove.legacy();
5496 }
5497 else {
5498 module.debug('Using legacy non-flex dimmer');
5499 module.set.legacy();
5500 }
5501 if(settings.opacity !== 'auto') {
5502 module.set.opacity();
5503 }
5504 $dimmer
5505 .transition({
5506 displayType : settings.useFlex
5507 ? 'flex'
5508 : 'block',
5509 animation : settings.transition + ' in',
5510 queue : false,
5511 duration : module.get.duration(),
5512 useFailSafe : true,
5513 onStart : function() {
5514 module.set.dimmed();
5515 },
5516 onComplete : function() {
5517 module.set.active();
5518 callback();
5519 }
5520 })
5521 ;
5522 }
5523 else {
5524 module.verbose('Showing dimmer animation with javascript');
5525 module.set.dimmed();
5526 if(settings.opacity == 'auto') {
5527 settings.opacity = 0.8;
5528 }
5529 $dimmer
5530 .stop()
5531 .css({
5532 opacity : 0,
5533 width : '100%',
5534 height : '100%'
5535 })
5536 .fadeTo(module.get.duration(), settings.opacity, function() {
5537 $dimmer.removeAttr('style');
5538 module.set.active();
5539 callback();
5540 })
5541 ;
5542 }
5543 },
5544 hide: function(callback) {
5545 callback = $.isFunction(callback)
5546 ? callback
5547 : function(){}
5548 ;
5549 if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
5550 module.verbose('Hiding dimmer with css');
5551 $dimmer
5552 .transition({
5553 displayType : settings.useFlex
5554 ? 'flex'
5555 : 'block',
5556 animation : settings.transition + ' out',
5557 queue : false,
5558 duration : module.get.duration(),
5559 useFailSafe : true,
5560 onComplete : function() {
5561 module.remove.dimmed();
5562 module.remove.variation();
5563 module.remove.active();
5564 callback();
5565 }
5566 })
5567 ;
5568 }
5569 else {
5570 module.verbose('Hiding dimmer with javascript');
5571 $dimmer
5572 .stop()
5573 .fadeOut(module.get.duration(), function() {
5574 module.remove.dimmed();
5575 module.remove.active();
5576 $dimmer.removeAttr('style');
5577 callback();
5578 })
5579 ;
5580 }
5581 }
5582 },
5583
5584 get: {
5585 dimmer: function() {
5586 return $dimmer;
5587 },
5588 duration: function() {
5589 if(typeof settings.duration == 'object') {
5590 if( module.is.active() ) {
5591 return settings.duration.hide;
5592 }
5593 else {
5594 return settings.duration.show;
5595 }
5596 }
5597 return settings.duration;
5598 }
5599 },
5600
5601 has: {
5602 dimmer: function() {
5603 if(settings.dimmerName) {
5604 return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
5605 }
5606 else {
5607 return ( $module.find(selector.dimmer).length > 0 );
5608 }
5609 }
5610 },
5611
5612 is: {
5613 active: function() {
5614 return $dimmer.hasClass(className.active);
5615 },
5616 animating: function() {
5617 return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
5618 },
5619 closable: function() {
5620 if(settings.closable == 'auto') {
5621 if(settings.on == 'hover') {
5622 return false;
5623 }
5624 return true;
5625 }
5626 return settings.closable;
5627 },
5628 dimmer: function() {
5629 return $module.hasClass(className.dimmer);
5630 },
5631 dimmable: function() {
5632 return $module.hasClass(className.dimmable);
5633 },
5634 dimmed: function() {
5635 return $dimmable.hasClass(className.dimmed);
5636 },
5637 disabled: function() {
5638 return $dimmable.hasClass(className.disabled);
5639 },
5640 enabled: function() {
5641 return !module.is.disabled();
5642 },
5643 page: function () {
5644 return $dimmable.is('body');
5645 },
5646 pageDimmer: function() {
5647 return $dimmer.hasClass(className.pageDimmer);
5648 }
5649 },
5650
5651 can: {
5652 show: function() {
5653 return !$dimmer.hasClass(className.disabled);
5654 }
5655 },
5656
5657 set: {
5658 opacity: function(opacity) {
5659 var
5660 color = $dimmer.css('background-color'),
5661 colorArray = color.split(','),
5662 isRGB = (colorArray && colorArray.length == 3),
5663 isRGBA = (colorArray && colorArray.length == 4)
5664 ;
5665 opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
5666 if(isRGB || isRGBA) {
5667 colorArray[3] = opacity + ')';
5668 color = colorArray.join(',');
5669 }
5670 else {
5671 color = 'rgba(0, 0, 0, ' + opacity + ')';
5672 }
5673 module.debug('Setting opacity to', opacity);
5674 $dimmer.css('background-color', color);
5675 },
5676 legacy: function() {
5677 $dimmer.addClass(className.legacy);
5678 },
5679 active: function() {
5680 $dimmer.addClass(className.active);
5681 },
5682 dimmable: function() {
5683 $dimmable.addClass(className.dimmable);
5684 },
5685 dimmed: function() {
5686 $dimmable.addClass(className.dimmed);
5687 },
5688 pageDimmer: function() {
5689 $dimmer.addClass(className.pageDimmer);
5690 },
5691 disabled: function() {
5692 $dimmer.addClass(className.disabled);
5693 },
5694 variation: function(variation) {
5695 variation = variation || settings.variation;
5696 if(variation) {
5697 $dimmer.addClass(variation);
5698 }
5699 }
5700 },
5701
5702 remove: {
5703 active: function() {
5704 $dimmer
5705 .removeClass(className.active)
5706 ;
5707 },
5708 legacy: function() {
5709 $dimmer.removeClass(className.legacy);
5710 },
5711 dimmed: function() {
5712 $dimmable.removeClass(className.dimmed);
5713 },
5714 disabled: function() {
5715 $dimmer.removeClass(className.disabled);
5716 },
5717 variation: function(variation) {
5718 variation = variation || settings.variation;
5719 if(variation) {
5720 $dimmer.removeClass(variation);
5721 }
5722 }
5723 },
5724
5725 setting: function(name, value) {
5726 module.debug('Changing setting', name, value);
5727 if( $.isPlainObject(name) ) {
5728 $.extend(true, settings, name);
5729 }
5730 else if(value !== undefined) {
5731 if($.isPlainObject(settings[name])) {
5732 $.extend(true, settings[name], value);
5733 }
5734 else {
5735 settings[name] = value;
5736 }
5737 }
5738 else {
5739 return settings[name];
5740 }
5741 },
5742 internal: function(name, value) {
5743 if( $.isPlainObject(name) ) {
5744 $.extend(true, module, name);
5745 }
5746 else if(value !== undefined) {
5747 module[name] = value;
5748 }
5749 else {
5750 return module[name];
5751 }
5752 },
5753 debug: function() {
5754 if(!settings.silent && settings.debug) {
5755 if(settings.performance) {
5756 module.performance.log(arguments);
5757 }
5758 else {
5759 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
5760 module.debug.apply(console, arguments);
5761 }
5762 }
5763 },
5764 verbose: function() {
5765 if(!settings.silent && settings.verbose && settings.debug) {
5766 if(settings.performance) {
5767 module.performance.log(arguments);
5768 }
5769 else {
5770 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
5771 module.verbose.apply(console, arguments);
5772 }
5773 }
5774 },
5775 error: function() {
5776 if(!settings.silent) {
5777 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
5778 module.error.apply(console, arguments);
5779 }
5780 },
5781 performance: {
5782 log: function(message) {
5783 var
5784 currentTime,
5785 executionTime,
5786 previousTime
5787 ;
5788 if(settings.performance) {
5789 currentTime = new Date().getTime();
5790 previousTime = time || currentTime;
5791 executionTime = currentTime - previousTime;
5792 time = currentTime;
5793 performance.push({
5794 'Name' : message[0],
5795 'Arguments' : [].slice.call(message, 1) || '',
5796 'Element' : element,
5797 'Execution Time' : executionTime
5798 });
5799 }
5800 clearTimeout(module.performance.timer);
5801 module.performance.timer = setTimeout(module.performance.display, 500);
5802 },
5803 display: function() {
5804 var
5805 title = settings.name + ':',
5806 totalTime = 0
5807 ;
5808 time = false;
5809 clearTimeout(module.performance.timer);
5810 $.each(performance, function(index, data) {
5811 totalTime += data['Execution Time'];
5812 });
5813 title += ' ' + totalTime + 'ms';
5814 if(moduleSelector) {
5815 title += ' \'' + moduleSelector + '\'';
5816 }
5817 if($allModules.length > 1) {
5818 title += ' ' + '(' + $allModules.length + ')';
5819 }
5820 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
5821 console.groupCollapsed(title);
5822 if(console.table) {
5823 console.table(performance);
5824 }
5825 else {
5826 $.each(performance, function(index, data) {
5827 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
5828 });
5829 }
5830 console.groupEnd();
5831 }
5832 performance = [];
5833 }
5834 },
5835 invoke: function(query, passedArguments, context) {
5836 var
5837 object = instance,
5838 maxDepth,
5839 found,
5840 response
5841 ;
5842 passedArguments = passedArguments || queryArguments;
5843 context = element || context;
5844 if(typeof query == 'string' && object !== undefined) {
5845 query = query.split(/[\. ]/);
5846 maxDepth = query.length - 1;
5847 $.each(query, function(depth, value) {
5848 var camelCaseValue = (depth != maxDepth)
5849 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
5850 : query
5851 ;
5852 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
5853 object = object[camelCaseValue];
5854 }
5855 else if( object[camelCaseValue] !== undefined ) {
5856 found = object[camelCaseValue];
5857 return false;
5858 }
5859 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
5860 object = object[value];
5861 }
5862 else if( object[value] !== undefined ) {
5863 found = object[value];
5864 return false;
5865 }
5866 else {
5867 module.error(error.method, query);
5868 return false;
5869 }
5870 });
5871 }
5872 if ( $.isFunction( found ) ) {
5873 response = found.apply(context, passedArguments);
5874 }
5875 else if(found !== undefined) {
5876 response = found;
5877 }
5878 if(Array.isArray(returnedValue)) {
5879 returnedValue.push(response);
5880 }
5881 else if(returnedValue !== undefined) {
5882 returnedValue = [returnedValue, response];
5883 }
5884 else if(response !== undefined) {
5885 returnedValue = response;
5886 }
5887 return found;
5888 }
5889 };
5890
5891 module.preinitialize();
5892
5893 if(methodInvoked) {
5894 if(instance === undefined) {
5895 module.initialize();
5896 }
5897 module.invoke(query);
5898 }
5899 else {
5900 if(instance !== undefined) {
5901 instance.invoke('destroy');
5902 }
5903 module.initialize();
5904 }
5905 })
5906 ;
5907
5908 return (returnedValue !== undefined)
5909 ? returnedValue
5910 : this
5911 ;
5912};
5913
5914$.fn.dimmer.settings = {
5915
5916 name : 'Dimmer',
5917 namespace : 'dimmer',
5918
5919 silent : false,
5920 debug : false,
5921 verbose : false,
5922 performance : true,
5923
5924 // whether should use flex layout
5925 useFlex : true,
5926
5927 // name to distinguish between multiple dimmers in context
5928 dimmerName : false,
5929
5930 // whether to add a variation type
5931 variation : false,
5932
5933 // whether to bind close events
5934 closable : 'auto',
5935
5936 // whether to use css animations
5937 useCSS : true,
5938
5939 // css animation to use
5940 transition : 'fade',
5941
5942 // event to bind to
5943 on : false,
5944
5945 // overriding opacity value
5946 opacity : 'auto',
5947
5948 // transition durations
5949 duration : {
5950 show : 500,
5951 hide : 500
5952 },
5953// whether the dynamically created dimmer should have a loader
5954 displayLoader: false,
5955 loaderText : false,
5956 loaderVariation : '',
5957
5958 onChange : function(){},
5959 onShow : function(){},
5960 onHide : function(){},
5961
5962 error : {
5963 method : 'The method you called is not defined.'
5964 },
5965
5966 className : {
5967 active : 'active',
5968 animating : 'animating',
5969 dimmable : 'dimmable',
5970 dimmed : 'dimmed',
5971 dimmer : 'dimmer',
5972 disabled : 'disabled',
5973 hide : 'hide',
5974 legacy : 'legacy',
5975 pageDimmer : 'page',
5976 show : 'show',
5977 loader : 'ui loader'
5978 },
5979
5980 selector: {
5981 dimmer : '> .ui.dimmer',
5982 content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
5983 },
5984
5985 template: {
5986 dimmer: function(settings) {
5987 var d = $('<div/>').addClass('ui dimmer'),l;
5988 if(settings.displayLoader) {
5989 l = $('<div/>')
5990 .addClass(settings.className.loader)
5991 .addClass(settings.loaderVariation);
5992 if(!!settings.loaderText){
5993 l.text(settings.loaderText);
5994 l.addClass('text');
5995 }
5996 d.append(l);
5997 }
5998 return d;
5999 }
6000 }
6001
6002};
6003
6004})( jQuery, window, document );
6005
6006/*!
6007 * # Semantic UI 2.7.2 - Dropdown
6008 * http://github.com/semantic-org/semantic-ui/
6009 *
6010 *
6011 * Released under the MIT license
6012 * http://opensource.org/licenses/MIT
6013 *
6014 */
6015
6016;(function ($, window, document, undefined) {
6017
6018'use strict';
6019
6020$.isFunction = $.isFunction || function(obj) {
6021 return typeof obj === "function" && typeof obj.nodeType !== "number";
6022};
6023
6024window = (typeof window != 'undefined' && window.Math == Math)
6025 ? window
6026 : (typeof self != 'undefined' && self.Math == Math)
6027 ? self
6028 : Function('return this')()
6029;
6030
6031$.fn.dropdown = function(parameters) {
6032 var
6033 $allModules = $(this),
6034 $document = $(document),
6035
6036 moduleSelector = $allModules.selector || '',
6037
6038 hasTouch = ('ontouchstart' in document.documentElement),
6039 time = new Date().getTime(),
6040 performance = [],
6041
6042 query = arguments[0],
6043 methodInvoked = (typeof query == 'string'),
6044 queryArguments = [].slice.call(arguments, 1),
6045 returnedValue
6046 ;
6047
6048 $allModules
6049 .each(function(elementIndex) {
6050 var
6051 settings = ( $.isPlainObject(parameters) )
6052 ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
6053 : $.extend({}, $.fn.dropdown.settings),
6054
6055 className = settings.className,
6056 message = settings.message,
6057 fields = settings.fields,
6058 keys = settings.keys,
6059 metadata = settings.metadata,
6060 namespace = settings.namespace,
6061 regExp = settings.regExp,
6062 selector = settings.selector,
6063 error = settings.error,
6064 templates = settings.templates,
6065
6066 eventNamespace = '.' + namespace,
6067 moduleNamespace = 'module-' + namespace,
6068
6069 $module = $(this),
6070 $context = $(settings.context),
6071 $text = $module.find(selector.text),
6072 $search = $module.find(selector.search),
6073 $sizer = $module.find(selector.sizer),
6074 $input = $module.find(selector.input),
6075 $icon = $module.find(selector.icon),
6076 $clear = $module.find(selector.clearIcon),
6077
6078 $combo = ($module.prev().find(selector.text).length > 0)
6079 ? $module.prev().find(selector.text)
6080 : $module.prev(),
6081
6082 $menu = $module.children(selector.menu),
6083 $item = $menu.find(selector.item),
6084 $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $(),
6085
6086 activated = false,
6087 itemActivated = false,
6088 internalChange = false,
6089 iconClicked = false,
6090 element = this,
6091 instance = $module.data(moduleNamespace),
6092
6093 initialLoad,
6094 pageLostFocus,
6095 willRefocus,
6096 elementNamespace,
6097 id,
6098 selectObserver,
6099 menuObserver,
6100 module
6101 ;
6102
6103 module = {
6104
6105 initialize: function() {
6106 module.debug('Initializing dropdown', settings);
6107
6108 if( module.is.alreadySetup() ) {
6109 module.setup.reference();
6110 }
6111 else {
6112 if (settings.ignoreDiacritics && !String.prototype.normalize) {
6113 settings.ignoreDiacritics = false;
6114 module.error(error.noNormalize, element);
6115 }
6116
6117 module.setup.layout();
6118
6119 if(settings.values) {
6120 module.change.values(settings.values);
6121 }
6122
6123 module.refreshData();
6124
6125 module.save.defaults();
6126 module.restore.selected();
6127
6128 module.create.id();
6129 module.bind.events();
6130
6131 module.observeChanges();
6132 module.instantiate();
6133 }
6134
6135 },
6136
6137 instantiate: function() {
6138 module.verbose('Storing instance of dropdown', module);
6139 instance = module;
6140 $module
6141 .data(moduleNamespace, module)
6142 ;
6143 },
6144
6145 destroy: function() {
6146 module.verbose('Destroying previous dropdown', $module);
6147 module.remove.tabbable();
6148 $module
6149 .off(eventNamespace)
6150 .removeData(moduleNamespace)
6151 ;
6152 $menu
6153 .off(eventNamespace)
6154 ;
6155 $document
6156 .off(elementNamespace)
6157 ;
6158 module.disconnect.menuObserver();
6159 module.disconnect.selectObserver();
6160 },
6161
6162 observeChanges: function() {
6163 if('MutationObserver' in window) {
6164 selectObserver = new MutationObserver(module.event.select.mutation);
6165 menuObserver = new MutationObserver(module.event.menu.mutation);
6166 module.debug('Setting up mutation observer', selectObserver, menuObserver);
6167 module.observe.select();
6168 module.observe.menu();
6169 }
6170 },
6171
6172 disconnect: {
6173 menuObserver: function() {
6174 if(menuObserver) {
6175 menuObserver.disconnect();
6176 }
6177 },
6178 selectObserver: function() {
6179 if(selectObserver) {
6180 selectObserver.disconnect();
6181 }
6182 }
6183 },
6184 observe: {
6185 select: function() {
6186 if(module.has.input()) {
6187 selectObserver.observe($module[0], {
6188 childList : true,
6189 subtree : true
6190 });
6191 }
6192 },
6193 menu: function() {
6194 if(module.has.menu()) {
6195 menuObserver.observe($menu[0], {
6196 childList : true,
6197 subtree : true
6198 });
6199 }
6200 }
6201 },
6202
6203 create: {
6204 id: function() {
6205 id = (Math.random().toString(16) + '000000000').substr(2, 8);
6206 elementNamespace = '.' + id;
6207 module.verbose('Creating unique id for element', id);
6208 },
6209 userChoice: function(values) {
6210 var
6211 $userChoices,
6212 $userChoice,
6213 isUserValue,
6214 html
6215 ;
6216 values = values || module.get.userValues();
6217 if(!values) {
6218 return false;
6219 }
6220 values = Array.isArray(values)
6221 ? values
6222 : [values]
6223 ;
6224 $.each(values, function(index, value) {
6225 if(module.get.item(value) === false) {
6226 html = settings.templates.addition( module.add.variables(message.addResult, value) );
6227 $userChoice = $('<div />')
6228 .html(html)
6229 .attr('data-' + metadata.value, value)
6230 .attr('data-' + metadata.text, value)
6231 .addClass(className.addition)
6232 .addClass(className.item)
6233 ;
6234 if(settings.hideAdditions) {
6235 $userChoice.addClass(className.hidden);
6236 }
6237 $userChoices = ($userChoices === undefined)
6238 ? $userChoice
6239 : $userChoices.add($userChoice)
6240 ;
6241 module.verbose('Creating user choices for value', value, $userChoice);
6242 }
6243 });
6244 return $userChoices;
6245 },
6246 userLabels: function(value) {
6247 var
6248 userValues = module.get.userValues()
6249 ;
6250 if(userValues) {
6251 module.debug('Adding user labels', userValues);
6252 $.each(userValues, function(index, value) {
6253 module.verbose('Adding custom user value');
6254 module.add.label(value, value);
6255 });
6256 }
6257 },
6258 menu: function() {
6259 $menu = $('<div />')
6260 .addClass(className.menu)
6261 .appendTo($module)
6262 ;
6263 },
6264 sizer: function() {
6265 $sizer = $('<span />')
6266 .addClass(className.sizer)
6267 .insertAfter($search)
6268 ;
6269 }
6270 },
6271
6272 search: function(query) {
6273 query = (query !== undefined)
6274 ? query
6275 : module.get.query()
6276 ;
6277 module.verbose('Searching for query', query);
6278 if(module.has.minCharacters(query)) {
6279 module.filter(query);
6280 }
6281 else {
6282 module.hide();
6283 }
6284 },
6285
6286 select: {
6287 firstUnfiltered: function() {
6288 module.verbose('Selecting first non-filtered element');
6289 module.remove.selectedItem();
6290 $item
6291 .not(selector.unselectable)
6292 .not(selector.addition + selector.hidden)
6293 .eq(0)
6294 .addClass(className.selected)
6295 ;
6296 },
6297 nextAvailable: function($selected) {
6298 $selected = $selected.eq(0);
6299 var
6300 $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
6301 $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
6302 hasNext = ($nextAvailable.length > 0)
6303 ;
6304 if(hasNext) {
6305 module.verbose('Moving selection to', $nextAvailable);
6306 $nextAvailable.addClass(className.selected);
6307 }
6308 else {
6309 module.verbose('Moving selection to', $prevAvailable);
6310 $prevAvailable.addClass(className.selected);
6311 }
6312 }
6313 },
6314
6315 setup: {
6316 api: function() {
6317 var
6318 apiSettings = {
6319 debug : settings.debug,
6320 urlData : {
6321 value : module.get.value(),
6322 query : module.get.query()
6323 },
6324 on : false
6325 }
6326 ;
6327 module.verbose('First request, initializing API');
6328 $module
6329 .api(apiSettings)
6330 ;
6331 },
6332 layout: function() {
6333 if( $module.is('select') ) {
6334 module.setup.select();
6335 module.setup.returnedObject();
6336 }
6337 if( !module.has.menu() ) {
6338 module.create.menu();
6339 }
6340 if ( module.is.selection() && module.is.clearable() && !module.has.clearItem() ) {
6341 module.verbose('Adding clear icon');
6342 $clear = $('<i />')
6343 .addClass('remove icon')
6344 .insertBefore($text)
6345 ;
6346 }
6347 if( module.is.search() && !module.has.search() ) {
6348 module.verbose('Adding search input');
6349 $search = $('<input />')
6350 .addClass(className.search)
6351 .prop('autocomplete', 'off')
6352 .insertBefore($text)
6353 ;
6354 }
6355 if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
6356 module.create.sizer();
6357 }
6358 if(settings.allowTab) {
6359 module.set.tabbable();
6360 }
6361 },
6362 select: function() {
6363 var
6364 selectValues = module.get.selectValues()
6365 ;
6366 module.debug('Dropdown initialized on a select', selectValues);
6367 if( $module.is('select') ) {
6368 $input = $module;
6369 }
6370 // see if select is placed correctly already
6371 if($input.parent(selector.dropdown).length > 0) {
6372 module.debug('UI dropdown already exists. Creating dropdown menu only');
6373 $module = $input.closest(selector.dropdown);
6374 if( !module.has.menu() ) {
6375 module.create.menu();
6376 }
6377 $menu = $module.children(selector.menu);
6378 module.setup.menu(selectValues);
6379 }
6380 else {
6381 module.debug('Creating entire dropdown from select');
6382 $module = $('<div />')
6383 .attr('class', $input.attr('class') )
6384 .addClass(className.selection)
6385 .addClass(className.dropdown)
6386 .html( templates.dropdown(selectValues,settings.preserveHTML, settings.className) )
6387 .insertBefore($input)
6388 ;
6389 if($input.hasClass(className.multiple) && $input.prop('multiple') === false) {
6390 module.error(error.missingMultiple);
6391 $input.prop('multiple', true);
6392 }
6393 if($input.is('[multiple]')) {
6394 module.set.multiple();
6395 }
6396 if ($input.prop('disabled')) {
6397 module.debug('Disabling dropdown');
6398 $module.addClass(className.disabled);
6399 }
6400 $input
6401 .removeAttr('class')
6402 .detach()
6403 .prependTo($module)
6404 ;
6405 }
6406 module.refresh();
6407 },
6408 menu: function(values) {
6409 $menu.html( templates.menu(values, fields,settings.preserveHTML,settings.className));
6410 $item = $menu.find(selector.item);
6411 $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
6412 },
6413 reference: function() {
6414 module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
6415 // replace module reference
6416 $module = $module.parent(selector.dropdown);
6417 instance = $module.data(moduleNamespace);
6418 element = $module.get(0);
6419 module.refresh();
6420 module.setup.returnedObject();
6421 },
6422 returnedObject: function() {
6423 var
6424 $firstModules = $allModules.slice(0, elementIndex),
6425 $lastModules = $allModules.slice(elementIndex + 1)
6426 ;
6427 // adjust all modules to use correct reference
6428 $allModules = $firstModules.add($module).add($lastModules);
6429 }
6430 },
6431
6432 refresh: function() {
6433 module.refreshSelectors();
6434 module.refreshData();
6435 },
6436
6437 refreshItems: function() {
6438 $item = $menu.find(selector.item);
6439 $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
6440 },
6441
6442 refreshSelectors: function() {
6443 module.verbose('Refreshing selector cache');
6444 $text = $module.find(selector.text);
6445 $search = $module.find(selector.search);
6446 $input = $module.find(selector.input);
6447 $icon = $module.find(selector.icon);
6448 $combo = ($module.prev().find(selector.text).length > 0)
6449 ? $module.prev().find(selector.text)
6450 : $module.prev()
6451 ;
6452 $menu = $module.children(selector.menu);
6453 $item = $menu.find(selector.item);
6454 $divider = settings.hideDividers ? $item.parent().children(selector.divider) : $();
6455 },
6456
6457 refreshData: function() {
6458 module.verbose('Refreshing cached metadata');
6459 $item
6460 .removeData(metadata.text)
6461 .removeData(metadata.value)
6462 ;
6463 },
6464
6465 clearData: function() {
6466 module.verbose('Clearing metadata');
6467 $item
6468 .removeData(metadata.text)
6469 .removeData(metadata.value)
6470 ;
6471 $module
6472 .removeData(metadata.defaultText)
6473 .removeData(metadata.defaultValue)
6474 .removeData(metadata.placeholderText)
6475 ;
6476 },
6477
6478 toggle: function() {
6479 module.verbose('Toggling menu visibility');
6480 if( !module.is.active() ) {
6481 module.show();
6482 }
6483 else {
6484 module.hide();
6485 }
6486 },
6487
6488 show: function(callback) {
6489 callback = $.isFunction(callback)
6490 ? callback
6491 : function(){}
6492 ;
6493 if(!module.can.show() && module.is.remote()) {
6494 module.debug('No API results retrieved, searching before show');
6495 module.queryRemote(module.get.query(), module.show);
6496 }
6497 if( module.can.show() && !module.is.active() ) {
6498 module.debug('Showing dropdown');
6499 if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
6500 module.remove.message();
6501 }
6502 if(module.is.allFiltered()) {
6503 return true;
6504 }
6505 if(settings.onShow.call(element) !== false) {
6506 module.animate.show(function() {
6507 if( module.can.click() ) {
6508 module.bind.intent();
6509 }
6510 if(module.has.search()) {
6511 module.focusSearch();
6512 }
6513 module.set.visible();
6514 callback.call(element);
6515 });
6516 }
6517 }
6518 },
6519
6520 hide: function(callback) {
6521 callback = $.isFunction(callback)
6522 ? callback
6523 : function(){}
6524 ;
6525 if( module.is.active() && !module.is.animatingOutward() ) {
6526 module.debug('Hiding dropdown');
6527 if(settings.onHide.call(element) !== false) {
6528 module.animate.hide(function() {
6529 module.remove.visible();
6530 // hidding search focus
6531 if ( module.is.focusedOnSearch() ) {
6532 $search.blur();
6533 }
6534 callback.call(element);
6535 });
6536 }
6537 }
6538 },
6539
6540 hideOthers: function() {
6541 module.verbose('Finding other dropdowns to hide');
6542 $allModules
6543 .not($module)
6544 .has(selector.menu + '.' + className.visible)
6545 .dropdown('hide')
6546 ;
6547 },
6548
6549 hideMenu: function() {
6550 module.verbose('Hiding menu instantaneously');
6551 module.remove.active();
6552 module.remove.visible();
6553 $menu.transition('hide');
6554 },
6555
6556 hideSubMenus: function() {
6557 var
6558 $subMenus = $menu.children(selector.item).find(selector.menu)
6559 ;
6560 module.verbose('Hiding sub menus', $subMenus);
6561 $subMenus.transition('hide');
6562 },
6563
6564 bind: {
6565 events: function() {
6566 if(hasTouch) {
6567 module.bind.touchEvents();
6568 }
6569 module.bind.keyboardEvents();
6570 module.bind.inputEvents();
6571 module.bind.mouseEvents();
6572 },
6573 touchEvents: function() {
6574 module.debug('Touch device detected binding additional touch events');
6575 if( module.is.searchSelection() ) {
6576 // do nothing special yet
6577 }
6578 else if( module.is.single() ) {
6579 $module
6580 .on('touchstart' + eventNamespace, module.event.test.toggle)
6581 ;
6582 }
6583 $menu
6584 .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
6585 ;
6586 },
6587 keyboardEvents: function() {
6588 module.verbose('Binding keyboard events');
6589 $module
6590 .on('keydown' + eventNamespace, module.event.keydown)
6591 ;
6592 if( module.has.search() ) {
6593 $module
6594 .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
6595 ;
6596 }
6597 if( module.is.multiple() ) {
6598 $document
6599 .on('keydown' + elementNamespace, module.event.document.keydown)
6600 ;
6601 }
6602 },
6603 inputEvents: function() {
6604 module.verbose('Binding input change events');
6605 $module
6606 .on('change' + eventNamespace, selector.input, module.event.change)
6607 ;
6608 },
6609 mouseEvents: function() {
6610 module.verbose('Binding mouse events');
6611 if(module.is.multiple()) {
6612 $module
6613 .on('click' + eventNamespace, selector.label, module.event.label.click)
6614 .on('click' + eventNamespace, selector.remove, module.event.remove.click)
6615 ;
6616 }
6617 if( module.is.searchSelection() ) {
6618 $module
6619 .on('mousedown' + eventNamespace, module.event.mousedown)
6620 .on('mouseup' + eventNamespace, module.event.mouseup)
6621 .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
6622 .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
6623 .on('click' + eventNamespace, selector.icon, module.event.icon.click)
6624 .on('click' + eventNamespace, selector.clearIcon, module.event.clearIcon.click)
6625 .on('focus' + eventNamespace, selector.search, module.event.search.focus)
6626 .on('click' + eventNamespace, selector.search, module.event.search.focus)
6627 .on('blur' + eventNamespace, selector.search, module.event.search.blur)
6628 .on('click' + eventNamespace, selector.text, module.event.text.focus)
6629 ;
6630 if(module.is.multiple()) {
6631 $module
6632 .on('click' + eventNamespace, module.event.click)
6633 ;
6634 }
6635 }
6636 else {
6637 if(settings.on == 'click') {
6638 $module
6639 .on('click' + eventNamespace, selector.icon, module.event.icon.click)
6640 .on('click' + eventNamespace, module.event.test.toggle)
6641 ;
6642 }
6643 else if(settings.on == 'hover') {
6644 $module
6645 .on('mouseenter' + eventNamespace, module.delay.show)
6646 .on('mouseleave' + eventNamespace, module.delay.hide)
6647 ;
6648 }
6649 else {
6650 $module
6651 .on(settings.on + eventNamespace, module.toggle)
6652 ;
6653 }
6654 $module
6655 .on('mousedown' + eventNamespace, module.event.mousedown)
6656 .on('mouseup' + eventNamespace, module.event.mouseup)
6657 .on('focus' + eventNamespace, module.event.focus)
6658 .on('click' + eventNamespace, selector.clearIcon, module.event.clearIcon.click)
6659 ;
6660 if(module.has.menuSearch() ) {
6661 $module
6662 .on('blur' + eventNamespace, selector.search, module.event.search.blur)
6663 ;
6664 }
6665 else {
6666 $module
6667 .on('blur' + eventNamespace, module.event.blur)
6668 ;
6669 }
6670 }
6671 $menu
6672 .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
6673 .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
6674 .on('click' + eventNamespace, selector.item, module.event.item.click)
6675 ;
6676 },
6677 intent: function() {
6678 module.verbose('Binding hide intent event to document');
6679 if(hasTouch) {
6680 $document
6681 .on('touchstart' + elementNamespace, module.event.test.touch)
6682 .on('touchmove' + elementNamespace, module.event.test.touch)
6683 ;
6684 }
6685 $document
6686 .on('click' + elementNamespace, module.event.test.hide)
6687 ;
6688 }
6689 },
6690
6691 unbind: {
6692 intent: function() {
6693 module.verbose('Removing hide intent event from document');
6694 if(hasTouch) {
6695 $document
6696 .off('touchstart' + elementNamespace)
6697 .off('touchmove' + elementNamespace)
6698 ;
6699 }
6700 $document
6701 .off('click' + elementNamespace)
6702 ;
6703 }
6704 },
6705
6706 filter: function(query) {
6707 var
6708 searchTerm = (query !== undefined)
6709 ? query
6710 : module.get.query(),
6711 afterFiltered = function() {
6712 if(module.is.multiple()) {
6713 module.filterActive();
6714 }
6715 if(query || (!query && module.get.activeItem().length == 0)) {
6716 module.select.firstUnfiltered();
6717 }
6718 if( module.has.allResultsFiltered() ) {
6719 if( settings.onNoResults.call(element, searchTerm) ) {
6720 if(settings.allowAdditions) {
6721 if(settings.hideAdditions) {
6722 module.verbose('User addition with no menu, setting empty style');
6723 module.set.empty();
6724 module.hideMenu();
6725 }
6726 }
6727 else {
6728 module.verbose('All items filtered, showing message', searchTerm);
6729 module.add.message(message.noResults);
6730 }
6731 }
6732 else {
6733 module.verbose('All items filtered, hiding dropdown', searchTerm);
6734 module.hideMenu();
6735 }
6736 }
6737 else {
6738 module.remove.empty();
6739 module.remove.message();
6740 }
6741 if(settings.allowAdditions) {
6742 module.add.userSuggestion(module.escape.htmlEntities(query));
6743 }
6744 if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
6745 module.show();
6746 }
6747 }
6748 ;
6749 if(settings.useLabels && module.has.maxSelections()) {
6750 return;
6751 }
6752 if(settings.apiSettings) {
6753 if( module.can.useAPI() ) {
6754 module.queryRemote(searchTerm, function() {
6755 if(settings.filterRemoteData) {
6756 module.filterItems(searchTerm);
6757 }
6758 var preSelected = $input.val();
6759 if(!Array.isArray(preSelected)) {
6760 preSelected = preSelected && preSelected!=="" ? preSelected.split(settings.delimiter) : [];
6761 }
6762 $.each(preSelected,function(index,value){
6763 $item.filter('[data-value="'+value+'"]')
6764 .addClass(className.filtered)
6765 ;
6766 });
6767 afterFiltered();
6768 });
6769 }
6770 else {
6771 module.error(error.noAPI);
6772 }
6773 }
6774 else {
6775 module.filterItems(searchTerm);
6776 afterFiltered();
6777 }
6778 },
6779
6780 queryRemote: function(query, callback) {
6781 var
6782 apiSettings = {
6783 errorDuration : false,
6784 cache : 'local',
6785 throttle : settings.throttle,
6786 urlData : {
6787 query: query
6788 },
6789 onError: function() {
6790 module.add.message(message.serverError);
6791 callback();
6792 },
6793 onFailure: function() {
6794 module.add.message(message.serverError);
6795 callback();
6796 },
6797 onSuccess : function(response) {
6798 var
6799 values = response[fields.remoteValues]
6800 ;
6801 if (!Array.isArray(values)){
6802 values = [];
6803 }
6804 module.remove.message();
6805 module.setup.menu({
6806 values: values
6807 });
6808
6809 if(values.length===0 && !settings.allowAdditions) {
6810 module.add.message(message.noResults);
6811 }
6812 callback();
6813 }
6814 }
6815 ;
6816 if( !$module.api('get request') ) {
6817 module.setup.api();
6818 }
6819 apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
6820 $module
6821 .api('setting', apiSettings)
6822 .api('query')
6823 ;
6824 },
6825
6826 filterItems: function(query) {
6827 var
6828 searchTerm = module.remove.diacritics(query !== undefined
6829 ? query
6830 : module.get.query()
6831 ),
6832 results = null,
6833 escapedTerm = module.escape.string(searchTerm),
6834 beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm')
6835 ;
6836 // avoid loop if we're matching nothing
6837 if( module.has.query() ) {
6838 results = [];
6839
6840 module.verbose('Searching for matching values', searchTerm);
6841 $item
6842 .each(function(){
6843 var
6844 $choice = $(this),
6845 text,
6846 value
6847 ;
6848 if(settings.match === 'both' || settings.match === 'text') {
6849 text = module.remove.diacritics(String(module.get.choiceText($choice, false)));
6850 if(text.search(beginsWithRegExp) !== -1) {
6851 results.push(this);
6852 return true;
6853 }
6854 else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) {
6855 results.push(this);
6856 return true;
6857 }
6858 else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) {
6859 results.push(this);
6860 return true;
6861 }
6862 }
6863 if(settings.match === 'both' || settings.match === 'value') {
6864 value = module.remove.diacritics(String(module.get.choiceValue($choice, text)));
6865 if(value.search(beginsWithRegExp) !== -1) {
6866 results.push(this);
6867 return true;
6868 }
6869 else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, value)) {
6870 results.push(this);
6871 return true;
6872 }
6873 else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, value)) {
6874 results.push(this);
6875 return true;
6876 }
6877 }
6878 })
6879 ;
6880 }
6881 module.debug('Showing only matched items', searchTerm);
6882 module.remove.filteredItem();
6883 if(results) {
6884 $item
6885 .not(results)
6886 .addClass(className.filtered)
6887 ;
6888 }
6889
6890 if(!module.has.query()) {
6891 $divider
6892 .removeClass(className.hidden);
6893 } else if(settings.hideDividers === true) {
6894 $divider
6895 .addClass(className.hidden);
6896 } else if(settings.hideDividers === 'empty') {
6897 $divider
6898 .removeClass(className.hidden)
6899 .filter(function() {
6900 // First find the last divider in this divider group
6901 // Dividers which are direct siblings are considered a group
6902 var lastDivider = $(this).nextUntil(selector.item);
6903
6904 return (lastDivider.length ? lastDivider : $(this))
6905 // Count all non-filtered items until the next divider (or end of the dropdown)
6906 .nextUntil(selector.divider)
6907 .filter(selector.item + ":not(." + className.filtered + ")")
6908 // Hide divider if no items are found
6909 .length === 0;
6910 })
6911 .addClass(className.hidden);
6912 }
6913 },
6914
6915 fuzzySearch: function(query, term) {
6916 var
6917 termLength = term.length,
6918 queryLength = query.length
6919 ;
6920 query = query.toLowerCase();
6921 term = term.toLowerCase();
6922 if(queryLength > termLength) {
6923 return false;
6924 }
6925 if(queryLength === termLength) {
6926 return (query === term);
6927 }
6928 search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
6929 var
6930 queryCharacter = query.charCodeAt(characterIndex)
6931 ;
6932 while(nextCharacterIndex < termLength) {
6933 if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
6934 continue search;
6935 }
6936 }
6937 return false;
6938 }
6939 return true;
6940 },
6941 exactSearch: function (query, term) {
6942 query = query.toLowerCase();
6943 term = term.toLowerCase();
6944 return term.indexOf(query) > -1;
6945
6946 },
6947 filterActive: function() {
6948 if(settings.useLabels) {
6949 $item.filter('.' + className.active)
6950 .addClass(className.filtered)
6951 ;
6952 }
6953 },
6954
6955 focusSearch: function(skipHandler) {
6956 if( module.has.search() && !module.is.focusedOnSearch() ) {
6957 if(skipHandler) {
6958 $module.off('focus' + eventNamespace, selector.search);
6959 $search.focus();
6960 $module.on('focus' + eventNamespace, selector.search, module.event.search.focus);
6961 }
6962 else {
6963 $search.focus();
6964 }
6965 }
6966 },
6967
6968 blurSearch: function() {
6969 if( module.has.search() ) {
6970 $search.blur();
6971 }
6972 },
6973
6974 forceSelection: function() {
6975 var
6976 $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
6977 $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
6978 $selectedItem = ($currentlySelected.length > 0)
6979 ? $currentlySelected
6980 : $activeItem,
6981 hasSelected = ($selectedItem.length > 0)
6982 ;
6983 if(hasSelected && !module.is.multiple()) {
6984 module.debug('Forcing partial selection to selected item', $selectedItem);
6985 module.event.item.click.call($selectedItem, {}, true);
6986 }
6987 else {
6988 if(settings.allowAdditions) {
6989 module.set.selected(module.get.query());
6990 module.remove.searchTerm();
6991 }
6992 else {
6993 module.remove.searchTerm();
6994 }
6995 }
6996 },
6997
6998 change: {
6999 values: function(values) {
7000 if(!settings.allowAdditions) {
7001 module.clear();
7002 }
7003 module.debug('Creating dropdown with specified values', values);
7004 module.setup.menu({values: values});
7005 $.each(values, function(index, item) {
7006 if(item.selected == true) {
7007 module.debug('Setting initial selection to', item[fields.value]);
7008 module.set.selected(item[fields.value]);
7009 if(!module.is.multiple()) {
7010 return false;
7011 }
7012 }
7013 });
7014 }
7015 },
7016
7017 event: {
7018 change: function() {
7019 if(!internalChange) {
7020 module.debug('Input changed, updating selection');
7021 module.set.selected();
7022 }
7023 },
7024 focus: function() {
7025 if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
7026 module.show();
7027 }
7028 },
7029 blur: function(event) {
7030 pageLostFocus = (document.activeElement === this);
7031 if(!activated && !pageLostFocus) {
7032 module.remove.activeLabel();
7033 module.hide();
7034 }
7035 },
7036 mousedown: function() {
7037 if(module.is.searchSelection()) {
7038 // prevent menu hiding on immediate re-focus
7039 willRefocus = true;
7040 }
7041 else {
7042 // prevents focus callback from occurring on mousedown
7043 activated = true;
7044 }
7045 },
7046 mouseup: function() {
7047 if(module.is.searchSelection()) {
7048 // prevent menu hiding on immediate re-focus
7049 willRefocus = false;
7050 }
7051 else {
7052 activated = false;
7053 }
7054 },
7055 click: function(event) {
7056 var
7057 $target = $(event.target)
7058 ;
7059 // focus search
7060 if($target.is($module)) {
7061 if(!module.is.focusedOnSearch()) {
7062 module.focusSearch();
7063 }
7064 else {
7065 module.show();
7066 }
7067 }
7068 },
7069 search: {
7070 focus: function(event) {
7071 activated = true;
7072 if(module.is.multiple()) {
7073 module.remove.activeLabel();
7074 }
7075 if(settings.showOnFocus || (event.type !== 'focus' && event.type !== 'focusin')) {
7076 module.search();
7077 }
7078 },
7079 blur: function(event) {
7080 pageLostFocus = (document.activeElement === this);
7081 if(module.is.searchSelection() && !willRefocus) {
7082 if(!itemActivated && !pageLostFocus) {
7083 if(settings.forceSelection) {
7084 module.forceSelection();
7085 }
7086 module.hide();
7087 }
7088 }
7089 willRefocus = false;
7090 }
7091 },
7092 clearIcon: {
7093 click: function(event) {
7094 module.clear();
7095 if(module.is.searchSelection()) {
7096 module.remove.searchTerm();
7097 }
7098 module.hide();
7099 event.stopPropagation();
7100 }
7101 },
7102 icon: {
7103 click: function(event) {
7104 iconClicked=true;
7105 if(module.has.search()) {
7106 if(!module.is.active()) {
7107 if(settings.showOnFocus){
7108 module.focusSearch();
7109 } else {
7110 module.toggle();
7111 }
7112 } else {
7113 module.blurSearch();
7114 }
7115 } else {
7116 module.toggle();
7117 }
7118 }
7119 },
7120 text: {
7121 focus: function(event) {
7122 activated = true;
7123 module.focusSearch();
7124 }
7125 },
7126 input: function(event) {
7127 if(module.is.multiple() || module.is.searchSelection()) {
7128 module.set.filtered();
7129 }
7130 clearTimeout(module.timer);
7131 module.timer = setTimeout(module.search, settings.delay.search);
7132 },
7133 label: {
7134 click: function(event) {
7135 var
7136 $label = $(this),
7137 $labels = $module.find(selector.label),
7138 $activeLabels = $labels.filter('.' + className.active),
7139 $nextActive = $label.nextAll('.' + className.active),
7140 $prevActive = $label.prevAll('.' + className.active),
7141 $range = ($nextActive.length > 0)
7142 ? $label.nextUntil($nextActive).add($activeLabels).add($label)
7143 : $label.prevUntil($prevActive).add($activeLabels).add($label)
7144 ;
7145 if(event.shiftKey) {
7146 $activeLabels.removeClass(className.active);
7147 $range.addClass(className.active);
7148 }
7149 else if(event.ctrlKey) {
7150 $label.toggleClass(className.active);
7151 }
7152 else {
7153 $activeLabels.removeClass(className.active);
7154 $label.addClass(className.active);
7155 }
7156 settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
7157 }
7158 },
7159 remove: {
7160 click: function() {
7161 var
7162 $label = $(this).parent()
7163 ;
7164 if( $label.hasClass(className.active) ) {
7165 // remove all selected labels
7166 module.remove.activeLabels();
7167 }
7168 else {
7169 // remove this label only
7170 module.remove.activeLabels( $label );
7171 }
7172 }
7173 },
7174 test: {
7175 toggle: function(event) {
7176 var
7177 toggleBehavior = (module.is.multiple())
7178 ? module.show
7179 : module.toggle
7180 ;
7181 if(module.is.bubbledLabelClick(event) || module.is.bubbledIconClick(event)) {
7182 return;
7183 }
7184 if( module.determine.eventOnElement(event, toggleBehavior) ) {
7185 event.preventDefault();
7186 }
7187 },
7188 touch: function(event) {
7189 module.determine.eventOnElement(event, function() {
7190 if(event.type == 'touchstart') {
7191 module.timer = setTimeout(function() {
7192 module.hide();
7193 }, settings.delay.touch);
7194 }
7195 else if(event.type == 'touchmove') {
7196 clearTimeout(module.timer);
7197 }
7198 });
7199 event.stopPropagation();
7200 },
7201 hide: function(event) {
7202 if(module.determine.eventInModule(event, module.hide)){
7203 event.preventDefault();
7204 }
7205 }
7206 },
7207 select: {
7208 mutation: function(mutations) {
7209 module.debug('<select> modified, recreating menu');
7210 if(module.is.selectMutation(mutations)) {
7211 module.disconnect.selectObserver();
7212 module.refresh();
7213 module.setup.select();
7214 module.set.selected();
7215 module.observe.select();
7216 }
7217 }
7218 },
7219 menu: {
7220 mutation: function(mutations) {
7221 var
7222 mutation = mutations[0],
7223 $addedNode = mutation.addedNodes
7224 ? $(mutation.addedNodes[0])
7225 : $(false),
7226 $removedNode = mutation.removedNodes
7227 ? $(mutation.removedNodes[0])
7228 : $(false),
7229 $changedNodes = $addedNode.add($removedNode),
7230 isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
7231 isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
7232 ;
7233 if(isUserAddition || isMessage) {
7234 module.debug('Updating item selector cache');
7235 module.refreshItems();
7236 }
7237 else {
7238 module.debug('Menu modified, updating selector cache');
7239 module.refresh();
7240 }
7241 },
7242 mousedown: function() {
7243 itemActivated = true;
7244 },
7245 mouseup: function() {
7246 itemActivated = false;
7247 }
7248 },
7249 item: {
7250 mouseenter: function(event) {
7251 var
7252 $target = $(event.target),
7253 $item = $(this),
7254 $subMenu = $item.children(selector.menu),
7255 $otherMenus = $item.siblings(selector.item).children(selector.menu),
7256 hasSubMenu = ($subMenu.length > 0),
7257 isBubbledEvent = ($subMenu.find($target).length > 0)
7258 ;
7259 if( !isBubbledEvent && hasSubMenu ) {
7260 clearTimeout(module.itemTimer);
7261 module.itemTimer = setTimeout(function() {
7262 module.verbose('Showing sub-menu', $subMenu);
7263 $.each($otherMenus, function() {
7264 module.animate.hide(false, $(this));
7265 });
7266 module.animate.show(false, $subMenu);
7267 }, settings.delay.show);
7268 event.preventDefault();
7269 }
7270 },
7271 mouseleave: function(event) {
7272 var
7273 $subMenu = $(this).children(selector.menu)
7274 ;
7275 if($subMenu.length > 0) {
7276 clearTimeout(module.itemTimer);
7277 module.itemTimer = setTimeout(function() {
7278 module.verbose('Hiding sub-menu', $subMenu);
7279 module.animate.hide(false, $subMenu);
7280 }, settings.delay.hide);
7281 }
7282 },
7283 click: function (event, skipRefocus) {
7284 var
7285 $choice = $(this),
7286 $target = (event)
7287 ? $(event.target)
7288 : $(''),
7289 $subMenu = $choice.find(selector.menu),
7290 text = module.get.choiceText($choice),
7291 value = module.get.choiceValue($choice, text),
7292 hasSubMenu = ($subMenu.length > 0),
7293 isBubbledEvent = ($subMenu.find($target).length > 0)
7294 ;
7295 // prevents IE11 bug where menu receives focus even though `tabindex=-1`
7296 if (!module.has.search() || !document.activeElement.isEqualNode($search[0])) {
7297 $(document.activeElement).blur();
7298 }
7299 if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
7300 if(module.is.searchSelection()) {
7301 if(settings.allowAdditions) {
7302 module.remove.userAddition();
7303 }
7304 module.remove.searchTerm();
7305 if(!module.is.focusedOnSearch() && !(skipRefocus == true)) {
7306 module.focusSearch(true);
7307 }
7308 }
7309 if(!settings.useLabels) {
7310 module.remove.filteredItem();
7311 module.set.scrollPosition($choice);
7312 }
7313 module.determine.selectAction.call(this, text, value);
7314 }
7315 }
7316 },
7317
7318 document: {
7319 // label selection should occur even when element has no focus
7320 keydown: function(event) {
7321 var
7322 pressedKey = event.which,
7323 isShortcutKey = module.is.inObject(pressedKey, keys)
7324 ;
7325 if(isShortcutKey) {
7326 var
7327 $label = $module.find(selector.label),
7328 $activeLabel = $label.filter('.' + className.active),
7329 activeValue = $activeLabel.data(metadata.value),
7330 labelIndex = $label.index($activeLabel),
7331 labelCount = $label.length,
7332 hasActiveLabel = ($activeLabel.length > 0),
7333 hasMultipleActive = ($activeLabel.length > 1),
7334 isFirstLabel = (labelIndex === 0),
7335 isLastLabel = (labelIndex + 1 == labelCount),
7336 isSearch = module.is.searchSelection(),
7337 isFocusedOnSearch = module.is.focusedOnSearch(),
7338 isFocused = module.is.focused(),
7339 caretAtStart = (isFocusedOnSearch && module.get.caretPosition(false) === 0),
7340 isSelectedSearch = (caretAtStart && module.get.caretPosition(true) !== 0),
7341 $nextLabel
7342 ;
7343 if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
7344 return;
7345 }
7346
7347 if(pressedKey == keys.leftArrow) {
7348 // activate previous label
7349 if((isFocused || caretAtStart) && !hasActiveLabel) {
7350 module.verbose('Selecting previous label');
7351 $label.last().addClass(className.active);
7352 }
7353 else if(hasActiveLabel) {
7354 if(!event.shiftKey) {
7355 module.verbose('Selecting previous label');
7356 $label.removeClass(className.active);
7357 }
7358 else {
7359 module.verbose('Adding previous label to selection');
7360 }
7361 if(isFirstLabel && !hasMultipleActive) {
7362 $activeLabel.addClass(className.active);
7363 }
7364 else {
7365 $activeLabel.prev(selector.siblingLabel)
7366 .addClass(className.active)
7367 .end()
7368 ;
7369 }
7370 event.preventDefault();
7371 }
7372 }
7373 else if(pressedKey == keys.rightArrow) {
7374 // activate first label
7375 if(isFocused && !hasActiveLabel) {
7376 $label.first().addClass(className.active);
7377 }
7378 // activate next label
7379 if(hasActiveLabel) {
7380 if(!event.shiftKey) {
7381 module.verbose('Selecting next label');
7382 $label.removeClass(className.active);
7383 }
7384 else {
7385 module.verbose('Adding next label to selection');
7386 }
7387 if(isLastLabel) {
7388 if(isSearch) {
7389 if(!isFocusedOnSearch) {
7390 module.focusSearch();
7391 }
7392 else {
7393 $label.removeClass(className.active);
7394 }
7395 }
7396 else if(hasMultipleActive) {
7397 $activeLabel.next(selector.siblingLabel).addClass(className.active);
7398 }
7399 else {
7400 $activeLabel.addClass(className.active);
7401 }
7402 }
7403 else {
7404 $activeLabel.next(selector.siblingLabel).addClass(className.active);
7405 }
7406 event.preventDefault();
7407 }
7408 }
7409 else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
7410 if(hasActiveLabel) {
7411 module.verbose('Removing active labels');
7412 if(isLastLabel) {
7413 if(isSearch && !isFocusedOnSearch) {
7414 module.focusSearch();
7415 }
7416 }
7417 $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
7418 module.remove.activeLabels($activeLabel);
7419 event.preventDefault();
7420 }
7421 else if(caretAtStart && !isSelectedSearch && !hasActiveLabel && pressedKey == keys.backspace) {
7422 module.verbose('Removing last label on input backspace');
7423 $activeLabel = $label.last().addClass(className.active);
7424 module.remove.activeLabels($activeLabel);
7425 }
7426 }
7427 else {
7428 $activeLabel.removeClass(className.active);
7429 }
7430 }
7431 }
7432 },
7433
7434 keydown: function(event) {
7435 var
7436 pressedKey = event.which,
7437 isShortcutKey = module.is.inObject(pressedKey, keys)
7438 ;
7439 if(isShortcutKey) {
7440 var
7441 $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
7442 $activeItem = $menu.children('.' + className.active).eq(0),
7443 $selectedItem = ($currentlySelected.length > 0)
7444 ? $currentlySelected
7445 : $activeItem,
7446 $visibleItems = ($selectedItem.length > 0)
7447 ? $selectedItem.siblings(':not(.' + className.filtered +')').addBack()
7448 : $menu.children(':not(.' + className.filtered +')'),
7449 $subMenu = $selectedItem.children(selector.menu),
7450 $parentMenu = $selectedItem.closest(selector.menu),
7451 inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
7452 hasSubMenu = ($subMenu.length> 0),
7453 hasSelectedItem = ($selectedItem.length > 0),
7454 selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
7455 delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
7456 isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable),
7457 $nextItem,
7458 isSubMenuItem,
7459 newIndex
7460 ;
7461 // allow selection with menu closed
7462 if(isAdditionWithoutMenu) {
7463 module.verbose('Selecting item from keyboard shortcut', $selectedItem);
7464 module.event.item.click.call($selectedItem, event);
7465 if(module.is.searchSelection()) {
7466 module.remove.searchTerm();
7467 }
7468 if(module.is.multiple()){
7469 event.preventDefault();
7470 }
7471 }
7472
7473 // visible menu keyboard shortcuts
7474 if( module.is.visible() ) {
7475
7476 // enter (select or open sub-menu)
7477 if(pressedKey == keys.enter || delimiterPressed) {
7478 if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
7479 module.verbose('Pressed enter on unselectable category, opening sub menu');
7480 pressedKey = keys.rightArrow;
7481 }
7482 else if(selectedIsSelectable) {
7483 module.verbose('Selecting item from keyboard shortcut', $selectedItem);
7484 module.event.item.click.call($selectedItem, event);
7485 if(module.is.searchSelection()) {
7486 module.remove.searchTerm();
7487 if(module.is.multiple()) {
7488 $search.focus();
7489 }
7490 }
7491 }
7492 event.preventDefault();
7493 }
7494
7495 // sub-menu actions
7496 if(hasSelectedItem) {
7497
7498 if(pressedKey == keys.leftArrow) {
7499
7500 isSubMenuItem = ($parentMenu[0] !== $menu[0]);
7501
7502 if(isSubMenuItem) {
7503 module.verbose('Left key pressed, closing sub-menu');
7504 module.animate.hide(false, $parentMenu);
7505 $selectedItem
7506 .removeClass(className.selected)
7507 ;
7508 $parentMenu
7509 .closest(selector.item)
7510 .addClass(className.selected)
7511 ;
7512 event.preventDefault();
7513 }
7514 }
7515
7516 // right arrow (show sub-menu)
7517 if(pressedKey == keys.rightArrow) {
7518 if(hasSubMenu) {
7519 module.verbose('Right key pressed, opening sub-menu');
7520 module.animate.show(false, $subMenu);
7521 $selectedItem
7522 .removeClass(className.selected)
7523 ;
7524 $subMenu
7525 .find(selector.item).eq(0)
7526 .addClass(className.selected)
7527 ;
7528 event.preventDefault();
7529 }
7530 }
7531 }
7532
7533 // up arrow (traverse menu up)
7534 if(pressedKey == keys.upArrow) {
7535 $nextItem = (hasSelectedItem && inVisibleMenu)
7536 ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
7537 : $item.eq(0)
7538 ;
7539 if($visibleItems.index( $nextItem ) < 0) {
7540 module.verbose('Up key pressed but reached top of current menu');
7541 event.preventDefault();
7542 return;
7543 }
7544 else {
7545 module.verbose('Up key pressed, changing active item');
7546 $selectedItem
7547 .removeClass(className.selected)
7548 ;
7549 $nextItem
7550 .addClass(className.selected)
7551 ;
7552 module.set.scrollPosition($nextItem);
7553 if(settings.selectOnKeydown && module.is.single()) {
7554 module.set.selectedItem($nextItem);
7555 }
7556 }
7557 event.preventDefault();
7558 }
7559
7560 // down arrow (traverse menu down)
7561 if(pressedKey == keys.downArrow) {
7562 $nextItem = (hasSelectedItem && inVisibleMenu)
7563 ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
7564 : $item.eq(0)
7565 ;
7566 if($nextItem.length === 0) {
7567 module.verbose('Down key pressed but reached bottom of current menu');
7568 event.preventDefault();
7569 return;
7570 }
7571 else {
7572 module.verbose('Down key pressed, changing active item');
7573 $item
7574 .removeClass(className.selected)
7575 ;
7576 $nextItem
7577 .addClass(className.selected)
7578 ;
7579 module.set.scrollPosition($nextItem);
7580 if(settings.selectOnKeydown && module.is.single()) {
7581 module.set.selectedItem($nextItem);
7582 }
7583 }
7584 event.preventDefault();
7585 }
7586
7587 // page down (show next page)
7588 if(pressedKey == keys.pageUp) {
7589 module.scrollPage('up');
7590 event.preventDefault();
7591 }
7592 if(pressedKey == keys.pageDown) {
7593 module.scrollPage('down');
7594 event.preventDefault();
7595 }
7596
7597 // escape (close menu)
7598 if(pressedKey == keys.escape) {
7599 module.verbose('Escape key pressed, closing dropdown');
7600 module.hide();
7601 }
7602
7603 }
7604 else {
7605 // delimiter key
7606 if(delimiterPressed) {
7607 event.preventDefault();
7608 }
7609 // down arrow (open menu)
7610 if(pressedKey == keys.downArrow && !module.is.visible()) {
7611 module.verbose('Down key pressed, showing dropdown');
7612 module.show();
7613 event.preventDefault();
7614 }
7615 }
7616 }
7617 else {
7618 if( !module.has.search() ) {
7619 module.set.selectedLetter( String.fromCharCode(pressedKey) );
7620 }
7621 }
7622 }
7623 },
7624
7625 trigger: {
7626 change: function() {
7627 var
7628 events = document.createEvent('HTMLEvents'),
7629 inputElement = $input[0]
7630 ;
7631 if(inputElement) {
7632 module.verbose('Triggering native change event');
7633 events.initEvent('change', true, false);
7634 inputElement.dispatchEvent(events);
7635 }
7636 }
7637 },
7638
7639 determine: {
7640 selectAction: function(text, value) {
7641 module.verbose('Determining action', settings.action);
7642 if( $.isFunction( module.action[settings.action] ) ) {
7643 module.verbose('Triggering preset action', settings.action, text, value);
7644 module.action[ settings.action ].call(element, text, value, this);
7645 }
7646 else if( $.isFunction(settings.action) ) {
7647 module.verbose('Triggering user action', settings.action, text, value);
7648 settings.action.call(element, text, value, this);
7649 }
7650 else {
7651 module.error(error.action, settings.action);
7652 }
7653 },
7654 eventInModule: function(event, callback) {
7655 var
7656 $target = $(event.target),
7657 inDocument = ($target.closest(document.documentElement).length > 0),
7658 inModule = ($target.closest($module).length > 0)
7659 ;
7660 callback = $.isFunction(callback)
7661 ? callback
7662 : function(){}
7663 ;
7664 if(inDocument && !inModule) {
7665 module.verbose('Triggering event', callback);
7666 callback();
7667 return true;
7668 }
7669 else {
7670 module.verbose('Event occurred in dropdown, canceling callback');
7671 return false;
7672 }
7673 },
7674 eventOnElement: function(event, callback) {
7675 var
7676 $target = $(event.target),
7677 $label = $target.closest(selector.siblingLabel),
7678 inVisibleDOM = document.body.contains(event.target),
7679 notOnLabel = ($module.find($label).length === 0 || !(module.is.multiple() && settings.useLabels)),
7680 notInMenu = ($target.closest($menu).length === 0)
7681 ;
7682 callback = $.isFunction(callback)
7683 ? callback
7684 : function(){}
7685 ;
7686 if(inVisibleDOM && notOnLabel && notInMenu) {
7687 module.verbose('Triggering event', callback);
7688 callback();
7689 return true;
7690 }
7691 else {
7692 module.verbose('Event occurred in dropdown menu, canceling callback');
7693 return false;
7694 }
7695 }
7696 },
7697
7698 action: {
7699
7700 nothing: function() {},
7701
7702 activate: function(text, value, element) {
7703 value = (value !== undefined)
7704 ? value
7705 : text
7706 ;
7707 if( module.can.activate( $(element) ) ) {
7708 module.set.selected(value, $(element));
7709 if(!module.is.multiple()) {
7710 module.hideAndClear();
7711 }
7712 }
7713 },
7714
7715 select: function(text, value, element) {
7716 value = (value !== undefined)
7717 ? value
7718 : text
7719 ;
7720 if( module.can.activate( $(element) ) ) {
7721 module.set.value(value, text, $(element));
7722 if(!module.is.multiple()) {
7723 module.hideAndClear();
7724 }
7725 }
7726 },
7727
7728 combo: function(text, value, element) {
7729 value = (value !== undefined)
7730 ? value
7731 : text
7732 ;
7733 module.set.selected(value, $(element));
7734 module.hideAndClear();
7735 },
7736
7737 hide: function(text, value, element) {
7738 module.set.value(value, text, $(element));
7739 module.hideAndClear();
7740 }
7741
7742 },
7743
7744 get: {
7745 id: function() {
7746 return id;
7747 },
7748 defaultText: function() {
7749 return $module.data(metadata.defaultText);
7750 },
7751 defaultValue: function() {
7752 return $module.data(metadata.defaultValue);
7753 },
7754 placeholderText: function() {
7755 if(settings.placeholder != 'auto' && typeof settings.placeholder == 'string') {
7756 return settings.placeholder;
7757 }
7758 return $module.data(metadata.placeholderText) || '';
7759 },
7760 text: function() {
7761 return $text.text();
7762 },
7763 query: function() {
7764 return $.trim($search.val());
7765 },
7766 searchWidth: function(value) {
7767 value = (value !== undefined)
7768 ? value
7769 : $search.val()
7770 ;
7771 $sizer.text(value);
7772 // prevent rounding issues
7773 return Math.ceil( $sizer.width() + 1);
7774 },
7775 selectionCount: function() {
7776 var
7777 values = module.get.values(),
7778 count
7779 ;
7780 count = ( module.is.multiple() )
7781 ? Array.isArray(values)
7782 ? values.length
7783 : 0
7784 : (module.get.value() !== '')
7785 ? 1
7786 : 0
7787 ;
7788 return count;
7789 },
7790 transition: function($subMenu) {
7791 return (settings.transition == 'auto')
7792 ? module.is.upward($subMenu)
7793 ? 'slide up'
7794 : 'slide down'
7795 : settings.transition
7796 ;
7797 },
7798 userValues: function() {
7799 var
7800 values = module.get.values()
7801 ;
7802 if(!values) {
7803 return false;
7804 }
7805 values = Array.isArray(values)
7806 ? values
7807 : [values]
7808 ;
7809 return $.grep(values, function(value) {
7810 return (module.get.item(value) === false);
7811 });
7812 },
7813 uniqueArray: function(array) {
7814 return $.grep(array, function (value, index) {
7815 return $.inArray(value, array) === index;
7816 });
7817 },
7818 caretPosition: function(returnEndPos) {
7819 var
7820 input = $search.get(0),
7821 range,
7822 rangeLength
7823 ;
7824 if(returnEndPos && 'selectionEnd' in input){
7825 return input.selectionEnd;
7826 }
7827 else if(!returnEndPos && 'selectionStart' in input) {
7828 return input.selectionStart;
7829 }
7830 if (document.selection) {
7831 input.focus();
7832 range = document.selection.createRange();
7833 rangeLength = range.text.length;
7834 if(returnEndPos) {
7835 return rangeLength;
7836 }
7837 range.moveStart('character', -input.value.length);
7838 return range.text.length - rangeLength;
7839 }
7840 },
7841 value: function() {
7842 var
7843 value = ($input.length > 0)
7844 ? $input.val()
7845 : $module.data(metadata.value),
7846 isEmptyMultiselect = (Array.isArray(value) && value.length === 1 && value[0] === '')
7847 ;
7848 // prevents placeholder element from being selected when multiple
7849 return (value === undefined || isEmptyMultiselect)
7850 ? ''
7851 : value
7852 ;
7853 },
7854 values: function() {
7855 var
7856 value = module.get.value()
7857 ;
7858 if(value === '') {
7859 return '';
7860 }
7861 return ( !module.has.selectInput() && module.is.multiple() )
7862 ? (typeof value == 'string') // delimited string
7863 ? value.split(settings.delimiter)
7864 : ''
7865 : value
7866 ;
7867 },
7868 remoteValues: function() {
7869 var
7870 values = module.get.values(),
7871 remoteValues = false
7872 ;
7873 if(values) {
7874 if(typeof values == 'string') {
7875 values = [values];
7876 }
7877 $.each(values, function(index, value) {
7878 var
7879 name = module.read.remoteData(value)
7880 ;
7881 module.verbose('Restoring value from session data', name, value);
7882 if(name) {
7883 if(!remoteValues) {
7884 remoteValues = {};
7885 }
7886 remoteValues[value] = name;
7887 }
7888 });
7889 }
7890 return remoteValues;
7891 },
7892 choiceText: function($choice, preserveHTML) {
7893 preserveHTML = (preserveHTML !== undefined)
7894 ? preserveHTML
7895 : settings.preserveHTML
7896 ;
7897 if($choice) {
7898 if($choice.find(selector.menu).length > 0) {
7899 module.verbose('Retrieving text of element with sub-menu');
7900 $choice = $choice.clone();
7901 $choice.find(selector.menu).remove();
7902 $choice.find(selector.menuIcon).remove();
7903 }
7904 return ($choice.data(metadata.text) !== undefined)
7905 ? $choice.data(metadata.text)
7906 : (preserveHTML)
7907 ? $.trim($choice.html())
7908 : $.trim($choice.text())
7909 ;
7910 }
7911 },
7912 choiceValue: function($choice, choiceText) {
7913 choiceText = choiceText || module.get.choiceText($choice);
7914 if(!$choice) {
7915 return false;
7916 }
7917 return ($choice.data(metadata.value) !== undefined)
7918 ? String( $choice.data(metadata.value) )
7919 : (typeof choiceText === 'string')
7920 ? $.trim(choiceText.toLowerCase())
7921 : String(choiceText)
7922 ;
7923 },
7924 inputEvent: function() {
7925 var
7926 input = $search[0]
7927 ;
7928 if(input) {
7929 return (input.oninput !== undefined)
7930 ? 'input'
7931 : (input.onpropertychange !== undefined)
7932 ? 'propertychange'
7933 : 'keyup'
7934 ;
7935 }
7936 return false;
7937 },
7938 selectValues: function() {
7939 var
7940 select = {}
7941 ;
7942 select.values = [];
7943 $module
7944 .find('option')
7945 .each(function() {
7946 var
7947 $option = $(this),
7948 name = $option.html(),
7949 disabled = $option.attr('disabled'),
7950 value = ( $option.attr('value') !== undefined )
7951 ? $option.attr('value')
7952 : name
7953 ;
7954 if(settings.placeholder === 'auto' && value === '') {
7955 select.placeholder = name;
7956 }
7957 else {
7958 select.values.push({
7959 name : name,
7960 value : value,
7961 disabled : disabled
7962 });
7963 }
7964 })
7965 ;
7966 if(settings.placeholder && settings.placeholder !== 'auto') {
7967 module.debug('Setting placeholder value to', settings.placeholder);
7968 select.placeholder = settings.placeholder;
7969 }
7970 if(settings.sortSelect) {
7971 if(settings.sortSelect === true) {
7972 select.values.sort(function(a, b) {
7973 return a.name.localeCompare(b.name);
7974 });
7975 } else if(settings.sortSelect === 'natural') {
7976 select.values.sort(function(a, b) {
7977 return (a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
7978 });
7979 } else if($.isFunction(settings.sortSelect)) {
7980 select.values.sort(settings.sortSelect);
7981 }
7982 module.debug('Retrieved and sorted values from select', select);
7983 }
7984 else {
7985 module.debug('Retrieved values from select', select);
7986 }
7987 return select;
7988 },
7989 activeItem: function() {
7990 return $item.filter('.' + className.active);
7991 },
7992 selectedItem: function() {
7993 var
7994 $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
7995 ;
7996 return ($selectedItem.length > 0)
7997 ? $selectedItem
7998 : $item.eq(0)
7999 ;
8000 },
8001 itemWithAdditions: function(value) {
8002 var
8003 $items = module.get.item(value),
8004 $userItems = module.create.userChoice(value),
8005 hasUserItems = ($userItems && $userItems.length > 0)
8006 ;
8007 if(hasUserItems) {
8008 $items = ($items.length > 0)
8009 ? $items.add($userItems)
8010 : $userItems
8011 ;
8012 }
8013 return $items;
8014 },
8015 item: function(value, strict) {
8016 var
8017 $selectedItem = false,
8018 shouldSearch,
8019 isMultiple
8020 ;
8021 value = (value !== undefined)
8022 ? value
8023 : ( module.get.values() !== undefined)
8024 ? module.get.values()
8025 : module.get.text()
8026 ;
8027 shouldSearch = (isMultiple)
8028 ? (value.length > 0)
8029 : (value !== undefined && value !== null)
8030 ;
8031 isMultiple = (module.is.multiple() && Array.isArray(value));
8032 strict = (value === '' || value === false || value === true)
8033 ? true
8034 : strict || false
8035 ;
8036 if(shouldSearch) {
8037 $item
8038 .each(function() {
8039 var
8040 $choice = $(this),
8041 optionText = module.get.choiceText($choice),
8042 optionValue = module.get.choiceValue($choice, optionText)
8043 ;
8044 // safe early exit
8045 if(optionValue === null || optionValue === undefined) {
8046 return;
8047 }
8048 if(isMultiple) {
8049 if($.inArray( String(optionValue), value) !== -1) {
8050 $selectedItem = ($selectedItem)
8051 ? $selectedItem.add($choice)
8052 : $choice
8053 ;
8054 }
8055 }
8056 else if(strict) {
8057 module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
8058 if( optionValue === value) {
8059 $selectedItem = $choice;
8060 return true;
8061 }
8062 }
8063 else {
8064 if( String(optionValue) == String(value)) {
8065 module.verbose('Found select item by value', optionValue, value);
8066 $selectedItem = $choice;
8067 return true;
8068 }
8069 }
8070 })
8071 ;
8072 }
8073 return $selectedItem;
8074 }
8075 },
8076
8077 check: {
8078 maxSelections: function(selectionCount) {
8079 if(settings.maxSelections) {
8080 selectionCount = (selectionCount !== undefined)
8081 ? selectionCount
8082 : module.get.selectionCount()
8083 ;
8084 if(selectionCount >= settings.maxSelections) {
8085 module.debug('Maximum selection count reached');
8086 if(settings.useLabels) {
8087 $item.addClass(className.filtered);
8088 module.add.message(message.maxSelections);
8089 }
8090 return true;
8091 }
8092 else {
8093 module.verbose('No longer at maximum selection count');
8094 module.remove.message();
8095 module.remove.filteredItem();
8096 if(module.is.searchSelection()) {
8097 module.filterItems();
8098 }
8099 return false;
8100 }
8101 }
8102 return true;
8103 }
8104 },
8105
8106 restore: {
8107 defaults: function() {
8108 module.clear();
8109 module.restore.defaultText();
8110 module.restore.defaultValue();
8111 },
8112 defaultText: function() {
8113 var
8114 defaultText = module.get.defaultText(),
8115 placeholderText = module.get.placeholderText
8116 ;
8117 if(defaultText === placeholderText) {
8118 module.debug('Restoring default placeholder text', defaultText);
8119 module.set.placeholderText(defaultText);
8120 }
8121 else {
8122 module.debug('Restoring default text', defaultText);
8123 module.set.text(defaultText);
8124 }
8125 },
8126 placeholderText: function() {
8127 module.set.placeholderText();
8128 },
8129 defaultValue: function() {
8130 var
8131 defaultValue = module.get.defaultValue()
8132 ;
8133 if(defaultValue !== undefined) {
8134 module.debug('Restoring default value', defaultValue);
8135 if(defaultValue !== '') {
8136 module.set.value(defaultValue);
8137 module.set.selected();
8138 }
8139 else {
8140 module.remove.activeItem();
8141 module.remove.selectedItem();
8142 }
8143 }
8144 },
8145 labels: function() {
8146 if(settings.allowAdditions) {
8147 if(!settings.useLabels) {
8148 module.error(error.labels);
8149 settings.useLabels = true;
8150 }
8151 module.debug('Restoring selected values');
8152 module.create.userLabels();
8153 }
8154 module.check.maxSelections();
8155 },
8156 selected: function() {
8157 module.restore.values();
8158 if(module.is.multiple()) {
8159 module.debug('Restoring previously selected values and labels');
8160 module.restore.labels();
8161 }
8162 else {
8163 module.debug('Restoring previously selected values');
8164 }
8165 },
8166 values: function() {
8167 // prevents callbacks from occurring on initial load
8168 module.set.initialLoad();
8169 if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) {
8170 module.restore.remoteValues();
8171 }
8172 else {
8173 module.set.selected();
8174 }
8175 if(module.get.item()) {
8176 $input.removeClass(className.noselection);
8177 } else {
8178 $input.addClass(className.noselection);
8179 }
8180 module.remove.initialLoad();
8181 },
8182 remoteValues: function() {
8183 var
8184 values = module.get.remoteValues()
8185 ;
8186 module.debug('Recreating selected from session data', values);
8187 if(values) {
8188 if( module.is.single() ) {
8189 $.each(values, function(value, name) {
8190 module.set.text(name);
8191 });
8192 }
8193 else {
8194 $.each(values, function(value, name) {
8195 module.add.label(value, name);
8196 });
8197 }
8198 }
8199 }
8200 },
8201
8202 read: {
8203 remoteData: function(value) {
8204 var
8205 name
8206 ;
8207 if(window.Storage === undefined) {
8208 module.error(error.noStorage);
8209 return;
8210 }
8211 name = sessionStorage.getItem(value);
8212 return (name !== undefined)
8213 ? name
8214 : false
8215 ;
8216 }
8217 },
8218
8219 save: {
8220 defaults: function() {
8221 module.save.defaultText();
8222 module.save.placeholderText();
8223 module.save.defaultValue();
8224 },
8225 defaultValue: function() {
8226 var
8227 value = module.get.value()
8228 ;
8229 module.verbose('Saving default value as', value);
8230 $module.data(metadata.defaultValue, value);
8231 },
8232 defaultText: function() {
8233 var
8234 text = module.get.text()
8235 ;
8236 module.verbose('Saving default text as', text);
8237 $module.data(metadata.defaultText, text);
8238 },
8239 placeholderText: function() {
8240 var
8241 text
8242 ;
8243 if(settings.placeholder !== false && $text.hasClass(className.placeholder)) {
8244 text = module.get.text();
8245 module.verbose('Saving placeholder text as', text);
8246 $module.data(metadata.placeholderText, text);
8247 }
8248 },
8249 remoteData: function(name, value) {
8250 if(window.Storage === undefined) {
8251 module.error(error.noStorage);
8252 return;
8253 }
8254 module.verbose('Saving remote data to session storage', value, name);
8255 sessionStorage.setItem(value, name);
8256 }
8257 },
8258
8259 clear: function() {
8260 if(module.is.multiple() && settings.useLabels) {
8261 module.remove.labels();
8262 }
8263 else {
8264 module.remove.activeItem();
8265 module.remove.selectedItem();
8266 module.remove.filteredItem();
8267 }
8268 module.set.placeholderText();
8269 module.clearValue();
8270 },
8271
8272 clearValue: function() {
8273 module.set.value('');
8274 },
8275
8276 scrollPage: function(direction, $selectedItem) {
8277 var
8278 $currentItem = $selectedItem || module.get.selectedItem(),
8279 $menu = $currentItem.closest(selector.menu),
8280 menuHeight = $menu.outerHeight(),
8281 currentScroll = $menu.scrollTop(),
8282 itemHeight = $item.eq(0).outerHeight(),
8283 itemsPerPage = Math.floor(menuHeight / itemHeight),
8284 maxScroll = $menu.prop('scrollHeight'),
8285 newScroll = (direction == 'up')
8286 ? currentScroll - (itemHeight * itemsPerPage)
8287 : currentScroll + (itemHeight * itemsPerPage),
8288 $selectableItem = $item.not(selector.unselectable),
8289 isWithinRange,
8290 $nextSelectedItem,
8291 elementIndex
8292 ;
8293 elementIndex = (direction == 'up')
8294 ? $selectableItem.index($currentItem) - itemsPerPage
8295 : $selectableItem.index($currentItem) + itemsPerPage
8296 ;
8297 isWithinRange = (direction == 'up')
8298 ? (elementIndex >= 0)
8299 : (elementIndex < $selectableItem.length)
8300 ;
8301 $nextSelectedItem = (isWithinRange)
8302 ? $selectableItem.eq(elementIndex)
8303 : (direction == 'up')
8304 ? $selectableItem.first()
8305 : $selectableItem.last()
8306 ;
8307 if($nextSelectedItem.length > 0) {
8308 module.debug('Scrolling page', direction, $nextSelectedItem);
8309 $currentItem
8310 .removeClass(className.selected)
8311 ;
8312 $nextSelectedItem
8313 .addClass(className.selected)
8314 ;
8315 if(settings.selectOnKeydown && module.is.single()) {
8316 module.set.selectedItem($nextSelectedItem);
8317 }
8318 $menu
8319 .scrollTop(newScroll)
8320 ;
8321 }
8322 },
8323
8324 set: {
8325 filtered: function() {
8326 var
8327 isMultiple = module.is.multiple(),
8328 isSearch = module.is.searchSelection(),
8329 isSearchMultiple = (isMultiple && isSearch),
8330 searchValue = (isSearch)
8331 ? module.get.query()
8332 : '',
8333 hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
8334 searchWidth = module.get.searchWidth(),
8335 valueIsSet = searchValue !== ''
8336 ;
8337 if(isMultiple && hasSearchValue) {
8338 module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
8339 $search.css('width', searchWidth);
8340 }
8341 if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
8342 module.verbose('Hiding placeholder text');
8343 $text.addClass(className.filtered);
8344 }
8345 else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
8346 module.verbose('Showing placeholder text');
8347 $text.removeClass(className.filtered);
8348 }
8349 },
8350 empty: function() {
8351 $module.addClass(className.empty);
8352 },
8353 loading: function() {
8354 $module.addClass(className.loading);
8355 },
8356 placeholderText: function(text) {
8357 text = text || module.get.placeholderText();
8358 module.debug('Setting placeholder text', text);
8359 module.set.text(text);
8360 $text.addClass(className.placeholder);
8361 },
8362 tabbable: function() {
8363 if( module.is.searchSelection() ) {
8364 module.debug('Added tabindex to searchable dropdown');
8365 $search
8366 .val('')
8367 .attr('tabindex', 0)
8368 ;
8369 $menu
8370 .attr('tabindex', -1)
8371 ;
8372 }
8373 else {
8374 module.debug('Added tabindex to dropdown');
8375 if( $module.attr('tabindex') === undefined) {
8376 $module
8377 .attr('tabindex', 0)
8378 ;
8379 $menu
8380 .attr('tabindex', -1)
8381 ;
8382 }
8383 }
8384 },
8385 initialLoad: function() {
8386 module.verbose('Setting initial load');
8387 initialLoad = true;
8388 },
8389 activeItem: function($item) {
8390 if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) {
8391 $item.addClass(className.filtered);
8392 }
8393 else {
8394 $item.addClass(className.active);
8395 }
8396 },
8397 partialSearch: function(text) {
8398 var
8399 length = module.get.query().length
8400 ;
8401 $search.val( text.substr(0, length));
8402 },
8403 scrollPosition: function($item, forceScroll) {
8404 var
8405 edgeTolerance = 5,
8406 $menu,
8407 hasActive,
8408 offset,
8409 itemHeight,
8410 itemOffset,
8411 menuOffset,
8412 menuScroll,
8413 menuHeight,
8414 abovePage,
8415 belowPage
8416 ;
8417
8418 $item = $item || module.get.selectedItem();
8419 $menu = $item.closest(selector.menu);
8420 hasActive = ($item && $item.length > 0);
8421 forceScroll = (forceScroll !== undefined)
8422 ? forceScroll
8423 : false
8424 ;
8425 if($item && $menu.length > 0 && hasActive) {
8426 itemOffset = $item.position().top;
8427
8428 $menu.addClass(className.loading);
8429 menuScroll = $menu.scrollTop();
8430 menuOffset = $menu.offset().top;
8431 itemOffset = $item.offset().top;
8432 offset = menuScroll - menuOffset + itemOffset;
8433 if(!forceScroll) {
8434 menuHeight = $menu.height();
8435 belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
8436 abovePage = ((offset - edgeTolerance) < menuScroll);
8437 }
8438 module.debug('Scrolling to active item', offset);
8439 if(forceScroll || abovePage || belowPage) {
8440 $menu.scrollTop(offset);
8441 }
8442 $menu.removeClass(className.loading);
8443 }
8444 },
8445 text: function(text) {
8446 if(settings.action === 'combo') {
8447 module.debug('Changing combo button text', text, $combo);
8448 if(settings.preserveHTML) {
8449 $combo.html(text);
8450 }
8451 else {
8452 $combo.text(text);
8453 }
8454 }
8455 else if(settings.action === 'activate') {
8456 if(text !== module.get.placeholderText()) {
8457 $text.removeClass(className.placeholder);
8458 }
8459 module.debug('Changing text', text, $text);
8460 $text
8461 .removeClass(className.filtered)
8462 ;
8463 if(settings.preserveHTML) {
8464 $text.html(text);
8465 }
8466 else {
8467 $text.text(text);
8468 }
8469 }
8470 },
8471 selectedItem: function($item) {
8472 var
8473 value = module.get.choiceValue($item),
8474 searchText = module.get.choiceText($item, false),
8475 text = module.get.choiceText($item, true)
8476 ;
8477 module.debug('Setting user selection to item', $item);
8478 module.remove.activeItem();
8479 module.set.partialSearch(searchText);
8480 module.set.activeItem($item);
8481 module.set.selected(value, $item);
8482 module.set.text(text);
8483 },
8484 selectedLetter: function(letter) {
8485 var
8486 $selectedItem = $item.filter('.' + className.selected),
8487 alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter),
8488 $nextValue = false,
8489 $nextItem
8490 ;
8491 // check next of same letter
8492 if(alreadySelectedLetter) {
8493 $nextItem = $selectedItem.nextAll($item).eq(0);
8494 if( module.has.firstLetter($nextItem, letter) ) {
8495 $nextValue = $nextItem;
8496 }
8497 }
8498 // check all values
8499 if(!$nextValue) {
8500 $item
8501 .each(function(){
8502 if(module.has.firstLetter($(this), letter)) {
8503 $nextValue = $(this);
8504 return false;
8505 }
8506 })
8507 ;
8508 }
8509 // set next value
8510 if($nextValue) {
8511 module.verbose('Scrolling to next value with letter', letter);
8512 module.set.scrollPosition($nextValue);
8513 $selectedItem.removeClass(className.selected);
8514 $nextValue.addClass(className.selected);
8515 if(settings.selectOnKeydown && module.is.single()) {
8516 module.set.selectedItem($nextValue);
8517 }
8518 }
8519 },
8520 direction: function($menu) {
8521 if(settings.direction == 'auto') {
8522 // reset position, remove upward if it's base menu
8523 if (!$menu) {
8524 module.remove.upward();
8525 } else if (module.is.upward($menu)) {
8526 //we need make sure when make assertion openDownward for $menu, $menu does not have upward class
8527 module.remove.upward($menu);
8528 }
8529
8530 if(module.can.openDownward($menu)) {
8531 module.remove.upward($menu);
8532 }
8533 else {
8534 module.set.upward($menu);
8535 }
8536 if(!module.is.leftward($menu) && !module.can.openRightward($menu)) {
8537 module.set.leftward($menu);
8538 }
8539 }
8540 else if(settings.direction == 'upward') {
8541 module.set.upward($menu);
8542 }
8543 },
8544 upward: function($currentMenu) {
8545 var $element = $currentMenu || $module;
8546 $element.addClass(className.upward);
8547 },
8548 leftward: function($currentMenu) {
8549 var $element = $currentMenu || $menu;
8550 $element.addClass(className.leftward);
8551 },
8552 value: function(value, text, $selected) {
8553 if(value !== undefined && value !== '' && !(Array.isArray(value) && value.length === 0)) {
8554 $input.removeClass(className.noselection);
8555 } else {
8556 $input.addClass(className.noselection);
8557 }
8558 var
8559 escapedValue = module.escape.value(value),
8560 hasInput = ($input.length > 0),
8561 currentValue = module.get.values(),
8562 stringValue = (value !== undefined)
8563 ? String(value)
8564 : value,
8565 newValue
8566 ;
8567 if(hasInput) {
8568 if(!settings.allowReselection && stringValue == currentValue) {
8569 module.verbose('Skipping value update already same value', value, currentValue);
8570 if(!module.is.initialLoad()) {
8571 return;
8572 }
8573 }
8574
8575 if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) {
8576 module.debug('Adding user option', value);
8577 module.add.optionValue(value);
8578 }
8579 module.debug('Updating input value', escapedValue, currentValue);
8580 internalChange = true;
8581 $input
8582 .val(escapedValue)
8583 ;
8584 if(settings.fireOnInit === false && module.is.initialLoad()) {
8585 module.debug('Input native change event ignored on initial load');
8586 }
8587 else {
8588 module.trigger.change();
8589 }
8590 internalChange = false;
8591 }
8592 else {
8593 module.verbose('Storing value in metadata', escapedValue, $input);
8594 if(escapedValue !== currentValue) {
8595 $module.data(metadata.value, stringValue);
8596 }
8597 }
8598 if(settings.fireOnInit === false && module.is.initialLoad()) {
8599 module.verbose('No callback on initial load', settings.onChange);
8600 }
8601 else {
8602 settings.onChange.call(element, value, text, $selected);
8603 }
8604 },
8605 active: function() {
8606 $module
8607 .addClass(className.active)
8608 ;
8609 },
8610 multiple: function() {
8611 $module.addClass(className.multiple);
8612 },
8613 visible: function() {
8614 $module.addClass(className.visible);
8615 },
8616 exactly: function(value, $selectedItem) {
8617 module.debug('Setting selected to exact values');
8618 module.clear();
8619 module.set.selected(value, $selectedItem);
8620 },
8621 selected: function(value, $selectedItem) {
8622 var
8623 isMultiple = module.is.multiple()
8624 ;
8625 $selectedItem = (settings.allowAdditions)
8626 ? $selectedItem || module.get.itemWithAdditions(value)
8627 : $selectedItem || module.get.item(value)
8628 ;
8629 if(!$selectedItem) {
8630 return;
8631 }
8632 module.debug('Setting selected menu item to', $selectedItem);
8633 if(module.is.multiple()) {
8634 module.remove.searchWidth();
8635 }
8636 if(module.is.single()) {
8637 module.remove.activeItem();
8638 module.remove.selectedItem();
8639 }
8640 else if(settings.useLabels) {
8641 module.remove.selectedItem();
8642 }
8643 // select each item
8644 $selectedItem
8645 .each(function() {
8646 var
8647 $selected = $(this),
8648 selectedText = module.get.choiceText($selected),
8649 selectedValue = module.get.choiceValue($selected, selectedText),
8650
8651 isFiltered = $selected.hasClass(className.filtered),
8652 isActive = $selected.hasClass(className.active),
8653 isUserValue = $selected.hasClass(className.addition),
8654 shouldAnimate = (isMultiple && $selectedItem.length == 1)
8655 ;
8656 if(isMultiple) {
8657 if(!isActive || isUserValue) {
8658 if(settings.apiSettings && settings.saveRemoteData) {
8659 module.save.remoteData(selectedText, selectedValue);
8660 }
8661 if(settings.useLabels) {
8662 module.add.label(selectedValue, selectedText, shouldAnimate);
8663 module.add.value(selectedValue, selectedText, $selected);
8664 module.set.activeItem($selected);
8665 module.filterActive();
8666 module.select.nextAvailable($selectedItem);
8667 }
8668 else {
8669 module.add.value(selectedValue, selectedText, $selected);
8670 module.set.text(module.add.variables(message.count));
8671 module.set.activeItem($selected);
8672 }
8673 }
8674 else if(!isFiltered) {
8675 module.debug('Selected active value, removing label');
8676 module.remove.selected(selectedValue);
8677 }
8678 }
8679 else {
8680 if(settings.apiSettings && settings.saveRemoteData) {
8681 module.save.remoteData(selectedText, selectedValue);
8682 }
8683 module.set.text(selectedText);
8684 module.set.value(selectedValue, selectedText, $selected);
8685 $selected
8686 .addClass(className.active)
8687 .addClass(className.selected)
8688 ;
8689 }
8690 })
8691 ;
8692 },
8693 },
8694
8695 add: {
8696 label: function(value, text, shouldAnimate) {
8697 var
8698 $next = module.is.searchSelection()
8699 ? $search
8700 : $text,
8701 escapedValue = module.escape.value(value),
8702 $label
8703 ;
8704 if(settings.ignoreCase) {
8705 escapedValue = escapedValue.toLowerCase();
8706 }
8707 $label = $('<a />')
8708 .addClass(className.label)
8709 .attr('data-' + metadata.value, escapedValue)
8710 .html(templates.label(escapedValue, text, settings.preserveHTML, settings.className))
8711 ;
8712 $label = settings.onLabelCreate.call($label, escapedValue, text);
8713
8714 if(module.has.label(value)) {
8715 module.debug('User selection already exists, skipping', escapedValue);
8716 return;
8717 }
8718 if(settings.label.variation) {
8719 $label.addClass(settings.label.variation);
8720 }
8721 if(shouldAnimate === true) {
8722 module.debug('Animating in label', $label);
8723 $label
8724 .addClass(className.hidden)
8725 .insertBefore($next)
8726 .transition(settings.label.transition, settings.label.duration)
8727 ;
8728 }
8729 else {
8730 module.debug('Adding selection label', $label);
8731 $label
8732 .insertBefore($next)
8733 ;
8734 }
8735 },
8736 message: function(message) {
8737 var
8738 $message = $menu.children(selector.message),
8739 html = settings.templates.message(module.add.variables(message))
8740 ;
8741 if($message.length > 0) {
8742 $message
8743 .html(html)
8744 ;
8745 }
8746 else {
8747 $message = $('<div/>')
8748 .html(html)
8749 .addClass(className.message)
8750 .appendTo($menu)
8751 ;
8752 }
8753 },
8754 optionValue: function(value) {
8755 var
8756 escapedValue = module.escape.value(value),
8757 $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
8758 hasOption = ($option.length > 0)
8759 ;
8760 if(hasOption) {
8761 return;
8762 }
8763 // temporarily disconnect observer
8764 module.disconnect.selectObserver();
8765 if( module.is.single() ) {
8766 module.verbose('Removing previous user addition');
8767 $input.find('option.' + className.addition).remove();
8768 }
8769 $('<option/>')
8770 .prop('value', escapedValue)
8771 .addClass(className.addition)
8772 .html(value)
8773 .appendTo($input)
8774 ;
8775 module.verbose('Adding user addition as an <option>', value);
8776 module.observe.select();
8777 },
8778 userSuggestion: function(value) {
8779 var
8780 $addition = $menu.children(selector.addition),
8781 $existingItem = module.get.item(value),
8782 alreadyHasValue = $existingItem && $existingItem.not(selector.addition).length,
8783 hasUserSuggestion = $addition.length > 0,
8784 html
8785 ;
8786 if(settings.useLabels && module.has.maxSelections()) {
8787 return;
8788 }
8789 if(value === '' || alreadyHasValue) {
8790 $addition.remove();
8791 return;
8792 }
8793 if(hasUserSuggestion) {
8794 $addition
8795 .data(metadata.value, value)
8796 .data(metadata.text, value)
8797 .attr('data-' + metadata.value, value)
8798 .attr('data-' + metadata.text, value)
8799 .removeClass(className.filtered)
8800 ;
8801 if(!settings.hideAdditions) {
8802 html = settings.templates.addition( module.add.variables(message.addResult, value) );
8803 $addition
8804 .html(html)
8805 ;
8806 }
8807 module.verbose('Replacing user suggestion with new value', $addition);
8808 }
8809 else {
8810 $addition = module.create.userChoice(value);
8811 $addition
8812 .prependTo($menu)
8813 ;
8814 module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
8815 }
8816 if(!settings.hideAdditions || module.is.allFiltered()) {
8817 $addition
8818 .addClass(className.selected)
8819 .siblings()
8820 .removeClass(className.selected)
8821 ;
8822 }
8823 module.refreshItems();
8824 },
8825 variables: function(message, term) {
8826 var
8827 hasCount = (message.search('{count}') !== -1),
8828 hasMaxCount = (message.search('{maxCount}') !== -1),
8829 hasTerm = (message.search('{term}') !== -1),
8830 count,
8831 query
8832 ;
8833 module.verbose('Adding templated variables to message', message);
8834 if(hasCount) {
8835 count = module.get.selectionCount();
8836 message = message.replace('{count}', count);
8837 }
8838 if(hasMaxCount) {
8839 count = module.get.selectionCount();
8840 message = message.replace('{maxCount}', settings.maxSelections);
8841 }
8842 if(hasTerm) {
8843 query = term || module.get.query();
8844 message = message.replace('{term}', query);
8845 }
8846 return message;
8847 },
8848 value: function(addedValue, addedText, $selectedItem) {
8849 var
8850 currentValue = module.get.values(),
8851 newValue
8852 ;
8853 if(module.has.value(addedValue)) {
8854 module.debug('Value already selected');
8855 return;
8856 }
8857 if(addedValue === '') {
8858 module.debug('Cannot select blank values from multiselect');
8859 return;
8860 }
8861 // extend current array
8862 if(Array.isArray(currentValue)) {
8863 newValue = currentValue.concat([addedValue]);
8864 newValue = module.get.uniqueArray(newValue);
8865 }
8866 else {
8867 newValue = [addedValue];
8868 }
8869 // add values
8870 if( module.has.selectInput() ) {
8871 if(module.can.extendSelect()) {
8872 module.debug('Adding value to select', addedValue, newValue, $input);
8873 module.add.optionValue(addedValue);
8874 }
8875 }
8876 else {
8877 newValue = newValue.join(settings.delimiter);
8878 module.debug('Setting hidden input to delimited value', newValue, $input);
8879 }
8880
8881 if(settings.fireOnInit === false && module.is.initialLoad()) {
8882 module.verbose('Skipping onadd callback on initial load', settings.onAdd);
8883 }
8884 else {
8885 settings.onAdd.call(element, addedValue, addedText, $selectedItem);
8886 }
8887 module.set.value(newValue, addedValue, addedText, $selectedItem);
8888 module.check.maxSelections();
8889 },
8890 },
8891
8892 remove: {
8893 active: function() {
8894 $module.removeClass(className.active);
8895 },
8896 activeLabel: function() {
8897 $module.find(selector.label).removeClass(className.active);
8898 },
8899 empty: function() {
8900 $module.removeClass(className.empty);
8901 },
8902 loading: function() {
8903 $module.removeClass(className.loading);
8904 },
8905 initialLoad: function() {
8906 initialLoad = false;
8907 },
8908 upward: function($currentMenu) {
8909 var $element = $currentMenu || $module;
8910 $element.removeClass(className.upward);
8911 },
8912 leftward: function($currentMenu) {
8913 var $element = $currentMenu || $menu;
8914 $element.removeClass(className.leftward);
8915 },
8916 visible: function() {
8917 $module.removeClass(className.visible);
8918 },
8919 activeItem: function() {
8920 $item.removeClass(className.active);
8921 },
8922 filteredItem: function() {
8923 if(settings.useLabels && module.has.maxSelections() ) {
8924 return;
8925 }
8926 if(settings.useLabels && module.is.multiple()) {
8927 $item.not('.' + className.active).removeClass(className.filtered);
8928 }
8929 else {
8930 $item.removeClass(className.filtered);
8931 }
8932 if(settings.hideDividers) {
8933 $divider.removeClass(className.hidden);
8934 }
8935 module.remove.empty();
8936 },
8937 optionValue: function(value) {
8938 var
8939 escapedValue = module.escape.value(value),
8940 $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
8941 hasOption = ($option.length > 0)
8942 ;
8943 if(!hasOption || !$option.hasClass(className.addition)) {
8944 return;
8945 }
8946 // temporarily disconnect observer
8947 if(selectObserver) {
8948 selectObserver.disconnect();
8949 module.verbose('Temporarily disconnecting mutation observer');
8950 }
8951 $option.remove();
8952 module.verbose('Removing user addition as an <option>', escapedValue);
8953 if(selectObserver) {
8954 selectObserver.observe($input[0], {
8955 childList : true,
8956 subtree : true
8957 });
8958 }
8959 },
8960 message: function() {
8961 $menu.children(selector.message).remove();
8962 },
8963 searchWidth: function() {
8964 $search.css('width', '');
8965 },
8966 searchTerm: function() {
8967 module.verbose('Cleared search term');
8968 $search.val('');
8969 module.set.filtered();
8970 },
8971 userAddition: function() {
8972 $item.filter(selector.addition).remove();
8973 },
8974 selected: function(value, $selectedItem) {
8975 $selectedItem = (settings.allowAdditions)
8976 ? $selectedItem || module.get.itemWithAdditions(value)
8977 : $selectedItem || module.get.item(value)
8978 ;
8979
8980 if(!$selectedItem) {
8981 return false;
8982 }
8983
8984 $selectedItem
8985 .each(function() {
8986 var
8987 $selected = $(this),
8988 selectedText = module.get.choiceText($selected),
8989 selectedValue = module.get.choiceValue($selected, selectedText)
8990 ;
8991 if(module.is.multiple()) {
8992 if(settings.useLabels) {
8993 module.remove.value(selectedValue, selectedText, $selected);
8994 module.remove.label(selectedValue);
8995 }
8996 else {
8997 module.remove.value(selectedValue, selectedText, $selected);
8998 if(module.get.selectionCount() === 0) {
8999 module.set.placeholderText();
9000 }
9001 else {
9002 module.set.text(module.add.variables(message.count));
9003 }
9004 }
9005 }
9006 else {
9007 module.remove.value(selectedValue, selectedText, $selected);
9008 }
9009 $selected
9010 .removeClass(className.filtered)
9011 .removeClass(className.active)
9012 ;
9013 if(settings.useLabels) {
9014 $selected.removeClass(className.selected);
9015 }
9016 })
9017 ;
9018 },
9019 selectedItem: function() {
9020 $item.removeClass(className.selected);
9021 },
9022 value: function(removedValue, removedText, $removedItem) {
9023 var
9024 values = module.get.values(),
9025 newValue
9026 ;
9027 if( module.has.selectInput() ) {
9028 module.verbose('Input is <select> removing selected option', removedValue);
9029 newValue = module.remove.arrayValue(removedValue, values);
9030 module.remove.optionValue(removedValue);
9031 }
9032 else {
9033 module.verbose('Removing from delimited values', removedValue);
9034 newValue = module.remove.arrayValue(removedValue, values);
9035 newValue = newValue.join(settings.delimiter);
9036 }
9037 if(settings.fireOnInit === false && module.is.initialLoad()) {
9038 module.verbose('No callback on initial load', settings.onRemove);
9039 }
9040 else {
9041 settings.onRemove.call(element, removedValue, removedText, $removedItem);
9042 }
9043 module.set.value(newValue, removedText, $removedItem);
9044 module.check.maxSelections();
9045 },
9046 arrayValue: function(removedValue, values) {
9047 if( !Array.isArray(values) ) {
9048 values = [values];
9049 }
9050 values = $.grep(values, function(value){
9051 return (removedValue != value);
9052 });
9053 module.verbose('Removed value from delimited string', removedValue, values);
9054 return values;
9055 },
9056 label: function(value, shouldAnimate) {
9057 var
9058 $labels = $module.find(selector.label),
9059 $removedLabel = $labels.filter('[data-' + metadata.value + '="' + module.escape.string(value) +'"]')
9060 ;
9061 module.verbose('Removing label', $removedLabel);
9062 $removedLabel.remove();
9063 },
9064 activeLabels: function($activeLabels) {
9065 $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
9066 module.verbose('Removing active label selections', $activeLabels);
9067 module.remove.labels($activeLabels);
9068 },
9069 labels: function($labels) {
9070 $labels = $labels || $module.find(selector.label);
9071 module.verbose('Removing labels', $labels);
9072 $labels
9073 .each(function(){
9074 var
9075 $label = $(this),
9076 value = $label.data(metadata.value),
9077 stringValue = (value !== undefined)
9078 ? String(value)
9079 : value,
9080 isUserValue = module.is.userValue(stringValue)
9081 ;
9082 if(settings.onLabelRemove.call($label, value) === false) {
9083 module.debug('Label remove callback cancelled removal');
9084 return;
9085 }
9086 module.remove.message();
9087 if(isUserValue) {
9088 module.remove.value(stringValue);
9089 module.remove.label(stringValue);
9090 }
9091 else {
9092 // selected will also remove label
9093 module.remove.selected(stringValue);
9094 }
9095 })
9096 ;
9097 },
9098 tabbable: function() {
9099 if( module.is.searchSelection() ) {
9100 module.debug('Searchable dropdown initialized');
9101 $search
9102 .removeAttr('tabindex')
9103 ;
9104 $menu
9105 .removeAttr('tabindex')
9106 ;
9107 }
9108 else {
9109 module.debug('Simple selection dropdown initialized');
9110 $module
9111 .removeAttr('tabindex')
9112 ;
9113 $menu
9114 .removeAttr('tabindex')
9115 ;
9116 }
9117 },
9118 diacritics: function(text) {
9119 return settings.ignoreDiacritics ? text.normalize('NFD').replace(/[\u0300-\u036f]/g, '') : text;
9120 }
9121 },
9122
9123 has: {
9124 menuSearch: function() {
9125 return (module.has.search() && $search.closest($menu).length > 0);
9126 },
9127 clearItem: function() {
9128 return ($clear.length > 0);
9129 },
9130 search: function() {
9131 return ($search.length > 0);
9132 },
9133 sizer: function() {
9134 return ($sizer.length > 0);
9135 },
9136 selectInput: function() {
9137 return ( $input.is('select') );
9138 },
9139 minCharacters: function(searchTerm) {
9140 if(settings.minCharacters && !iconClicked) {
9141 searchTerm = (searchTerm !== undefined)
9142 ? String(searchTerm)
9143 : String(module.get.query())
9144 ;
9145 return (searchTerm.length >= settings.minCharacters);
9146 }
9147 iconClicked=false;
9148 return true;
9149 },
9150 firstLetter: function($item, letter) {
9151 var
9152 text,
9153 firstLetter
9154 ;
9155 if(!$item || $item.length === 0 || typeof letter !== 'string') {
9156 return false;
9157 }
9158 text = module.get.choiceText($item, false);
9159 letter = letter.toLowerCase();
9160 firstLetter = String(text).charAt(0).toLowerCase();
9161 return (letter == firstLetter);
9162 },
9163 input: function() {
9164 return ($input.length > 0);
9165 },
9166 items: function() {
9167 return ($item.length > 0);
9168 },
9169 menu: function() {
9170 return ($menu.length > 0);
9171 },
9172 message: function() {
9173 return ($menu.children(selector.message).length !== 0);
9174 },
9175 label: function(value) {
9176 var
9177 escapedValue = module.escape.value(value),
9178 $labels = $module.find(selector.label)
9179 ;
9180 if(settings.ignoreCase) {
9181 escapedValue = escapedValue.toLowerCase();
9182 }
9183 return ($labels.filter('[data-' + metadata.value + '="' + module.escape.string(escapedValue) +'"]').length > 0);
9184 },
9185 maxSelections: function() {
9186 return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
9187 },
9188 allResultsFiltered: function() {
9189 var
9190 $normalResults = $item.not(selector.addition)
9191 ;
9192 return ($normalResults.filter(selector.unselectable).length === $normalResults.length);
9193 },
9194 userSuggestion: function() {
9195 return ($menu.children(selector.addition).length > 0);
9196 },
9197 query: function() {
9198 return (module.get.query() !== '');
9199 },
9200 value: function(value) {
9201 return (settings.ignoreCase)
9202 ? module.has.valueIgnoringCase(value)
9203 : module.has.valueMatchingCase(value)
9204 ;
9205 },
9206 valueMatchingCase: function(value) {
9207 var
9208 values = module.get.values(),
9209 hasValue = Array.isArray(values)
9210 ? values && ($.inArray(value, values) !== -1)
9211 : (values == value)
9212 ;
9213 return (hasValue)
9214 ? true
9215 : false
9216 ;
9217 },
9218 valueIgnoringCase: function(value) {
9219 var
9220 values = module.get.values(),
9221 hasValue = false
9222 ;
9223 if(!Array.isArray(values)) {
9224 values = [values];
9225 }
9226 $.each(values, function(index, existingValue) {
9227 if(String(value).toLowerCase() == String(existingValue).toLowerCase()) {
9228 hasValue = true;
9229 return false;
9230 }
9231 });
9232 return hasValue;
9233 }
9234 },
9235
9236 is: {
9237 active: function() {
9238 return $module.hasClass(className.active);
9239 },
9240 animatingInward: function() {
9241 return $menu.transition('is inward');
9242 },
9243 animatingOutward: function() {
9244 return $menu.transition('is outward');
9245 },
9246 bubbledLabelClick: function(event) {
9247 return $(event.target).is('select, input') && $module.closest('label').length > 0;
9248 },
9249 bubbledIconClick: function(event) {
9250 return $(event.target).closest($icon).length > 0;
9251 },
9252 alreadySetup: function() {
9253 return ($module.is('select') && $module.parent(selector.dropdown).data(moduleNamespace) !== undefined && $module.prev().length === 0);
9254 },
9255 animating: function($subMenu) {
9256 return ($subMenu)
9257 ? $subMenu.transition && $subMenu.transition('is animating')
9258 : $menu.transition && $menu.transition('is animating')
9259 ;
9260 },
9261 leftward: function($subMenu) {
9262 var $selectedMenu = $subMenu || $menu;
9263 return $selectedMenu.hasClass(className.leftward);
9264 },
9265 clearable: function() {
9266 return ($module.hasClass(className.clearable) || settings.clearable);
9267 },
9268 disabled: function() {
9269 return $module.hasClass(className.disabled);
9270 },
9271 focused: function() {
9272 return (document.activeElement === $module[0]);
9273 },
9274 focusedOnSearch: function() {
9275 return (document.activeElement === $search[0]);
9276 },
9277 allFiltered: function() {
9278 return( (module.is.multiple() || module.has.search()) && !(settings.hideAdditions == false && module.has.userSuggestion()) && !module.has.message() && module.has.allResultsFiltered() );
9279 },
9280 hidden: function($subMenu) {
9281 return !module.is.visible($subMenu);
9282 },
9283 initialLoad: function() {
9284 return initialLoad;
9285 },
9286 inObject: function(needle, object) {
9287 var
9288 found = false
9289 ;
9290 $.each(object, function(index, property) {
9291 if(property == needle) {
9292 found = true;
9293 return true;
9294 }
9295 });
9296 return found;
9297 },
9298 multiple: function() {
9299 return $module.hasClass(className.multiple);
9300 },
9301 remote: function() {
9302 return settings.apiSettings && module.can.useAPI();
9303 },
9304 single: function() {
9305 return !module.is.multiple();
9306 },
9307 selectMutation: function(mutations) {
9308 var
9309 selectChanged = false
9310 ;
9311 $.each(mutations, function(index, mutation) {
9312 if($(mutation.target).is('select') || $(mutation.addedNodes).is('select')) {
9313 selectChanged = true;
9314 return false;
9315 }
9316 });
9317 return selectChanged;
9318 },
9319 search: function() {
9320 return $module.hasClass(className.search);
9321 },
9322 searchSelection: function() {
9323 return ( module.has.search() && $search.parent(selector.dropdown).length === 1 );
9324 },
9325 selection: function() {
9326 return $module.hasClass(className.selection);
9327 },
9328 userValue: function(value) {
9329 return ($.inArray(value, module.get.userValues()) !== -1);
9330 },
9331 upward: function($menu) {
9332 var $element = $menu || $module;
9333 return $element.hasClass(className.upward);
9334 },
9335 visible: function($subMenu) {
9336 return ($subMenu)
9337 ? $subMenu.hasClass(className.visible)
9338 : $menu.hasClass(className.visible)
9339 ;
9340 },
9341 verticallyScrollableContext: function() {
9342 var
9343 overflowY = ($context.get(0) !== window)
9344 ? $context.css('overflow-y')
9345 : false
9346 ;
9347 return (overflowY == 'auto' || overflowY == 'scroll');
9348 },
9349 horizontallyScrollableContext: function() {
9350 var
9351 overflowX = ($context.get(0) !== window)
9352 ? $context.css('overflow-X')
9353 : false
9354 ;
9355 return (overflowX == 'auto' || overflowX == 'scroll');
9356 }
9357 },
9358
9359 can: {
9360 activate: function($item) {
9361 if(settings.useLabels) {
9362 return true;
9363 }
9364 if(!module.has.maxSelections()) {
9365 return true;
9366 }
9367 if(module.has.maxSelections() && $item.hasClass(className.active)) {
9368 return true;
9369 }
9370 return false;
9371 },
9372 openDownward: function($subMenu) {
9373 var
9374 $currentMenu = $subMenu || $menu,
9375 canOpenDownward = true,
9376 onScreen = {},
9377 calculations
9378 ;
9379 $currentMenu
9380 .addClass(className.loading)
9381 ;
9382 calculations = {
9383 context: {
9384 offset : ($context.get(0) === window)
9385 ? { top: 0, left: 0}
9386 : $context.offset(),
9387 scrollTop : $context.scrollTop(),
9388 height : $context.outerHeight()
9389 },
9390 menu : {
9391 offset: $currentMenu.offset(),
9392 height: $currentMenu.outerHeight()
9393 }
9394 };
9395 if(module.is.verticallyScrollableContext()) {
9396 calculations.menu.offset.top += calculations.context.scrollTop;
9397 }
9398 onScreen = {
9399 above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.context.offset.top - calculations.menu.height,
9400 below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top - calculations.context.offset.top + calculations.menu.height
9401 };
9402 if(onScreen.below) {
9403 module.verbose('Dropdown can fit in context downward', onScreen);
9404 canOpenDownward = true;
9405 }
9406 else if(!onScreen.below && !onScreen.above) {
9407 module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
9408 canOpenDownward = true;
9409 }
9410 else {
9411 module.verbose('Dropdown cannot fit below, opening upward', onScreen);
9412 canOpenDownward = false;
9413 }
9414 $currentMenu.removeClass(className.loading);
9415 return canOpenDownward;
9416 },
9417 openRightward: function($subMenu) {
9418 var
9419 $currentMenu = $subMenu || $menu,
9420 canOpenRightward = true,
9421 isOffscreenRight = false,
9422 calculations
9423 ;
9424 $currentMenu
9425 .addClass(className.loading)
9426 ;
9427 calculations = {
9428 context: {
9429 offset : ($context.get(0) === window)
9430 ? { top: 0, left: 0}
9431 : $context.offset(),
9432 scrollLeft : $context.scrollLeft(),
9433 width : $context.outerWidth()
9434 },
9435 menu: {
9436 offset : $currentMenu.offset(),
9437 width : $currentMenu.outerWidth()
9438 }
9439 };
9440 if(module.is.horizontallyScrollableContext()) {
9441 calculations.menu.offset.left += calculations.context.scrollLeft;
9442 }
9443 isOffscreenRight = (calculations.menu.offset.left - calculations.context.offset.left + calculations.menu.width >= calculations.context.scrollLeft + calculations.context.width);
9444 if(isOffscreenRight) {
9445 module.verbose('Dropdown cannot fit in context rightward', isOffscreenRight);
9446 canOpenRightward = false;
9447 }
9448 $currentMenu.removeClass(className.loading);
9449 return canOpenRightward;
9450 },
9451 click: function() {
9452 return (hasTouch || settings.on == 'click');
9453 },
9454 extendSelect: function() {
9455 return settings.allowAdditions || settings.apiSettings;
9456 },
9457 show: function() {
9458 return !module.is.disabled() && (module.has.items() || module.has.message());
9459 },
9460 useAPI: function() {
9461 return $.fn.api !== undefined;
9462 }
9463 },
9464
9465 animate: {
9466 show: function(callback, $subMenu) {
9467 var
9468 $currentMenu = $subMenu || $menu,
9469 start = ($subMenu)
9470 ? function() {}
9471 : function() {
9472 module.hideSubMenus();
9473 module.hideOthers();
9474 module.set.active();
9475 },
9476 transition
9477 ;
9478 callback = $.isFunction(callback)
9479 ? callback
9480 : function(){}
9481 ;
9482 module.verbose('Doing menu show animation', $currentMenu);
9483 module.set.direction($subMenu);
9484 transition = module.get.transition($subMenu);
9485 if( module.is.selection() ) {
9486 module.set.scrollPosition(module.get.selectedItem(), true);
9487 }
9488 if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
9489 if(transition == 'none') {
9490 start();
9491 $currentMenu.transition('show');
9492 callback.call(element);
9493 }
9494 else if($.fn.transition !== undefined && $module.transition('is supported')) {
9495 $currentMenu
9496 .transition({
9497 animation : transition + ' in',
9498 debug : settings.debug,
9499 verbose : settings.verbose,
9500 duration : settings.duration,
9501 queue : true,
9502 onStart : start,
9503 onComplete : function() {
9504 callback.call(element);
9505 }
9506 })
9507 ;
9508 }
9509 else {
9510 module.error(error.noTransition, transition);
9511 }
9512 }
9513 },
9514 hide: function(callback, $subMenu) {
9515 var
9516 $currentMenu = $subMenu || $menu,
9517 start = ($subMenu)
9518 ? function() {}
9519 : function() {
9520 if( module.can.click() ) {
9521 module.unbind.intent();
9522 }
9523 module.remove.active();
9524 },
9525 transition = module.get.transition($subMenu)
9526 ;
9527 callback = $.isFunction(callback)
9528 ? callback
9529 : function(){}
9530 ;
9531 if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
9532 module.verbose('Doing menu hide animation', $currentMenu);
9533
9534 if(transition == 'none') {
9535 start();
9536 $currentMenu.transition('hide');
9537 callback.call(element);
9538 }
9539 else if($.fn.transition !== undefined && $module.transition('is supported')) {
9540 $currentMenu
9541 .transition({
9542 animation : transition + ' out',
9543 duration : settings.duration,
9544 debug : settings.debug,
9545 verbose : settings.verbose,
9546 queue : false,
9547 onStart : start,
9548 onComplete : function() {
9549 callback.call(element);
9550 }
9551 })
9552 ;
9553 }
9554 else {
9555 module.error(error.transition);
9556 }
9557 }
9558 }
9559 },
9560
9561 hideAndClear: function() {
9562 module.remove.searchTerm();
9563 if( module.has.maxSelections() ) {
9564 return;
9565 }
9566 if(module.has.search()) {
9567 module.hide(function() {
9568 module.remove.filteredItem();
9569 });
9570 }
9571 else {
9572 module.hide();
9573 }
9574 },
9575
9576 delay: {
9577 show: function() {
9578 module.verbose('Delaying show event to ensure user intent');
9579 clearTimeout(module.timer);
9580 module.timer = setTimeout(module.show, settings.delay.show);
9581 },
9582 hide: function() {
9583 module.verbose('Delaying hide event to ensure user intent');
9584 clearTimeout(module.timer);
9585 module.timer = setTimeout(module.hide, settings.delay.hide);
9586 }
9587 },
9588
9589 escape: {
9590 value: function(value) {
9591 var
9592 multipleValues = Array.isArray(value),
9593 stringValue = (typeof value === 'string'),
9594 isUnparsable = (!stringValue && !multipleValues),
9595 hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
9596 values = []
9597 ;
9598 if(isUnparsable || !hasQuotes) {
9599 return value;
9600 }
9601 module.debug('Encoding quote values for use in select', value);
9602 if(multipleValues) {
9603 $.each(value, function(index, value){
9604 values.push(value.replace(regExp.quote, '&quot;'));
9605 });
9606 return values;
9607 }
9608 return value.replace(regExp.quote, '&quot;');
9609 },
9610 string: function(text) {
9611 text = String(text);
9612 return text.replace(regExp.escape, '\\$&');
9613 },
9614 htmlEntities: function(string) {
9615 var
9616 badChars = /[&<>"'`]/g,
9617 shouldEscape = /[&<>"'`]/,
9618 escape = {
9619 "&": "&amp;",
9620 "<": "&lt;",
9621 ">": "&gt;",
9622 '"': "&quot;",
9623 "'": "&#x27;",
9624 "`": "&#x60;"
9625 },
9626 escapedChar = function(chr) {
9627 return escape[chr];
9628 }
9629 ;
9630 if(shouldEscape.test(string)) {
9631 return string.replace(badChars, escapedChar);
9632 }
9633 return string;
9634 }
9635 },
9636
9637 setting: function(name, value) {
9638 module.debug('Changing setting', name, value);
9639 if( $.isPlainObject(name) ) {
9640 $.extend(true, settings, name);
9641 }
9642 else if(value !== undefined) {
9643 if($.isPlainObject(settings[name])) {
9644 $.extend(true, settings[name], value);
9645 }
9646 else {
9647 settings[name] = value;
9648 }
9649 }
9650 else {
9651 return settings[name];
9652 }
9653 },
9654 internal: function(name, value) {
9655 if( $.isPlainObject(name) ) {
9656 $.extend(true, module, name);
9657 }
9658 else if(value !== undefined) {
9659 module[name] = value;
9660 }
9661 else {
9662 return module[name];
9663 }
9664 },
9665 debug: function() {
9666 if(!settings.silent && settings.debug) {
9667 if(settings.performance) {
9668 module.performance.log(arguments);
9669 }
9670 else {
9671 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
9672 module.debug.apply(console, arguments);
9673 }
9674 }
9675 },
9676 verbose: function() {
9677 if(!settings.silent && settings.verbose && settings.debug) {
9678 if(settings.performance) {
9679 module.performance.log(arguments);
9680 }
9681 else {
9682 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
9683 module.verbose.apply(console, arguments);
9684 }
9685 }
9686 },
9687 error: function() {
9688 if(!settings.silent) {
9689 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
9690 module.error.apply(console, arguments);
9691 }
9692 },
9693 performance: {
9694 log: function(message) {
9695 var
9696 currentTime,
9697 executionTime,
9698 previousTime
9699 ;
9700 if(settings.performance) {
9701 currentTime = new Date().getTime();
9702 previousTime = time || currentTime;
9703 executionTime = currentTime - previousTime;
9704 time = currentTime;
9705 performance.push({
9706 'Name' : message[0],
9707 'Arguments' : [].slice.call(message, 1) || '',
9708 'Element' : element,
9709 'Execution Time' : executionTime
9710 });
9711 }
9712 clearTimeout(module.performance.timer);
9713 module.performance.timer = setTimeout(module.performance.display, 500);
9714 },
9715 display: function() {
9716 var
9717 title = settings.name + ':',
9718 totalTime = 0
9719 ;
9720 time = false;
9721 clearTimeout(module.performance.timer);
9722 $.each(performance, function(index, data) {
9723 totalTime += data['Execution Time'];
9724 });
9725 title += ' ' + totalTime + 'ms';
9726 if(moduleSelector) {
9727 title += ' \'' + moduleSelector + '\'';
9728 }
9729 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
9730 console.groupCollapsed(title);
9731 if(console.table) {
9732 console.table(performance);
9733 }
9734 else {
9735 $.each(performance, function(index, data) {
9736 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
9737 });
9738 }
9739 console.groupEnd();
9740 }
9741 performance = [];
9742 }
9743 },
9744 invoke: function(query, passedArguments, context) {
9745 var
9746 object = instance,
9747 maxDepth,
9748 found,
9749 response
9750 ;
9751 passedArguments = passedArguments || queryArguments;
9752 context = element || context;
9753 if(typeof query == 'string' && object !== undefined) {
9754 query = query.split(/[\. ]/);
9755 maxDepth = query.length - 1;
9756 $.each(query, function(depth, value) {
9757 var camelCaseValue = (depth != maxDepth)
9758 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
9759 : query
9760 ;
9761 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
9762 object = object[camelCaseValue];
9763 }
9764 else if( object[camelCaseValue] !== undefined ) {
9765 found = object[camelCaseValue];
9766 return false;
9767 }
9768 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
9769 object = object[value];
9770 }
9771 else if( object[value] !== undefined ) {
9772 found = object[value];
9773 return false;
9774 }
9775 else {
9776 module.error(error.method, query);
9777 return false;
9778 }
9779 });
9780 }
9781 if ( $.isFunction( found ) ) {
9782 response = found.apply(context, passedArguments);
9783 }
9784 else if(found !== undefined) {
9785 response = found;
9786 }
9787 if(Array.isArray(returnedValue)) {
9788 returnedValue.push(response);
9789 }
9790 else if(returnedValue !== undefined) {
9791 returnedValue = [returnedValue, response];
9792 }
9793 else if(response !== undefined) {
9794 returnedValue = response;
9795 }
9796 return found;
9797 }
9798 };
9799
9800 if(methodInvoked) {
9801 if(instance === undefined) {
9802 module.initialize();
9803 }
9804 module.invoke(query);
9805 }
9806 else {
9807 if(instance !== undefined) {
9808 instance.invoke('destroy');
9809 }
9810 module.initialize();
9811 }
9812 })
9813 ;
9814 return (returnedValue !== undefined)
9815 ? returnedValue
9816 : $allModules
9817 ;
9818};
9819
9820$.fn.dropdown.settings = {
9821
9822 silent : false,
9823 debug : false,
9824 verbose : false,
9825 performance : true,
9826
9827 on : 'click', // what event should show menu action on item selection
9828 action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
9829
9830 values : false, // specify values to use for dropdown
9831
9832 clearable : false, // whether the value of the dropdown can be cleared
9833
9834 apiSettings : false,
9835 selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
9836 minCharacters : 0, // Minimum characters required to trigger API call
9837
9838 filterRemoteData : false, // Whether API results should be filtered after being returned for query term
9839 saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
9840
9841 throttle : 200, // How long to wait after last user input to search remotely
9842
9843 context : window, // Context to use when determining if on screen
9844 direction : 'auto', // Whether dropdown should always open in one direction
9845 keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
9846
9847 match : 'both', // what to match against with search selection (both, text, or label)
9848 fullTextSearch : false, // search anywhere in value (set to 'exact' to require exact matches)
9849 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...)
9850 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)
9851
9852 placeholder : 'auto', // whether to convert blank <select> values to placeholder text
9853 preserveHTML : true, // preserve html when selecting value
9854 sortSelect : false, // sort selection on init
9855
9856 forceSelection : true, // force a choice on blur with search selection
9857
9858 allowAdditions : false, // whether multiple select should allow user added values
9859 ignoreCase : false, // whether to consider values not matching in case to be the same
9860 hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
9861
9862 maxSelections : false, // When set to a number limits the number of selections to this count
9863 useLabels : true, // whether multiple select should filter currently active selections from choices
9864 delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
9865
9866 showOnFocus : true, // show menu on focus
9867 allowReselection : false, // whether current value should trigger callbacks when reselected
9868 allowTab : true, // add tabindex to element
9869 allowCategorySelection : false, // allow elements with sub-menus to be selected
9870
9871 fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
9872
9873 transition : 'auto', // auto transition will slide down or up based on direction
9874 duration : 200, // duration of transition
9875
9876 glyphWidth : 1.037, // widest glyph width in em (W is 1.037 em) used to calculate multiselect input width
9877
9878 // label settings on multi-select
9879 label: {
9880 transition : 'scale',
9881 duration : 200,
9882 variation : false
9883 },
9884
9885 // delay before event
9886 delay : {
9887 hide : 300,
9888 show : 200,
9889 search : 20,
9890 touch : 50
9891 },
9892
9893 /* Callbacks */
9894 onChange : function(value, text, $selected){},
9895 onAdd : function(value, text, $selected){},
9896 onRemove : function(value, text, $selected){},
9897
9898 onLabelSelect : function($selectedLabels){},
9899 onLabelCreate : function(value, text) { return $(this); },
9900 onLabelRemove : function(value) { return true; },
9901 onNoResults : function(searchTerm) { return true; },
9902 onShow : function(){},
9903 onHide : function(){},
9904
9905 /* Component */
9906 name : 'Dropdown',
9907 namespace : 'dropdown',
9908
9909 message: {
9910 addResult : 'Add <b>{term}</b>',
9911 count : '{count} selected',
9912 maxSelections : 'Max {maxCount} selections',
9913 noResults : 'No results found.',
9914 serverError : 'There was an error contacting the server'
9915 },
9916
9917 error : {
9918 action : 'You called a dropdown action that was not defined',
9919 alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
9920 labels : 'Allowing user additions currently requires the use of labels.',
9921 missingMultiple : '<select> requires multiple property to be set to correctly preserve multiple values',
9922 method : 'The method you called is not defined.',
9923 noAPI : 'The API module is required to load resources remotely',
9924 noStorage : 'Saving remote data requires session storage',
9925 noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
9926 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.'
9927 },
9928
9929 regExp : {
9930 escape : /[-[\]{}()*+?.,\\^$|#\s:=@]/g,
9931 quote : /"/g
9932 },
9933
9934 metadata : {
9935 defaultText : 'defaultText',
9936 defaultValue : 'defaultValue',
9937 placeholderText : 'placeholder',
9938 text : 'text',
9939 value : 'value'
9940 },
9941
9942 // property names for remote query
9943 fields: {
9944 remoteValues : 'results', // grouping for api results
9945 values : 'values', // grouping for all dropdown values
9946 disabled : 'disabled', // whether value should be disabled
9947 name : 'name', // displayed dropdown text
9948 value : 'value', // actual dropdown value
9949 text : 'text', // displayed text when selected
9950 type : 'type' // type of dropdown element
9951 },
9952
9953 keys : {
9954 backspace : 8,
9955 delimiter : 188, // comma
9956 deleteKey : 46,
9957 enter : 13,
9958 escape : 27,
9959 pageUp : 33,
9960 pageDown : 34,
9961 leftArrow : 37,
9962 upArrow : 38,
9963 rightArrow : 39,
9964 downArrow : 40
9965 },
9966
9967 selector : {
9968 addition : '.addition',
9969 divider : '.divider, .header',
9970 dropdown : '.ui.dropdown',
9971 hidden : '.hidden',
9972 icon : '> .dropdown.icon',
9973 input : '> input[type="hidden"], > select',
9974 item : '.item',
9975 label : '> .label',
9976 remove : '> .label > .delete.icon',
9977 siblingLabel : '.label',
9978 menu : '.menu',
9979 message : '.message',
9980 menuIcon : '.dropdown.icon',
9981 search : 'input.search, .menu > .search > input, .menu input.search',
9982 sizer : '> input.sizer',
9983 text : '> .text:not(.icon)',
9984 unselectable : '.disabled, .filtered',
9985 clearIcon : '> .remove.icon'
9986 },
9987
9988 className : {
9989 active : 'active',
9990 addition : 'addition',
9991 animating : 'animating',
9992 disabled : 'disabled',
9993 empty : 'empty',
9994 dropdown : 'ui dropdown',
9995 filtered : 'filtered',
9996 hidden : 'hidden transition',
9997 item : 'item',
9998 label : 'ui label',
9999 loading : 'loading',
10000 menu : 'menu',
10001 message : 'message',
10002 multiple : 'multiple',
10003 placeholder : 'default',
10004 sizer : 'sizer',
10005 search : 'search',
10006 selected : 'selected',
10007 selection : 'selection',
10008 upward : 'upward',
10009 leftward : 'left',
10010 visible : 'visible',
10011 clearable : 'clearable',
10012 noselection : 'noselection',
10013 delete : 'delete'
10014 }
10015
10016};
10017
10018/* Templates */
10019$.fn.dropdown.settings.templates = {
10020 escape: function(string, preserveHTML) {
10021 if (preserveHTML){
10022 return string;
10023 }
10024 var
10025 badChars = /[&<>"'`]/g,
10026 shouldEscape = /[&<>"'`]/,
10027 escape = {
10028 "&": "&amp;",
10029 "<": "&lt;",
10030 ">": "&gt;",
10031 '"': "&quot;",
10032 "'": "&#x27;",
10033 "`": "&#x60;"
10034 },
10035 escapedChar = function(chr) {
10036 return escape[chr];
10037 }
10038 ;
10039 if(shouldEscape.test(string)) {
10040 return string.replace(badChars, escapedChar);
10041 }
10042 return string;
10043 },
10044 // generates dropdown from select values
10045 dropdown: function(select, preserveHTML, className) {
10046 var
10047 placeholder = select.placeholder || false,
10048 values = select.values || [],
10049 html = '',
10050 escape = $.fn.dropdown.settings.templates.escape
10051 ;
10052 html += '<i class="dropdown icon"></i>';
10053 if(placeholder) {
10054 html += '<div class="default text">' + escape(placeholder,preserveHTML) + '</div>';
10055 }
10056 else {
10057 html += '<div class="text"></div>';
10058 }
10059 html += '<div class="'+className.menu+'">';
10060 $.each(values, function(index, option) {
10061 html += '<div class="'+(option.disabled ? className.disabled+' ':'')+className.item+'" data-value="' + String(option.value).replace(/"/g,"") + '">' + escape(option.name,preserveHTML) + '</div>';
10062 });
10063 html += '</div>';
10064 return html;
10065 },
10066
10067 // generates just menu from select
10068 menu: function(response, fields, preserveHTML, className) {
10069 var
10070 values = response[fields.values] || [],
10071 html = '',
10072 escape = $.fn.dropdown.settings.templates.escape
10073 ;
10074 $.each(values, function(index, option) {
10075 var
10076 itemType = (option[fields.type])
10077 ? option[fields.type]
10078 : 'item'
10079 ;
10080
10081 if( itemType === 'item' ) {
10082 var
10083 maybeText = (option[fields.text])
10084 ? ' data-text="' + String(option[fields.text]).replace(/"/g,"") + '"'
10085 : '',
10086 maybeDisabled = (option[fields.disabled])
10087 ? className.disabled+' '
10088 : ''
10089 ;
10090 html += '<div class="'+ maybeDisabled + className.item+'" data-value="' + String(option[fields.value]).replace(/"/g,"") + '"' + maybeText + '>';
10091 html += escape(option[fields.name],preserveHTML);
10092 html += '</div>';
10093 } else if (itemType === 'header') {
10094 html += '<div class="header">';
10095 html += escape(option[fields.name],preserveHTML);
10096 html += '</div>';
10097 }
10098 });
10099 return html;
10100 },
10101
10102 // generates label for multiselect
10103 label: function(value, text, preserveHTML, className) {
10104 var
10105 escape = $.fn.dropdown.settings.templates.escape;
10106 return escape(text,preserveHTML) + '<i class="'+className.delete+' icon"></i>';
10107 },
10108
10109
10110 // generates messages like "No results"
10111 message: function(message) {
10112 return message;
10113 },
10114
10115 // generates user addition to selection menu
10116 addition: function(choice) {
10117 return choice;
10118 }
10119
10120};
10121
10122})( jQuery, window, document );
10123
10124/*!
10125 * # Semantic UI 2.7.2 - Embed
10126 * http://github.com/semantic-org/semantic-ui/
10127 *
10128 *
10129 * Released under the MIT license
10130 * http://opensource.org/licenses/MIT
10131 *
10132 */
10133
10134;(function ($, window, document, undefined) {
10135
10136"use strict";
10137
10138$.isFunction = $.isFunction || function(obj) {
10139 return typeof obj === "function" && typeof obj.nodeType !== "number";
10140};
10141
10142window = (typeof window != 'undefined' && window.Math == Math)
10143 ? window
10144 : (typeof self != 'undefined' && self.Math == Math)
10145 ? self
10146 : Function('return this')()
10147;
10148
10149$.fn.embed = function(parameters) {
10150
10151 var
10152 $allModules = $(this),
10153
10154 moduleSelector = $allModules.selector || '',
10155
10156 time = new Date().getTime(),
10157 performance = [],
10158
10159 query = arguments[0],
10160 methodInvoked = (typeof query == 'string'),
10161 queryArguments = [].slice.call(arguments, 1),
10162
10163 returnedValue
10164 ;
10165
10166 $allModules
10167 .each(function() {
10168 var
10169 settings = ( $.isPlainObject(parameters) )
10170 ? $.extend(true, {}, $.fn.embed.settings, parameters)
10171 : $.extend({}, $.fn.embed.settings),
10172
10173 selector = settings.selector,
10174 className = settings.className,
10175 sources = settings.sources,
10176 error = settings.error,
10177 metadata = settings.metadata,
10178 namespace = settings.namespace,
10179 templates = settings.templates,
10180
10181 eventNamespace = '.' + namespace,
10182 moduleNamespace = 'module-' + namespace,
10183
10184 $module = $(this),
10185 $placeholder = $module.find(selector.placeholder),
10186 $icon = $module.find(selector.icon),
10187 $embed = $module.find(selector.embed),
10188
10189 element = this,
10190 instance = $module.data(moduleNamespace),
10191 module
10192 ;
10193
10194 module = {
10195
10196 initialize: function() {
10197 module.debug('Initializing embed');
10198 module.determine.autoplay();
10199 module.create();
10200 module.bind.events();
10201 module.instantiate();
10202 },
10203
10204 instantiate: function() {
10205 module.verbose('Storing instance of module', module);
10206 instance = module;
10207 $module
10208 .data(moduleNamespace, module)
10209 ;
10210 },
10211
10212 destroy: function() {
10213 module.verbose('Destroying previous instance of embed');
10214 module.reset();
10215 $module
10216 .removeData(moduleNamespace)
10217 .off(eventNamespace)
10218 ;
10219 },
10220
10221 refresh: function() {
10222 module.verbose('Refreshing selector cache');
10223 $placeholder = $module.find(selector.placeholder);
10224 $icon = $module.find(selector.icon);
10225 $embed = $module.find(selector.embed);
10226 },
10227
10228 bind: {
10229 events: function() {
10230 if( module.has.placeholder() ) {
10231 module.debug('Adding placeholder events');
10232 $module
10233 .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
10234 .on('click' + eventNamespace, selector.icon, module.createAndShow)
10235 ;
10236 }
10237 }
10238 },
10239
10240 create: function() {
10241 var
10242 placeholder = module.get.placeholder()
10243 ;
10244 if(placeholder) {
10245 module.createPlaceholder();
10246 }
10247 else {
10248 module.createAndShow();
10249 }
10250 },
10251
10252 createPlaceholder: function(placeholder) {
10253 var
10254 icon = module.get.icon(),
10255 url = module.get.url(),
10256 embed = module.generate.embed(url)
10257 ;
10258 placeholder = placeholder || module.get.placeholder();
10259 $module.html( templates.placeholder(placeholder, icon) );
10260 module.debug('Creating placeholder for embed', placeholder, icon);
10261 },
10262
10263 createEmbed: function(url) {
10264 module.refresh();
10265 url = url || module.get.url();
10266 $embed = $('<div/>')
10267 .addClass(className.embed)
10268 .html( module.generate.embed(url) )
10269 .appendTo($module)
10270 ;
10271 settings.onCreate.call(element, url);
10272 module.debug('Creating embed object', $embed);
10273 },
10274
10275 changeEmbed: function(url) {
10276 $embed
10277 .html( module.generate.embed(url) )
10278 ;
10279 },
10280
10281 createAndShow: function() {
10282 module.createEmbed();
10283 module.show();
10284 },
10285
10286 // sets new embed
10287 change: function(source, id, url) {
10288 module.debug('Changing video to ', source, id, url);
10289 $module
10290 .data(metadata.source, source)
10291 .data(metadata.id, id)
10292 ;
10293 if(url) {
10294 $module.data(metadata.url, url);
10295 }
10296 else {
10297 $module.removeData(metadata.url);
10298 }
10299 if(module.has.embed()) {
10300 module.changeEmbed();
10301 }
10302 else {
10303 module.create();
10304 }
10305 },
10306
10307 // clears embed
10308 reset: function() {
10309 module.debug('Clearing embed and showing placeholder');
10310 module.remove.data();
10311 module.remove.active();
10312 module.remove.embed();
10313 module.showPlaceholder();
10314 settings.onReset.call(element);
10315 },
10316
10317 // shows current embed
10318 show: function() {
10319 module.debug('Showing embed');
10320 module.set.active();
10321 settings.onDisplay.call(element);
10322 },
10323
10324 hide: function() {
10325 module.debug('Hiding embed');
10326 module.showPlaceholder();
10327 },
10328
10329 showPlaceholder: function() {
10330 module.debug('Showing placeholder image');
10331 module.remove.active();
10332 settings.onPlaceholderDisplay.call(element);
10333 },
10334
10335 get: {
10336 id: function() {
10337 return settings.id || $module.data(metadata.id);
10338 },
10339 placeholder: function() {
10340 return settings.placeholder || $module.data(metadata.placeholder);
10341 },
10342 icon: function() {
10343 return (settings.icon)
10344 ? settings.icon
10345 : ($module.data(metadata.icon) !== undefined)
10346 ? $module.data(metadata.icon)
10347 : module.determine.icon()
10348 ;
10349 },
10350 source: function(url) {
10351 return (settings.source)
10352 ? settings.source
10353 : ($module.data(metadata.source) !== undefined)
10354 ? $module.data(metadata.source)
10355 : module.determine.source()
10356 ;
10357 },
10358 type: function() {
10359 var source = module.get.source();
10360 return (sources[source] !== undefined)
10361 ? sources[source].type
10362 : false
10363 ;
10364 },
10365 url: function() {
10366 return (settings.url)
10367 ? settings.url
10368 : ($module.data(metadata.url) !== undefined)
10369 ? $module.data(metadata.url)
10370 : module.determine.url()
10371 ;
10372 }
10373 },
10374
10375 determine: {
10376 autoplay: function() {
10377 if(module.should.autoplay()) {
10378 settings.autoplay = true;
10379 }
10380 },
10381 source: function(url) {
10382 var
10383 matchedSource = false
10384 ;
10385 url = url || module.get.url();
10386 if(url) {
10387 $.each(sources, function(name, source) {
10388 if(url.search(source.domain) !== -1) {
10389 matchedSource = name;
10390 return false;
10391 }
10392 });
10393 }
10394 return matchedSource;
10395 },
10396 icon: function() {
10397 var
10398 source = module.get.source()
10399 ;
10400 return (sources[source] !== undefined)
10401 ? sources[source].icon
10402 : false
10403 ;
10404 },
10405 url: function() {
10406 var
10407 id = settings.id || $module.data(metadata.id),
10408 source = settings.source || $module.data(metadata.source),
10409 url
10410 ;
10411 url = (sources[source] !== undefined)
10412 ? sources[source].url.replace('{id}', id)
10413 : false
10414 ;
10415 if(url) {
10416 $module.data(metadata.url, url);
10417 }
10418 return url;
10419 }
10420 },
10421
10422
10423 set: {
10424 active: function() {
10425 $module.addClass(className.active);
10426 }
10427 },
10428
10429 remove: {
10430 data: function() {
10431 $module
10432 .removeData(metadata.id)
10433 .removeData(metadata.icon)
10434 .removeData(metadata.placeholder)
10435 .removeData(metadata.source)
10436 .removeData(metadata.url)
10437 ;
10438 },
10439 active: function() {
10440 $module.removeClass(className.active);
10441 },
10442 embed: function() {
10443 $embed.empty();
10444 }
10445 },
10446
10447 encode: {
10448 parameters: function(parameters) {
10449 var
10450 urlString = [],
10451 index
10452 ;
10453 for (index in parameters) {
10454 urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
10455 }
10456 return urlString.join('&amp;');
10457 }
10458 },
10459
10460 generate: {
10461 embed: function(url) {
10462 module.debug('Generating embed html');
10463 var
10464 source = module.get.source(),
10465 html,
10466 parameters
10467 ;
10468 url = module.get.url(url);
10469 if(url) {
10470 parameters = module.generate.parameters(source);
10471 html = templates.iframe(url, parameters);
10472 }
10473 else {
10474 module.error(error.noURL, $module);
10475 }
10476 return html;
10477 },
10478 parameters: function(source, extraParameters) {
10479 var
10480 parameters = (sources[source] && sources[source].parameters !== undefined)
10481 ? sources[source].parameters(settings)
10482 : {}
10483 ;
10484 extraParameters = extraParameters || settings.parameters;
10485 if(extraParameters) {
10486 parameters = $.extend({}, parameters, extraParameters);
10487 }
10488 parameters = settings.onEmbed(parameters);
10489 return module.encode.parameters(parameters);
10490 }
10491 },
10492
10493 has: {
10494 embed: function() {
10495 return ($embed.length > 0);
10496 },
10497 placeholder: function() {
10498 return settings.placeholder || $module.data(metadata.placeholder);
10499 }
10500 },
10501
10502 should: {
10503 autoplay: function() {
10504 return (settings.autoplay === 'auto')
10505 ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
10506 : settings.autoplay
10507 ;
10508 }
10509 },
10510
10511 is: {
10512 video: function() {
10513 return module.get.type() == 'video';
10514 }
10515 },
10516
10517 setting: function(name, value) {
10518 module.debug('Changing setting', name, value);
10519 if( $.isPlainObject(name) ) {
10520 $.extend(true, settings, name);
10521 }
10522 else if(value !== undefined) {
10523 if($.isPlainObject(settings[name])) {
10524 $.extend(true, settings[name], value);
10525 }
10526 else {
10527 settings[name] = value;
10528 }
10529 }
10530 else {
10531 return settings[name];
10532 }
10533 },
10534 internal: function(name, value) {
10535 if( $.isPlainObject(name) ) {
10536 $.extend(true, module, name);
10537 }
10538 else if(value !== undefined) {
10539 module[name] = value;
10540 }
10541 else {
10542 return module[name];
10543 }
10544 },
10545 debug: function() {
10546 if(!settings.silent && settings.debug) {
10547 if(settings.performance) {
10548 module.performance.log(arguments);
10549 }
10550 else {
10551 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
10552 module.debug.apply(console, arguments);
10553 }
10554 }
10555 },
10556 verbose: function() {
10557 if(!settings.silent && settings.verbose && settings.debug) {
10558 if(settings.performance) {
10559 module.performance.log(arguments);
10560 }
10561 else {
10562 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
10563 module.verbose.apply(console, arguments);
10564 }
10565 }
10566 },
10567 error: function() {
10568 if(!settings.silent) {
10569 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
10570 module.error.apply(console, arguments);
10571 }
10572 },
10573 performance: {
10574 log: function(message) {
10575 var
10576 currentTime,
10577 executionTime,
10578 previousTime
10579 ;
10580 if(settings.performance) {
10581 currentTime = new Date().getTime();
10582 previousTime = time || currentTime;
10583 executionTime = currentTime - previousTime;
10584 time = currentTime;
10585 performance.push({
10586 'Name' : message[0],
10587 'Arguments' : [].slice.call(message, 1) || '',
10588 'Element' : element,
10589 'Execution Time' : executionTime
10590 });
10591 }
10592 clearTimeout(module.performance.timer);
10593 module.performance.timer = setTimeout(module.performance.display, 500);
10594 },
10595 display: function() {
10596 var
10597 title = settings.name + ':',
10598 totalTime = 0
10599 ;
10600 time = false;
10601 clearTimeout(module.performance.timer);
10602 $.each(performance, function(index, data) {
10603 totalTime += data['Execution Time'];
10604 });
10605 title += ' ' + totalTime + 'ms';
10606 if(moduleSelector) {
10607 title += ' \'' + moduleSelector + '\'';
10608 }
10609 if($allModules.length > 1) {
10610 title += ' ' + '(' + $allModules.length + ')';
10611 }
10612 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
10613 console.groupCollapsed(title);
10614 if(console.table) {
10615 console.table(performance);
10616 }
10617 else {
10618 $.each(performance, function(index, data) {
10619 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
10620 });
10621 }
10622 console.groupEnd();
10623 }
10624 performance = [];
10625 }
10626 },
10627 invoke: function(query, passedArguments, context) {
10628 var
10629 object = instance,
10630 maxDepth,
10631 found,
10632 response
10633 ;
10634 passedArguments = passedArguments || queryArguments;
10635 context = element || context;
10636 if(typeof query == 'string' && object !== undefined) {
10637 query = query.split(/[\. ]/);
10638 maxDepth = query.length - 1;
10639 $.each(query, function(depth, value) {
10640 var camelCaseValue = (depth != maxDepth)
10641 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
10642 : query
10643 ;
10644 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
10645 object = object[camelCaseValue];
10646 }
10647 else if( object[camelCaseValue] !== undefined ) {
10648 found = object[camelCaseValue];
10649 return false;
10650 }
10651 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
10652 object = object[value];
10653 }
10654 else if( object[value] !== undefined ) {
10655 found = object[value];
10656 return false;
10657 }
10658 else {
10659 module.error(error.method, query);
10660 return false;
10661 }
10662 });
10663 }
10664 if ( $.isFunction( found ) ) {
10665 response = found.apply(context, passedArguments);
10666 }
10667 else if(found !== undefined) {
10668 response = found;
10669 }
10670 if(Array.isArray(returnedValue)) {
10671 returnedValue.push(response);
10672 }
10673 else if(returnedValue !== undefined) {
10674 returnedValue = [returnedValue, response];
10675 }
10676 else if(response !== undefined) {
10677 returnedValue = response;
10678 }
10679 return found;
10680 }
10681 };
10682
10683 if(methodInvoked) {
10684 if(instance === undefined) {
10685 module.initialize();
10686 }
10687 module.invoke(query);
10688 }
10689 else {
10690 if(instance !== undefined) {
10691 instance.invoke('destroy');
10692 }
10693 module.initialize();
10694 }
10695 })
10696 ;
10697 return (returnedValue !== undefined)
10698 ? returnedValue
10699 : this
10700 ;
10701};
10702
10703$.fn.embed.settings = {
10704
10705 name : 'Embed',
10706 namespace : 'embed',
10707
10708 silent : false,
10709 debug : false,
10710 verbose : false,
10711 performance : true,
10712
10713 icon : false,
10714 source : false,
10715 url : false,
10716 id : false,
10717
10718 // standard video settings
10719 autoplay : 'auto',
10720 color : '#444444',
10721 hd : true,
10722 brandedUI : false,
10723
10724 // additional parameters to include with the embed
10725 parameters: false,
10726
10727 onDisplay : function() {},
10728 onPlaceholderDisplay : function() {},
10729 onReset : function() {},
10730 onCreate : function(url) {},
10731 onEmbed : function(parameters) {
10732 return parameters;
10733 },
10734
10735 metadata : {
10736 id : 'id',
10737 icon : 'icon',
10738 placeholder : 'placeholder',
10739 source : 'source',
10740 url : 'url'
10741 },
10742
10743 error : {
10744 noURL : 'No URL specified',
10745 method : 'The method you called is not defined'
10746 },
10747
10748 className : {
10749 active : 'active',
10750 embed : 'embed'
10751 },
10752
10753 selector : {
10754 embed : '.embed',
10755 placeholder : '.placeholder',
10756 icon : '.icon'
10757 },
10758
10759 sources: {
10760 youtube: {
10761 name : 'youtube',
10762 type : 'video',
10763 icon : 'video play',
10764 domain : 'youtube.com',
10765 url : '//www.youtube.com/embed/{id}',
10766 parameters: function(settings) {
10767 return {
10768 autohide : !settings.brandedUI,
10769 autoplay : settings.autoplay,
10770 color : settings.color || undefined,
10771 hq : settings.hd,
10772 jsapi : settings.api,
10773 modestbranding : !settings.brandedUI
10774 };
10775 }
10776 },
10777 vimeo: {
10778 name : 'vimeo',
10779 type : 'video',
10780 icon : 'video play',
10781 domain : 'vimeo.com',
10782 url : '//player.vimeo.com/video/{id}',
10783 parameters: function(settings) {
10784 return {
10785 api : settings.api,
10786 autoplay : settings.autoplay,
10787 byline : settings.brandedUI,
10788 color : settings.color || undefined,
10789 portrait : settings.brandedUI,
10790 title : settings.brandedUI
10791 };
10792 }
10793 }
10794 },
10795
10796 templates: {
10797 iframe : function(url, parameters) {
10798 var src = url;
10799 if (parameters) {
10800 src += '?' + parameters;
10801 }
10802 return ''
10803 + '<iframe src="' + src + '"'
10804 + ' width="100%" height="100%"'
10805 + ' frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
10806 ;
10807 },
10808 placeholder : function(image, icon) {
10809 var
10810 html = ''
10811 ;
10812 if(icon) {
10813 html += '<i class="' + icon + ' icon"></i>';
10814 }
10815 if(image) {
10816 html += '<img class="placeholder" src="' + image + '">';
10817 }
10818 return html;
10819 }
10820 },
10821
10822 // NOT YET IMPLEMENTED
10823 api : false,
10824 onPause : function() {},
10825 onPlay : function() {},
10826 onStop : function() {}
10827
10828};
10829
10830
10831
10832})( jQuery, window, document );
10833
10834/*!
10835 * # Semantic UI 2.7.2 - Modal
10836 * http://github.com/semantic-org/semantic-ui/
10837 *
10838 *
10839 * Released under the MIT license
10840 * http://opensource.org/licenses/MIT
10841 *
10842 */
10843
10844;(function ($, window, document, undefined) {
10845
10846'use strict';
10847
10848$.isFunction = $.isFunction || function(obj) {
10849 return typeof obj === "function" && typeof obj.nodeType !== "number";
10850};
10851
10852window = (typeof window != 'undefined' && window.Math == Math)
10853 ? window
10854 : (typeof self != 'undefined' && self.Math == Math)
10855 ? self
10856 : Function('return this')()
10857;
10858
10859$.fn.modal = function(parameters) {
10860 var
10861 $allModules = $(this),
10862 $window = $(window),
10863 $document = $(document),
10864 $body = $('body'),
10865
10866 moduleSelector = $allModules.selector || '',
10867
10868 time = new Date().getTime(),
10869 performance = [],
10870
10871 query = arguments[0],
10872 methodInvoked = (typeof query == 'string'),
10873 queryArguments = [].slice.call(arguments, 1),
10874
10875 requestAnimationFrame = window.requestAnimationFrame
10876 || window.mozRequestAnimationFrame
10877 || window.webkitRequestAnimationFrame
10878 || window.msRequestAnimationFrame
10879 || function(callback) { setTimeout(callback, 0); },
10880
10881 returnedValue
10882 ;
10883
10884 $allModules
10885 .each(function() {
10886 var
10887 settings = ( $.isPlainObject(parameters) )
10888 ? $.extend(true, {}, $.fn.modal.settings, parameters)
10889 : $.extend({}, $.fn.modal.settings),
10890
10891 selector = settings.selector,
10892 className = settings.className,
10893 namespace = settings.namespace,
10894 error = settings.error,
10895
10896 eventNamespace = '.' + namespace,
10897 moduleNamespace = 'module-' + namespace,
10898
10899 $module = $(this),
10900 $context = $(settings.context),
10901 $close = $module.find(selector.close),
10902
10903 $allModals,
10904 $otherModals,
10905 $focusedElement,
10906 $dimmable,
10907 $dimmer,
10908
10909 element = this,
10910 instance = $module.data(moduleNamespace),
10911
10912 ignoreRepeatedEvents = false,
10913
10914 initialMouseDownInModal,
10915 initialMouseDownInScrollbar,
10916 initialBodyMargin = '',
10917
10918 elementEventNamespace,
10919 id,
10920 observer,
10921 module
10922 ;
10923 module = {
10924
10925 initialize: function() {
10926 module.verbose('Initializing dimmer', $context);
10927
10928 module.create.id();
10929 module.create.dimmer();
10930
10931 if ( settings.allowMultiple ) {
10932 module.create.innerDimmer();
10933 }
10934 if (!settings.centered){
10935 $module.addClass('top aligned');
10936 }
10937 module.refreshModals();
10938
10939 module.bind.events();
10940 if(settings.observeChanges) {
10941 module.observeChanges();
10942 }
10943 module.instantiate();
10944 },
10945
10946 instantiate: function() {
10947 module.verbose('Storing instance of modal');
10948 instance = module;
10949 $module
10950 .data(moduleNamespace, instance)
10951 ;
10952 },
10953
10954 create: {
10955 dimmer: function() {
10956 var
10957 defaultSettings = {
10958 debug : settings.debug,
10959 dimmerName : 'modals'
10960 },
10961 dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
10962 ;
10963 if($.fn.dimmer === undefined) {
10964 module.error(error.dimmer);
10965 return;
10966 }
10967 module.debug('Creating dimmer');
10968 $dimmable = $context.dimmer(dimmerSettings);
10969 if(settings.detachable) {
10970 module.verbose('Modal is detachable, moving content into dimmer');
10971 $dimmable.dimmer('add content', $module);
10972 }
10973 else {
10974 module.set.undetached();
10975 }
10976 $dimmer = $dimmable.dimmer('get dimmer');
10977 },
10978 id: function() {
10979 id = (Math.random().toString(16) + '000000000').substr(2, 8);
10980 elementEventNamespace = '.' + id;
10981 module.verbose('Creating unique id for element', id);
10982 },
10983 innerDimmer: function() {
10984 if ( $module.find(selector.dimmer).length == 0 ) {
10985 $module.prepend('<div class="ui inverted dimmer"></div>');
10986 }
10987 }
10988 },
10989
10990 destroy: function() {
10991 module.verbose('Destroying previous modal');
10992 $module
10993 .removeData(moduleNamespace)
10994 .off(eventNamespace)
10995 ;
10996 $window.off(elementEventNamespace);
10997 $dimmer.off(elementEventNamespace);
10998 $close.off(eventNamespace);
10999 $context.dimmer('destroy');
11000 },
11001
11002 observeChanges: function() {
11003 if('MutationObserver' in window) {
11004 observer = new MutationObserver(function(mutations) {
11005 module.debug('DOM tree modified, refreshing');
11006 module.refresh();
11007 });
11008 observer.observe(element, {
11009 childList : true,
11010 subtree : true
11011 });
11012 module.debug('Setting up mutation observer', observer);
11013 }
11014 },
11015
11016 refresh: function() {
11017 module.remove.scrolling();
11018 module.cacheSizes();
11019 if(!module.can.useFlex()) {
11020 module.set.modalOffset();
11021 }
11022 module.set.screenHeight();
11023 module.set.type();
11024 },
11025
11026 refreshModals: function() {
11027 $otherModals = $module.siblings(selector.modal);
11028 $allModals = $otherModals.add($module);
11029 },
11030
11031 attachEvents: function(selector, event) {
11032 var
11033 $toggle = $(selector)
11034 ;
11035 event = $.isFunction(module[event])
11036 ? module[event]
11037 : module.toggle
11038 ;
11039 if($toggle.length > 0) {
11040 module.debug('Attaching modal events to element', selector, event);
11041 $toggle
11042 .off(eventNamespace)
11043 .on('click' + eventNamespace, event)
11044 ;
11045 }
11046 else {
11047 module.error(error.notFound, selector);
11048 }
11049 },
11050
11051 bind: {
11052 events: function() {
11053 module.verbose('Attaching events');
11054 $module
11055 .on('click' + eventNamespace, selector.close, module.event.close)
11056 .on('click' + eventNamespace, selector.approve, module.event.approve)
11057 .on('click' + eventNamespace, selector.deny, module.event.deny)
11058 ;
11059 $window
11060 .on('resize' + elementEventNamespace, module.event.resize)
11061 ;
11062 },
11063 scrollLock: function() {
11064 // touch events default to passive, due to changes in chrome to optimize mobile perf
11065 $dimmable.get(0).addEventListener('touchmove', module.event.preventScroll, { passive: false });
11066 }
11067 },
11068
11069 unbind: {
11070 scrollLock: function() {
11071 $dimmable.get(0).removeEventListener('touchmove', module.event.preventScroll, { passive: false });
11072 }
11073 },
11074
11075 get: {
11076 id: function() {
11077 return (Math.random().toString(16) + '000000000').substr(2, 8);
11078 }
11079 },
11080
11081 event: {
11082 approve: function() {
11083 if(ignoreRepeatedEvents || settings.onApprove.call(element, $(this)) === false) {
11084 module.verbose('Approve callback returned false cancelling hide');
11085 return;
11086 }
11087 ignoreRepeatedEvents = true;
11088 module.hide(function() {
11089 ignoreRepeatedEvents = false;
11090 });
11091 },
11092 preventScroll: function(event) {
11093 if(event.target.className.indexOf('dimmer') !== -1) {
11094 event.preventDefault();
11095 }
11096 },
11097 deny: function() {
11098 if(ignoreRepeatedEvents || settings.onDeny.call(element, $(this)) === false) {
11099 module.verbose('Deny callback returned false cancelling hide');
11100 return;
11101 }
11102 ignoreRepeatedEvents = true;
11103 module.hide(function() {
11104 ignoreRepeatedEvents = false;
11105 });
11106 },
11107 close: function() {
11108 module.hide();
11109 },
11110 mousedown: function(event) {
11111 var
11112 $target = $(event.target)
11113 ;
11114 initialMouseDownInModal = ($target.closest(selector.modal).length > 0);
11115 if(initialMouseDownInModal) {
11116 module.verbose('Mouse down event registered inside the modal');
11117 }
11118 initialMouseDownInScrollbar = module.is.scrolling() && $(window).outerWidth() - settings.scrollbarWidth <= event.clientX;
11119 if(initialMouseDownInScrollbar) {
11120 module.verbose('Mouse down event registered inside the scrollbar');
11121 }
11122 },
11123 mouseup: function(event) {
11124 if(!settings.closable) {
11125 module.verbose('Dimmer clicked but closable setting is disabled');
11126 return;
11127 }
11128 if(initialMouseDownInModal) {
11129 module.debug('Dimmer clicked but mouse down was initially registered inside the modal');
11130 return;
11131 }
11132 if(initialMouseDownInScrollbar){
11133 module.debug('Dimmer clicked but mouse down was initially registered inside the scrollbar');
11134 return;
11135 }
11136 var
11137 $target = $(event.target),
11138 isInModal = ($target.closest(selector.modal).length > 0),
11139 isInDOM = $.contains(document.documentElement, event.target)
11140 ;
11141 if(!isInModal && isInDOM && module.is.active() && $module.hasClass(className.front) ) {
11142 module.debug('Dimmer clicked, hiding all modals');
11143 if(settings.allowMultiple) {
11144 if(!module.hideAll()) {
11145 return;
11146 }
11147 }
11148 else if(!module.hide()){
11149 return;
11150 }
11151 module.remove.clickaway();
11152 }
11153 },
11154 debounce: function(method, delay) {
11155 clearTimeout(module.timer);
11156 module.timer = setTimeout(method, delay);
11157 },
11158 keyboard: function(event) {
11159 var
11160 keyCode = event.which,
11161 escapeKey = 27
11162 ;
11163 if(keyCode == escapeKey) {
11164 if(settings.closable) {
11165 module.debug('Escape key pressed hiding modal');
11166 if ( $module.hasClass(className.front) ) {
11167 module.hide();
11168 }
11169 }
11170 else {
11171 module.debug('Escape key pressed, but closable is set to false');
11172 }
11173 event.preventDefault();
11174 }
11175 },
11176 resize: function() {
11177 if( $dimmable.dimmer('is active') && ( module.is.animating() || module.is.active() ) ) {
11178 requestAnimationFrame(module.refresh);
11179 }
11180 }
11181 },
11182
11183 toggle: function() {
11184 if( module.is.active() || module.is.animating() ) {
11185 module.hide();
11186 }
11187 else {
11188 module.show();
11189 }
11190 },
11191
11192 show: function(callback) {
11193 callback = $.isFunction(callback)
11194 ? callback
11195 : function(){}
11196 ;
11197 module.refreshModals();
11198 module.set.dimmerSettings();
11199 module.set.dimmerStyles();
11200
11201 module.showModal(callback);
11202 },
11203
11204 hide: function(callback) {
11205 callback = $.isFunction(callback)
11206 ? callback
11207 : function(){}
11208 ;
11209 module.refreshModals();
11210 return module.hideModal(callback);
11211 },
11212
11213 showModal: function(callback) {
11214 callback = $.isFunction(callback)
11215 ? callback
11216 : function(){}
11217 ;
11218 if( module.is.animating() || !module.is.active() ) {
11219 module.showDimmer();
11220 module.cacheSizes();
11221 if(module.can.useFlex()) {
11222 module.remove.legacy();
11223 }
11224 else {
11225 module.set.legacy();
11226 module.set.modalOffset();
11227 module.debug('Using non-flex legacy modal positioning.');
11228 }
11229 module.set.screenHeight();
11230 module.set.type();
11231 module.set.clickaway();
11232
11233 if( !settings.allowMultiple && module.others.active() ) {
11234 module.hideOthers(module.showModal);
11235 }
11236 else {
11237 ignoreRepeatedEvents = false;
11238 if( settings.allowMultiple ) {
11239 if ( module.others.active() ) {
11240 $otherModals.filter('.' + className.active).find(selector.dimmer).addClass('active');
11241 }
11242
11243 if ( settings.detachable ) {
11244 $module.detach().appendTo($dimmer);
11245 }
11246 }
11247 settings.onShow.call(element);
11248 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
11249 module.debug('Showing modal with css animations');
11250 $module
11251 .transition({
11252 debug : settings.debug,
11253 animation : settings.transition + ' in',
11254 queue : settings.queue,
11255 duration : settings.duration,
11256 useFailSafe : true,
11257 onComplete : function() {
11258 settings.onVisible.apply(element);
11259 if(settings.keyboardShortcuts) {
11260 module.add.keyboardShortcuts();
11261 }
11262 module.save.focus();
11263 module.set.active();
11264 if(settings.autofocus) {
11265 module.set.autofocus();
11266 }
11267 callback();
11268 }
11269 })
11270 ;
11271 }
11272 else {
11273 module.error(error.noTransition);
11274 }
11275 }
11276 }
11277 else {
11278 module.debug('Modal is already visible');
11279 }
11280 },
11281
11282 hideModal: function(callback, keepDimmed, hideOthersToo) {
11283 var
11284 $previousModal = $otherModals.filter('.' + className.active).last()
11285 ;
11286 callback = $.isFunction(callback)
11287 ? callback
11288 : function(){}
11289 ;
11290 module.debug('Hiding modal');
11291 if(settings.onHide.call(element, $(this)) === false) {
11292 module.verbose('Hide callback returned false cancelling hide');
11293 ignoreRepeatedEvents = false;
11294 return false;
11295 }
11296
11297 if( module.is.animating() || module.is.active() ) {
11298 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
11299 module.remove.active();
11300 $module
11301 .transition({
11302 debug : settings.debug,
11303 animation : settings.transition + ' out',
11304 queue : settings.queue,
11305 duration : settings.duration,
11306 useFailSafe : true,
11307 onStart : function() {
11308 if(!module.others.active() && !keepDimmed) {
11309 module.hideDimmer();
11310 }
11311 if( settings.keyboardShortcuts && !module.others.active() ) {
11312 module.remove.keyboardShortcuts();
11313 }
11314 },
11315 onComplete : function() {
11316 module.unbind.scrollLock();
11317 if ( settings.allowMultiple ) {
11318 $previousModal.addClass(className.front);
11319 $module.removeClass(className.front);
11320
11321 if ( hideOthersToo ) {
11322 $allModals.find(selector.dimmer).removeClass('active');
11323 }
11324 else {
11325 $previousModal.find(selector.dimmer).removeClass('active');
11326 }
11327 }
11328 settings.onHidden.call(element);
11329 module.remove.dimmerStyles();
11330 module.restore.focus();
11331 callback();
11332 }
11333 })
11334 ;
11335 }
11336 else {
11337 module.error(error.noTransition);
11338 }
11339 }
11340 },
11341
11342 showDimmer: function() {
11343 if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
11344 module.save.bodyMargin();
11345 module.debug('Showing dimmer');
11346 $dimmable.dimmer('show');
11347 }
11348 else {
11349 module.debug('Dimmer already visible');
11350 }
11351 },
11352
11353 hideDimmer: function() {
11354 if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
11355 module.unbind.scrollLock();
11356 $dimmable.dimmer('hide', function() {
11357 module.restore.bodyMargin();
11358 module.remove.clickaway();
11359 module.remove.screenHeight();
11360 });
11361 }
11362 else {
11363 module.debug('Dimmer is not visible cannot hide');
11364 return;
11365 }
11366 },
11367
11368 hideAll: function(callback) {
11369 var
11370 $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
11371 ;
11372 callback = $.isFunction(callback)
11373 ? callback
11374 : function(){}
11375 ;
11376 if( $visibleModals.length > 0 ) {
11377 module.debug('Hiding all visible modals');
11378 var hideOk = true;
11379//check in reverse order trying to hide most top displayed modal first
11380 $($visibleModals.get().reverse()).each(function(index,element){
11381 if(hideOk){
11382 hideOk = $(element).modal('hide modal', callback, false, true);
11383 }
11384 });
11385 if(hideOk) {
11386 module.hideDimmer();
11387 }
11388 return hideOk;
11389 }
11390 },
11391
11392 hideOthers: function(callback) {
11393 var
11394 $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
11395 ;
11396 callback = $.isFunction(callback)
11397 ? callback
11398 : function(){}
11399 ;
11400 if( $visibleModals.length > 0 ) {
11401 module.debug('Hiding other modals', $otherModals);
11402 $visibleModals
11403 .modal('hide modal', callback, true)
11404 ;
11405 }
11406 },
11407
11408 others: {
11409 active: function() {
11410 return ($otherModals.filter('.' + className.active).length > 0);
11411 },
11412 animating: function() {
11413 return ($otherModals.filter('.' + className.animating).length > 0);
11414 }
11415 },
11416
11417
11418 add: {
11419 keyboardShortcuts: function() {
11420 module.verbose('Adding keyboard shortcuts');
11421 $document
11422 .on('keyup' + eventNamespace, module.event.keyboard)
11423 ;
11424 }
11425 },
11426
11427 save: {
11428 focus: function() {
11429 var
11430 $activeElement = $(document.activeElement),
11431 inCurrentModal = $activeElement.closest($module).length > 0
11432 ;
11433 if(!inCurrentModal) {
11434 $focusedElement = $(document.activeElement).blur();
11435 }
11436 },
11437 bodyMargin: function() {
11438 initialBodyMargin = $body.css('margin-right');
11439 var bodyMarginRightPixel = parseInt(initialBodyMargin.replace(/[^\d.]/g, '')),
11440 bodyScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
11441 $body.css('margin-right', (bodyMarginRightPixel + bodyScrollbarWidth) + 'px');
11442 }
11443 },
11444
11445 restore: {
11446 focus: function() {
11447 if($focusedElement && $focusedElement.length > 0 && settings.restoreFocus) {
11448 $focusedElement.focus();
11449 }
11450 },
11451 bodyMargin: function() {
11452 $body.css('margin-right', initialBodyMargin);
11453 }
11454 },
11455
11456 remove: {
11457 active: function() {
11458 $module.removeClass(className.active);
11459 },
11460 legacy: function() {
11461 $module.removeClass(className.legacy);
11462 },
11463 clickaway: function() {
11464 $dimmer
11465 .off('mousedown' + elementEventNamespace)
11466 ;
11467 $dimmer
11468 .off('mouseup' + elementEventNamespace)
11469 ;
11470 },
11471 dimmerStyles: function() {
11472 $dimmer.removeClass(className.inverted);
11473 $dimmable.removeClass(className.blurring);
11474 },
11475 bodyStyle: function() {
11476 if($body.attr('style') === '') {
11477 module.verbose('Removing style attribute');
11478 $body.removeAttr('style');
11479 }
11480 },
11481 screenHeight: function() {
11482 module.debug('Removing page height');
11483 $body
11484 .css('height', '')
11485 ;
11486 },
11487 keyboardShortcuts: function() {
11488 module.verbose('Removing keyboard shortcuts');
11489 $document
11490 .off('keyup' + eventNamespace)
11491 ;
11492 },
11493 scrolling: function() {
11494 $dimmable.removeClass(className.scrolling);
11495 $module.removeClass(className.scrolling);
11496 }
11497 },
11498
11499 cacheSizes: function() {
11500 $module.addClass(className.loading);
11501 var
11502 scrollHeight = $module.prop('scrollHeight'),
11503 modalWidth = $module.outerWidth(),
11504 modalHeight = $module.outerHeight()
11505 ;
11506 if(module.cache === undefined || modalHeight !== 0) {
11507 module.cache = {
11508 pageHeight : $(document).outerHeight(),
11509 width : modalWidth,
11510 height : modalHeight + settings.offset,
11511 scrollHeight : scrollHeight + settings.offset,
11512 contextHeight : (settings.context == 'body')
11513 ? $(window).height()
11514 : $dimmable.height(),
11515 };
11516 module.cache.topOffset = -(module.cache.height / 2);
11517 }
11518 $module.removeClass(className.loading);
11519 module.debug('Caching modal and container sizes', module.cache);
11520 },
11521
11522 can: {
11523 useFlex: function() {
11524 return (settings.useFlex == 'auto')
11525 ? settings.detachable && !module.is.ie()
11526 : settings.useFlex
11527 ;
11528 },
11529 fit: function() {
11530 var
11531 contextHeight = module.cache.contextHeight,
11532 verticalCenter = module.cache.contextHeight / 2,
11533 topOffset = module.cache.topOffset,
11534 scrollHeight = module.cache.scrollHeight,
11535 height = module.cache.height,
11536 paddingHeight = settings.padding,
11537 startPosition = (verticalCenter + topOffset)
11538 ;
11539 return (scrollHeight > height)
11540 ? (startPosition + scrollHeight + paddingHeight < contextHeight)
11541 : (height + (paddingHeight * 2) < contextHeight)
11542 ;
11543 }
11544 },
11545
11546 is: {
11547 active: function() {
11548 return $module.hasClass(className.active);
11549 },
11550 ie: function() {
11551 var
11552 isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
11553 isIE = ('ActiveXObject' in window)
11554 ;
11555 return (isIE11 || isIE);
11556 },
11557 animating: function() {
11558 return $module.transition('is supported')
11559 ? $module.transition('is animating')
11560 : $module.is(':visible')
11561 ;
11562 },
11563 scrolling: function() {
11564 return $dimmable.hasClass(className.scrolling);
11565 },
11566 modernBrowser: function() {
11567 // appName for IE11 reports 'Netscape' can no longer use
11568 return !(window.ActiveXObject || 'ActiveXObject' in window);
11569 }
11570 },
11571
11572 set: {
11573 autofocus: function() {
11574 var
11575 $inputs = $module.find('[tabindex], :input').filter(':visible'),
11576 $autofocus = $inputs.filter('[autofocus]'),
11577 $input = ($autofocus.length > 0)
11578 ? $autofocus.first()
11579 : $inputs.first()
11580 ;
11581 if($input.length > 0) {
11582 $input.focus();
11583 }
11584 },
11585 clickaway: function() {
11586 $dimmer
11587 .on('mousedown' + elementEventNamespace, module.event.mousedown)
11588 ;
11589 $dimmer
11590 .on('mouseup' + elementEventNamespace, module.event.mouseup)
11591 ;
11592 },
11593 dimmerSettings: function() {
11594 if($.fn.dimmer === undefined) {
11595 module.error(error.dimmer);
11596 return;
11597 }
11598 var
11599 defaultSettings = {
11600 debug : settings.debug,
11601 dimmerName : 'modals',
11602 closable : 'auto',
11603 useFlex : module.can.useFlex(),
11604 duration : {
11605 show : settings.duration,
11606 hide : settings.duration
11607 }
11608 },
11609 dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
11610 ;
11611 if(settings.inverted) {
11612 dimmerSettings.variation = (dimmerSettings.variation !== undefined)
11613 ? dimmerSettings.variation + ' inverted'
11614 : 'inverted'
11615 ;
11616 }
11617 $context.dimmer('setting', dimmerSettings);
11618 },
11619 dimmerStyles: function() {
11620 if(settings.inverted) {
11621 $dimmer.addClass(className.inverted);
11622 }
11623 else {
11624 $dimmer.removeClass(className.inverted);
11625 }
11626 if(settings.blurring) {
11627 $dimmable.addClass(className.blurring);
11628 }
11629 else {
11630 $dimmable.removeClass(className.blurring);
11631 }
11632 },
11633 modalOffset: function() {
11634 var
11635 width = module.cache.width,
11636 height = module.cache.height
11637 ;
11638 $module
11639 .css({
11640 marginTop: (!$module.hasClass('aligned') && module.can.fit())
11641 ? -(height / 2)
11642 : 0,
11643 marginLeft: -(width / 2)
11644 })
11645 ;
11646 module.verbose('Setting modal offset for legacy mode');
11647 },
11648 screenHeight: function() {
11649 if( module.can.fit() ) {
11650 $body.css('height', '');
11651 }
11652 else if(!$module.hasClass('bottom')) {
11653 module.debug('Modal is taller than page content, resizing page height');
11654 $body
11655 .css('height', module.cache.height + (settings.padding * 2) )
11656 ;
11657 }
11658 },
11659 active: function() {
11660 $module.addClass(className.active + ' ' + className.front);
11661 $otherModals.filter('.' + className.active).removeClass(className.front);
11662 },
11663 scrolling: function() {
11664 $dimmable.addClass(className.scrolling);
11665 $module.addClass(className.scrolling);
11666 module.unbind.scrollLock();
11667 },
11668 legacy: function() {
11669 $module.addClass(className.legacy);
11670 },
11671 type: function() {
11672 if(module.can.fit()) {
11673 module.verbose('Modal fits on screen');
11674 if(!module.others.active() && !module.others.animating()) {
11675 module.remove.scrolling();
11676 module.bind.scrollLock();
11677 }
11678 }
11679 else if (!$module.hasClass('bottom')){
11680 module.verbose('Modal cannot fit on screen setting to scrolling');
11681 module.set.scrolling();
11682 } else {
11683 module.verbose('Bottom aligned modal not fitting on screen is unsupported for scrolling');
11684 }
11685 },
11686 undetached: function() {
11687 $dimmable.addClass(className.undetached);
11688 }
11689 },
11690
11691 setting: function(name, value) {
11692 module.debug('Changing setting', name, value);
11693 if( $.isPlainObject(name) ) {
11694 $.extend(true, settings, name);
11695 }
11696 else if(value !== undefined) {
11697 if($.isPlainObject(settings[name])) {
11698 $.extend(true, settings[name], value);
11699 }
11700 else {
11701 settings[name] = value;
11702 }
11703 }
11704 else {
11705 return settings[name];
11706 }
11707 },
11708 internal: function(name, value) {
11709 if( $.isPlainObject(name) ) {
11710 $.extend(true, module, name);
11711 }
11712 else if(value !== undefined) {
11713 module[name] = value;
11714 }
11715 else {
11716 return module[name];
11717 }
11718 },
11719 debug: function() {
11720 if(!settings.silent && settings.debug) {
11721 if(settings.performance) {
11722 module.performance.log(arguments);
11723 }
11724 else {
11725 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
11726 module.debug.apply(console, arguments);
11727 }
11728 }
11729 },
11730 verbose: function() {
11731 if(!settings.silent && settings.verbose && settings.debug) {
11732 if(settings.performance) {
11733 module.performance.log(arguments);
11734 }
11735 else {
11736 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
11737 module.verbose.apply(console, arguments);
11738 }
11739 }
11740 },
11741 error: function() {
11742 if(!settings.silent) {
11743 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
11744 module.error.apply(console, arguments);
11745 }
11746 },
11747 performance: {
11748 log: function(message) {
11749 var
11750 currentTime,
11751 executionTime,
11752 previousTime
11753 ;
11754 if(settings.performance) {
11755 currentTime = new Date().getTime();
11756 previousTime = time || currentTime;
11757 executionTime = currentTime - previousTime;
11758 time = currentTime;
11759 performance.push({
11760 'Name' : message[0],
11761 'Arguments' : [].slice.call(message, 1) || '',
11762 'Element' : element,
11763 'Execution Time' : executionTime
11764 });
11765 }
11766 clearTimeout(module.performance.timer);
11767 module.performance.timer = setTimeout(module.performance.display, 500);
11768 },
11769 display: function() {
11770 var
11771 title = settings.name + ':',
11772 totalTime = 0
11773 ;
11774 time = false;
11775 clearTimeout(module.performance.timer);
11776 $.each(performance, function(index, data) {
11777 totalTime += data['Execution Time'];
11778 });
11779 title += ' ' + totalTime + 'ms';
11780 if(moduleSelector) {
11781 title += ' \'' + moduleSelector + '\'';
11782 }
11783 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
11784 console.groupCollapsed(title);
11785 if(console.table) {
11786 console.table(performance);
11787 }
11788 else {
11789 $.each(performance, function(index, data) {
11790 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
11791 });
11792 }
11793 console.groupEnd();
11794 }
11795 performance = [];
11796 }
11797 },
11798 invoke: function(query, passedArguments, context) {
11799 var
11800 object = instance,
11801 maxDepth,
11802 found,
11803 response
11804 ;
11805 passedArguments = passedArguments || queryArguments;
11806 context = element || context;
11807 if(typeof query == 'string' && object !== undefined) {
11808 query = query.split(/[\. ]/);
11809 maxDepth = query.length - 1;
11810 $.each(query, function(depth, value) {
11811 var camelCaseValue = (depth != maxDepth)
11812 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
11813 : query
11814 ;
11815 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
11816 object = object[camelCaseValue];
11817 }
11818 else if( object[camelCaseValue] !== undefined ) {
11819 found = object[camelCaseValue];
11820 return false;
11821 }
11822 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
11823 object = object[value];
11824 }
11825 else if( object[value] !== undefined ) {
11826 found = object[value];
11827 return false;
11828 }
11829 else {
11830 return false;
11831 }
11832 });
11833 }
11834 if ( $.isFunction( found ) ) {
11835 response = found.apply(context, passedArguments);
11836 }
11837 else if(found !== undefined) {
11838 response = found;
11839 }
11840 if(Array.isArray(returnedValue)) {
11841 returnedValue.push(response);
11842 }
11843 else if(returnedValue !== undefined) {
11844 returnedValue = [returnedValue, response];
11845 }
11846 else if(response !== undefined) {
11847 returnedValue = response;
11848 }
11849 return found;
11850 }
11851 };
11852
11853 if(methodInvoked) {
11854 if(instance === undefined) {
11855 module.initialize();
11856 }
11857 module.invoke(query);
11858 }
11859 else {
11860 if(instance !== undefined) {
11861 instance.invoke('destroy');
11862 }
11863 module.initialize();
11864 }
11865 })
11866 ;
11867
11868 return (returnedValue !== undefined)
11869 ? returnedValue
11870 : this
11871 ;
11872};
11873
11874$.fn.modal.settings = {
11875
11876 name : 'Modal',
11877 namespace : 'modal',
11878
11879 useFlex : 'auto',
11880 offset : 0,
11881
11882 silent : false,
11883 debug : false,
11884 verbose : false,
11885 performance : true,
11886
11887 observeChanges : false,
11888
11889 allowMultiple : false,
11890 detachable : true,
11891 closable : true,
11892 autofocus : true,
11893 restoreFocus : true,
11894
11895 inverted : false,
11896 blurring : false,
11897
11898 centered : true,
11899
11900 dimmerSettings : {
11901 closable : false,
11902 useCSS : true
11903 },
11904
11905 // whether to use keyboard shortcuts
11906 keyboardShortcuts: true,
11907
11908 context : 'body',
11909
11910 queue : false,
11911 duration : 500,
11912 transition : 'scale',
11913
11914 // padding with edge of page
11915 padding : 50,
11916 scrollbarWidth: 10,
11917
11918 // called before show animation
11919 onShow : function(){},
11920
11921 // called after show animation
11922 onVisible : function(){},
11923
11924 // called before hide animation
11925 onHide : function(){ return true; },
11926
11927 // called after hide animation
11928 onHidden : function(){},
11929
11930 // called after approve selector match
11931 onApprove : function(){ return true; },
11932
11933 // called after deny selector match
11934 onDeny : function(){ return true; },
11935
11936 selector : {
11937 close : '> .close',
11938 approve : '.actions .positive, .actions .approve, .actions .ok',
11939 deny : '.actions .negative, .actions .deny, .actions .cancel',
11940 modal : '.ui.modal',
11941 dimmer : '> .ui.dimmer'
11942 },
11943 error : {
11944 dimmer : 'UI Dimmer, a required component is not included in this page',
11945 method : 'The method you called is not defined.',
11946 notFound : 'The element you specified could not be found'
11947 },
11948 className : {
11949 active : 'active',
11950 animating : 'animating',
11951 blurring : 'blurring',
11952 inverted : 'inverted',
11953 legacy : 'legacy',
11954 loading : 'loading',
11955 scrolling : 'scrolling',
11956 undetached : 'undetached',
11957 front : 'front'
11958 }
11959};
11960
11961
11962})( jQuery, window, document );
11963
11964/*!
11965 * # Semantic UI 2.7.2 - Nag
11966 * http://github.com/semantic-org/semantic-ui/
11967 *
11968 *
11969 * Released under the MIT license
11970 * http://opensource.org/licenses/MIT
11971 *
11972 */
11973
11974;(function ($, window, document, undefined) {
11975
11976'use strict';
11977
11978$.isFunction = $.isFunction || function(obj) {
11979 return typeof obj === "function" && typeof obj.nodeType !== "number";
11980};
11981
11982window = (typeof window != 'undefined' && window.Math == Math)
11983 ? window
11984 : (typeof self != 'undefined' && self.Math == Math)
11985 ? self
11986 : Function('return this')()
11987;
11988
11989$.fn.nag = function(parameters) {
11990 var
11991 $allModules = $(this),
11992 moduleSelector = $allModules.selector || '',
11993
11994 time = new Date().getTime(),
11995 performance = [],
11996
11997 query = arguments[0],
11998 methodInvoked = (typeof query == 'string'),
11999 queryArguments = [].slice.call(arguments, 1),
12000 returnedValue
12001 ;
12002 $allModules
12003 .each(function() {
12004 var
12005 settings = ( $.isPlainObject(parameters) )
12006 ? $.extend(true, {}, $.fn.nag.settings, parameters)
12007 : $.extend({}, $.fn.nag.settings),
12008
12009 selector = settings.selector,
12010 error = settings.error,
12011 namespace = settings.namespace,
12012
12013 eventNamespace = '.' + namespace,
12014 moduleNamespace = namespace + '-module',
12015
12016 $module = $(this),
12017
12018 $context = (settings.context)
12019 ? $(settings.context)
12020 : $('body'),
12021
12022 element = this,
12023 instance = $module.data(moduleNamespace),
12024
12025 module
12026 ;
12027 module = {
12028
12029 initialize: function() {
12030 module.verbose('Initializing element');
12031
12032 $module
12033 .on('click' + eventNamespace, selector.close, module.dismiss)
12034 .data(moduleNamespace, module)
12035 ;
12036
12037 if(settings.detachable && $module.parent()[0] !== $context[0]) {
12038 $module
12039 .detach()
12040 .prependTo($context)
12041 ;
12042 }
12043
12044 if(settings.displayTime > 0) {
12045 setTimeout(module.hide, settings.displayTime);
12046 }
12047 module.show();
12048 },
12049
12050 destroy: function() {
12051 module.verbose('Destroying instance');
12052 $module
12053 .removeData(moduleNamespace)
12054 .off(eventNamespace)
12055 ;
12056 },
12057
12058 show: function() {
12059 if( module.should.show() && !$module.is(':visible') ) {
12060 module.debug('Showing nag', settings.animation.show);
12061 if(settings.animation.show == 'fade') {
12062 $module
12063 .fadeIn(settings.duration, settings.easing)
12064 ;
12065 }
12066 else {
12067 $module
12068 .slideDown(settings.duration, settings.easing)
12069 ;
12070 }
12071 }
12072 },
12073
12074 hide: function() {
12075 module.debug('Showing nag', settings.animation.hide);
12076 if(settings.animation.show == 'fade') {
12077 $module
12078 .fadeIn(settings.duration, settings.easing)
12079 ;
12080 }
12081 else {
12082 $module
12083 .slideUp(settings.duration, settings.easing)
12084 ;
12085 }
12086 },
12087
12088 onHide: function() {
12089 module.debug('Removing nag', settings.animation.hide);
12090 $module.remove();
12091 if (settings.onHide) {
12092 settings.onHide();
12093 }
12094 },
12095
12096 dismiss: function(event) {
12097 if(settings.storageMethod) {
12098 module.storage.set(settings.key, settings.value);
12099 }
12100 module.hide();
12101 event.stopImmediatePropagation();
12102 event.preventDefault();
12103 },
12104
12105 should: {
12106 show: function() {
12107 if(settings.persist) {
12108 module.debug('Persistent nag is set, can show nag');
12109 return true;
12110 }
12111 if( module.storage.get(settings.key) != settings.value.toString() ) {
12112 module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
12113 return true;
12114 }
12115 module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
12116 return false;
12117 }
12118 },
12119
12120 get: {
12121 storageOptions: function() {
12122 var
12123 options = {}
12124 ;
12125 if(settings.expires) {
12126 options.expires = settings.expires;
12127 }
12128 if(settings.domain) {
12129 options.domain = settings.domain;
12130 }
12131 if(settings.path) {
12132 options.path = settings.path;
12133 }
12134 return options;
12135 }
12136 },
12137
12138 clear: function() {
12139 module.storage.remove(settings.key);
12140 },
12141
12142 storage: {
12143 set: function(key, value) {
12144 var
12145 options = module.get.storageOptions()
12146 ;
12147 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
12148 window.localStorage.setItem(key, value);
12149 module.debug('Value stored using local storage', key, value);
12150 }
12151 else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
12152 window.sessionStorage.setItem(key, value);
12153 module.debug('Value stored using session storage', key, value);
12154 }
12155 else if($.cookie !== undefined) {
12156 $.cookie(key, value, options);
12157 module.debug('Value stored using cookie', key, value, options);
12158 }
12159 else {
12160 module.error(error.noCookieStorage);
12161 return;
12162 }
12163 },
12164 get: function(key, value) {
12165 var
12166 storedValue
12167 ;
12168 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
12169 storedValue = window.localStorage.getItem(key);
12170 }
12171 else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
12172 storedValue = window.sessionStorage.getItem(key);
12173 }
12174 // get by cookie
12175 else if($.cookie !== undefined) {
12176 storedValue = $.cookie(key);
12177 }
12178 else {
12179 module.error(error.noCookieStorage);
12180 }
12181 if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
12182 storedValue = undefined;
12183 }
12184 return storedValue;
12185 },
12186 remove: function(key) {
12187 var
12188 options = module.get.storageOptions()
12189 ;
12190 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
12191 window.localStorage.removeItem(key);
12192 }
12193 else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
12194 window.sessionStorage.removeItem(key);
12195 }
12196 // store by cookie
12197 else if($.cookie !== undefined) {
12198 $.removeCookie(key, options);
12199 }
12200 else {
12201 module.error(error.noStorage);
12202 }
12203 }
12204 },
12205
12206 setting: function(name, value) {
12207 module.debug('Changing setting', name, value);
12208 if( $.isPlainObject(name) ) {
12209 $.extend(true, settings, name);
12210 }
12211 else if(value !== undefined) {
12212 if($.isPlainObject(settings[name])) {
12213 $.extend(true, settings[name], value);
12214 }
12215 else {
12216 settings[name] = value;
12217 }
12218 }
12219 else {
12220 return settings[name];
12221 }
12222 },
12223 internal: function(name, value) {
12224 if( $.isPlainObject(name) ) {
12225 $.extend(true, module, name);
12226 }
12227 else if(value !== undefined) {
12228 module[name] = value;
12229 }
12230 else {
12231 return module[name];
12232 }
12233 },
12234 debug: function() {
12235 if(!settings.silent && settings.debug) {
12236 if(settings.performance) {
12237 module.performance.log(arguments);
12238 }
12239 else {
12240 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
12241 module.debug.apply(console, arguments);
12242 }
12243 }
12244 },
12245 verbose: function() {
12246 if(!settings.silent && settings.verbose && settings.debug) {
12247 if(settings.performance) {
12248 module.performance.log(arguments);
12249 }
12250 else {
12251 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
12252 module.verbose.apply(console, arguments);
12253 }
12254 }
12255 },
12256 error: function() {
12257 if(!settings.silent) {
12258 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
12259 module.error.apply(console, arguments);
12260 }
12261 },
12262 performance: {
12263 log: function(message) {
12264 var
12265 currentTime,
12266 executionTime,
12267 previousTime
12268 ;
12269 if(settings.performance) {
12270 currentTime = new Date().getTime();
12271 previousTime = time || currentTime;
12272 executionTime = currentTime - previousTime;
12273 time = currentTime;
12274 performance.push({
12275 'Name' : message[0],
12276 'Arguments' : [].slice.call(message, 1) || '',
12277 'Element' : element,
12278 'Execution Time' : executionTime
12279 });
12280 }
12281 clearTimeout(module.performance.timer);
12282 module.performance.timer = setTimeout(module.performance.display, 500);
12283 },
12284 display: function() {
12285 var
12286 title = settings.name + ':',
12287 totalTime = 0
12288 ;
12289 time = false;
12290 clearTimeout(module.performance.timer);
12291 $.each(performance, function(index, data) {
12292 totalTime += data['Execution Time'];
12293 });
12294 title += ' ' + totalTime + 'ms';
12295 if(moduleSelector) {
12296 title += ' \'' + moduleSelector + '\'';
12297 }
12298 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
12299 console.groupCollapsed(title);
12300 if(console.table) {
12301 console.table(performance);
12302 }
12303 else {
12304 $.each(performance, function(index, data) {
12305 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
12306 });
12307 }
12308 console.groupEnd();
12309 }
12310 performance = [];
12311 }
12312 },
12313 invoke: function(query, passedArguments, context) {
12314 var
12315 object = instance,
12316 maxDepth,
12317 found,
12318 response
12319 ;
12320 passedArguments = passedArguments || queryArguments;
12321 context = element || context;
12322 if(typeof query == 'string' && object !== undefined) {
12323 query = query.split(/[\. ]/);
12324 maxDepth = query.length - 1;
12325 $.each(query, function(depth, value) {
12326 var camelCaseValue = (depth != maxDepth)
12327 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
12328 : query
12329 ;
12330 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
12331 object = object[camelCaseValue];
12332 }
12333 else if( object[camelCaseValue] !== undefined ) {
12334 found = object[camelCaseValue];
12335 return false;
12336 }
12337 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
12338 object = object[value];
12339 }
12340 else if( object[value] !== undefined ) {
12341 found = object[value];
12342 return false;
12343 }
12344 else {
12345 module.error(error.method, query);
12346 return false;
12347 }
12348 });
12349 }
12350 if ( $.isFunction( found ) ) {
12351 response = found.apply(context, passedArguments);
12352 }
12353 else if(found !== undefined) {
12354 response = found;
12355 }
12356 if(Array.isArray(returnedValue)) {
12357 returnedValue.push(response);
12358 }
12359 else if(returnedValue !== undefined) {
12360 returnedValue = [returnedValue, response];
12361 }
12362 else if(response !== undefined) {
12363 returnedValue = response;
12364 }
12365 return found;
12366 }
12367 };
12368
12369 if(methodInvoked) {
12370 if(instance === undefined) {
12371 module.initialize();
12372 }
12373 module.invoke(query);
12374 }
12375 else {
12376 if(instance !== undefined) {
12377 instance.invoke('destroy');
12378 }
12379 module.initialize();
12380 }
12381 })
12382 ;
12383
12384 return (returnedValue !== undefined)
12385 ? returnedValue
12386 : this
12387 ;
12388};
12389
12390$.fn.nag.settings = {
12391
12392 name : 'Nag',
12393
12394 silent : false,
12395 debug : false,
12396 verbose : false,
12397 performance : true,
12398
12399 namespace : 'Nag',
12400
12401 // allows cookie to be overridden
12402 persist : false,
12403
12404 // set to zero to require manually dismissal, otherwise hides on its own
12405 displayTime : 0,
12406
12407 animation : {
12408 show : 'slide',
12409 hide : 'slide'
12410 },
12411
12412 context : false,
12413 detachable : false,
12414
12415 expires : 30,
12416 domain : false,
12417 path : '/',
12418
12419 // type of storage to use
12420 storageMethod : 'cookie',
12421
12422 // value to store in dismissed localstorage/cookie
12423 key : 'nag',
12424 value : 'dismiss',
12425
12426 error: {
12427 noCookieStorage : '$.cookie is not included. A storage solution is required.',
12428 noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
12429 method : 'The method you called is not defined.'
12430 },
12431
12432 className : {
12433 bottom : 'bottom',
12434 fixed : 'fixed'
12435 },
12436
12437 selector : {
12438 close : '.close.icon'
12439 },
12440
12441 speed : 500,
12442 easing : 'easeOutQuad',
12443
12444 onHide: function() {}
12445
12446};
12447
12448// Adds easing
12449$.extend( $.easing, {
12450 easeOutQuad: function (x, t, b, c, d) {
12451 return -c *(t/=d)*(t-2) + b;
12452 }
12453});
12454
12455})( jQuery, window, document );
12456
12457/*!
12458 * # Semantic UI 2.7.2 - Popup
12459 * http://github.com/semantic-org/semantic-ui/
12460 *
12461 *
12462 * Released under the MIT license
12463 * http://opensource.org/licenses/MIT
12464 *
12465 */
12466
12467;(function ($, window, document, undefined) {
12468
12469'use strict';
12470
12471$.isFunction = $.isFunction || function(obj) {
12472 return typeof obj === "function" && typeof obj.nodeType !== "number";
12473};
12474
12475window = (typeof window != 'undefined' && window.Math == Math)
12476 ? window
12477 : (typeof self != 'undefined' && self.Math == Math)
12478 ? self
12479 : Function('return this')()
12480;
12481
12482$.fn.popup = function(parameters) {
12483 var
12484 $allModules = $(this),
12485 $document = $(document),
12486 $window = $(window),
12487 $body = $('body'),
12488
12489 moduleSelector = $allModules.selector || '',
12490
12491 time = new Date().getTime(),
12492 performance = [],
12493
12494 query = arguments[0],
12495 methodInvoked = (typeof query == 'string'),
12496 queryArguments = [].slice.call(arguments, 1),
12497
12498 returnedValue
12499 ;
12500 $allModules
12501 .each(function() {
12502 var
12503 settings = ( $.isPlainObject(parameters) )
12504 ? $.extend(true, {}, $.fn.popup.settings, parameters)
12505 : $.extend({}, $.fn.popup.settings),
12506
12507 selector = settings.selector,
12508 className = settings.className,
12509 error = settings.error,
12510 metadata = settings.metadata,
12511 namespace = settings.namespace,
12512
12513 eventNamespace = '.' + settings.namespace,
12514 moduleNamespace = 'module-' + namespace,
12515
12516 $module = $(this),
12517 $context = $(settings.context),
12518 $scrollContext = $(settings.scrollContext),
12519 $boundary = $(settings.boundary),
12520 $target = (settings.target)
12521 ? $(settings.target)
12522 : $module,
12523
12524 $popup,
12525 $offsetParent,
12526
12527 searchDepth = 0,
12528 triedPositions = false,
12529 openedWithTouch = false,
12530
12531 element = this,
12532 instance = $module.data(moduleNamespace),
12533
12534 documentObserver,
12535 elementNamespace,
12536 id,
12537 module
12538 ;
12539
12540 module = {
12541
12542 // binds events
12543 initialize: function() {
12544 module.debug('Initializing', $module);
12545 module.createID();
12546 module.bind.events();
12547 if(!module.exists() && settings.preserve) {
12548 module.create();
12549 }
12550 if(settings.observeChanges) {
12551 module.observeChanges();
12552 }
12553 module.instantiate();
12554 },
12555
12556 instantiate: function() {
12557 module.verbose('Storing instance', module);
12558 instance = module;
12559 $module
12560 .data(moduleNamespace, instance)
12561 ;
12562 },
12563
12564 observeChanges: function() {
12565 if('MutationObserver' in window) {
12566 documentObserver = new MutationObserver(module.event.documentChanged);
12567 documentObserver.observe(document, {
12568 childList : true,
12569 subtree : true
12570 });
12571 module.debug('Setting up mutation observer', documentObserver);
12572 }
12573 },
12574
12575 refresh: function() {
12576 if(settings.popup) {
12577 $popup = $(settings.popup).eq(0);
12578 }
12579 else {
12580 if(settings.inline) {
12581 $popup = $target.nextAll(selector.popup).eq(0);
12582 settings.popup = $popup;
12583 }
12584 }
12585 if(settings.popup) {
12586 $popup.addClass(className.loading);
12587 $offsetParent = module.get.offsetParent();
12588 $popup.removeClass(className.loading);
12589 if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
12590 module.debug('Moving popup to the same offset parent as target');
12591 $popup
12592 .detach()
12593 .appendTo($offsetParent)
12594 ;
12595 }
12596 }
12597 else {
12598 $offsetParent = (settings.inline)
12599 ? module.get.offsetParent($target)
12600 : module.has.popup()
12601 ? module.get.offsetParent($popup)
12602 : $body
12603 ;
12604 }
12605 if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
12606 module.debug('Setting page as offset parent');
12607 $offsetParent = $body;
12608 }
12609 if( module.get.variation() ) {
12610 module.set.variation();
12611 }
12612 },
12613
12614 reposition: function() {
12615 module.refresh();
12616 module.set.position();
12617 },
12618
12619 destroy: function() {
12620 module.debug('Destroying previous module');
12621 if(documentObserver) {
12622 documentObserver.disconnect();
12623 }
12624 // remove element only if was created dynamically
12625 if($popup && !settings.preserve) {
12626 module.removePopup();
12627 }
12628 // clear all timeouts
12629 clearTimeout(module.hideTimer);
12630 clearTimeout(module.showTimer);
12631 // remove events
12632 module.unbind.close();
12633 module.unbind.events();
12634 $module
12635 .removeData(moduleNamespace)
12636 ;
12637 },
12638
12639 event: {
12640 start: function(event) {
12641 var
12642 delay = ($.isPlainObject(settings.delay))
12643 ? settings.delay.show
12644 : settings.delay
12645 ;
12646 clearTimeout(module.hideTimer);
12647 if(!openedWithTouch || (openedWithTouch && settings.addTouchEvents) ) {
12648 module.showTimer = setTimeout(module.show, delay);
12649 }
12650 },
12651 end: function() {
12652 var
12653 delay = ($.isPlainObject(settings.delay))
12654 ? settings.delay.hide
12655 : settings.delay
12656 ;
12657 clearTimeout(module.showTimer);
12658 module.hideTimer = setTimeout(module.hide, delay);
12659 },
12660 touchstart: function(event) {
12661 openedWithTouch = true;
12662 if(settings.addTouchEvents) {
12663 module.show();
12664 }
12665 },
12666 resize: function() {
12667 if( module.is.visible() ) {
12668 module.set.position();
12669 }
12670 },
12671 documentChanged: function(mutations) {
12672 [].forEach.call(mutations, function(mutation) {
12673 if(mutation.removedNodes) {
12674 [].forEach.call(mutation.removedNodes, function(node) {
12675 if(node == element || $(node).find(element).length > 0) {
12676 module.debug('Element removed from DOM, tearing down events');
12677 module.destroy();
12678 }
12679 });
12680 }
12681 });
12682 },
12683 hideGracefully: function(event) {
12684 var
12685 $target = $(event.target),
12686 isInDOM = $.contains(document.documentElement, event.target),
12687 inPopup = ($target.closest(selector.popup).length > 0)
12688 ;
12689 // don't close on clicks inside popup
12690 if(event && !inPopup && isInDOM) {
12691 module.debug('Click occurred outside popup hiding popup');
12692 module.hide();
12693 }
12694 else {
12695 module.debug('Click was inside popup, keeping popup open');
12696 }
12697 }
12698 },
12699
12700 // generates popup html from metadata
12701 create: function() {
12702 var
12703 html = module.get.html(),
12704 title = module.get.title(),
12705 content = module.get.content()
12706 ;
12707
12708 if(html || content || title) {
12709 module.debug('Creating pop-up html');
12710 if(!html) {
12711 html = settings.templates.popup({
12712 title : title,
12713 content : content
12714 });
12715 }
12716 $popup = $('<div/>')
12717 .addClass(className.popup)
12718 .data(metadata.activator, $module)
12719 .html(html)
12720 ;
12721 if(settings.inline) {
12722 module.verbose('Inserting popup element inline', $popup);
12723 $popup
12724 .insertAfter($module)
12725 ;
12726 }
12727 else {
12728 module.verbose('Appending popup element to body', $popup);
12729 $popup
12730 .appendTo( $context )
12731 ;
12732 }
12733 module.refresh();
12734 module.set.variation();
12735
12736 if(settings.hoverable) {
12737 module.bind.popup();
12738 }
12739 settings.onCreate.call($popup, element);
12740 }
12741 else if($target.next(selector.popup).length !== 0) {
12742 module.verbose('Pre-existing popup found');
12743 settings.inline = true;
12744 settings.popup = $target.next(selector.popup).data(metadata.activator, $module);
12745 module.refresh();
12746 if(settings.hoverable) {
12747 module.bind.popup();
12748 }
12749 }
12750 else if(settings.popup) {
12751 $(settings.popup).data(metadata.activator, $module);
12752 module.verbose('Used popup specified in settings');
12753 module.refresh();
12754 if(settings.hoverable) {
12755 module.bind.popup();
12756 }
12757 }
12758 else {
12759 module.debug('No content specified skipping display', element);
12760 }
12761 },
12762
12763 createID: function() {
12764 id = (Math.random().toString(16) + '000000000').substr(2, 8);
12765 elementNamespace = '.' + id;
12766 module.verbose('Creating unique id for element', id);
12767 },
12768
12769 // determines popup state
12770 toggle: function() {
12771 module.debug('Toggling pop-up');
12772 if( module.is.hidden() ) {
12773 module.debug('Popup is hidden, showing pop-up');
12774 module.unbind.close();
12775 module.show();
12776 }
12777 else {
12778 module.debug('Popup is visible, hiding pop-up');
12779 module.hide();
12780 }
12781 },
12782
12783 show: function(callback) {
12784 callback = callback || function(){};
12785 module.debug('Showing pop-up', settings.transition);
12786 if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
12787 if( !module.exists() ) {
12788 module.create();
12789 }
12790 if(settings.onShow.call($popup, element) === false) {
12791 module.debug('onShow callback returned false, cancelling popup animation');
12792 return;
12793 }
12794 else if(!settings.preserve && !settings.popup) {
12795 module.refresh();
12796 }
12797 if( $popup && module.set.position() ) {
12798 module.save.conditions();
12799 if(settings.exclusive) {
12800 module.hideAll();
12801 }
12802 module.animate.show(callback);
12803 }
12804 }
12805 },
12806
12807
12808 hide: function(callback) {
12809 callback = callback || function(){};
12810 if( module.is.visible() || module.is.animating() ) {
12811 if(settings.onHide.call($popup, element) === false) {
12812 module.debug('onHide callback returned false, cancelling popup animation');
12813 return;
12814 }
12815 module.remove.visible();
12816 module.unbind.close();
12817 module.restore.conditions();
12818 module.animate.hide(callback);
12819 }
12820 },
12821
12822 hideAll: function() {
12823 $(selector.popup)
12824 .filter('.' + className.popupVisible)
12825 .each(function() {
12826 $(this)
12827 .data(metadata.activator)
12828 .popup('hide')
12829 ;
12830 })
12831 ;
12832 },
12833 exists: function() {
12834 if(!$popup) {
12835 return false;
12836 }
12837 if(settings.inline || settings.popup) {
12838 return ( module.has.popup() );
12839 }
12840 else {
12841 return ( $popup.closest($context).length >= 1 )
12842 ? true
12843 : false
12844 ;
12845 }
12846 },
12847
12848 removePopup: function() {
12849 if( module.has.popup() && !settings.popup) {
12850 module.debug('Removing popup', $popup);
12851 $popup.remove();
12852 $popup = undefined;
12853 settings.onRemove.call($popup, element);
12854 }
12855 },
12856
12857 save: {
12858 conditions: function() {
12859 module.cache = {
12860 title: $module.attr('title')
12861 };
12862 if (module.cache.title) {
12863 $module.removeAttr('title');
12864 }
12865 module.verbose('Saving original attributes', module.cache.title);
12866 }
12867 },
12868 restore: {
12869 conditions: function() {
12870 if(module.cache && module.cache.title) {
12871 $module.attr('title', module.cache.title);
12872 module.verbose('Restoring original attributes', module.cache.title);
12873 }
12874 return true;
12875 }
12876 },
12877 supports: {
12878 svg: function() {
12879 return (typeof SVGGraphicsElement !== 'undefined');
12880 }
12881 },
12882 animate: {
12883 show: function(callback) {
12884 callback = $.isFunction(callback) ? callback : function(){};
12885 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
12886 module.set.visible();
12887 $popup
12888 .transition({
12889 animation : settings.transition + ' in',
12890 queue : false,
12891 debug : settings.debug,
12892 verbose : settings.verbose,
12893 duration : settings.duration,
12894 onComplete : function() {
12895 module.bind.close();
12896 callback.call($popup, element);
12897 settings.onVisible.call($popup, element);
12898 }
12899 })
12900 ;
12901 }
12902 else {
12903 module.error(error.noTransition);
12904 }
12905 },
12906 hide: function(callback) {
12907 callback = $.isFunction(callback) ? callback : function(){};
12908 module.debug('Hiding pop-up');
12909 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
12910 $popup
12911 .transition({
12912 animation : settings.transition + ' out',
12913 queue : false,
12914 duration : settings.duration,
12915 debug : settings.debug,
12916 verbose : settings.verbose,
12917 onComplete : function() {
12918 module.reset();
12919 callback.call($popup, element);
12920 settings.onHidden.call($popup, element);
12921 }
12922 })
12923 ;
12924 }
12925 else {
12926 module.error(error.noTransition);
12927 }
12928 }
12929 },
12930
12931 change: {
12932 content: function(html) {
12933 $popup.html(html);
12934 }
12935 },
12936
12937 get: {
12938 html: function() {
12939 $module.removeData(metadata.html);
12940 return $module.data(metadata.html) || settings.html;
12941 },
12942 title: function() {
12943 $module.removeData(metadata.title);
12944 return $module.data(metadata.title) || settings.title;
12945 },
12946 content: function() {
12947 $module.removeData(metadata.content);
12948 return $module.data(metadata.content) || settings.content || $module.attr('title');
12949 },
12950 variation: function() {
12951 $module.removeData(metadata.variation);
12952 return $module.data(metadata.variation) || settings.variation;
12953 },
12954 popup: function() {
12955 return $popup;
12956 },
12957 popupOffset: function() {
12958 return $popup.offset();
12959 },
12960 calculations: function() {
12961 var
12962 $popupOffsetParent = module.get.offsetParent($popup),
12963 targetElement = $target[0],
12964 isWindow = ($boundary[0] == window),
12965 targetPosition = (settings.inline || (settings.popup && settings.movePopup))
12966 ? $target.position()
12967 : $target.offset(),
12968 screenPosition = (isWindow)
12969 ? { top: 0, left: 0 }
12970 : $boundary.offset(),
12971 calculations = {},
12972 scroll = (isWindow)
12973 ? { top: $window.scrollTop(), left: $window.scrollLeft() }
12974 : { top: 0, left: 0},
12975 screen
12976 ;
12977 calculations = {
12978 // element which is launching popup
12979 target : {
12980 element : $target[0],
12981 width : $target.outerWidth(),
12982 height : $target.outerHeight(),
12983 top : targetPosition.top,
12984 left : targetPosition.left,
12985 margin : {}
12986 },
12987 // popup itself
12988 popup : {
12989 width : $popup.outerWidth(),
12990 height : $popup.outerHeight()
12991 },
12992 // offset container (or 3d context)
12993 parent : {
12994 width : $offsetParent.outerWidth(),
12995 height : $offsetParent.outerHeight()
12996 },
12997 // screen boundaries
12998 screen : {
12999 top : screenPosition.top,
13000 left : screenPosition.left,
13001 scroll: {
13002 top : scroll.top,
13003 left : scroll.left
13004 },
13005 width : $boundary.width(),
13006 height : $boundary.height()
13007 }
13008 };
13009
13010 // if popup offset context is not same as target, then adjust calculations
13011 if($popupOffsetParent.get(0) !== $offsetParent.get(0)) {
13012 var
13013 popupOffset = $popupOffsetParent.offset()
13014 ;
13015 calculations.target.top -= popupOffset.top;
13016 calculations.target.left -= popupOffset.left;
13017 calculations.parent.width = $popupOffsetParent.outerWidth();
13018 calculations.parent.height = $popupOffsetParent.outerHeight();
13019 }
13020
13021 // add in container calcs if fluid
13022 if( settings.setFluidWidth && module.is.fluid() ) {
13023 calculations.container = {
13024 width: $popup.parent().outerWidth()
13025 };
13026 calculations.popup.width = calculations.container.width;
13027 }
13028
13029 // add in margins if inline
13030 calculations.target.margin.top = (settings.inline)
13031 ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
13032 : 0
13033 ;
13034 calculations.target.margin.left = (settings.inline)
13035 ? module.is.rtl()
13036 ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
13037 : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
13038 : 0
13039 ;
13040 // calculate screen boundaries
13041 screen = calculations.screen;
13042 calculations.boundary = {
13043 top : screen.top + screen.scroll.top,
13044 bottom : screen.top + screen.scroll.top + screen.height,
13045 left : screen.left + screen.scroll.left,
13046 right : screen.left + screen.scroll.left + screen.width
13047 };
13048 return calculations;
13049 },
13050 id: function() {
13051 return id;
13052 },
13053 startEvent: function() {
13054 if(settings.on == 'hover') {
13055 return 'mouseenter';
13056 }
13057 else if(settings.on == 'focus') {
13058 return 'focus';
13059 }
13060 return false;
13061 },
13062 scrollEvent: function() {
13063 return 'scroll';
13064 },
13065 endEvent: function() {
13066 if(settings.on == 'hover') {
13067 return 'mouseleave';
13068 }
13069 else if(settings.on == 'focus') {
13070 return 'blur';
13071 }
13072 return false;
13073 },
13074 distanceFromBoundary: function(offset, calculations) {
13075 var
13076 distanceFromBoundary = {},
13077 popup,
13078 boundary
13079 ;
13080 calculations = calculations || module.get.calculations();
13081
13082 // shorthand
13083 popup = calculations.popup;
13084 boundary = calculations.boundary;
13085
13086 if(offset) {
13087 distanceFromBoundary = {
13088 top : (offset.top - boundary.top),
13089 left : (offset.left - boundary.left),
13090 right : (boundary.right - (offset.left + popup.width) ),
13091 bottom : (boundary.bottom - (offset.top + popup.height) )
13092 };
13093 module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
13094 }
13095 return distanceFromBoundary;
13096 },
13097 offsetParent: function($element) {
13098 var
13099 element = ($element !== undefined)
13100 ? $element[0]
13101 : $target[0],
13102 parentNode = element.parentNode,
13103 $node = $(parentNode)
13104 ;
13105 if(parentNode) {
13106 var
13107 is2D = ($node.css('transform') === 'none'),
13108 isStatic = ($node.css('position') === 'static'),
13109 isBody = $node.is('body')
13110 ;
13111 while(parentNode && !isBody && isStatic && is2D) {
13112 parentNode = parentNode.parentNode;
13113 $node = $(parentNode);
13114 is2D = ($node.css('transform') === 'none');
13115 isStatic = ($node.css('position') === 'static');
13116 isBody = $node.is('body');
13117 }
13118 }
13119 return ($node && $node.length > 0)
13120 ? $node
13121 : $()
13122 ;
13123 },
13124 positions: function() {
13125 return {
13126 'top left' : false,
13127 'top center' : false,
13128 'top right' : false,
13129 'bottom left' : false,
13130 'bottom center' : false,
13131 'bottom right' : false,
13132 'left center' : false,
13133 'right center' : false
13134 };
13135 },
13136 nextPosition: function(position) {
13137 var
13138 positions = position.split(' '),
13139 verticalPosition = positions[0],
13140 horizontalPosition = positions[1],
13141 opposite = {
13142 top : 'bottom',
13143 bottom : 'top',
13144 left : 'right',
13145 right : 'left'
13146 },
13147 adjacent = {
13148 left : 'center',
13149 center : 'right',
13150 right : 'left'
13151 },
13152 backup = {
13153 'top left' : 'top center',
13154 'top center' : 'top right',
13155 'top right' : 'right center',
13156 'right center' : 'bottom right',
13157 'bottom right' : 'bottom center',
13158 'bottom center' : 'bottom left',
13159 'bottom left' : 'left center',
13160 'left center' : 'top left'
13161 },
13162 adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
13163 oppositeTried = false,
13164 adjacentTried = false,
13165 nextPosition = false
13166 ;
13167 if(!triedPositions) {
13168 module.verbose('All available positions available');
13169 triedPositions = module.get.positions();
13170 }
13171
13172 module.debug('Recording last position tried', position);
13173 triedPositions[position] = true;
13174
13175 if(settings.prefer === 'opposite') {
13176 nextPosition = [opposite[verticalPosition], horizontalPosition];
13177 nextPosition = nextPosition.join(' ');
13178 oppositeTried = (triedPositions[nextPosition] === true);
13179 module.debug('Trying opposite strategy', nextPosition);
13180 }
13181 if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
13182 nextPosition = [verticalPosition, adjacent[horizontalPosition]];
13183 nextPosition = nextPosition.join(' ');
13184 adjacentTried = (triedPositions[nextPosition] === true);
13185 module.debug('Trying adjacent strategy', nextPosition);
13186 }
13187 if(adjacentTried || oppositeTried) {
13188 module.debug('Using backup position', nextPosition);
13189 nextPosition = backup[position];
13190 }
13191 return nextPosition;
13192 }
13193 },
13194
13195 set: {
13196 position: function(position, calculations) {
13197
13198 // exit conditions
13199 if($target.length === 0 || $popup.length === 0) {
13200 module.error(error.notFound);
13201 return;
13202 }
13203 var
13204 offset,
13205 distanceAway,
13206 target,
13207 popup,
13208 parent,
13209 positioning,
13210 popupOffset,
13211 distanceFromBoundary
13212 ;
13213
13214 calculations = calculations || module.get.calculations();
13215 position = position || $module.data(metadata.position) || settings.position;
13216
13217 offset = $module.data(metadata.offset) || settings.offset;
13218 distanceAway = settings.distanceAway;
13219
13220 // shorthand
13221 target = calculations.target;
13222 popup = calculations.popup;
13223 parent = calculations.parent;
13224
13225 if(module.should.centerArrow(calculations)) {
13226 module.verbose('Adjusting offset to center arrow on small target element');
13227 if(position == 'top left' || position == 'bottom left') {
13228 offset += (target.width / 2)
13229 offset -= settings.arrowPixelsFromEdge;
13230 }
13231 if(position == 'top right' || position == 'bottom right') {
13232 offset -= (target.width / 2)
13233 offset += settings.arrowPixelsFromEdge;
13234 }
13235 }
13236
13237 if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) {
13238 module.debug('Popup target is hidden, no action taken');
13239 return false;
13240 }
13241
13242 if(settings.inline) {
13243 module.debug('Adding margin to calculation', target.margin);
13244 if(position == 'left center' || position == 'right center') {
13245 offset += target.margin.top;
13246 distanceAway += -target.margin.left;
13247 }
13248 else if (position == 'top left' || position == 'top center' || position == 'top right') {
13249 offset += target.margin.left;
13250 distanceAway -= target.margin.top;
13251 }
13252 else {
13253 offset += target.margin.left;
13254 distanceAway += target.margin.top;
13255 }
13256 }
13257
13258 module.debug('Determining popup position from calculations', position, calculations);
13259
13260 if (module.is.rtl()) {
13261 position = position.replace(/left|right/g, function (match) {
13262 return (match == 'left')
13263 ? 'right'
13264 : 'left'
13265 ;
13266 });
13267 module.debug('RTL: Popup position updated', position);
13268 }
13269
13270 // if last attempt use specified last resort position
13271 if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
13272 position = settings.lastResort;
13273 }
13274
13275 switch (position) {
13276 case 'top left':
13277 positioning = {
13278 top : 'auto',
13279 bottom : parent.height - target.top + distanceAway,
13280 left : target.left + offset,
13281 right : 'auto'
13282 };
13283 break;
13284 case 'top center':
13285 positioning = {
13286 bottom : parent.height - target.top + distanceAway,
13287 left : target.left + (target.width / 2) - (popup.width / 2) + offset,
13288 top : 'auto',
13289 right : 'auto'
13290 };
13291 break;
13292 case 'top right':
13293 positioning = {
13294 bottom : parent.height - target.top + distanceAway,
13295 right : parent.width - target.left - target.width - offset,
13296 top : 'auto',
13297 left : 'auto'
13298 };
13299 break;
13300 case 'left center':
13301 positioning = {
13302 top : target.top + (target.height / 2) - (popup.height / 2) + offset,
13303 right : parent.width - target.left + distanceAway,
13304 left : 'auto',
13305 bottom : 'auto'
13306 };
13307 break;
13308 case 'right center':
13309 positioning = {
13310 top : target.top + (target.height / 2) - (popup.height / 2) + offset,
13311 left : target.left + target.width + distanceAway,
13312 bottom : 'auto',
13313 right : 'auto'
13314 };
13315 break;
13316 case 'bottom left':
13317 positioning = {
13318 top : target.top + target.height + distanceAway,
13319 left : target.left + offset,
13320 bottom : 'auto',
13321 right : 'auto'
13322 };
13323 break;
13324 case 'bottom center':
13325 positioning = {
13326 top : target.top + target.height + distanceAway,
13327 left : target.left + (target.width / 2) - (popup.width / 2) + offset,
13328 bottom : 'auto',
13329 right : 'auto'
13330 };
13331 break;
13332 case 'bottom right':
13333 positioning = {
13334 top : target.top + target.height + distanceAway,
13335 right : parent.width - target.left - target.width - offset,
13336 left : 'auto',
13337 bottom : 'auto'
13338 };
13339 break;
13340 }
13341 if(positioning === undefined) {
13342 module.error(error.invalidPosition, position);
13343 }
13344
13345 module.debug('Calculated popup positioning values', positioning);
13346
13347 // tentatively place on stage
13348 $popup
13349 .css(positioning)
13350 .removeClass(className.position)
13351 .addClass(position)
13352 .addClass(className.loading)
13353 ;
13354
13355 popupOffset = module.get.popupOffset();
13356
13357 // see if any boundaries are surpassed with this tentative position
13358 distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
13359
13360 if( module.is.offstage(distanceFromBoundary, position) ) {
13361 module.debug('Position is outside viewport', position);
13362 if(searchDepth < settings.maxSearchDepth) {
13363 searchDepth++;
13364 position = module.get.nextPosition(position);
13365 module.debug('Trying new position', position);
13366 return ($popup)
13367 ? module.set.position(position, calculations)
13368 : false
13369 ;
13370 }
13371 else {
13372 if(settings.lastResort) {
13373 module.debug('No position found, showing with last position');
13374 }
13375 else {
13376 module.debug('Popup could not find a position to display', $popup);
13377 module.error(error.cannotPlace, element);
13378 module.remove.attempts();
13379 module.remove.loading();
13380 module.reset();
13381 settings.onUnplaceable.call($popup, element);
13382 return false;
13383 }
13384 }
13385 }
13386 module.debug('Position is on stage', position);
13387 module.remove.attempts();
13388 module.remove.loading();
13389 if( settings.setFluidWidth && module.is.fluid() ) {
13390 module.set.fluidWidth(calculations);
13391 }
13392 return true;
13393 },
13394
13395 fluidWidth: function(calculations) {
13396 calculations = calculations || module.get.calculations();
13397 module.debug('Automatically setting element width to parent width', calculations.parent.width);
13398 $popup.css('width', calculations.container.width);
13399 },
13400
13401 variation: function(variation) {
13402 variation = variation || module.get.variation();
13403 if(variation && module.has.popup() ) {
13404 module.verbose('Adding variation to popup', variation);
13405 $popup.addClass(variation);
13406 }
13407 },
13408
13409 visible: function() {
13410 $module.addClass(className.visible);
13411 }
13412 },
13413
13414 remove: {
13415 loading: function() {
13416 $popup.removeClass(className.loading);
13417 },
13418 variation: function(variation) {
13419 variation = variation || module.get.variation();
13420 if(variation) {
13421 module.verbose('Removing variation', variation);
13422 $popup.removeClass(variation);
13423 }
13424 },
13425 visible: function() {
13426 $module.removeClass(className.visible);
13427 },
13428 attempts: function() {
13429 module.verbose('Resetting all searched positions');
13430 searchDepth = 0;
13431 triedPositions = false;
13432 }
13433 },
13434
13435 bind: {
13436 events: function() {
13437 module.debug('Binding popup events to module');
13438 if(settings.on == 'click') {
13439 $module
13440 .on('click' + eventNamespace, module.toggle)
13441 ;
13442 }
13443 if(settings.on == 'hover') {
13444 $module
13445 .on('touchstart' + eventNamespace, module.event.touchstart)
13446 ;
13447 }
13448 if( module.get.startEvent() ) {
13449 $module
13450 .on(module.get.startEvent() + eventNamespace, module.event.start)
13451 .on(module.get.endEvent() + eventNamespace, module.event.end)
13452 ;
13453 }
13454 if(settings.target) {
13455 module.debug('Target set to element', $target);
13456 }
13457 $window.on('resize' + elementNamespace, module.event.resize);
13458 },
13459 popup: function() {
13460 module.verbose('Allowing hover events on popup to prevent closing');
13461 if( $popup && module.has.popup() ) {
13462 $popup
13463 .on('mouseenter' + eventNamespace, module.event.start)
13464 .on('mouseleave' + eventNamespace, module.event.end)
13465 ;
13466 }
13467 },
13468 close: function() {
13469 if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
13470 module.bind.closeOnScroll();
13471 }
13472 if(module.is.closable()) {
13473 module.bind.clickaway();
13474 }
13475 else if(settings.on == 'hover' && openedWithTouch) {
13476 module.bind.touchClose();
13477 }
13478 },
13479 closeOnScroll: function() {
13480 module.verbose('Binding scroll close event to document');
13481 $scrollContext
13482 .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
13483 ;
13484 },
13485 touchClose: function() {
13486 module.verbose('Binding popup touchclose event to document');
13487 $document
13488 .on('touchstart' + elementNamespace, function(event) {
13489 module.verbose('Touched away from popup');
13490 module.event.hideGracefully.call(element, event);
13491 })
13492 ;
13493 },
13494 clickaway: function() {
13495 module.verbose('Binding popup close event to document');
13496 $document
13497 .on('click' + elementNamespace, function(event) {
13498 module.verbose('Clicked away from popup');
13499 module.event.hideGracefully.call(element, event);
13500 })
13501 ;
13502 }
13503 },
13504
13505 unbind: {
13506 events: function() {
13507 $window
13508 .off(elementNamespace)
13509 ;
13510 $module
13511 .off(eventNamespace)
13512 ;
13513 },
13514 close: function() {
13515 $document
13516 .off(elementNamespace)
13517 ;
13518 $scrollContext
13519 .off(elementNamespace)
13520 ;
13521 },
13522 },
13523
13524 has: {
13525 popup: function() {
13526 return ($popup && $popup.length > 0);
13527 }
13528 },
13529
13530 should: {
13531 centerArrow: function(calculations) {
13532 return !module.is.basic() && calculations.target.width <= (settings.arrowPixelsFromEdge * 2);
13533 },
13534 },
13535
13536 is: {
13537 closable: function() {
13538 if(settings.closable == 'auto') {
13539 if(settings.on == 'hover') {
13540 return false;
13541 }
13542 return true;
13543 }
13544 return settings.closable;
13545 },
13546 offstage: function(distanceFromBoundary, position) {
13547 var
13548 offstage = []
13549 ;
13550 // return boundaries that have been surpassed
13551 $.each(distanceFromBoundary, function(direction, distance) {
13552 if(distance < -settings.jitter) {
13553 module.debug('Position exceeds allowable distance from edge', direction, distance, position);
13554 offstage.push(direction);
13555 }
13556 });
13557 if(offstage.length > 0) {
13558 return true;
13559 }
13560 else {
13561 return false;
13562 }
13563 },
13564 svg: function(element) {
13565 return module.supports.svg() && (element instanceof SVGGraphicsElement);
13566 },
13567 basic: function() {
13568 return $module.hasClass(className.basic);
13569 },
13570 active: function() {
13571 return $module.hasClass(className.active);
13572 },
13573 animating: function() {
13574 return ($popup !== undefined && $popup.hasClass(className.animating) );
13575 },
13576 fluid: function() {
13577 return ($popup !== undefined && $popup.hasClass(className.fluid));
13578 },
13579 visible: function() {
13580 return ($popup !== undefined && $popup.hasClass(className.popupVisible));
13581 },
13582 dropdown: function() {
13583 return $module.hasClass(className.dropdown);
13584 },
13585 hidden: function() {
13586 return !module.is.visible();
13587 },
13588 rtl: function () {
13589 return $module.css('direction') == 'rtl';
13590 }
13591 },
13592
13593 reset: function() {
13594 module.remove.visible();
13595 if(settings.preserve) {
13596 if($.fn.transition !== undefined) {
13597 $popup
13598 .transition('remove transition')
13599 ;
13600 }
13601 }
13602 else {
13603 module.removePopup();
13604 }
13605 },
13606
13607 setting: function(name, value) {
13608 if( $.isPlainObject(name) ) {
13609 $.extend(true, settings, name);
13610 }
13611 else if(value !== undefined) {
13612 settings[name] = value;
13613 }
13614 else {
13615 return settings[name];
13616 }
13617 },
13618 internal: function(name, value) {
13619 if( $.isPlainObject(name) ) {
13620 $.extend(true, module, name);
13621 }
13622 else if(value !== undefined) {
13623 module[name] = value;
13624 }
13625 else {
13626 return module[name];
13627 }
13628 },
13629 debug: function() {
13630 if(!settings.silent && settings.debug) {
13631 if(settings.performance) {
13632 module.performance.log(arguments);
13633 }
13634 else {
13635 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
13636 module.debug.apply(console, arguments);
13637 }
13638 }
13639 },
13640 verbose: function() {
13641 if(!settings.silent && settings.verbose && settings.debug) {
13642 if(settings.performance) {
13643 module.performance.log(arguments);
13644 }
13645 else {
13646 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
13647 module.verbose.apply(console, arguments);
13648 }
13649 }
13650 },
13651 error: function() {
13652 if(!settings.silent) {
13653 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
13654 module.error.apply(console, arguments);
13655 }
13656 },
13657 performance: {
13658 log: function(message) {
13659 var
13660 currentTime,
13661 executionTime,
13662 previousTime
13663 ;
13664 if(settings.performance) {
13665 currentTime = new Date().getTime();
13666 previousTime = time || currentTime;
13667 executionTime = currentTime - previousTime;
13668 time = currentTime;
13669 performance.push({
13670 'Name' : message[0],
13671 'Arguments' : [].slice.call(message, 1) || '',
13672 'Element' : element,
13673 'Execution Time' : executionTime
13674 });
13675 }
13676 clearTimeout(module.performance.timer);
13677 module.performance.timer = setTimeout(module.performance.display, 500);
13678 },
13679 display: function() {
13680 var
13681 title = settings.name + ':',
13682 totalTime = 0
13683 ;
13684 time = false;
13685 clearTimeout(module.performance.timer);
13686 $.each(performance, function(index, data) {
13687 totalTime += data['Execution Time'];
13688 });
13689 title += ' ' + totalTime + 'ms';
13690 if(moduleSelector) {
13691 title += ' \'' + moduleSelector + '\'';
13692 }
13693 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
13694 console.groupCollapsed(title);
13695 if(console.table) {
13696 console.table(performance);
13697 }
13698 else {
13699 $.each(performance, function(index, data) {
13700 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
13701 });
13702 }
13703 console.groupEnd();
13704 }
13705 performance = [];
13706 }
13707 },
13708 invoke: function(query, passedArguments, context) {
13709 var
13710 object = instance,
13711 maxDepth,
13712 found,
13713 response
13714 ;
13715 passedArguments = passedArguments || queryArguments;
13716 context = element || context;
13717 if(typeof query == 'string' && object !== undefined) {
13718 query = query.split(/[\. ]/);
13719 maxDepth = query.length - 1;
13720 $.each(query, function(depth, value) {
13721 var camelCaseValue = (depth != maxDepth)
13722 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
13723 : query
13724 ;
13725 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
13726 object = object[camelCaseValue];
13727 }
13728 else if( object[camelCaseValue] !== undefined ) {
13729 found = object[camelCaseValue];
13730 return false;
13731 }
13732 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
13733 object = object[value];
13734 }
13735 else if( object[value] !== undefined ) {
13736 found = object[value];
13737 return false;
13738 }
13739 else {
13740 return false;
13741 }
13742 });
13743 }
13744 if ( $.isFunction( found ) ) {
13745 response = found.apply(context, passedArguments);
13746 }
13747 else if(found !== undefined) {
13748 response = found;
13749 }
13750 if(Array.isArray(returnedValue)) {
13751 returnedValue.push(response);
13752 }
13753 else if(returnedValue !== undefined) {
13754 returnedValue = [returnedValue, response];
13755 }
13756 else if(response !== undefined) {
13757 returnedValue = response;
13758 }
13759 return found;
13760 }
13761 };
13762
13763 if(methodInvoked) {
13764 if(instance === undefined) {
13765 module.initialize();
13766 }
13767 module.invoke(query);
13768 }
13769 else {
13770 if(instance !== undefined) {
13771 instance.invoke('destroy');
13772 }
13773 module.initialize();
13774 }
13775 })
13776 ;
13777
13778 return (returnedValue !== undefined)
13779 ? returnedValue
13780 : this
13781 ;
13782};
13783
13784$.fn.popup.settings = {
13785
13786 name : 'Popup',
13787
13788 // module settings
13789 silent : false,
13790 debug : false,
13791 verbose : false,
13792 performance : true,
13793 namespace : 'popup',
13794
13795 // whether it should use dom mutation observers
13796 observeChanges : true,
13797
13798 // callback only when element added to dom
13799 onCreate : function(){},
13800
13801 // callback before element removed from dom
13802 onRemove : function(){},
13803
13804 // callback before show animation
13805 onShow : function(){},
13806
13807 // callback after show animation
13808 onVisible : function(){},
13809
13810 // callback before hide animation
13811 onHide : function(){},
13812
13813 // callback when popup cannot be positioned in visible screen
13814 onUnplaceable : function(){},
13815
13816 // callback after hide animation
13817 onHidden : function(){},
13818
13819 // when to show popup
13820 on : 'hover',
13821
13822 // element to use to determine if popup is out of boundary
13823 boundary : window,
13824
13825 // whether to add touchstart events when using hover
13826 addTouchEvents : true,
13827
13828 // default position relative to element
13829 position : 'top left',
13830
13831 // name of variation to use
13832 variation : '',
13833
13834 // whether popup should be moved to context
13835 movePopup : true,
13836
13837 // element which popup should be relative to
13838 target : false,
13839
13840 // jq selector or element that should be used as popup
13841 popup : false,
13842
13843 // popup should remain inline next to activator
13844 inline : false,
13845
13846 // popup should be removed from page on hide
13847 preserve : false,
13848
13849 // popup should not close when being hovered on
13850 hoverable : false,
13851
13852 // explicitly set content
13853 content : false,
13854
13855 // explicitly set html
13856 html : false,
13857
13858 // explicitly set title
13859 title : false,
13860
13861 // whether automatically close on clickaway when on click
13862 closable : true,
13863
13864 // automatically hide on scroll
13865 hideOnScroll : 'auto',
13866
13867 // hide other popups on show
13868 exclusive : false,
13869
13870 // context to attach popups
13871 context : 'body',
13872
13873 // context for binding scroll events
13874 scrollContext : window,
13875
13876 // position to prefer when calculating new position
13877 prefer : 'opposite',
13878
13879 // specify position to appear even if it doesn't fit
13880 lastResort : false,
13881
13882 // number of pixels from edge of popup to pointing arrow center (used from centering)
13883 arrowPixelsFromEdge: 20,
13884
13885 // delay used to prevent accidental refiring of animations due to user error
13886 delay : {
13887 show : 50,
13888 hide : 70
13889 },
13890
13891 // whether fluid variation should assign width explicitly
13892 setFluidWidth : true,
13893
13894 // transition settings
13895 duration : 200,
13896 transition : 'scale',
13897
13898 // distance away from activating element in px
13899 distanceAway : 0,
13900
13901 // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
13902 jitter : 2,
13903
13904 // offset on aligning axis from calculated position
13905 offset : 0,
13906
13907 // maximum times to look for a position before failing (9 positions total)
13908 maxSearchDepth : 15,
13909
13910 error: {
13911 invalidPosition : 'The position you specified is not a valid position',
13912 cannotPlace : 'Popup does not fit within the boundaries of the viewport',
13913 method : 'The method you called is not defined.',
13914 noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
13915 notFound : 'The target or popup you specified does not exist on the page'
13916 },
13917
13918 metadata: {
13919 activator : 'activator',
13920 content : 'content',
13921 html : 'html',
13922 offset : 'offset',
13923 position : 'position',
13924 title : 'title',
13925 variation : 'variation'
13926 },
13927
13928 className : {
13929 active : 'active',
13930 basic : 'basic',
13931 animating : 'animating',
13932 dropdown : 'dropdown',
13933 fluid : 'fluid',
13934 loading : 'loading',
13935 popup : 'ui popup',
13936 position : 'top left center bottom right',
13937 visible : 'visible',
13938 popupVisible : 'visible'
13939 },
13940
13941 selector : {
13942 popup : '.ui.popup'
13943 },
13944
13945 templates: {
13946 escape: function(string) {
13947 var
13948 badChars = /[&<>"'`]/g,
13949 shouldEscape = /[&<>"'`]/,
13950 escape = {
13951 "&": "&amp;",
13952 "<": "&lt;",
13953 ">": "&gt;",
13954 '"': "&quot;",
13955 "'": "&#x27;",
13956 "`": "&#x60;"
13957 },
13958 escapedChar = function(chr) {
13959 return escape[chr];
13960 }
13961 ;
13962 if(shouldEscape.test(string)) {
13963 return string.replace(badChars, escapedChar);
13964 }
13965 return string;
13966 },
13967 popup: function(text) {
13968 var
13969 html = '',
13970 escape = $.fn.popup.settings.templates.escape
13971 ;
13972 if(typeof text !== undefined) {
13973 if(typeof text.title !== undefined && text.title) {
13974 text.title = escape(text.title);
13975 html += '<div class="header">' + text.title + '</div>';
13976 }
13977 if(typeof text.content !== undefined && text.content) {
13978 text.content = escape(text.content);
13979 html += '<div class="content">' + text.content + '</div>';
13980 }
13981 }
13982 return html;
13983 }
13984 }
13985
13986};
13987
13988
13989})( jQuery, window, document );
13990
13991/*!
13992 * # Semantic UI 2.7.2 - Progress
13993 * http://github.com/semantic-org/semantic-ui/
13994 *
13995 *
13996 * Released under the MIT license
13997 * http://opensource.org/licenses/MIT
13998 *
13999 */
14000
14001;(function ($, window, document, undefined) {
14002
14003'use strict';
14004
14005$.isFunction = $.isFunction || function(obj) {
14006 return typeof obj === "function" && typeof obj.nodeType !== "number";
14007};
14008
14009window = (typeof window != 'undefined' && window.Math == Math)
14010 ? window
14011 : (typeof self != 'undefined' && self.Math == Math)
14012 ? self
14013 : Function('return this')()
14014;
14015
14016$.fn.progress = function(parameters) {
14017 var
14018 $allModules = $(this),
14019
14020 moduleSelector = $allModules.selector || '',
14021
14022 time = new Date().getTime(),
14023 performance = [],
14024
14025 query = arguments[0],
14026 methodInvoked = (typeof query == 'string'),
14027 queryArguments = [].slice.call(arguments, 1),
14028
14029 returnedValue
14030 ;
14031
14032 $allModules
14033 .each(function() {
14034 var
14035 settings = ( $.isPlainObject(parameters) )
14036 ? $.extend(true, {}, $.fn.progress.settings, parameters)
14037 : $.extend({}, $.fn.progress.settings),
14038
14039 className = settings.className,
14040 metadata = settings.metadata,
14041 namespace = settings.namespace,
14042 selector = settings.selector,
14043 error = settings.error,
14044
14045 eventNamespace = '.' + namespace,
14046 moduleNamespace = 'module-' + namespace,
14047
14048 $module = $(this),
14049 $bars = $(this).find(selector.bar),
14050 $progresses = $(this).find(selector.progress),
14051 $label = $(this).find(selector.label),
14052
14053 element = this,
14054 instance = $module.data(moduleNamespace),
14055
14056 animating = false,
14057 transitionEnd,
14058 module
14059 ;
14060 module = {
14061 helper: {
14062 sum: function (nums) {
14063 return nums.reduce(function (left, right) {
14064 return left + right;
14065 }, 0);
14066 },
14067 forceArray: function (element) {
14068 return Array.isArray(element)
14069 ? element
14070 : !isNaN(element)
14071 ? [element]
14072 : typeof element == 'string'
14073 ? element.split(',')
14074 : []
14075 ;
14076 }
14077 },
14078
14079 initialize: function() {
14080 module.set.duration();
14081 module.set.transitionEvent();
14082 module.debug(element);
14083
14084 module.read.metadata();
14085 module.read.settings();
14086
14087 module.instantiate();
14088 },
14089
14090 instantiate: function() {
14091 module.verbose('Storing instance of progress', module);
14092 instance = module;
14093 $module
14094 .data(moduleNamespace, module)
14095 ;
14096 },
14097 destroy: function() {
14098 module.verbose('Destroying previous progress for', $module);
14099 clearInterval(instance.interval);
14100 module.remove.state();
14101 $module.removeData(moduleNamespace);
14102 instance = undefined;
14103 },
14104
14105 reset: function() {
14106 module.remove.nextValue();
14107 module.update.progress(0);
14108 },
14109
14110 complete: function() {
14111 if(module.percent === undefined || module.percent < 100) {
14112 module.remove.progressPoll();
14113 module.set.percent(100);
14114 }
14115 },
14116
14117 read: {
14118 metadata: function() {
14119 var
14120 data = {
14121 percent : module.helper.forceArray($module.data(metadata.percent)),
14122 total : $module.data(metadata.total),
14123 value : module.helper.forceArray($module.data(metadata.value))
14124 }
14125 ;
14126 if(data.total) {
14127 module.debug('Total value set from metadata', data.total);
14128 module.set.total(data.total);
14129 }
14130 if(data.value.length > 0) {
14131 module.debug('Current value set from metadata', data.value);
14132 module.set.value(data.value);
14133 module.set.progress(data.value);
14134 }
14135 if(data.percent.length > 0) {
14136 module.debug('Current percent value set from metadata', data.percent);
14137 module.set.percent(data.percent);
14138 }
14139 },
14140 settings: function() {
14141 if(settings.total !== false) {
14142 module.debug('Current total set in settings', settings.total);
14143 module.set.total(settings.total);
14144 }
14145 if(settings.value !== false) {
14146 module.debug('Current value set in settings', settings.value);
14147 module.set.value(settings.value);
14148 module.set.progress(module.value);
14149 }
14150 if(settings.percent !== false) {
14151 module.debug('Current percent set in settings', settings.percent);
14152 module.set.percent(settings.percent);
14153 }
14154 }
14155 },
14156
14157 bind: {
14158 transitionEnd: function(callback) {
14159 var
14160 transitionEnd = module.get.transitionEnd()
14161 ;
14162 $bars
14163 .one(transitionEnd + eventNamespace, function(event) {
14164 clearTimeout(module.failSafeTimer);
14165 callback.call(this, event);
14166 })
14167 ;
14168 module.failSafeTimer = setTimeout(function() {
14169 $bars.triggerHandler(transitionEnd);
14170 }, settings.duration + settings.failSafeDelay);
14171 module.verbose('Adding fail safe timer', module.timer);
14172 }
14173 },
14174
14175 increment: function(incrementValue) {
14176 var
14177 startValue,
14178 newValue
14179 ;
14180 if( module.has.total() ) {
14181 startValue = module.get.value();
14182 incrementValue = incrementValue || 1;
14183 }
14184 else {
14185 startValue = module.get.percent();
14186 incrementValue = incrementValue || module.get.randomValue();
14187 }
14188 newValue = startValue + incrementValue;
14189 module.debug('Incrementing percentage by', startValue, newValue, incrementValue);
14190 newValue = module.get.normalizedValue(newValue);
14191 module.set.progress(newValue);
14192 },
14193 decrement: function(decrementValue) {
14194 var
14195 total = module.get.total(),
14196 startValue,
14197 newValue
14198 ;
14199 if(total) {
14200 startValue = module.get.value();
14201 decrementValue = decrementValue || 1;
14202 newValue = startValue - decrementValue;
14203 module.debug('Decrementing value by', decrementValue, startValue);
14204 }
14205 else {
14206 startValue = module.get.percent();
14207 decrementValue = decrementValue || module.get.randomValue();
14208 newValue = startValue - decrementValue;
14209 module.debug('Decrementing percentage by', decrementValue, startValue);
14210 }
14211 newValue = module.get.normalizedValue(newValue);
14212 module.set.progress(newValue);
14213 },
14214
14215 has: {
14216 progressPoll: function() {
14217 return module.progressPoll;
14218 },
14219 total: function() {
14220 return (module.get.total() !== false);
14221 }
14222 },
14223
14224 get: {
14225 text: function(templateText, index) {
14226 var
14227 index_ = index || 0,
14228 value = module.value[index_] || 0,
14229 total = module.total || 0,
14230 percent = (animating)
14231 ? module.get.displayPercent(index_)
14232 : module.percent[index_] || 0,
14233 left = (module.total > 0)
14234 ? (total - value)
14235 : (100 - percent)
14236 ;
14237 templateText = templateText || '';
14238 templateText = templateText
14239 .replace('{value}', value)
14240 .replace('{total}', total)
14241 .replace('{left}', left)
14242 .replace('{percent}', percent)
14243 .replace('{bar}', settings.text.bars[index_] || '')
14244 ;
14245 module.verbose('Adding variables to progress bar text', templateText);
14246 return templateText;
14247 },
14248
14249 normalizedValue: function(value) {
14250 if(value < 0) {
14251 module.debug('Value cannot decrement below 0');
14252 return 0;
14253 }
14254 if(module.has.total()) {
14255 if(value > module.total) {
14256 module.debug('Value cannot increment above total', module.total);
14257 return module.total;
14258 }
14259 }
14260 else if(value > 100 ) {
14261 module.debug('Value cannot increment above 100 percent');
14262 return 100;
14263 }
14264 return value;
14265 },
14266
14267 updateInterval: function() {
14268 if(settings.updateInterval == 'auto') {
14269 return settings.duration;
14270 }
14271 return settings.updateInterval;
14272 },
14273
14274 randomValue: function() {
14275 module.debug('Generating random increment percentage');
14276 return Math.floor((Math.random() * settings.random.max) + settings.random.min);
14277 },
14278
14279 numericValue: function(value) {
14280 return (typeof value === 'string')
14281 ? (value.replace(/[^\d.]/g, '') !== '')
14282 ? +(value.replace(/[^\d.]/g, ''))
14283 : false
14284 : value
14285 ;
14286 },
14287
14288 transitionEnd: function() {
14289 var
14290 element = document.createElement('element'),
14291 transitions = {
14292 'transition' :'transitionend',
14293 'OTransition' :'oTransitionEnd',
14294 'MozTransition' :'transitionend',
14295 'WebkitTransition' :'webkitTransitionEnd'
14296 },
14297 transition
14298 ;
14299 for(transition in transitions){
14300 if( element.style[transition] !== undefined ){
14301 return transitions[transition];
14302 }
14303 }
14304 },
14305
14306 // gets current displayed percentage (if animating values this is the intermediary value)
14307 displayPercent: function() {
14308 return $bars.map(function(index, element) {
14309 var
14310 $bar = $(element),
14311 barWidth = $bar.width(),
14312 totalWidth = $module.width(),
14313 minDisplay = parseInt($bar.css('min-width'), 10),
14314 displayPercent = (barWidth > minDisplay)
14315 ? (barWidth / totalWidth * 100)
14316 : module.percent
14317 ;
14318 return (settings.precision > 0)
14319 ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
14320 : Math.round(displayPercent)
14321 ;
14322 }).toArray();
14323 },
14324
14325 percent: function(index) {
14326 return module.percent[index || 0] || 0;
14327 },
14328 value: function(index) {
14329 return module.nextValue || module.value[index || 0] || 0;
14330 },
14331 total: function() {
14332 return module.total || false;
14333 }
14334 },
14335
14336 create: {
14337 progressPoll: function() {
14338 module.progressPoll = setTimeout(function() {
14339 module.update.toNextValue();
14340 module.remove.progressPoll();
14341 }, module.get.updateInterval());
14342 },
14343 },
14344
14345 is: {
14346 complete: function() {
14347 return module.is.success() || module.is.warning() || module.is.error();
14348 },
14349 success: function() {
14350 return $module.hasClass(className.success);
14351 },
14352 warning: function() {
14353 return $module.hasClass(className.warning);
14354 },
14355 error: function() {
14356 return $module.hasClass(className.error);
14357 },
14358 active: function() {
14359 return $module.hasClass(className.active);
14360 },
14361 visible: function() {
14362 return $module.is(':visible');
14363 }
14364 },
14365
14366 remove: {
14367 progressPoll: function() {
14368 module.verbose('Removing progress poll timer');
14369 if(module.progressPoll) {
14370 clearTimeout(module.progressPoll);
14371 delete module.progressPoll;
14372 }
14373 },
14374 nextValue: function() {
14375 module.verbose('Removing progress value stored for next update');
14376 delete module.nextValue;
14377 },
14378 state: function() {
14379 module.verbose('Removing stored state');
14380 delete module.total;
14381 delete module.percent;
14382 delete module.value;
14383 },
14384 active: function() {
14385 module.verbose('Removing active state');
14386 $module.removeClass(className.active);
14387 },
14388 success: function() {
14389 module.verbose('Removing success state');
14390 $module.removeClass(className.success);
14391 },
14392 warning: function() {
14393 module.verbose('Removing warning state');
14394 $module.removeClass(className.warning);
14395 },
14396 error: function() {
14397 module.verbose('Removing error state');
14398 $module.removeClass(className.error);
14399 }
14400 },
14401
14402 set: {
14403 barWidth: function(values) {
14404 module.debug("set bar width with ", values);
14405 values = module.helper.forceArray(values);
14406 var total = module.helper.sum(values);
14407 if(total > 100) {
14408 module.error(error.tooHigh, total);
14409 }
14410 else if (total < 0) {
14411 module.error(error.tooLow, total);
14412 }
14413 else {
14414 var firstNonZeroIndex = -1;
14415 var lastNonZeroIndex = -1;
14416 var percents = values.map(function(value, index) {
14417 var $bar = $($bars[index]);
14418 if (value === 0) {
14419 $bar.css('display', 'none');
14420 } else {
14421 if (firstNonZeroIndex == -1) {
14422 firstNonZeroIndex = index;
14423 }
14424 lastNonZeroIndex = index;
14425 $bar.css({
14426 display: 'block',
14427 width: value + '%'
14428 });
14429 }
14430 return parseInt(value, 10);
14431 });
14432 values.forEach(function(_, index) {
14433 var $bar = $($bars[index]);
14434 $bar.css({
14435 borderTopLeftRadius: index == firstNonZeroIndex ? '' : 0,
14436 borderBottomLeftRadius: index == firstNonZeroIndex ? '' : 0,
14437 borderTopRightRadius: index == lastNonZeroIndex ? '' : 0,
14438 borderBottomRightRadius: index == lastNonZeroIndex ? '' : 0
14439 });
14440 });
14441 $module
14442 .attr('data-percent', percents)
14443 ;
14444 }
14445 },
14446 duration: function(duration) {
14447 duration = duration || settings.duration;
14448 duration = (typeof duration == 'number')
14449 ? duration + 'ms'
14450 : duration
14451 ;
14452 module.verbose('Setting progress bar transition duration', duration);
14453 $bars
14454 .css({
14455 'transition-duration': duration
14456 })
14457 ;
14458 },
14459 percent: function(percents) {
14460 percents = module.helper.forceArray(percents).map(function(percent) {
14461 return (typeof percent == 'string')
14462 ? +(percent.replace('%', ''))
14463 : percent
14464 ;
14465 });
14466 // round display percentage
14467 percents = percents.map(function(percent){
14468 return (settings.precision > 0)
14469 ? Math.round(percent * (10 * settings.precision)) / (10 * settings.precision)
14470 : Math.round(percent)
14471 ;
14472 });
14473 module.percent = percents;
14474 if( !module.has.total() ) {
14475 module.value = percents.map(function(percent){
14476 return (settings.precision > 0)
14477 ? Math.round( (percent / 100) * module.total * (10 * settings.precision)) / (10 * settings.precision)
14478 : Math.round( (percent / 100) * module.total * 10) / 10
14479 ;
14480 });
14481 if(settings.limitValues) {
14482 module.value = module.value.map(function(value) {
14483 return (value > 100)
14484 ? 100
14485 : (module.value < 0)
14486 ? 0
14487 : module.value;
14488 });
14489 }
14490 }
14491 module.set.barWidth(percents);
14492 module.set.labelInterval();
14493 module.set.labels();
14494 settings.onChange.call(element, percents, module.value, module.total);
14495 },
14496 labelInterval: function() {
14497 var
14498 animationCallback = function() {
14499 module.verbose('Bar finished animating, removing continuous label updates');
14500 clearInterval(module.interval);
14501 animating = false;
14502 module.set.labels();
14503 }
14504 ;
14505 clearInterval(module.interval);
14506 module.bind.transitionEnd(animationCallback);
14507 animating = true;
14508 module.interval = setInterval(function() {
14509 var
14510 isInDOM = $.contains(document.documentElement, element)
14511 ;
14512 if(!isInDOM) {
14513 clearInterval(module.interval);
14514 animating = false;
14515 }
14516 module.set.labels();
14517 }, settings.framerate);
14518 },
14519 labels: function() {
14520 module.verbose('Setting both bar progress and outer label text');
14521 module.set.barLabel();
14522 module.set.state();
14523 },
14524 label: function(text) {
14525 text = text || '';
14526 if(text) {
14527 text = module.get.text(text);
14528 module.verbose('Setting label to text', text);
14529 $label.text(text);
14530 }
14531 },
14532 state: function(percent) {
14533 percent = (percent !== undefined)
14534 ? percent
14535 : module.helper.sum(module.percent)
14536 ;
14537 if(percent === 100) {
14538 if(settings.autoSuccess && !(module.is.warning() || module.is.error() || module.is.success())) {
14539 module.set.success();
14540 module.debug('Automatically triggering success at 100%');
14541 }
14542 else {
14543 module.verbose('Reached 100% removing active state');
14544 module.remove.active();
14545 module.remove.progressPoll();
14546 }
14547 }
14548 else if(percent > 0) {
14549 module.verbose('Adjusting active progress bar label', percent);
14550 module.set.active();
14551 }
14552 else {
14553 module.remove.active();
14554 module.set.label(settings.text.active);
14555 }
14556 },
14557 barLabel: function(text) {
14558 $progresses.map(function(index, element){
14559 var $progress = $(element);
14560 if (text !== undefined) {
14561 $progress.text( module.get.text(text, index) );
14562 }
14563 else if (settings.label == 'ratio' && module.total) {
14564 module.verbose('Adding ratio to bar label');
14565 $progress.text( module.get.text(settings.text.ratio, index) );
14566 }
14567 else if (settings.label == 'percent') {
14568 module.verbose('Adding percentage to bar label');
14569 $progress.text( module.get.text(settings.text.percent, index) );
14570 }
14571 });
14572 },
14573 active: function(text) {
14574 text = text || settings.text.active;
14575 module.debug('Setting active state');
14576 if(settings.showActivity && !module.is.active() ) {
14577 $module.addClass(className.active);
14578 }
14579 module.remove.warning();
14580 module.remove.error();
14581 module.remove.success();
14582 text = settings.onLabelUpdate('active', text, module.value, module.total);
14583 if(text) {
14584 module.set.label(text);
14585 }
14586 module.bind.transitionEnd(function() {
14587 settings.onActive.call(element, module.value, module.total);
14588 });
14589 },
14590 success : function(text) {
14591 text = text || settings.text.success || settings.text.active;
14592 module.debug('Setting success state');
14593 $module.addClass(className.success);
14594 module.remove.active();
14595 module.remove.warning();
14596 module.remove.error();
14597 module.complete();
14598 if(settings.text.success) {
14599 text = settings.onLabelUpdate('success', text, module.value, module.total);
14600 module.set.label(text);
14601 }
14602 else {
14603 text = settings.onLabelUpdate('active', text, module.value, module.total);
14604 module.set.label(text);
14605 }
14606 module.bind.transitionEnd(function() {
14607 settings.onSuccess.call(element, module.total);
14608 });
14609 },
14610 warning : function(text) {
14611 text = text || settings.text.warning;
14612 module.debug('Setting warning state');
14613 $module.addClass(className.warning);
14614 module.remove.active();
14615 module.remove.success();
14616 module.remove.error();
14617 module.complete();
14618 text = settings.onLabelUpdate('warning', text, module.value, module.total);
14619 if(text) {
14620 module.set.label(text);
14621 }
14622 module.bind.transitionEnd(function() {
14623 settings.onWarning.call(element, module.value, module.total);
14624 });
14625 },
14626 error : function(text) {
14627 text = text || settings.text.error;
14628 module.debug('Setting error state');
14629 $module.addClass(className.error);
14630 module.remove.active();
14631 module.remove.success();
14632 module.remove.warning();
14633 module.complete();
14634 text = settings.onLabelUpdate('error', text, module.value, module.total);
14635 if(text) {
14636 module.set.label(text);
14637 }
14638 module.bind.transitionEnd(function() {
14639 settings.onError.call(element, module.value, module.total);
14640 });
14641 },
14642 transitionEvent: function() {
14643 transitionEnd = module.get.transitionEnd();
14644 },
14645 total: function(totalValue) {
14646 module.total = totalValue;
14647 },
14648 value: function(value) {
14649 module.value = module.helper.forceArray(value);
14650 },
14651 progress: function(value) {
14652 if(!module.has.progressPoll()) {
14653 module.debug('First update in progress update interval, immediately updating', value);
14654 module.update.progress(value);
14655 module.create.progressPoll();
14656 }
14657 else {
14658 module.debug('Updated within interval, setting next update to use new value', value);
14659 module.set.nextValue(value);
14660 }
14661 },
14662 nextValue: function(value) {
14663 module.nextValue = value;
14664 }
14665 },
14666
14667 update: {
14668 toNextValue: function() {
14669 var
14670 nextValue = module.nextValue
14671 ;
14672 if(nextValue) {
14673 module.debug('Update interval complete using last updated value', nextValue);
14674 module.update.progress(nextValue);
14675 module.remove.nextValue();
14676 }
14677 },
14678 progress: function(values) {
14679 var hasTotal = module.has.total();
14680 if (hasTotal) {
14681 module.set.value(values);
14682 }
14683 var percentCompletes = module.helper.forceArray(values).map(function(value) {
14684 var
14685 percentComplete
14686 ;
14687 value = module.get.numericValue(value);
14688 if (value === false) {
14689 module.error(error.nonNumeric, value);
14690 }
14691 value = module.get.normalizedValue(value);
14692 if (hasTotal) {
14693 percentComplete = (value / module.total) * 100;
14694 module.debug('Calculating percent complete from total', percentComplete);
14695 }
14696 else {
14697 percentComplete = value;
14698 module.debug('Setting value to exact percentage value', percentComplete);
14699 }
14700 return percentComplete;
14701 });
14702 module.set.percent( percentCompletes );
14703 }
14704 },
14705
14706 setting: function(name, value) {
14707 module.debug('Changing setting', name, value);
14708 if( $.isPlainObject(name) ) {
14709 $.extend(true, settings, name);
14710 }
14711 else if(value !== undefined) {
14712 if($.isPlainObject(settings[name])) {
14713 $.extend(true, settings[name], value);
14714 }
14715 else {
14716 settings[name] = value;
14717 }
14718 }
14719 else {
14720 return settings[name];
14721 }
14722 },
14723 internal: function(name, value) {
14724 if( $.isPlainObject(name) ) {
14725 $.extend(true, module, name);
14726 }
14727 else if(value !== undefined) {
14728 module[name] = value;
14729 }
14730 else {
14731 return module[name];
14732 }
14733 },
14734 debug: function() {
14735 if(!settings.silent && settings.debug) {
14736 if(settings.performance) {
14737 module.performance.log(arguments);
14738 }
14739 else {
14740 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
14741 module.debug.apply(console, arguments);
14742 }
14743 }
14744 },
14745 verbose: function() {
14746 if(!settings.silent && settings.verbose && settings.debug) {
14747 if(settings.performance) {
14748 module.performance.log(arguments);
14749 }
14750 else {
14751 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
14752 module.verbose.apply(console, arguments);
14753 }
14754 }
14755 },
14756 error: function() {
14757 if(!settings.silent) {
14758 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
14759 module.error.apply(console, arguments);
14760 }
14761 },
14762 performance: {
14763 log: function(message) {
14764 var
14765 currentTime,
14766 executionTime,
14767 previousTime
14768 ;
14769 if(settings.performance) {
14770 currentTime = new Date().getTime();
14771 previousTime = time || currentTime;
14772 executionTime = currentTime - previousTime;
14773 time = currentTime;
14774 performance.push({
14775 'Name' : message[0],
14776 'Arguments' : [].slice.call(message, 1) || '',
14777 'Element' : element,
14778 'Execution Time' : executionTime
14779 });
14780 }
14781 clearTimeout(module.performance.timer);
14782 module.performance.timer = setTimeout(module.performance.display, 500);
14783 },
14784 display: function() {
14785 var
14786 title = settings.name + ':',
14787 totalTime = 0
14788 ;
14789 time = false;
14790 clearTimeout(module.performance.timer);
14791 $.each(performance, function(index, data) {
14792 totalTime += data['Execution Time'];
14793 });
14794 title += ' ' + totalTime + 'ms';
14795 if(moduleSelector) {
14796 title += ' \'' + moduleSelector + '\'';
14797 }
14798 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
14799 console.groupCollapsed(title);
14800 if(console.table) {
14801 console.table(performance);
14802 }
14803 else {
14804 $.each(performance, function(index, data) {
14805 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
14806 });
14807 }
14808 console.groupEnd();
14809 }
14810 performance = [];
14811 }
14812 },
14813 invoke: function(query, passedArguments, context) {
14814 var
14815 object = instance,
14816 maxDepth,
14817 found,
14818 response
14819 ;
14820 passedArguments = passedArguments || queryArguments;
14821 context = element || context;
14822 if(typeof query == 'string' && object !== undefined) {
14823 query = query.split(/[\. ]/);
14824 maxDepth = query.length - 1;
14825 $.each(query, function(depth, value) {
14826 var camelCaseValue = (depth != maxDepth)
14827 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
14828 : query
14829 ;
14830 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
14831 object = object[camelCaseValue];
14832 }
14833 else if( object[camelCaseValue] !== undefined ) {
14834 found = object[camelCaseValue];
14835 return false;
14836 }
14837 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
14838 object = object[value];
14839 }
14840 else if( object[value] !== undefined ) {
14841 found = object[value];
14842 return false;
14843 }
14844 else {
14845 module.error(error.method, query);
14846 return false;
14847 }
14848 });
14849 }
14850 if ( $.isFunction( found ) ) {
14851 response = found.apply(context, passedArguments);
14852 }
14853 else if(found !== undefined) {
14854 response = found;
14855 }
14856 if(Array.isArray(returnedValue)) {
14857 returnedValue.push(response);
14858 }
14859 else if(returnedValue !== undefined) {
14860 returnedValue = [returnedValue, response];
14861 }
14862 else if(response !== undefined) {
14863 returnedValue = response;
14864 }
14865 return found;
14866 }
14867 };
14868
14869 if(methodInvoked) {
14870 if(instance === undefined) {
14871 module.initialize();
14872 }
14873 module.invoke(query);
14874 }
14875 else {
14876 if(instance !== undefined) {
14877 instance.invoke('destroy');
14878 }
14879 module.initialize();
14880 }
14881 })
14882 ;
14883
14884 return (returnedValue !== undefined)
14885 ? returnedValue
14886 : this
14887 ;
14888};
14889
14890$.fn.progress.settings = {
14891
14892 name : 'Progress',
14893 namespace : 'progress',
14894
14895 silent : false,
14896 debug : false,
14897 verbose : false,
14898 performance : true,
14899
14900 random : {
14901 min : 2,
14902 max : 5
14903 },
14904
14905 duration : 300,
14906
14907 updateInterval : 'auto',
14908
14909 autoSuccess : true,
14910 showActivity : true,
14911 limitValues : true,
14912
14913 label : 'percent',
14914 precision : 0,
14915 framerate : (1000 / 30), /// 30 fps
14916
14917 percent : false,
14918 total : false,
14919 value : false,
14920
14921 // delay in ms for fail safe animation callback
14922 failSafeDelay : 100,
14923
14924 onLabelUpdate : function(state, text, value, total){
14925 return text;
14926 },
14927 onChange : function(percent, value, total){},
14928 onSuccess : function(total){},
14929 onActive : function(value, total){},
14930 onError : function(value, total){},
14931 onWarning : function(value, total){},
14932
14933 error : {
14934 method : 'The method you called is not defined.',
14935 nonNumeric : 'Progress value is non numeric',
14936 tooHigh : 'Value specified is above 100%',
14937 tooLow : 'Value specified is below 0%'
14938 },
14939
14940 regExp: {
14941 variable: /\{\$*[A-z0-9]+\}/g
14942 },
14943
14944 metadata: {
14945 percent : 'percent',
14946 total : 'total',
14947 value : 'value'
14948 },
14949
14950 selector : {
14951 bar : '> .bar',
14952 label : '> .label',
14953 progress : '.bar > .progress'
14954 },
14955
14956 text : {
14957 active : false,
14958 error : false,
14959 success : false,
14960 warning : false,
14961 percent : '{percent}%',
14962 ratio : '{value} of {total}',
14963 bars : ['']
14964 },
14965
14966 className : {
14967 active : 'active',
14968 error : 'error',
14969 success : 'success',
14970 warning : 'warning'
14971 }
14972
14973};
14974
14975
14976})( jQuery, window, document );
14977
14978/*!
14979 * # Semantic UI 2.7.2 - Slider
14980 * http://github.com/semantic-org/semantic-ui/
14981 *
14982 *
14983 * Released under the MIT license
14984 * http://opensource.org/licenses/MIT
14985 *
14986 */
14987
14988;(function ( $, window, document, undefined ) {
14989
14990"use strict";
14991
14992window = (typeof window != 'undefined' && window.Math == Math)
14993 ? window
14994 : (typeof self != 'undefined' && self.Math == Math)
14995 ? self
14996 : Function('return this')()
14997;
14998
14999$.fn.slider = function(parameters) {
15000
15001 var
15002 $allModules = $(this),
15003
15004 moduleSelector = $allModules.selector || '',
15005
15006 time = new Date().getTime(),
15007 performance = [],
15008
15009 query = arguments[0],
15010 methodInvoked = (typeof query == 'string'),
15011 queryArguments = [].slice.call(arguments, 1),
15012
15013 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'],
15014
15015 SINGLE_STEP = 1,
15016 BIG_STEP = 2,
15017 NO_STEP = 0,
15018 SINGLE_BACKSTEP = -1,
15019 BIG_BACKSTEP = -2,
15020
15021 // Used to manage document bound events.
15022 // Use this so that we can distinguish between which document events are bound to which range.
15023 currentRange = 0,
15024
15025 returnedValue
15026 ;
15027
15028 $allModules
15029 .each(function() {
15030
15031 var
15032 settings = ( $.isPlainObject(parameters) )
15033 ? $.extend(true, {}, $.fn.slider.settings, parameters)
15034 : $.extend({}, $.fn.slider.settings),
15035
15036 className = settings.className,
15037 metadata = settings.metadata,
15038 namespace = settings.namespace,
15039 error = settings.error,
15040 keys = settings.keys,
15041 interpretLabel = settings.interpretLabel,
15042
15043 isHover = false,
15044 eventNamespace = '.' + namespace,
15045 moduleNamespace = 'module-' + namespace,
15046
15047 $module = $(this),
15048 $currThumb,
15049 $thumb,
15050 $secondThumb,
15051 $track,
15052 $trackFill,
15053 $labels,
15054
15055 element = this,
15056 instance = $module.data(moduleNamespace),
15057
15058 documentEventID,
15059
15060 value,
15061 position,
15062 secondPos,
15063 offset,
15064 precision,
15065 isTouch,
15066
15067 module
15068 ;
15069
15070 module = {
15071
15072 initialize: function() {
15073 module.debug('Initializing slider', settings);
15074
15075 currentRange += 1;
15076 documentEventID = currentRange;
15077
15078 isTouch = module.setup.testOutTouch();
15079 module.setup.layout();
15080 module.setup.labels();
15081
15082 if(!module.is.disabled()) {
15083 module.bind.events();
15084 }
15085
15086 module.read.metadata();
15087 module.read.settings();
15088
15089 module.instantiate();
15090 },
15091
15092 instantiate: function() {
15093 module.verbose('Storing instance of slider', module);
15094 instance = module;
15095 $module
15096 .data(moduleNamespace, module)
15097 ;
15098 },
15099
15100 destroy: function() {
15101 module.verbose('Destroying previous slider for', $module);
15102 clearInterval(instance.interval);
15103 module.unbind.events();
15104 module.unbind.slidingEvents();
15105 $module.removeData(moduleNamespace);
15106 instance = undefined;
15107 },
15108
15109 setup: {
15110 layout: function() {
15111 if( $module.attr('tabindex') === undefined) {
15112 $module.attr('tabindex', 0);
15113 }
15114 if($module.find('.inner').length == 0) {
15115 $module.append("<div class='inner'>"
15116 + "<div class='track'></div>"
15117 + "<div class='track-fill'></div>"
15118 + "<div class='thumb'></div>"
15119 + "</div>");
15120 }
15121 precision = module.get.precision();
15122 $thumb = $module.find('.thumb:not(.second)');
15123 $currThumb = $thumb;
15124 if(module.is.range()) {
15125 if($module.find('.thumb.second').length == 0) {
15126 $module.find('.inner').append("<div class='thumb second'></div>");
15127 }
15128 $secondThumb = $module.find('.thumb.second');
15129 }
15130 $track = $module.find('.track');
15131 $trackFill = $module.find('.track-fill');
15132 offset = $thumb.width() / 2;
15133 },
15134 labels: function() {
15135 if(module.is.labeled()) {
15136 $labels = $module.find('.labels:not(.auto)');
15137 if($labels.length != 0) {
15138 module.setup.customLabel();
15139 } else {
15140 module.setup.autoLabel();
15141 }
15142
15143 if (settings.showLabelTicks) {
15144 $module.addClass(className.ticked)
15145 }
15146 }
15147 },
15148 testOutTouch: function() {
15149 try {
15150 document.createEvent('TouchEvent');
15151 return true;
15152 } catch (e) {
15153 return false;
15154 }
15155 },
15156 customLabel: function() {
15157 var
15158 $children = $labels.find('.label'),
15159 numChildren = $children.length,
15160 min = module.get.min(),
15161 max = module.get.max(),
15162 ratio
15163 ;
15164 $children.each(function(index) {
15165 var
15166 $child = $(this),
15167 attrValue = $child.attr('data-value')
15168 ;
15169 if(attrValue) {
15170 attrValue = attrValue > max ? max : attrValue < min ? min : attrValue;
15171 ratio = (attrValue - min) / (max - min);
15172 } else {
15173 ratio = (index + 1) / (numChildren + 1);
15174 }
15175 module.update.labelPosition(ratio, $(this));
15176 });
15177 },
15178 autoLabel: function() {
15179 if(module.get.step() != 0) {
15180 $labels = $module.find('.labels');
15181 if($labels.length != 0) {
15182 $labels.empty();
15183 }
15184 else {
15185 $labels = $module.append('<ul class="auto labels"></ul>').find('.labels');
15186 }
15187 for(var i = 0, len = module.get.numLabels(); i <= len; i++) {
15188 var
15189 labelText = module.get.label(i),
15190 $label = (labelText !== "") ? $('<li class="label">' + labelText + '</li>') : null,
15191 ratio = i / len
15192 ;
15193 if($label) {
15194 module.update.labelPosition(ratio, $label);
15195 $labels.append($label);
15196 }
15197 }
15198 }
15199 }
15200 },
15201
15202 bind: {
15203 events: function() {
15204 module.bind.globalKeyboardEvents();
15205 module.bind.keyboardEvents();
15206 module.bind.mouseEvents();
15207 if(module.is.touch()) {
15208 module.bind.touchEvents();
15209 }
15210 },
15211 keyboardEvents: function() {
15212 module.verbose('Binding keyboard events');
15213 $module.on('keydown' + eventNamespace, module.event.keydown);
15214 },
15215 globalKeyboardEvents: function() {
15216 $(document).on('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
15217 },
15218 mouseEvents: function() {
15219 module.verbose('Binding mouse events');
15220 $module.find('.track, .thumb, .inner').on('mousedown' + eventNamespace, function(event) {
15221 event.stopImmediatePropagation();
15222 event.preventDefault();
15223 module.event.down(event);
15224 });
15225 $module.on('mousedown' + eventNamespace, module.event.down);
15226 $module.on('mouseenter' + eventNamespace, function(event) {
15227 isHover = true;
15228 });
15229 $module.on('mouseleave' + eventNamespace, function(event) {
15230 isHover = false;
15231 });
15232 },
15233 touchEvents: function() {
15234 module.verbose('Binding touch events');
15235 $module.find('.track, .thumb, .inner').on('touchstart' + eventNamespace, function(event) {
15236 event.stopImmediatePropagation();
15237 event.preventDefault();
15238 module.event.down(event);
15239 });
15240 $module.on('touchstart' + eventNamespace, module.event.down);
15241 },
15242 slidingEvents: function() {
15243 // these don't need the identifier because we only ever want one of them to be registered with document
15244 module.verbose('Binding page wide events while handle is being draged');
15245 if(module.is.touch()) {
15246 $(document).on('touchmove' + eventNamespace, module.event.move);
15247 $(document).on('touchend' + eventNamespace, module.event.up);
15248 }
15249 else {
15250 $(document).on('mousemove' + eventNamespace, module.event.move);
15251 $(document).on('mouseup' + eventNamespace, module.event.up);
15252 }
15253 }
15254 },
15255
15256 unbind: {
15257 events: function() {
15258 $module.find('.track, .thumb, .inner').off('mousedown' + eventNamespace);
15259 $module.find('.track, .thumb, .inner').off('touchstart' + eventNamespace);
15260 $module.off('mousedown' + eventNamespace);
15261 $module.off('mouseenter' + eventNamespace);
15262 $module.off('mouseleave' + eventNamespace);
15263 $module.off('touchstart' + eventNamespace);
15264 $module.off('keydown' + eventNamespace);
15265 $module.off('focusout' + eventNamespace);
15266 $(document).off('keydown' + eventNamespace + documentEventID, module.event.activateFocus);
15267 },
15268 slidingEvents: function() {
15269 if(module.is.touch()) {
15270 $(document).off('touchmove' + eventNamespace);
15271 $(document).off('touchend' + eventNamespace);
15272 } else {
15273 $(document).off('mousemove' + eventNamespace);
15274 $(document).off('mouseup' + eventNamespace);
15275 }
15276 },
15277 },
15278
15279 event: {
15280 down: function(event, originalEvent) {
15281 event.preventDefault();
15282 if(module.is.range()) {
15283 var
15284 eventPos = module.determine.eventPos(event, originalEvent),
15285 newPos = module.determine.pos(eventPos)
15286 ;
15287 $currThumb = module.determine.closestThumb(newPos);
15288 }
15289 if(!module.is.disabled()) {
15290 module.bind.slidingEvents();
15291 }
15292 },
15293 move: function(event, originalEvent) {
15294 event.preventDefault();
15295 var value = module.determine.valueFromEvent(event, originalEvent);
15296 if(module.get.step() == 0 || module.is.smooth()) {
15297 var
15298 thumbVal = module.thumbVal,
15299 secondThumbVal = module.secondThumbVal,
15300 thumbSmoothVal = module.determine.smoothValueFromEvent(event, originalEvent)
15301 ;
15302 if(!$currThumb.hasClass('second')) {
15303 thumbVal = value;
15304 } else {
15305 secondThumbVal = value;
15306 }
15307 value = Math.abs(thumbVal - (secondThumbVal || 0));
15308 module.update.position(thumbSmoothVal);
15309 settings.onMove.call(element, value, thumbVal, secondThumbVal);
15310 } else {
15311 module.update.value(value, function(value, thumbVal, secondThumbVal) {
15312 settings.onMove.call(element, value, thumbVal, secondThumbVal);
15313 });
15314 }
15315 },
15316 up: function(event, originalEvent) {
15317 event.preventDefault();
15318 var value = module.determine.valueFromEvent(event, originalEvent);
15319 module.set.value(value);
15320 module.unbind.slidingEvents();
15321 },
15322 keydown: function(event, first) {
15323 if(module.is.focused()) {
15324 $(document).trigger(event);
15325 }
15326 if(first || module.is.focused()) {
15327 var step = module.determine.keyMovement(event);
15328 if(step != NO_STEP) {
15329 event.preventDefault();
15330 switch(step) {
15331 case SINGLE_STEP:
15332 module.takeStep();
15333 break;
15334 case BIG_STEP:
15335 module.takeStep(module.get.multiplier());
15336 break;
15337 case SINGLE_BACKSTEP:
15338 module.backStep();
15339 break;
15340 case BIG_BACKSTEP:
15341 module.backStep(module.get.multiplier());
15342 break;
15343 }
15344 }
15345 }
15346 },
15347 activateFocus: function(event) {
15348 if(!module.is.focused() && module.is.hover() && module.determine.keyMovement(event) != NO_STEP) {
15349 event.preventDefault();
15350 module.event.keydown(event, true);
15351 $module.focus();
15352 }
15353 },
15354 },
15355
15356 resync: function() {
15357 module.verbose('Resyncing thumb position based on value');
15358 if(module.is.range()) {
15359 module.update.position(module.secondThumbVal, $secondThumb);
15360 }
15361 module.update.position(module.thumbVal, $thumb);
15362 module.setup.labels();
15363 },
15364 takeStep: function(multiplier) {
15365 var
15366 multiplier = multiplier != undefined ? multiplier : 1,
15367 step = module.get.step(),
15368 currValue = module.get.currentThumbValue()
15369 ;
15370 module.verbose('Taking a step');
15371 if(step > 0) {
15372 module.set.value(currValue + step * multiplier);
15373 } else if (step == 0){
15374 var
15375 precision = module.get.precision(),
15376 newValue = currValue + (multiplier/precision)
15377 ;
15378 module.set.value(Math.round(newValue * precision) / precision);
15379 }
15380 },
15381
15382 backStep: function(multiplier) {
15383 var
15384 multiplier = multiplier != undefined ? multiplier : 1,
15385 step = module.get.step(),
15386 currValue = module.get.currentThumbValue()
15387 ;
15388 module.verbose('Going back a step');
15389 if(step > 0) {
15390 module.set.value(currValue - step * multiplier);
15391 } else if (step == 0) {
15392 var
15393 precision = module.get.precision(),
15394 newValue = currValue - (multiplier/precision)
15395 ;
15396 module.set.value(Math.round(newValue * precision) / precision);
15397 }
15398 },
15399
15400 is: {
15401 range: function() {
15402 return $module.hasClass(settings.className.range);
15403 },
15404 hover: function() {
15405 return isHover;
15406 },
15407 focused: function() {
15408 return $module.is(':focus');
15409 },
15410 disabled: function() {
15411 return $module.hasClass(settings.className.disabled);
15412 },
15413 labeled: function() {
15414 return $module.hasClass(settings.className.labeled);
15415 },
15416 reversed: function() {
15417 return $module.hasClass(settings.className.reversed);
15418 },
15419 vertical: function() {
15420 return $module.hasClass(settings.className.vertical);
15421 },
15422 smooth: function() {
15423 return settings.smooth || $module.hasClass(settings.className.smooth);
15424 },
15425 touch: function() {
15426 return isTouch;
15427 }
15428 },
15429
15430 get: {
15431 trackOffset: function() {
15432 if (module.is.vertical()) {
15433 return $track.offset().top;
15434 } else {
15435 return $track.offset().left;
15436 }
15437 },
15438 trackLength: function() {
15439 if (module.is.vertical()) {
15440 return $track.height();
15441 } else {
15442 return $track.width();
15443 }
15444 },
15445 trackLeft: function() {
15446 if (module.is.vertical()) {
15447 return $track.position().top;
15448 } else {
15449 return $track.position().left;
15450 }
15451 },
15452 trackStartPos: function() {
15453 return module.is.reversed() ? module.get.trackLeft() + module.get.trackLength() : module.get.trackLeft();
15454 },
15455 trackEndPos: function() {
15456 return module.is.reversed() ? module.get.trackLeft() : module.get.trackLeft() + module.get.trackLength();
15457 },
15458 trackStartMargin: function () {
15459 var margin;
15460 if (module.is.vertical()) {
15461 margin = module.is.reversed() ? $module.css('padding-bottom') : $module.css('padding-top');
15462 } else {
15463 margin = module.is.reversed() ? $module.css('padding-right') : $module.css('padding-left');
15464 }
15465 return margin || '0px';
15466 },
15467 trackEndMargin: function () {
15468 var margin;
15469 if (module.is.vertical()) {
15470 margin = module.is.reversed() ? $module.css('padding-top') : $module.css('padding-bottom');
15471 } else {
15472 margin = module.is.reversed() ? $module.css('padding-left') : $module.css('padding-right');
15473 }
15474 return margin || '0px';
15475 },
15476 precision: function() {
15477 var
15478 decimalPlaces,
15479 step = module.get.step()
15480 ;
15481 if(step != 0) {
15482 var split = String(step).split('.');
15483 if(split.length == 2) {
15484 decimalPlaces = split[1].length;
15485 } else {
15486 decimalPlaces = 0;
15487 }
15488 } else {
15489 decimalPlaces = settings.decimalPlaces;
15490 }
15491 var precision = Math.pow(10, decimalPlaces);
15492 module.debug('Precision determined', precision);
15493 return precision;
15494 },
15495 min: function() {
15496 return settings.min;
15497 },
15498 max: function() {
15499 return settings.max;
15500 },
15501 step: function() {
15502 return settings.step;
15503 },
15504 numLabels: function() {
15505 var value = Math.round((module.get.max() - module.get.min()) / module.get.step());
15506 module.debug('Determined that their should be ' + value + ' labels');
15507 return value;
15508 },
15509 labelType: function() {
15510 return settings.labelType;
15511 },
15512 label: function(value) {
15513 if(interpretLabel) {
15514 return interpretLabel(value);
15515 }
15516
15517 switch (settings.labelType) {
15518 case settings.labelTypes.number:
15519 return (value * module.get.step()) + module.get.min();
15520 case settings.labelTypes.letter:
15521 return alphabet[(value) % 26];
15522 default:
15523 return value;
15524 }
15525 },
15526 value: function() {
15527 return value;
15528 },
15529 currentThumbValue: function() {
15530 return $currThumb.hasClass('second') ? module.secondThumbVal : module.thumbVal;
15531 },
15532 thumbValue: function(which) {
15533 switch(which) {
15534 case 'second':
15535 if(module.is.range()) {
15536 return module.secondThumbVal;
15537 }
15538 else {
15539 module.error(error.notrange);
15540 break;
15541 }
15542 case 'first':
15543 default:
15544 return module.thumbVal;
15545 }
15546 },
15547 multiplier: function() {
15548 return settings.pageMultiplier;
15549 },
15550 thumbPosition: function(which) {
15551 switch(which) {
15552 case 'second':
15553 if(module.is.range()) {
15554 return secondPos;
15555 }
15556 else {
15557 module.error(error.notrange);
15558 break;
15559 }
15560 case 'first':
15561 default:
15562 return position;
15563 }
15564 }
15565 },
15566
15567 determine: {
15568 pos: function(pagePos) {
15569 return module.is.reversed()
15570 ?
15571 module.get.trackStartPos() - pagePos + module.get.trackOffset()
15572 :
15573 pagePos - module.get.trackOffset() - module.get.trackStartPos()
15574 ;
15575 },
15576 closestThumb: function(eventPos) {
15577 var
15578 thumbPos = parseFloat(module.determine.thumbPos($thumb)),
15579 thumbDelta = Math.abs(eventPos - thumbPos),
15580 secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
15581 secondThumbDelta = Math.abs(eventPos - secondThumbPos)
15582 ;
15583 return thumbDelta <= secondThumbDelta ? $thumb : $secondThumb;
15584 },
15585 closestThumbPos: function(eventPos) {
15586 var
15587 thumbPos = parseFloat(module.determine.thumbPos($thumb)),
15588 thumbDelta = Math.abs(eventPos - thumbPos),
15589 secondThumbPos = parseFloat(module.determine.thumbPos($secondThumb)),
15590 secondThumbDelta = Math.abs(eventPos - secondThumbPos)
15591 ;
15592 return thumbDelta <= secondThumbDelta ? thumbPos : secondThumbPos;
15593 },
15594 thumbPos: function($element) {
15595 var pos =
15596 module.is.vertical()
15597 ?
15598 module.is.reversed() ? $element.css('bottom') : $element.css('top')
15599 :
15600 module.is.reversed() ? $element.css('right') : $element.css('left')
15601 ;
15602 return pos;
15603 },
15604 positionFromValue: function(value) {
15605 var
15606 min = module.get.min(),
15607 max = module.get.max(),
15608 value = value > max ? max : value < min ? min : value,
15609 trackLength = module.get.trackLength(),
15610 ratio = (value - min) / (max - min),
15611 position = Math.round(ratio * trackLength)
15612 ;
15613 module.verbose('Determined position: ' + position + ' from value: ' + value);
15614 return position;
15615 },
15616 positionFromRatio: function(ratio) {
15617 var
15618 trackLength = module.get.trackLength(),
15619 step = module.get.step(),
15620 position = Math.round(ratio * trackLength),
15621 adjustedPos = (step == 0) ? position : Math.round(position / step) * step
15622 ;
15623 return adjustedPos;
15624 },
15625 valueFromEvent: function(event, originalEvent) {
15626 var
15627 eventPos = module.determine.eventPos(event, originalEvent),
15628 newPos = module.determine.pos(eventPos),
15629 value
15630 ;
15631 if(eventPos < module.get.trackOffset()) {
15632 value = module.is.reversed() ? module.get.max() : module.get.min();
15633 } else if(eventPos > module.get.trackOffset() + module.get.trackLength()) {
15634 value = module.is.reversed() ? module.get.min() : module.get.max();
15635 } else {
15636 value = module.determine.value(newPos);
15637 }
15638 return value;
15639 },
15640 smoothValueFromEvent: function(event, originalEvent) {
15641 var
15642 min = module.get.min(),
15643 max = module.get.max(),
15644 trackLength = module.get.trackLength(),
15645 eventPos = module.determine.eventPos(event, originalEvent),
15646 newPos = eventPos - module.get.trackOffset(),
15647 ratio,
15648 value
15649 ;
15650 newPos = newPos < 0 ? 0 : newPos > trackLength ? trackLength : newPos;
15651 ratio = newPos / trackLength;
15652 if (module.is.reversed()) {
15653 ratio = 1 - ratio;
15654 }
15655 value = ratio * (max - min) + min;
15656 return value;
15657 },
15658 eventPos: function(event, originalEvent) {
15659 if(module.is.touch()) {
15660 var
15661 touchY = event.changedTouches[0].pageY || event.touches[0].pageY,
15662 touchX = event.changedTouches[0].pageX || event.touches[0].pageX
15663 ;
15664 return module.is.vertical() ? touchY : touchX;
15665 }
15666 var
15667 clickY = event.pageY || originalEvent.pageY,
15668 clickX = event.pageX || originalEvent.pageX
15669 ;
15670 return module.is.vertical() ? clickY : clickX;
15671 },
15672 value: function(position) {
15673 var
15674 startPos = module.is.reversed() ? module.get.trackEndPos() : module.get.trackStartPos(),
15675 endPos = module.is.reversed() ? module.get.trackStartPos() : module.get.trackEndPos(),
15676 ratio = (position - startPos) / (endPos - startPos),
15677 range = module.get.max() - module.get.min(),
15678 step = module.get.step(),
15679 value = (ratio * range),
15680 difference = (step == 0) ? value : Math.round(value / step) * step
15681 ;
15682 module.verbose('Determined value based upon position: ' + position + ' as: ' + value);
15683 if(value != difference) {
15684 module.verbose('Rounding value to closest step: ' + difference);
15685 }
15686 // Use precision to avoid ugly Javascript floating point rounding issues
15687 // (like 35 * .01 = 0.35000000000000003)
15688 difference = Math.round(difference * precision) / precision;
15689 module.verbose('Cutting off additional decimal places');
15690 return difference + module.get.min();
15691 },
15692 keyMovement: function(event) {
15693 var
15694 key = event.which,
15695 downArrow =
15696 module.is.vertical()
15697 ?
15698 module.is.reversed() ? keys.downArrow : keys.upArrow
15699 :
15700 keys.downArrow
15701 ,
15702 upArrow =
15703 module.is.vertical()
15704 ?
15705 module.is.reversed() ? keys.upArrow : keys.downArrow
15706 :
15707 keys.upArrow
15708 ,
15709 leftArrow =
15710 !module.is.vertical()
15711 ?
15712 module.is.reversed() ? keys.rightArrow : keys.leftArrow
15713 :
15714 keys.leftArrow
15715 ,
15716 rightArrow =
15717 !module.is.vertical()
15718 ?
15719 module.is.reversed() ? keys.leftArrow : keys.rightArrow
15720 :
15721 keys.rightArrow
15722 ;
15723 if(key == downArrow || key == leftArrow) {
15724 return SINGLE_BACKSTEP;
15725 } else if(key == upArrow || key == rightArrow) {
15726 return SINGLE_STEP;
15727 } else if (key == keys.pageDown) {
15728 return BIG_BACKSTEP;
15729 } else if (key == keys.pageUp) {
15730 return BIG_STEP;
15731 } else {
15732 return NO_STEP;
15733 }
15734 }
15735 },
15736
15737 handleNewValuePosition: function(val) {
15738 var
15739 min = module.get.min(),
15740 max = module.get.max(),
15741 newPos
15742 ;
15743 if (val <= min) {
15744 val = min;
15745 } else if (val >= max) {
15746 val = max;
15747 }
15748 newPos = module.determine.positionFromValue(val);
15749 return newPos;
15750 },
15751
15752 set: {
15753 value: function(newValue) {
15754 module.update.value(newValue, function(value, thumbVal, secondThumbVal) {
15755 settings.onChange.call(element, value, thumbVal, secondThumbVal);
15756 settings.onMove.call(element, value, thumbVal, secondThumbVal);
15757 });
15758 },
15759 rangeValue: function(first, second) {
15760 if(module.is.range()) {
15761 var
15762 min = module.get.min(),
15763 max = module.get.max()
15764 ;
15765 if (first <= min) {
15766 first = min;
15767 } else if(first >= max){
15768 first = max;
15769 }
15770 if (second <= min) {
15771 second = min;
15772 } else if(second >= max){
15773 second = max;
15774 }
15775 module.thumbVal = first;
15776 module.secondThumbVal = second;
15777 value = Math.abs(module.thumbVal - module.secondThumbVal);
15778 module.update.position(module.thumbVal, $thumb);
15779 module.update.position(module.secondThumbVal, $secondThumb);
15780 settings.onChange.call(element, value, module.thumbVal, module.secondThumbVal);
15781 settings.onMove.call(element, value, module.thumbVal, module.secondThumbVal);
15782 } else {
15783 module.error(error.notrange);
15784 }
15785 },
15786 position: function(position, which) {
15787 var thumbVal = module.determine.value(position);
15788 switch (which) {
15789 case 'second':
15790 module.secondThumbVal = thumbVal;
15791 module.update.position(thumbVal, $secondThumb);
15792 break;
15793 default:
15794 module.thumbVal = thumbVal;
15795 module.update.position(thumbVal, $thumb);
15796 }
15797 value = Math.abs(module.thumbVal - (module.secondThumbVal || 0));
15798 module.set.value(value);
15799 }
15800 },
15801
15802 update: {
15803 value: function(newValue, callback) {
15804 var
15805 min = module.get.min(),
15806 max = module.get.max()
15807 ;
15808 if (newValue <= min) {
15809 newValue = min;
15810 } else if(newValue >= max){
15811 newValue = max;
15812 }
15813 if(!module.is.range()) {
15814 value = newValue;
15815 module.thumbVal = value;
15816 } else {
15817 if(!$currThumb.hasClass('second')) {
15818 module.thumbVal = newValue;
15819 } else {
15820 module.secondThumbVal = newValue;
15821 }
15822 value = Math.abs(module.thumbVal - module.secondThumbVal);
15823 }
15824 module.update.position(newValue);
15825 module.debug('Setting slider value to ' + value);
15826 if(typeof callback === 'function') {
15827 callback(value, module.thumbVal, module.secondThumbVal);
15828 }
15829 },
15830 position: function(newValue, $element) {
15831 var
15832 newPos = module.handleNewValuePosition(newValue),
15833 $targetThumb = $element != undefined ? $element : $currThumb,
15834 thumbVal = module.thumbVal || module.get.min(),
15835 secondThumbVal = module.secondThumbVal || module.get.min()
15836 ;
15837 if(module.is.range()) {
15838 if(!$targetThumb.hasClass('second')) {
15839 position = newPos;
15840 thumbVal = newValue;
15841 } else {
15842 secondPos = newPos;
15843 secondThumbVal = newValue;
15844 }
15845 } else {
15846 position = newPos;
15847 thumbVal = newValue;
15848 }
15849 var
15850 trackPosValue,
15851 thumbPosValue,
15852 min = module.get.min(),
15853 max = module.get.max(),
15854 thumbPosPercent = 100 * (newValue - min) / (max - min),
15855 trackStartPosPercent = 100 * (Math.min(thumbVal, secondThumbVal) - min) / (max - min),
15856 trackEndPosPercent = 100 * (1 - (Math.max(thumbVal, secondThumbVal) - min) / (max - min))
15857 ;
15858 if (module.is.vertical()) {
15859 if (module.is.reversed()) {
15860 thumbPosValue = {bottom: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', top: 'auto'};
15861 trackPosValue = {bottom: trackStartPosPercent + '%', top: trackEndPosPercent + '%'};
15862 }
15863 else {
15864 thumbPosValue = {top: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', bottom: 'auto'};
15865 trackPosValue = {top: trackStartPosPercent + '%', bottom: trackEndPosPercent + '%'};
15866 }
15867 } else {
15868 if (module.is.reversed()) {
15869 thumbPosValue = {right: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', left: 'auto'};
15870 trackPosValue = {right: trackStartPosPercent + '%', left: trackEndPosPercent + '%'};
15871 }
15872 else {
15873 thumbPosValue = {left: 'calc(' + thumbPosPercent + '% - ' + offset + 'px)', right: 'auto'};
15874 trackPosValue = {left: trackStartPosPercent + '%', right: trackEndPosPercent + '%'};
15875 }
15876 }
15877 $targetThumb.css(thumbPosValue);
15878 $trackFill.css(trackPosValue);
15879 module.debug('Setting slider position to ' + newPos);
15880 },
15881 labelPosition: function (ratio, $label) {
15882 var
15883 startMargin = module.get.trackStartMargin(),
15884 endMargin = module.get.trackEndMargin(),
15885 posDir =
15886 module.is.vertical()
15887 ?
15888 module.is.reversed() ? 'bottom' : 'top'
15889 :
15890 module.is.reversed() ? 'right' : 'left',
15891 startMarginMod = module.is.reversed() && !module.is.vertical() ? ' - ' : ' + '
15892 ;
15893 var position = '(100% - ' + startMargin + ' - ' + endMargin + ') * ' + ratio;
15894 $label.css(posDir, 'calc(' + position + startMarginMod + startMargin + ')');
15895 }
15896 },
15897
15898 goto: {
15899 max: function() {
15900 module.set.value(module.get.max());
15901 },
15902 min: function() {
15903 module.set.value(module.get.min());
15904 },
15905 },
15906
15907 read: {
15908 metadata: function() {
15909 var
15910 data = {
15911 thumbVal : $module.data(metadata.thumbVal),
15912 secondThumbVal : $module.data(metadata.secondThumbVal)
15913 }
15914 ;
15915 if(data.thumbVal) {
15916 if(module.is.range() && data.secondThumbVal) {
15917 module.debug('Current value set from metadata', data.thumbVal, data.secondThumbVal);
15918 module.set.rangeValue(data.thumbVal, data.secondThumbVal);
15919 } else {
15920 module.debug('Current value set from metadata', data.thumbVal);
15921 module.set.value(data.thumbVal);
15922 }
15923 }
15924 },
15925 settings: function() {
15926 if(settings.start !== false) {
15927 if(module.is.range()) {
15928 module.debug('Start position set from settings', settings.start, settings.end);
15929 module.set.rangeValue(settings.start, settings.end);
15930 } else {
15931 module.debug('Start position set from settings', settings.start);
15932 module.set.value(settings.start);
15933 }
15934 }
15935 }
15936 },
15937
15938 setting: function(name, value) {
15939 module.debug('Changing setting', name, value);
15940 if( $.isPlainObject(name) ) {
15941 $.extend(true, settings, name);
15942 }
15943 else if(value !== undefined) {
15944 if($.isPlainObject(settings[name])) {
15945 $.extend(true, settings[name], value);
15946 }
15947 else {
15948 settings[name] = value;
15949 }
15950 }
15951 else {
15952 return settings[name];
15953 }
15954 },
15955 internal: function(name, value) {
15956 if( $.isPlainObject(name) ) {
15957 $.extend(true, module, name);
15958 }
15959 else if(value !== undefined) {
15960 module[name] = value;
15961 }
15962 else {
15963 return module[name];
15964 }
15965 },
15966 debug: function() {
15967 if(!settings.silent && settings.debug) {
15968 if(settings.performance) {
15969 module.performance.log(arguments);
15970 }
15971 else {
15972 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
15973 module.debug.apply(console, arguments);
15974 }
15975 }
15976 },
15977 verbose: function() {
15978 if(!settings.silent && settings.verbose && settings.debug) {
15979 if(settings.performance) {
15980 module.performance.log(arguments);
15981 }
15982 else {
15983 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
15984 module.verbose.apply(console, arguments);
15985 }
15986 }
15987 },
15988 error: function() {
15989 if(!settings.silent) {
15990 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
15991 module.error.apply(console, arguments);
15992 }
15993 },
15994
15995 performance: {
15996 log: function(message) {
15997 var
15998 currentTime,
15999 executionTime,
16000 previousTime
16001 ;
16002 if(settings.performance) {
16003 currentTime = new Date().getTime();
16004 previousTime = time || currentTime;
16005 executionTime = currentTime - previousTime;
16006 time = currentTime;
16007 performance.push({
16008 'Name' : message[0],
16009 'Arguments' : [].slice.call(message, 1) || '',
16010 'Element' : element,
16011 'Execution Time' : executionTime
16012 });
16013 }
16014 clearTimeout(module.performance.timer);
16015 module.performance.timer = setTimeout(module.performance.display, 500);
16016 },
16017 display: function() {
16018 var
16019 title = settings.name + ':',
16020 totalTime = 0
16021 ;
16022 time = false;
16023 clearTimeout(module.performance.timer);
16024 $.each(performance, function(index, data) {
16025 totalTime += data['Execution Time'];
16026 });
16027 title += ' ' + totalTime + 'ms';
16028 if(moduleSelector) {
16029 title += ' \'' + moduleSelector + '\'';
16030 }
16031 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
16032 console.groupCollapsed(title);
16033 if(console.table) {
16034 console.table(performance);
16035 }
16036 else {
16037 $.each(performance, function(index, data) {
16038 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
16039 });
16040 }
16041 console.groupEnd();
16042 }
16043 performance = [];
16044 }
16045 },
16046
16047 invoke: function(query, passedArguments, context) {
16048 var
16049 object = instance,
16050 maxDepth,
16051 found,
16052 response
16053 ;
16054 passedArguments = passedArguments || queryArguments;
16055 context = element || context;
16056 if(typeof query == 'string' && object !== undefined) {
16057 query = query.split(/[\. ]/);
16058 maxDepth = query.length - 1;
16059 $.each(query, function(depth, value) {
16060 var camelCaseValue = (depth != maxDepth)
16061 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
16062 : query
16063 ;
16064 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
16065 object = object[camelCaseValue];
16066 }
16067 else if( object[camelCaseValue] !== undefined ) {
16068 found = object[camelCaseValue];
16069 return false;
16070 }
16071 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
16072 object = object[value];
16073 }
16074 else if( object[value] !== undefined ) {
16075 found = object[value];
16076 return false;
16077 }
16078 else {
16079 module.error(error.method, query);
16080 return false;
16081 }
16082 });
16083 }
16084 if ( $.isFunction( found ) ) {
16085 response = found.apply(context, passedArguments);
16086 }
16087 else if(found !== undefined) {
16088 response = found;
16089 }
16090 if($.isArray(returnedValue)) {
16091 returnedValue.push(response);
16092 }
16093 else if(returnedValue !== undefined) {
16094 returnedValue = [returnedValue, response];
16095 }
16096 else if(response !== undefined) {
16097 returnedValue = response;
16098 }
16099 return found;
16100 }
16101 };
16102
16103 if(methodInvoked) {
16104 if(instance === undefined) {
16105 module.initialize();
16106 }
16107 module.invoke(query);
16108 }
16109 else {
16110 if(instance !== undefined) {
16111 instance.invoke('destroy');
16112 }
16113 module.initialize();
16114 }
16115 })
16116 ;
16117
16118 return (returnedValue !== undefined)
16119 ? returnedValue
16120 : this
16121 ;
16122
16123};
16124
16125$.fn.slider.settings = {
16126
16127 silent : false,
16128 debug : false,
16129 verbose : false,
16130 performance : true,
16131
16132 name : 'Slider',
16133 namespace : 'slider',
16134
16135 error : {
16136 method : 'The method you called is not defined.',
16137 notrange : 'This slider is not a range slider'
16138 },
16139
16140 metadata: {
16141 thumbVal : 'thumbVal',
16142 secondThumbVal : 'secondThumbVal'
16143 },
16144
16145 min : 0,
16146 max : 20,
16147 step : 1,
16148 start : 0,
16149 end : 20,
16150 labelType : 'number',
16151 showLabelTicks : false,
16152 smooth : false,
16153
16154 //the decimal place to round to if step is undefined
16155 decimalPlaces : 2,
16156
16157 // page up/down multiplier. How many more times the steps to take on page up/down press
16158 pageMultiplier : 2,
16159
16160 selector: {
16161
16162 },
16163
16164 className : {
16165 reversed : 'reversed',
16166 disabled : 'disabled',
16167 labeled : 'labeled',
16168 ticked : 'ticked',
16169 vertical : 'vertical',
16170 range : 'range',
16171 smooth : 'smooth'
16172 },
16173
16174 keys : {
16175 pageUp : 33,
16176 pageDown : 34,
16177 leftArrow : 37,
16178 upArrow : 38,
16179 rightArrow : 39,
16180 downArrow : 40
16181 },
16182
16183 labelTypes : {
16184 number : 'number',
16185 letter : 'letter'
16186 },
16187
16188 onChange : function(value, thumbVal, secondThumbVal){},
16189 onMove : function(value, thumbVal, secondThumbVal){},
16190};
16191
16192
16193})( jQuery, window, document );
16194
16195/*!
16196 * # Semantic UI 2.7.2 - Rating
16197 * http://github.com/semantic-org/semantic-ui/
16198 *
16199 *
16200 * Released under the MIT license
16201 * http://opensource.org/licenses/MIT
16202 *
16203 */
16204
16205;(function ($, window, document, undefined) {
16206
16207'use strict';
16208
16209$.isFunction = $.isFunction || function(obj) {
16210 return typeof obj === "function" && typeof obj.nodeType !== "number";
16211};
16212
16213window = (typeof window != 'undefined' && window.Math == Math)
16214 ? window
16215 : (typeof self != 'undefined' && self.Math == Math)
16216 ? self
16217 : Function('return this')()
16218;
16219
16220$.fn.rating = function(parameters) {
16221 var
16222 $allModules = $(this),
16223 moduleSelector = $allModules.selector || '',
16224
16225 time = new Date().getTime(),
16226 performance = [],
16227
16228 query = arguments[0],
16229 methodInvoked = (typeof query == 'string'),
16230 queryArguments = [].slice.call(arguments, 1),
16231 returnedValue
16232 ;
16233 $allModules
16234 .each(function() {
16235 var
16236 settings = ( $.isPlainObject(parameters) )
16237 ? $.extend(true, {}, $.fn.rating.settings, parameters)
16238 : $.extend({}, $.fn.rating.settings),
16239
16240 namespace = settings.namespace,
16241 className = settings.className,
16242 metadata = settings.metadata,
16243 selector = settings.selector,
16244
16245 eventNamespace = '.' + namespace,
16246 moduleNamespace = 'module-' + namespace,
16247
16248 element = this,
16249 instance = $(this).data(moduleNamespace),
16250
16251 $module = $(this),
16252 $icon = $module.find(selector.icon),
16253
16254 initialLoad,
16255 module
16256 ;
16257
16258 module = {
16259
16260 initialize: function() {
16261 module.verbose('Initializing rating module', settings);
16262
16263 if($icon.length === 0) {
16264 module.setup.layout();
16265 }
16266
16267 if(settings.interactive && !module.is.disabled()) {
16268 module.enable();
16269 }
16270 else {
16271 module.disable();
16272 }
16273 module.set.initialLoad();
16274 module.set.rating( module.get.initialRating() );
16275 module.remove.initialLoad();
16276 module.instantiate();
16277 },
16278
16279 instantiate: function() {
16280 module.verbose('Instantiating module', settings);
16281 instance = module;
16282 $module
16283 .data(moduleNamespace, module)
16284 ;
16285 },
16286
16287 destroy: function() {
16288 module.verbose('Destroying previous instance', instance);
16289 module.remove.events();
16290 $module
16291 .removeData(moduleNamespace)
16292 ;
16293 },
16294
16295 refresh: function() {
16296 $icon = $module.find(selector.icon);
16297 },
16298
16299 setup: {
16300 layout: function() {
16301 var
16302 maxRating = module.get.maxRating(),
16303 icon = module.get.icon(),
16304 html = $.fn.rating.settings.templates.icon(maxRating, icon)
16305 ;
16306 module.debug('Generating icon html dynamically');
16307 $module
16308 .html(html)
16309 ;
16310 module.refresh();
16311 }
16312 },
16313
16314 event: {
16315 mouseenter: function() {
16316 var
16317 $activeIcon = $(this)
16318 ;
16319 $activeIcon
16320 .nextAll()
16321 .removeClass(className.selected)
16322 ;
16323 $module
16324 .addClass(className.selected)
16325 ;
16326 $activeIcon
16327 .addClass(className.selected)
16328 .prevAll()
16329 .addClass(className.selected)
16330 ;
16331 },
16332 mouseleave: function() {
16333 $module
16334 .removeClass(className.selected)
16335 ;
16336 $icon
16337 .removeClass(className.selected)
16338 ;
16339 },
16340 click: function() {
16341 var
16342 $activeIcon = $(this),
16343 currentRating = module.get.rating(),
16344 rating = $icon.index($activeIcon) + 1,
16345 canClear = (settings.clearable == 'auto')
16346 ? ($icon.length === 1)
16347 : settings.clearable
16348 ;
16349 if(canClear && currentRating == rating) {
16350 module.clearRating();
16351 }
16352 else {
16353 module.set.rating( rating );
16354 }
16355 }
16356 },
16357
16358 clearRating: function() {
16359 module.debug('Clearing current rating');
16360 module.set.rating(0);
16361 },
16362
16363 bind: {
16364 events: function() {
16365 module.verbose('Binding events');
16366 $module
16367 .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
16368 .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
16369 .on('click' + eventNamespace, selector.icon, module.event.click)
16370 ;
16371 }
16372 },
16373
16374 remove: {
16375 events: function() {
16376 module.verbose('Removing events');
16377 $module
16378 .off(eventNamespace)
16379 ;
16380 },
16381 initialLoad: function() {
16382 initialLoad = false;
16383 }
16384 },
16385
16386 enable: function() {
16387 module.debug('Setting rating to interactive mode');
16388 module.bind.events();
16389 $module
16390 .removeClass(className.disabled)
16391 ;
16392 },
16393
16394 disable: function() {
16395 module.debug('Setting rating to read-only mode');
16396 module.remove.events();
16397 $module
16398 .addClass(className.disabled)
16399 ;
16400 },
16401
16402 is: {
16403 initialLoad: function() {
16404 return initialLoad;
16405 },
16406 disabled: function() {
16407 return $module.hasClass(className.disabled);
16408 }
16409 },
16410
16411 get: {
16412 icon: function(){
16413 var icon = $module.data(metadata.icon);
16414 if (icon) {
16415 $module.removeData(metadata.icon);
16416 }
16417 return icon || settings.icon;
16418 },
16419 initialRating: function() {
16420 if($module.data(metadata.rating) !== undefined) {
16421 $module.removeData(metadata.rating);
16422 return $module.data(metadata.rating);
16423 }
16424 return settings.initialRating;
16425 },
16426 maxRating: function() {
16427 if($module.data(metadata.maxRating) !== undefined) {
16428 $module.removeData(metadata.maxRating);
16429 return $module.data(metadata.maxRating);
16430 }
16431 return settings.maxRating;
16432 },
16433 rating: function() {
16434 var
16435 currentRating = $icon.filter('.' + className.active).length
16436 ;
16437 module.verbose('Current rating retrieved', currentRating);
16438 return currentRating;
16439 }
16440 },
16441
16442 set: {
16443 rating: function(rating) {
16444 var
16445 ratingIndex = (rating - 1 >= 0)
16446 ? (rating - 1)
16447 : 0,
16448 $activeIcon = $icon.eq(ratingIndex)
16449 ;
16450 $module
16451 .removeClass(className.selected)
16452 ;
16453 $icon
16454 .removeClass(className.selected)
16455 .removeClass(className.active)
16456 ;
16457 if(rating > 0) {
16458 module.verbose('Setting current rating to', rating);
16459 $activeIcon
16460 .prevAll()
16461 .addBack()
16462 .addClass(className.active)
16463 ;
16464 }
16465 if(!module.is.initialLoad()) {
16466 settings.onRate.call(element, rating);
16467 }
16468 },
16469 initialLoad: function() {
16470 initialLoad = true;
16471 }
16472 },
16473
16474 setting: function(name, value) {
16475 module.debug('Changing setting', name, value);
16476 if( $.isPlainObject(name) ) {
16477 $.extend(true, settings, name);
16478 }
16479 else if(value !== undefined) {
16480 if($.isPlainObject(settings[name])) {
16481 $.extend(true, settings[name], value);
16482 }
16483 else {
16484 settings[name] = value;
16485 }
16486 }
16487 else {
16488 return settings[name];
16489 }
16490 },
16491 internal: function(name, value) {
16492 if( $.isPlainObject(name) ) {
16493 $.extend(true, module, name);
16494 }
16495 else if(value !== undefined) {
16496 module[name] = value;
16497 }
16498 else {
16499 return module[name];
16500 }
16501 },
16502 debug: function() {
16503 if(!settings.silent && settings.debug) {
16504 if(settings.performance) {
16505 module.performance.log(arguments);
16506 }
16507 else {
16508 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
16509 module.debug.apply(console, arguments);
16510 }
16511 }
16512 },
16513 verbose: function() {
16514 if(!settings.silent && settings.verbose && settings.debug) {
16515 if(settings.performance) {
16516 module.performance.log(arguments);
16517 }
16518 else {
16519 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
16520 module.verbose.apply(console, arguments);
16521 }
16522 }
16523 },
16524 error: function() {
16525 if(!settings.silent) {
16526 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
16527 module.error.apply(console, arguments);
16528 }
16529 },
16530 performance: {
16531 log: function(message) {
16532 var
16533 currentTime,
16534 executionTime,
16535 previousTime
16536 ;
16537 if(settings.performance) {
16538 currentTime = new Date().getTime();
16539 previousTime = time || currentTime;
16540 executionTime = currentTime - previousTime;
16541 time = currentTime;
16542 performance.push({
16543 'Name' : message[0],
16544 'Arguments' : [].slice.call(message, 1) || '',
16545 'Element' : element,
16546 'Execution Time' : executionTime
16547 });
16548 }
16549 clearTimeout(module.performance.timer);
16550 module.performance.timer = setTimeout(module.performance.display, 500);
16551 },
16552 display: function() {
16553 var
16554 title = settings.name + ':',
16555 totalTime = 0
16556 ;
16557 time = false;
16558 clearTimeout(module.performance.timer);
16559 $.each(performance, function(index, data) {
16560 totalTime += data['Execution Time'];
16561 });
16562 title += ' ' + totalTime + 'ms';
16563 if(moduleSelector) {
16564 title += ' \'' + moduleSelector + '\'';
16565 }
16566 if($allModules.length > 1) {
16567 title += ' ' + '(' + $allModules.length + ')';
16568 }
16569 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
16570 console.groupCollapsed(title);
16571 if(console.table) {
16572 console.table(performance);
16573 }
16574 else {
16575 $.each(performance, function(index, data) {
16576 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
16577 });
16578 }
16579 console.groupEnd();
16580 }
16581 performance = [];
16582 }
16583 },
16584 invoke: function(query, passedArguments, context) {
16585 var
16586 object = instance,
16587 maxDepth,
16588 found,
16589 response
16590 ;
16591 passedArguments = passedArguments || queryArguments;
16592 context = element || context;
16593 if(typeof query == 'string' && object !== undefined) {
16594 query = query.split(/[\. ]/);
16595 maxDepth = query.length - 1;
16596 $.each(query, function(depth, value) {
16597 var camelCaseValue = (depth != maxDepth)
16598 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
16599 : query
16600 ;
16601 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
16602 object = object[camelCaseValue];
16603 }
16604 else if( object[camelCaseValue] !== undefined ) {
16605 found = object[camelCaseValue];
16606 return false;
16607 }
16608 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
16609 object = object[value];
16610 }
16611 else if( object[value] !== undefined ) {
16612 found = object[value];
16613 return false;
16614 }
16615 else {
16616 return false;
16617 }
16618 });
16619 }
16620 if ( $.isFunction( found ) ) {
16621 response = found.apply(context, passedArguments);
16622 }
16623 else if(found !== undefined) {
16624 response = found;
16625 }
16626 if(Array.isArray(returnedValue)) {
16627 returnedValue.push(response);
16628 }
16629 else if(returnedValue !== undefined) {
16630 returnedValue = [returnedValue, response];
16631 }
16632 else if(response !== undefined) {
16633 returnedValue = response;
16634 }
16635 return found;
16636 }
16637 };
16638 if(methodInvoked) {
16639 if(instance === undefined) {
16640 module.initialize();
16641 }
16642 module.invoke(query);
16643 }
16644 else {
16645 if(instance !== undefined) {
16646 instance.invoke('destroy');
16647 }
16648 module.initialize();
16649 }
16650 })
16651 ;
16652
16653 return (returnedValue !== undefined)
16654 ? returnedValue
16655 : this
16656 ;
16657};
16658
16659$.fn.rating.settings = {
16660
16661 name : 'Rating',
16662 namespace : 'rating',
16663
16664 icon : 'star',
16665
16666 silent : false,
16667 debug : false,
16668 verbose : false,
16669 performance : true,
16670
16671 initialRating : 0,
16672 interactive : true,
16673 maxRating : 4,
16674 clearable : 'auto',
16675
16676 fireOnInit : false,
16677
16678 onRate : function(rating){},
16679
16680 error : {
16681 method : 'The method you called is not defined',
16682 noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
16683 },
16684
16685
16686 metadata: {
16687 rating : 'rating',
16688 maxRating : 'maxRating',
16689 icon : 'icon'
16690 },
16691
16692 className : {
16693 active : 'active',
16694 disabled : 'disabled',
16695 selected : 'selected',
16696 loading : 'loading'
16697 },
16698
16699 selector : {
16700 icon : '.icon'
16701 },
16702
16703 templates: {
16704 icon: function(maxRating, iconClass) {
16705 var
16706 icon = 1,
16707 html = ''
16708 ;
16709 while(icon <= maxRating) {
16710 html += '<i class="'+iconClass+' icon"></i>';
16711 icon++;
16712 }
16713 return html;
16714 }
16715 }
16716
16717};
16718
16719})( jQuery, window, document );
16720
16721/*!
16722 * # Semantic UI 2.7.2 - Search
16723 * http://github.com/semantic-org/semantic-ui/
16724 *
16725 *
16726 * Released under the MIT license
16727 * http://opensource.org/licenses/MIT
16728 *
16729 */
16730
16731;(function ($, window, document, undefined) {
16732
16733'use strict';
16734
16735$.isFunction = $.isFunction || function(obj) {
16736 return typeof obj === "function" && typeof obj.nodeType !== "number";
16737};
16738
16739window = (typeof window != 'undefined' && window.Math == Math)
16740 ? window
16741 : (typeof self != 'undefined' && self.Math == Math)
16742 ? self
16743 : Function('return this')()
16744;
16745
16746$.fn.search = function(parameters) {
16747 var
16748 $allModules = $(this),
16749 moduleSelector = $allModules.selector || '',
16750
16751 time = new Date().getTime(),
16752 performance = [],
16753
16754 query = arguments[0],
16755 methodInvoked = (typeof query == 'string'),
16756 queryArguments = [].slice.call(arguments, 1),
16757 returnedValue
16758 ;
16759 $(this)
16760 .each(function() {
16761 var
16762 settings = ( $.isPlainObject(parameters) )
16763 ? $.extend(true, {}, $.fn.search.settings, parameters)
16764 : $.extend({}, $.fn.search.settings),
16765
16766 className = settings.className,
16767 metadata = settings.metadata,
16768 regExp = settings.regExp,
16769 fields = settings.fields,
16770 selector = settings.selector,
16771 error = settings.error,
16772 namespace = settings.namespace,
16773
16774 eventNamespace = '.' + namespace,
16775 moduleNamespace = namespace + '-module',
16776
16777 $module = $(this),
16778 $prompt = $module.find(selector.prompt),
16779 $searchButton = $module.find(selector.searchButton),
16780 $results = $module.find(selector.results),
16781 $result = $module.find(selector.result),
16782 $category = $module.find(selector.category),
16783
16784 element = this,
16785 instance = $module.data(moduleNamespace),
16786
16787 disabledBubbled = false,
16788 resultsDismissed = false,
16789
16790 module
16791 ;
16792
16793 module = {
16794
16795 initialize: function() {
16796 module.verbose('Initializing module');
16797 module.get.settings();
16798 module.determine.searchFields();
16799 module.bind.events();
16800 module.set.type();
16801 module.create.results();
16802 module.instantiate();
16803 },
16804 instantiate: function() {
16805 module.verbose('Storing instance of module', module);
16806 instance = module;
16807 $module
16808 .data(moduleNamespace, module)
16809 ;
16810 },
16811 destroy: function() {
16812 module.verbose('Destroying instance');
16813 $module
16814 .off(eventNamespace)
16815 .removeData(moduleNamespace)
16816 ;
16817 },
16818
16819 refresh: function() {
16820 module.debug('Refreshing selector cache');
16821 $prompt = $module.find(selector.prompt);
16822 $searchButton = $module.find(selector.searchButton);
16823 $category = $module.find(selector.category);
16824 $results = $module.find(selector.results);
16825 $result = $module.find(selector.result);
16826 },
16827
16828 refreshResults: function() {
16829 $results = $module.find(selector.results);
16830 $result = $module.find(selector.result);
16831 },
16832
16833 bind: {
16834 events: function() {
16835 module.verbose('Binding events to search');
16836 if(settings.automatic) {
16837 $module
16838 .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
16839 ;
16840 $prompt
16841 .attr('autocomplete', 'off')
16842 ;
16843 }
16844 $module
16845 // prompt
16846 .on('focus' + eventNamespace, selector.prompt, module.event.focus)
16847 .on('blur' + eventNamespace, selector.prompt, module.event.blur)
16848 .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
16849 // search button
16850 .on('click' + eventNamespace, selector.searchButton, module.query)
16851 // results
16852 .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
16853 .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
16854 .on('click' + eventNamespace, selector.result, module.event.result.click)
16855 ;
16856 }
16857 },
16858
16859 determine: {
16860 searchFields: function() {
16861 // this makes sure $.extend does not add specified search fields to default fields
16862 // this is the only setting which should not extend defaults
16863 if(parameters && parameters.searchFields !== undefined) {
16864 settings.searchFields = parameters.searchFields;
16865 }
16866 }
16867 },
16868
16869 event: {
16870 input: function() {
16871 if(settings.searchDelay) {
16872 clearTimeout(module.timer);
16873 module.timer = setTimeout(function() {
16874 if(module.is.focused()) {
16875 module.query();
16876 }
16877 }, settings.searchDelay);
16878 }
16879 else {
16880 module.query();
16881 }
16882 },
16883 focus: function() {
16884 module.set.focus();
16885 if(settings.searchOnFocus && module.has.minimumCharacters() ) {
16886 module.query(function() {
16887 if(module.can.show() ) {
16888 module.showResults();
16889 }
16890 });
16891 }
16892 },
16893 blur: function(event) {
16894 var
16895 pageLostFocus = (document.activeElement === this),
16896 callback = function() {
16897 module.cancel.query();
16898 module.remove.focus();
16899 module.timer = setTimeout(module.hideResults, settings.hideDelay);
16900 }
16901 ;
16902 if(pageLostFocus) {
16903 return;
16904 }
16905 resultsDismissed = false;
16906 if(module.resultsClicked) {
16907 module.debug('Determining if user action caused search to close');
16908 $module
16909 .one('click.close' + eventNamespace, selector.results, function(event) {
16910 if(module.is.inMessage(event) || disabledBubbled) {
16911 $prompt.focus();
16912 return;
16913 }
16914 disabledBubbled = false;
16915 if( !module.is.animating() && !module.is.hidden()) {
16916 callback();
16917 }
16918 })
16919 ;
16920 }
16921 else {
16922 module.debug('Input blurred without user action, closing results');
16923 callback();
16924 }
16925 },
16926 result: {
16927 mousedown: function() {
16928 module.resultsClicked = true;
16929 },
16930 mouseup: function() {
16931 module.resultsClicked = false;
16932 },
16933 click: function(event) {
16934 module.debug('Search result selected');
16935 var
16936 $result = $(this),
16937 $title = $result.find(selector.title).eq(0),
16938 $link = $result.is('a[href]')
16939 ? $result
16940 : $result.find('a[href]').eq(0),
16941 href = $link.attr('href') || false,
16942 target = $link.attr('target') || false,
16943 // title is used for result lookup
16944 value = ($title.length > 0)
16945 ? $title.text()
16946 : false,
16947 results = module.get.results(),
16948 result = $result.data(metadata.result) || module.get.result(value, results)
16949 ;
16950 if(value) {
16951 module.set.value(value);
16952 }
16953 if( $.isFunction(settings.onSelect) ) {
16954 if(settings.onSelect.call(element, result, results) === false) {
16955 module.debug('Custom onSelect callback cancelled default select action');
16956 disabledBubbled = true;
16957 return;
16958 }
16959 }
16960 module.hideResults();
16961 if(href) {
16962 module.verbose('Opening search link found in result', $link);
16963 if(target == '_blank' || event.ctrlKey) {
16964 window.open(href);
16965 }
16966 else {
16967 window.location.href = (href);
16968 }
16969 }
16970 }
16971 }
16972 },
16973 handleKeyboard: function(event) {
16974 var
16975 // force selector refresh
16976 $result = $module.find(selector.result),
16977 $category = $module.find(selector.category),
16978 $activeResult = $result.filter('.' + className.active),
16979 currentIndex = $result.index( $activeResult ),
16980 resultSize = $result.length,
16981 hasActiveResult = $activeResult.length > 0,
16982
16983 keyCode = event.which,
16984 keys = {
16985 backspace : 8,
16986 enter : 13,
16987 escape : 27,
16988 upArrow : 38,
16989 downArrow : 40
16990 },
16991 newIndex
16992 ;
16993 // search shortcuts
16994 if(keyCode == keys.escape) {
16995 module.verbose('Escape key pressed, blurring search field');
16996 module.hideResults();
16997 resultsDismissed = true;
16998 }
16999 if( module.is.visible() ) {
17000 if(keyCode == keys.enter) {
17001 module.verbose('Enter key pressed, selecting active result');
17002 if( $result.filter('.' + className.active).length > 0 ) {
17003 module.event.result.click.call($result.filter('.' + className.active), event);
17004 event.preventDefault();
17005 return false;
17006 }
17007 }
17008 else if(keyCode == keys.upArrow && hasActiveResult) {
17009 module.verbose('Up key pressed, changing active result');
17010 newIndex = (currentIndex - 1 < 0)
17011 ? currentIndex
17012 : currentIndex - 1
17013 ;
17014 $category
17015 .removeClass(className.active)
17016 ;
17017 $result
17018 .removeClass(className.active)
17019 .eq(newIndex)
17020 .addClass(className.active)
17021 .closest($category)
17022 .addClass(className.active)
17023 ;
17024 event.preventDefault();
17025 }
17026 else if(keyCode == keys.downArrow) {
17027 module.verbose('Down key pressed, changing active result');
17028 newIndex = (currentIndex + 1 >= resultSize)
17029 ? currentIndex
17030 : currentIndex + 1
17031 ;
17032 $category
17033 .removeClass(className.active)
17034 ;
17035 $result
17036 .removeClass(className.active)
17037 .eq(newIndex)
17038 .addClass(className.active)
17039 .closest($category)
17040 .addClass(className.active)
17041 ;
17042 event.preventDefault();
17043 }
17044 }
17045 else {
17046 // query shortcuts
17047 if(keyCode == keys.enter) {
17048 module.verbose('Enter key pressed, executing query');
17049 module.query();
17050 module.set.buttonPressed();
17051 $prompt.one('keyup', module.remove.buttonFocus);
17052 }
17053 }
17054 },
17055
17056 setup: {
17057 api: function(searchTerm, callback) {
17058 var
17059 apiSettings = {
17060 debug : settings.debug,
17061 on : false,
17062 cache : settings.cache,
17063 action : 'search',
17064 urlData : {
17065 query : searchTerm
17066 },
17067 onSuccess : function(response) {
17068 module.parse.response.call(element, response, searchTerm);
17069 callback();
17070 },
17071 onFailure : function() {
17072 module.displayMessage(error.serverError);
17073 callback();
17074 },
17075 onAbort : function(response) {
17076 },
17077 onError : module.error
17078 }
17079 ;
17080 $.extend(true, apiSettings, settings.apiSettings);
17081 module.verbose('Setting up API request', apiSettings);
17082 $module.api(apiSettings);
17083 }
17084 },
17085
17086 can: {
17087 useAPI: function() {
17088 return $.fn.api !== undefined;
17089 },
17090 show: function() {
17091 return module.is.focused() && !module.is.visible() && !module.is.empty();
17092 },
17093 transition: function() {
17094 return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
17095 }
17096 },
17097
17098 is: {
17099 animating: function() {
17100 return $results.hasClass(className.animating);
17101 },
17102 hidden: function() {
17103 return $results.hasClass(className.hidden);
17104 },
17105 inMessage: function(event) {
17106 if(!event.target) {
17107 return;
17108 }
17109 var
17110 $target = $(event.target),
17111 isInDOM = $.contains(document.documentElement, event.target)
17112 ;
17113 return (isInDOM && $target.closest(selector.message).length > 0);
17114 },
17115 empty: function() {
17116 return ($results.html() === '');
17117 },
17118 visible: function() {
17119 return ($results.filter(':visible').length > 0);
17120 },
17121 focused: function() {
17122 return ($prompt.filter(':focus').length > 0);
17123 }
17124 },
17125
17126 get: {
17127 settings: function() {
17128 if($.isPlainObject(parameters) && parameters.searchFullText) {
17129 settings.fullTextSearch = parameters.searchFullText;
17130 module.error(settings.error.oldSearchSyntax, element);
17131 }
17132 if (settings.ignoreDiacritics && !String.prototype.normalize) {
17133 settings.ignoreDiacritics = false;
17134 module.error(error.noNormalize, element);
17135 }
17136 },
17137 inputEvent: function() {
17138 var
17139 prompt = $prompt[0],
17140 inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
17141 ? 'input'
17142 : (prompt !== undefined && prompt.onpropertychange !== undefined)
17143 ? 'propertychange'
17144 : 'keyup'
17145 ;
17146 return inputEvent;
17147 },
17148 value: function() {
17149 return $prompt.val();
17150 },
17151 results: function() {
17152 var
17153 results = $module.data(metadata.results)
17154 ;
17155 return results;
17156 },
17157 result: function(value, results) {
17158 var
17159 lookupFields = ['title', 'id'],
17160 result = false
17161 ;
17162 value = (value !== undefined)
17163 ? value
17164 : module.get.value()
17165 ;
17166 results = (results !== undefined)
17167 ? results
17168 : module.get.results()
17169 ;
17170 if(settings.type === 'category') {
17171 module.debug('Finding result that matches', value);
17172 $.each(results, function(index, category) {
17173 if(Array.isArray(category.results)) {
17174 result = module.search.object(value, category.results, lookupFields)[0];
17175 // don't continue searching if a result is found
17176 if(result) {
17177 return false;
17178 }
17179 }
17180 });
17181 }
17182 else {
17183 module.debug('Finding result in results object', value);
17184 result = module.search.object(value, results, lookupFields)[0];
17185 }
17186 return result || false;
17187 },
17188 },
17189
17190 select: {
17191 firstResult: function() {
17192 module.verbose('Selecting first result');
17193 $result.first().addClass(className.active);
17194 }
17195 },
17196
17197 set: {
17198 focus: function() {
17199 $module.addClass(className.focus);
17200 },
17201 loading: function() {
17202 $module.addClass(className.loading);
17203 },
17204 value: function(value) {
17205 module.verbose('Setting search input value', value);
17206 $prompt
17207 .val(value)
17208 ;
17209 },
17210 type: function(type) {
17211 type = type || settings.type;
17212 if(settings.type == 'category') {
17213 $module.addClass(settings.type);
17214 }
17215 },
17216 buttonPressed: function() {
17217 $searchButton.addClass(className.pressed);
17218 }
17219 },
17220
17221 remove: {
17222 loading: function() {
17223 $module.removeClass(className.loading);
17224 },
17225 focus: function() {
17226 $module.removeClass(className.focus);
17227 },
17228 buttonPressed: function() {
17229 $searchButton.removeClass(className.pressed);
17230 },
17231 diacritics: function(text) {
17232 return settings.ignoreDiacritics ? text.normalize('NFD').replace(/[\u0300-\u036f]/g, '') : text;
17233 }
17234 },
17235
17236 query: function(callback) {
17237 callback = $.isFunction(callback)
17238 ? callback
17239 : function(){}
17240 ;
17241 var
17242 searchTerm = module.get.value(),
17243 cache = module.read.cache(searchTerm)
17244 ;
17245 callback = callback || function() {};
17246 if( module.has.minimumCharacters() ) {
17247 if(cache) {
17248 module.debug('Reading result from cache', searchTerm);
17249 module.save.results(cache.results);
17250 module.addResults(cache.html);
17251 module.inject.id(cache.results);
17252 callback();
17253 }
17254 else {
17255 module.debug('Querying for', searchTerm);
17256 if($.isPlainObject(settings.source) || Array.isArray(settings.source)) {
17257 module.search.local(searchTerm);
17258 callback();
17259 }
17260 else if( module.can.useAPI() ) {
17261 module.search.remote(searchTerm, callback);
17262 }
17263 else {
17264 module.error(error.source);
17265 callback();
17266 }
17267 }
17268 settings.onSearchQuery.call(element, searchTerm);
17269 }
17270 else {
17271 module.hideResults();
17272 }
17273 },
17274
17275 search: {
17276 local: function(searchTerm) {
17277 var
17278 results = module.search.object(searchTerm, settings.content),
17279 searchHTML
17280 ;
17281 module.set.loading();
17282 module.save.results(results);
17283 module.debug('Returned full local search results', results);
17284 if(settings.maxResults > 0) {
17285 module.debug('Using specified max results', results);
17286 results = results.slice(0, settings.maxResults);
17287 }
17288 if(settings.type == 'category') {
17289 results = module.create.categoryResults(results);
17290 }
17291 searchHTML = module.generateResults({
17292 results: results
17293 });
17294 module.remove.loading();
17295 module.addResults(searchHTML);
17296 module.inject.id(results);
17297 module.write.cache(searchTerm, {
17298 html : searchHTML,
17299 results : results
17300 });
17301 },
17302 remote: function(searchTerm, callback) {
17303 callback = $.isFunction(callback)
17304 ? callback
17305 : function(){}
17306 ;
17307 if($module.api('is loading')) {
17308 $module.api('abort');
17309 }
17310 module.setup.api(searchTerm, callback);
17311 $module
17312 .api('query')
17313 ;
17314 },
17315 object: function(searchTerm, source, searchFields) {
17316 searchTerm = module.remove.diacritics(String(searchTerm));
17317 var
17318 results = [],
17319 exactResults = [],
17320 fuzzyResults = [],
17321 searchExp = searchTerm.replace(regExp.escape, '\\$&'),
17322 matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
17323
17324 // avoid duplicates when pushing results
17325 addResult = function(array, result) {
17326 var
17327 notResult = ($.inArray(result, results) == -1),
17328 notFuzzyResult = ($.inArray(result, fuzzyResults) == -1),
17329 notExactResults = ($.inArray(result, exactResults) == -1)
17330 ;
17331 if(notResult && notFuzzyResult && notExactResults) {
17332 array.push(result);
17333 }
17334 }
17335 ;
17336 source = source || settings.source;
17337 searchFields = (searchFields !== undefined)
17338 ? searchFields
17339 : settings.searchFields
17340 ;
17341
17342 // search fields should be array to loop correctly
17343 if(!Array.isArray(searchFields)) {
17344 searchFields = [searchFields];
17345 }
17346
17347 // exit conditions if no source
17348 if(source === undefined || source === false) {
17349 module.error(error.source);
17350 return [];
17351 }
17352 // iterate through search fields looking for matches
17353 $.each(searchFields, function(index, field) {
17354 $.each(source, function(label, content) {
17355 var
17356 fieldExists = (typeof content[field] == 'string')
17357 ;
17358 if(fieldExists) {
17359 var text = module.remove.diacritics(content[field]);
17360 if( text.search(matchRegExp) !== -1) {
17361 // content starts with value (first in results)
17362 addResult(results, content);
17363 }
17364 else if(settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text) ) {
17365 // content fuzzy matches (last in results)
17366 addResult(exactResults, content);
17367 }
17368 else if(settings.fullTextSearch == true && module.fuzzySearch(searchTerm, text) ) {
17369 // content fuzzy matches (last in results)
17370 addResult(fuzzyResults, content);
17371 }
17372 }
17373 });
17374 });
17375 $.merge(exactResults, fuzzyResults);
17376 $.merge(results, exactResults);
17377 return results;
17378 }
17379 },
17380 exactSearch: function (query, term) {
17381 query = query.toLowerCase();
17382 term = term.toLowerCase();
17383 return term.indexOf(query) > -1;
17384 },
17385 fuzzySearch: function(query, term) {
17386 var
17387 termLength = term.length,
17388 queryLength = query.length
17389 ;
17390 if(typeof query !== 'string') {
17391 return false;
17392 }
17393 query = query.toLowerCase();
17394 term = term.toLowerCase();
17395 if(queryLength > termLength) {
17396 return false;
17397 }
17398 if(queryLength === termLength) {
17399 return (query === term);
17400 }
17401 search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
17402 var
17403 queryCharacter = query.charCodeAt(characterIndex)
17404 ;
17405 while(nextCharacterIndex < termLength) {
17406 if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
17407 continue search;
17408 }
17409 }
17410 return false;
17411 }
17412 return true;
17413 },
17414
17415 parse: {
17416 response: function(response, searchTerm) {
17417 if(Array.isArray(response)){
17418 var o={};
17419 o[fields.results]=response;
17420 response = o;
17421 }
17422 var
17423 searchHTML = module.generateResults(response)
17424 ;
17425 module.verbose('Parsing server response', response);
17426 if(response !== undefined) {
17427 if(searchTerm !== undefined && response[fields.results] !== undefined) {
17428 module.addResults(searchHTML);
17429 module.inject.id(response[fields.results]);
17430 module.write.cache(searchTerm, {
17431 html : searchHTML,
17432 results : response[fields.results]
17433 });
17434 module.save.results(response[fields.results]);
17435 }
17436 }
17437 }
17438 },
17439
17440 cancel: {
17441 query: function() {
17442 if( module.can.useAPI() ) {
17443 $module.api('abort');
17444 }
17445 }
17446 },
17447
17448 has: {
17449 minimumCharacters: function() {
17450 var
17451 searchTerm = module.get.value(),
17452 numCharacters = searchTerm.length
17453 ;
17454 return (numCharacters >= settings.minCharacters);
17455 },
17456 results: function() {
17457 if($results.length === 0) {
17458 return false;
17459 }
17460 var
17461 html = $results.html()
17462 ;
17463 return html != '';
17464 }
17465 },
17466
17467 clear: {
17468 cache: function(value) {
17469 var
17470 cache = $module.data(metadata.cache)
17471 ;
17472 if(!value) {
17473 module.debug('Clearing cache', value);
17474 $module.removeData(metadata.cache);
17475 }
17476 else if(value && cache && cache[value]) {
17477 module.debug('Removing value from cache', value);
17478 delete cache[value];
17479 $module.data(metadata.cache, cache);
17480 }
17481 }
17482 },
17483
17484 read: {
17485 cache: function(name) {
17486 var
17487 cache = $module.data(metadata.cache)
17488 ;
17489 if(settings.cache) {
17490 module.verbose('Checking cache for generated html for query', name);
17491 return (typeof cache == 'object') && (cache[name] !== undefined)
17492 ? cache[name]
17493 : false
17494 ;
17495 }
17496 return false;
17497 }
17498 },
17499
17500 create: {
17501 categoryResults: function(results) {
17502 var
17503 categoryResults = {}
17504 ;
17505 $.each(results, function(index, result) {
17506 if(!result.category) {
17507 return;
17508 }
17509 if(categoryResults[result.category] === undefined) {
17510 module.verbose('Creating new category of results', result.category);
17511 categoryResults[result.category] = {
17512 name : result.category,
17513 results : [result]
17514 };
17515 }
17516 else {
17517 categoryResults[result.category].results.push(result);
17518 }
17519 });
17520 return categoryResults;
17521 },
17522 id: function(resultIndex, categoryIndex) {
17523 var
17524 resultID = (resultIndex + 1), // not zero indexed
17525 letterID,
17526 id
17527 ;
17528 if(categoryIndex !== undefined) {
17529 // start char code for "A"
17530 letterID = String.fromCharCode(97 + categoryIndex);
17531 id = letterID + resultID;
17532 module.verbose('Creating category result id', id);
17533 }
17534 else {
17535 id = resultID;
17536 module.verbose('Creating result id', id);
17537 }
17538 return id;
17539 },
17540 results: function() {
17541 if($results.length === 0) {
17542 $results = $('<div />')
17543 .addClass(className.results)
17544 .appendTo($module)
17545 ;
17546 }
17547 }
17548 },
17549
17550 inject: {
17551 result: function(result, resultIndex, categoryIndex) {
17552 module.verbose('Injecting result into results');
17553 var
17554 $selectedResult = (categoryIndex !== undefined)
17555 ? $results
17556 .children().eq(categoryIndex)
17557 .children(selector.results)
17558 .first()
17559 .children(selector.result)
17560 .eq(resultIndex)
17561 : $results
17562 .children(selector.result).eq(resultIndex)
17563 ;
17564 module.verbose('Injecting results metadata', $selectedResult);
17565 $selectedResult
17566 .data(metadata.result, result)
17567 ;
17568 },
17569 id: function(results) {
17570 module.debug('Injecting unique ids into results');
17571 var
17572 // since results may be object, we must use counters
17573 categoryIndex = 0,
17574 resultIndex = 0
17575 ;
17576 if(settings.type === 'category') {
17577 // iterate through each category result
17578 $.each(results, function(index, category) {
17579 if(category.results.length > 0){
17580 resultIndex = 0;
17581 $.each(category.results, function(index, result) {
17582 if(result.id === undefined) {
17583 result.id = module.create.id(resultIndex, categoryIndex);
17584 }
17585 module.inject.result(result, resultIndex, categoryIndex);
17586 resultIndex++;
17587 });
17588 categoryIndex++;
17589 }
17590 });
17591 }
17592 else {
17593 // top level
17594 $.each(results, function(index, result) {
17595 if(result.id === undefined) {
17596 result.id = module.create.id(resultIndex);
17597 }
17598 module.inject.result(result, resultIndex);
17599 resultIndex++;
17600 });
17601 }
17602 return results;
17603 }
17604 },
17605
17606 save: {
17607 results: function(results) {
17608 module.verbose('Saving current search results to metadata', results);
17609 $module.data(metadata.results, results);
17610 }
17611 },
17612
17613 write: {
17614 cache: function(name, value) {
17615 var
17616 cache = ($module.data(metadata.cache) !== undefined)
17617 ? $module.data(metadata.cache)
17618 : {}
17619 ;
17620 if(settings.cache) {
17621 module.verbose('Writing generated html to cache', name, value);
17622 cache[name] = value;
17623 $module
17624 .data(metadata.cache, cache)
17625 ;
17626 }
17627 }
17628 },
17629
17630 addResults: function(html) {
17631 if( $.isFunction(settings.onResultsAdd) ) {
17632 if( settings.onResultsAdd.call($results, html) === false ) {
17633 module.debug('onResultsAdd callback cancelled default action');
17634 return false;
17635 }
17636 }
17637 if(html) {
17638 $results
17639 .html(html)
17640 ;
17641 module.refreshResults();
17642 if(settings.selectFirstResult) {
17643 module.select.firstResult();
17644 }
17645 module.showResults();
17646 }
17647 else {
17648 module.hideResults(function() {
17649 $results.empty();
17650 });
17651 }
17652 },
17653
17654 showResults: function(callback) {
17655 callback = $.isFunction(callback)
17656 ? callback
17657 : function(){}
17658 ;
17659 if(resultsDismissed) {
17660 return;
17661 }
17662 if(!module.is.visible() && module.has.results()) {
17663 if( module.can.transition() ) {
17664 module.debug('Showing results with css animations');
17665 $results
17666 .transition({
17667 animation : settings.transition + ' in',
17668 debug : settings.debug,
17669 verbose : settings.verbose,
17670 duration : settings.duration,
17671 onComplete : function() {
17672 callback();
17673 },
17674 queue : true
17675 })
17676 ;
17677 }
17678 else {
17679 module.debug('Showing results with javascript');
17680 $results
17681 .stop()
17682 .fadeIn(settings.duration, settings.easing)
17683 ;
17684 }
17685 settings.onResultsOpen.call($results);
17686 }
17687 },
17688 hideResults: function(callback) {
17689 callback = $.isFunction(callback)
17690 ? callback
17691 : function(){}
17692 ;
17693 if( module.is.visible() ) {
17694 if( module.can.transition() ) {
17695 module.debug('Hiding results with css animations');
17696 $results
17697 .transition({
17698 animation : settings.transition + ' out',
17699 debug : settings.debug,
17700 verbose : settings.verbose,
17701 duration : settings.duration,
17702 onComplete : function() {
17703 callback();
17704 },
17705 queue : true
17706 })
17707 ;
17708 }
17709 else {
17710 module.debug('Hiding results with javascript');
17711 $results
17712 .stop()
17713 .fadeOut(settings.duration, settings.easing)
17714 ;
17715 }
17716 settings.onResultsClose.call($results);
17717 }
17718 },
17719
17720 generateResults: function(response) {
17721 module.debug('Generating html from response', response);
17722 var
17723 template = settings.templates[settings.type],
17724 isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])),
17725 isProperArray = (Array.isArray(response[fields.results]) && response[fields.results].length > 0),
17726 html = ''
17727 ;
17728 if(isProperObject || isProperArray ) {
17729 if(settings.maxResults > 0) {
17730 if(isProperObject) {
17731 if(settings.type == 'standard') {
17732 module.error(error.maxResults);
17733 }
17734 }
17735 else {
17736 response[fields.results] = response[fields.results].slice(0, settings.maxResults);
17737 }
17738 }
17739 if($.isFunction(template)) {
17740 html = template(response, fields, settings.preserveHTML);
17741 }
17742 else {
17743 module.error(error.noTemplate, false);
17744 }
17745 }
17746 else if(settings.showNoResults) {
17747 html = module.displayMessage(error.noResults, 'empty', error.noResultsHeader);
17748 }
17749 settings.onResults.call(element, response);
17750 return html;
17751 },
17752
17753 displayMessage: function(text, type, header) {
17754 type = type || 'standard';
17755 module.debug('Displaying message', text, type, header);
17756 module.addResults( settings.templates.message(text, type, header) );
17757 return settings.templates.message(text, type, header);
17758 },
17759
17760 setting: function(name, value) {
17761 if( $.isPlainObject(name) ) {
17762 $.extend(true, settings, name);
17763 }
17764 else if(value !== undefined) {
17765 settings[name] = value;
17766 }
17767 else {
17768 return settings[name];
17769 }
17770 },
17771 internal: function(name, value) {
17772 if( $.isPlainObject(name) ) {
17773 $.extend(true, module, name);
17774 }
17775 else if(value !== undefined) {
17776 module[name] = value;
17777 }
17778 else {
17779 return module[name];
17780 }
17781 },
17782 debug: function() {
17783 if(!settings.silent && settings.debug) {
17784 if(settings.performance) {
17785 module.performance.log(arguments);
17786 }
17787 else {
17788 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
17789 module.debug.apply(console, arguments);
17790 }
17791 }
17792 },
17793 verbose: function() {
17794 if(!settings.silent && settings.verbose && settings.debug) {
17795 if(settings.performance) {
17796 module.performance.log(arguments);
17797 }
17798 else {
17799 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
17800 module.verbose.apply(console, arguments);
17801 }
17802 }
17803 },
17804 error: function() {
17805 if(!settings.silent) {
17806 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
17807 module.error.apply(console, arguments);
17808 }
17809 },
17810 performance: {
17811 log: function(message) {
17812 var
17813 currentTime,
17814 executionTime,
17815 previousTime
17816 ;
17817 if(settings.performance) {
17818 currentTime = new Date().getTime();
17819 previousTime = time || currentTime;
17820 executionTime = currentTime - previousTime;
17821 time = currentTime;
17822 performance.push({
17823 'Name' : message[0],
17824 'Arguments' : [].slice.call(message, 1) || '',
17825 'Element' : element,
17826 'Execution Time' : executionTime
17827 });
17828 }
17829 clearTimeout(module.performance.timer);
17830 module.performance.timer = setTimeout(module.performance.display, 500);
17831 },
17832 display: function() {
17833 var
17834 title = settings.name + ':',
17835 totalTime = 0
17836 ;
17837 time = false;
17838 clearTimeout(module.performance.timer);
17839 $.each(performance, function(index, data) {
17840 totalTime += data['Execution Time'];
17841 });
17842 title += ' ' + totalTime + 'ms';
17843 if(moduleSelector) {
17844 title += ' \'' + moduleSelector + '\'';
17845 }
17846 if($allModules.length > 1) {
17847 title += ' ' + '(' + $allModules.length + ')';
17848 }
17849 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
17850 console.groupCollapsed(title);
17851 if(console.table) {
17852 console.table(performance);
17853 }
17854 else {
17855 $.each(performance, function(index, data) {
17856 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
17857 });
17858 }
17859 console.groupEnd();
17860 }
17861 performance = [];
17862 }
17863 },
17864 invoke: function(query, passedArguments, context) {
17865 var
17866 object = instance,
17867 maxDepth,
17868 found,
17869 response
17870 ;
17871 passedArguments = passedArguments || queryArguments;
17872 context = element || context;
17873 if(typeof query == 'string' && object !== undefined) {
17874 query = query.split(/[\. ]/);
17875 maxDepth = query.length - 1;
17876 $.each(query, function(depth, value) {
17877 var camelCaseValue = (depth != maxDepth)
17878 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
17879 : query
17880 ;
17881 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
17882 object = object[camelCaseValue];
17883 }
17884 else if( object[camelCaseValue] !== undefined ) {
17885 found = object[camelCaseValue];
17886 return false;
17887 }
17888 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
17889 object = object[value];
17890 }
17891 else if( object[value] !== undefined ) {
17892 found = object[value];
17893 return false;
17894 }
17895 else {
17896 return false;
17897 }
17898 });
17899 }
17900 if( $.isFunction( found ) ) {
17901 response = found.apply(context, passedArguments);
17902 }
17903 else if(found !== undefined) {
17904 response = found;
17905 }
17906 if(Array.isArray(returnedValue)) {
17907 returnedValue.push(response);
17908 }
17909 else if(returnedValue !== undefined) {
17910 returnedValue = [returnedValue, response];
17911 }
17912 else if(response !== undefined) {
17913 returnedValue = response;
17914 }
17915 return found;
17916 }
17917 };
17918 if(methodInvoked) {
17919 if(instance === undefined) {
17920 module.initialize();
17921 }
17922 module.invoke(query);
17923 }
17924 else {
17925 if(instance !== undefined) {
17926 instance.invoke('destroy');
17927 }
17928 module.initialize();
17929 }
17930
17931 })
17932 ;
17933
17934 return (returnedValue !== undefined)
17935 ? returnedValue
17936 : this
17937 ;
17938};
17939
17940$.fn.search.settings = {
17941
17942 name : 'Search',
17943 namespace : 'search',
17944
17945 silent : false,
17946 debug : false,
17947 verbose : false,
17948 performance : true,
17949
17950 // template to use (specified in settings.templates)
17951 type : 'standard',
17952
17953 // minimum characters required to search
17954 minCharacters : 1,
17955
17956 // whether to select first result after searching automatically
17957 selectFirstResult : false,
17958
17959 // API config
17960 apiSettings : false,
17961
17962 // object to search
17963 source : false,
17964
17965 // Whether search should query current term on focus
17966 searchOnFocus : true,
17967
17968 // fields to search
17969 searchFields : [
17970 'title',
17971 'description'
17972 ],
17973
17974 // field to display in standard results template
17975 displayField : '',
17976
17977 // search anywhere in value (set to 'exact' to require exact matches
17978 fullTextSearch : 'exact',
17979
17980 // match results also if they contain diacritics of the same base character (for example searching for "a" will also match "á" or "â" or "à", etc...)
17981 ignoreDiacritics : false,
17982
17983 // whether to add events to prompt automatically
17984 automatic : true,
17985
17986 // delay before hiding menu after blur
17987 hideDelay : 0,
17988
17989 // delay before searching
17990 searchDelay : 200,
17991
17992 // maximum results returned from search
17993 maxResults : 7,
17994
17995 // whether to store lookups in local cache
17996 cache : true,
17997
17998 // whether no results errors should be shown
17999 showNoResults : true,
18000
18001 // preserve possible html of resultset values
18002 preserveHTML : true,
18003
18004 // transition settings
18005 transition : 'scale',
18006 duration : 200,
18007 easing : 'easeOutExpo',
18008
18009 // callbacks
18010 onSelect : false,
18011 onResultsAdd : false,
18012
18013 onSearchQuery : function(query){},
18014 onResults : function(response){},
18015
18016 onResultsOpen : function(){},
18017 onResultsClose : function(){},
18018
18019 className: {
18020 animating : 'animating',
18021 active : 'active',
18022 empty : 'empty',
18023 focus : 'focus',
18024 hidden : 'hidden',
18025 loading : 'loading',
18026 results : 'results',
18027 pressed : 'down'
18028 },
18029
18030 error : {
18031 source : 'Cannot search. No source used, and Semantic API module was not included',
18032 noResultsHeader : 'No Results',
18033 noResults : 'Your search returned no results',
18034 logging : 'Error in debug logging, exiting.',
18035 noEndpoint : 'No search endpoint was specified',
18036 noTemplate : 'A valid template name was not specified.',
18037 oldSearchSyntax : 'searchFullText setting has been renamed fullTextSearch for consistency, please adjust your settings.',
18038 serverError : 'There was an issue querying the server.',
18039 maxResults : 'Results must be an array to use maxResults setting',
18040 method : 'The method you called is not defined.',
18041 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.'
18042 },
18043
18044 metadata: {
18045 cache : 'cache',
18046 results : 'results',
18047 result : 'result'
18048 },
18049
18050 regExp: {
18051 escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
18052 beginsWith : '(?:\s|^)'
18053 },
18054
18055 // maps api response attributes to internal representation
18056 fields: {
18057 categories : 'results', // array of categories (category view)
18058 categoryName : 'name', // name of category (category view)
18059 categoryResults : 'results', // array of results (category view)
18060 description : 'description', // result description
18061 image : 'image', // result image
18062 price : 'price', // result price
18063 results : 'results', // array of results (standard)
18064 title : 'title', // result title
18065 url : 'url', // result url
18066 action : 'action', // "view more" object name
18067 actionText : 'text', // "view more" text
18068 actionURL : 'url' // "view more" url
18069 },
18070
18071 selector : {
18072 prompt : '.prompt',
18073 searchButton : '.search.button',
18074 results : '.results',
18075 message : '.results > .message',
18076 category : '.category',
18077 result : '.result',
18078 title : '.title, .name'
18079 },
18080
18081 templates: {
18082 escape: function(string, preserveHTML) {
18083 if (preserveHTML){
18084 return string;
18085 }
18086 var
18087 badChars = /[&<>"'`]/g,
18088 shouldEscape = /[&<>"'`]/,
18089 escape = {
18090 "&": "&amp;",
18091 "<": "&lt;",
18092 ">": "&gt;",
18093 '"': "&quot;",
18094 "'": "&#x27;",
18095 "`": "&#x60;"
18096 },
18097 escapedChar = function(chr) {
18098 return escape[chr];
18099 }
18100 ;
18101 if(shouldEscape.test(string)) {
18102 return string.replace(badChars, escapedChar);
18103 }
18104 return string;
18105 },
18106 message: function(message, type, header) {
18107 var
18108 html = ''
18109 ;
18110 if(message !== undefined && type !== undefined) {
18111 html += ''
18112 + '<div class="message ' + type + '">'
18113 ;
18114 if(header) {
18115 html += ''
18116 + '<div class="header">' + header + '</div>'
18117 ;
18118 }
18119 html += ' <div class="description">' + message + '</div>';
18120 html += '</div>';
18121 }
18122 return html;
18123 },
18124 category: function(response, fields, preserveHTML) {
18125 var
18126 html = '',
18127 escape = $.fn.search.settings.templates.escape
18128 ;
18129 if(response[fields.categoryResults] !== undefined) {
18130
18131 // each category
18132 $.each(response[fields.categoryResults], function(index, category) {
18133 if(category[fields.results] !== undefined && category.results.length > 0) {
18134
18135 html += '<div class="category">';
18136
18137 if(category[fields.categoryName] !== undefined) {
18138 html += '<div class="name">' + escape(category[fields.categoryName], preserveHTML) + '</div>';
18139 }
18140
18141 // each item inside category
18142 html += '<div class="results">';
18143 $.each(category.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 html += '</div>';
18173 html += ''
18174 + '</div>'
18175 ;
18176 }
18177 });
18178 if(response[fields.action]) {
18179 if(fields.actionURL === false) {
18180 html += ''
18181 + '<div class="action">'
18182 + escape(response[fields.action][fields.actionText], preserveHTML)
18183 + '</div>';
18184 } else {
18185 html += ''
18186 + '<a href="' + response[fields.action][fields.actionURL].replace(/"/g,"") + '" class="action">'
18187 + escape(response[fields.action][fields.actionText], preserveHTML)
18188 + '</a>';
18189 }
18190 }
18191 return html;
18192 }
18193 return false;
18194 },
18195 standard: function(response, fields, preserveHTML) {
18196 var
18197 html = '',
18198 escape = $.fn.search.settings.templates.escape
18199 ;
18200 if(response[fields.results] !== undefined) {
18201
18202 // each result
18203 $.each(response[fields.results], function(index, result) {
18204 if(result[fields.url]) {
18205 html += '<a class="result" href="' + result[fields.url].replace(/"/g,"") + '">';
18206 }
18207 else {
18208 html += '<a class="result">';
18209 }
18210 if(result[fields.image] !== undefined) {
18211 html += ''
18212 + '<div class="image">'
18213 + ' <img src="' + result[fields.image].replace(/"/g,"") + '">'
18214 + '</div>'
18215 ;
18216 }
18217 html += '<div class="content">';
18218 if(result[fields.price] !== undefined) {
18219 html += '<div class="price">' + escape(result[fields.price], preserveHTML) + '</div>';
18220 }
18221 if(result[fields.title] !== undefined) {
18222 html += '<div class="title">' + escape(result[fields.title], preserveHTML) + '</div>';
18223 }
18224 if(result[fields.description] !== undefined) {
18225 html += '<div class="description">' + escape(result[fields.description], preserveHTML) + '</div>';
18226 }
18227 html += ''
18228 + '</div>'
18229 ;
18230 html += '</a>';
18231 });
18232 if(response[fields.action]) {
18233 if(fields.actionURL === false) {
18234 html += ''
18235 + '<div class="action">'
18236 + escape(response[fields.action][fields.actionText], preserveHTML)
18237 + '</div>';
18238 } else {
18239 html += ''
18240 + '<a href="' + response[fields.action][fields.actionURL].replace(/"/g,"") + '" class="action">'
18241 + escape(response[fields.action][fields.actionText], preserveHTML)
18242 + '</a>';
18243 }
18244 }
18245 return html;
18246 }
18247 return false;
18248 }
18249 }
18250};
18251
18252})( jQuery, window, document );
18253
18254/*!
18255 * # Semantic UI 2.7.2 - Shape
18256 * http://github.com/semantic-org/semantic-ui/
18257 *
18258 *
18259 * Released under the MIT license
18260 * http://opensource.org/licenses/MIT
18261 *
18262 */
18263
18264;(function ($, window, document, undefined) {
18265
18266'use strict';
18267
18268$.isFunction = $.isFunction || function(obj) {
18269 return typeof obj === "function" && typeof obj.nodeType !== "number";
18270};
18271
18272window = (typeof window != 'undefined' && window.Math == Math)
18273 ? window
18274 : (typeof self != 'undefined' && self.Math == Math)
18275 ? self
18276 : Function('return this')()
18277;
18278
18279$.fn.shape = function(parameters) {
18280 var
18281 $allModules = $(this),
18282
18283 time = new Date().getTime(),
18284 performance = [],
18285
18286 query = arguments[0],
18287 methodInvoked = (typeof query == 'string'),
18288 queryArguments = [].slice.call(arguments, 1),
18289
18290 requestAnimationFrame = window.requestAnimationFrame
18291 || window.mozRequestAnimationFrame
18292 || window.webkitRequestAnimationFrame
18293 || window.msRequestAnimationFrame
18294 || function(callback) { setTimeout(callback, 0); },
18295
18296 returnedValue
18297 ;
18298
18299 $allModules
18300 .each(function() {
18301 var
18302 moduleSelector = $allModules.selector || '',
18303 settings = ( $.isPlainObject(parameters) )
18304 ? $.extend(true, {}, $.fn.shape.settings, parameters)
18305 : $.extend({}, $.fn.shape.settings),
18306
18307 // internal aliases
18308 namespace = settings.namespace,
18309 selector = settings.selector,
18310 error = settings.error,
18311 className = settings.className,
18312
18313 // define namespaces for modules
18314 eventNamespace = '.' + namespace,
18315 moduleNamespace = 'module-' + namespace,
18316
18317 // selector cache
18318 $module = $(this),
18319 $sides = $module.find('>' + selector.sides),
18320 $side = $sides.find('>' + selector.side),
18321
18322 // private variables
18323 nextIndex = false,
18324 $activeSide,
18325 $nextSide,
18326
18327 // standard module
18328 element = this,
18329 instance = $module.data(moduleNamespace),
18330 module
18331 ;
18332
18333 module = {
18334
18335 initialize: function() {
18336 module.verbose('Initializing module for', element);
18337 module.set.defaultSide();
18338 module.instantiate();
18339 },
18340
18341 instantiate: function() {
18342 module.verbose('Storing instance of module', module);
18343 instance = module;
18344 $module
18345 .data(moduleNamespace, instance)
18346 ;
18347 },
18348
18349 destroy: function() {
18350 module.verbose('Destroying previous module for', element);
18351 $module
18352 .removeData(moduleNamespace)
18353 .off(eventNamespace)
18354 ;
18355 },
18356
18357 refresh: function() {
18358 module.verbose('Refreshing selector cache for', element);
18359 $module = $(element);
18360 $sides = $(this).find(selector.sides);
18361 $side = $(this).find(selector.side);
18362 },
18363
18364 repaint: function() {
18365 module.verbose('Forcing repaint event');
18366 var
18367 shape = $sides[0] || document.createElement('div'),
18368 fakeAssignment = shape.offsetWidth
18369 ;
18370 },
18371
18372 animate: function(propertyObject, callback) {
18373 module.verbose('Animating box with properties', propertyObject);
18374 callback = callback || function(event) {
18375 module.verbose('Executing animation callback');
18376 if(event !== undefined) {
18377 event.stopPropagation();
18378 }
18379 module.reset();
18380 module.set.active();
18381 };
18382 settings.beforeChange.call($nextSide[0]);
18383 if(module.get.transitionEvent()) {
18384 module.verbose('Starting CSS animation');
18385 $module
18386 .addClass(className.animating)
18387 ;
18388 $sides
18389 .css(propertyObject)
18390 .one(module.get.transitionEvent(), callback)
18391 ;
18392 module.set.duration(settings.duration);
18393 requestAnimationFrame(function() {
18394 $module
18395 .addClass(className.animating)
18396 ;
18397 $activeSide
18398 .addClass(className.hidden)
18399 ;
18400 });
18401 }
18402 else {
18403 callback();
18404 }
18405 },
18406
18407 queue: function(method) {
18408 module.debug('Queueing animation of', method);
18409 $sides
18410 .one(module.get.transitionEvent(), function() {
18411 module.debug('Executing queued animation');
18412 setTimeout(function(){
18413 $module.shape(method);
18414 }, 0);
18415 })
18416 ;
18417 },
18418
18419 reset: function() {
18420 module.verbose('Animating states reset');
18421 $module
18422 .removeClass(className.animating)
18423 .attr('style', '')
18424 .removeAttr('style')
18425 ;
18426 // removeAttr style does not consistently work in safari
18427 $sides
18428 .attr('style', '')
18429 .removeAttr('style')
18430 ;
18431 $side
18432 .attr('style', '')
18433 .removeAttr('style')
18434 .removeClass(className.hidden)
18435 ;
18436 $nextSide
18437 .removeClass(className.animating)
18438 .attr('style', '')
18439 .removeAttr('style')
18440 ;
18441 },
18442
18443 is: {
18444 complete: function() {
18445 return ($side.filter('.' + className.active)[0] == $nextSide[0]);
18446 },
18447 animating: function() {
18448 return $module.hasClass(className.animating);
18449 },
18450 hidden: function() {
18451 return $module.closest(':hidden').length > 0;
18452 }
18453 },
18454
18455 set: {
18456
18457 defaultSide: function() {
18458 $activeSide = $side.filter('.' + settings.className.active);
18459 $nextSide = ( $activeSide.next(selector.side).length > 0 )
18460 ? $activeSide.next(selector.side)
18461 : $side.first()
18462 ;
18463 nextIndex = false;
18464 module.verbose('Active side set to', $activeSide);
18465 module.verbose('Next side set to', $nextSide);
18466 },
18467
18468 duration: function(duration) {
18469 duration = duration || settings.duration;
18470 duration = (typeof duration == 'number')
18471 ? duration + 'ms'
18472 : duration
18473 ;
18474 module.verbose('Setting animation duration', duration);
18475 if(settings.duration || settings.duration === 0) {
18476 $sides.add($side)
18477 .css({
18478 '-webkit-transition-duration': duration,
18479 '-moz-transition-duration': duration,
18480 '-ms-transition-duration': duration,
18481 '-o-transition-duration': duration,
18482 'transition-duration': duration
18483 })
18484 ;
18485 }
18486 },
18487
18488 currentStageSize: function() {
18489 var
18490 $activeSide = $side.filter('.' + settings.className.active),
18491 width = $activeSide.outerWidth(true),
18492 height = $activeSide.outerHeight(true)
18493 ;
18494 $module
18495 .css({
18496 width: width,
18497 height: height
18498 })
18499 ;
18500 },
18501
18502 stageSize: function() {
18503 var
18504 $clone = $module.clone().addClass(className.loading),
18505 $side = $clone.find('>' + selector.sides + '>' + selector.side),
18506 $activeSide = $side.filter('.' + settings.className.active),
18507 $nextSide = (nextIndex)
18508 ? $side.eq(nextIndex)
18509 : ( $activeSide.next(selector.side).length > 0 )
18510 ? $activeSide.next(selector.side)
18511 : $side.first(),
18512 newWidth = (settings.width === 'next')
18513 ? $nextSide.outerWidth(true)
18514 : (settings.width === 'initial')
18515 ? $module.width()
18516 : settings.width,
18517 newHeight = (settings.height === 'next')
18518 ? $nextSide.outerHeight(true)
18519 : (settings.height === 'initial')
18520 ? $module.height()
18521 : settings.height
18522 ;
18523 $activeSide.removeClass(className.active);
18524 $nextSide.addClass(className.active);
18525 $clone.insertAfter($module);
18526 $clone.remove();
18527 if(settings.width !== 'auto') {
18528 $module.css('width', newWidth + settings.jitter);
18529 module.verbose('Specifying width during animation', newWidth);
18530 }
18531 if(settings.height !== 'auto') {
18532 $module.css('height', newHeight + settings.jitter);
18533 module.verbose('Specifying height during animation', newHeight);
18534 }
18535 },
18536
18537 nextSide: function(selector) {
18538 nextIndex = selector;
18539 $nextSide = $side.filter(selector);
18540 nextIndex = $side.index($nextSide);
18541 if($nextSide.length === 0) {
18542 module.set.defaultSide();
18543 module.error(error.side);
18544 }
18545 module.verbose('Next side manually set to', $nextSide);
18546 },
18547
18548 active: function() {
18549 module.verbose('Setting new side to active', $nextSide);
18550 $side
18551 .removeClass(className.active)
18552 ;
18553 $nextSide
18554 .addClass(className.active)
18555 ;
18556 settings.onChange.call($nextSide[0]);
18557 module.set.defaultSide();
18558 }
18559 },
18560
18561 flip: {
18562 to: function(type,stage){
18563 if(module.is.hidden()) {
18564 module.debug('Module not visible', $nextSide);
18565 return;
18566 }
18567 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
18568 module.debug('Side already visible', $nextSide);
18569 return;
18570 }
18571 var
18572 transform = module.get.transform[type]()
18573 ;
18574 if( !module.is.animating()) {
18575 module.debug('Flipping '+type, $nextSide);
18576 module.set.stageSize();
18577 module.stage[stage]();
18578 module.animate(transform);
18579 }
18580 else {
18581 module.queue('flip '+type);
18582 }
18583 },
18584
18585 up: function() {
18586 module.flip.to('up','above');
18587 },
18588
18589 down: function() {
18590 module.flip.to('down','below');
18591 },
18592
18593 left: function() {
18594 module.flip.to('left','left');
18595 },
18596
18597 right: function() {
18598 module.flip.to('right','right');
18599 },
18600
18601 over: function() {
18602 module.flip.to('over','behind');
18603 },
18604
18605 back: function() {
18606 module.flip.to('back','behind');
18607 }
18608
18609 },
18610
18611 get: {
18612
18613 transform: {
18614 up: function() {
18615 var
18616 translateZ = $activeSide.outerHeight(true) / 2,
18617 translateY = $nextSide.outerHeight(true) - translateZ
18618 ;
18619 return {
18620 transform: 'translateY(' + translateY + 'px) translateZ(-'+ translateZ + 'px) rotateX(-90deg)'
18621 };
18622 },
18623
18624 down: function() {
18625 var
18626 translate = {
18627 z: $activeSide.outerHeight(true) / 2
18628 }
18629 ;
18630 return {
18631 transform: 'translateY(-' + translate.z + 'px) translateZ(-'+ translate.z + 'px) rotateX(90deg)'
18632 };
18633 },
18634
18635 left: function() {
18636 var
18637 translateZ = $activeSide.outerWidth(true) / 2,
18638 translateX = $nextSide.outerWidth(true) - translateZ
18639 ;
18640 return {
18641 transform: 'translateX(' + translateX + 'px) translateZ(-' + translateZ + 'px) rotateY(90deg)'
18642 };
18643 },
18644
18645 right: function() {
18646 var
18647 translate = {
18648 z : $activeSide.outerWidth(true) / 2
18649 }
18650 ;
18651 return {
18652 transform: 'translateX(-' + translate.z + 'px) translateZ(-' + translate.z + 'px) rotateY(-90deg)'
18653 };
18654 },
18655
18656 over: function() {
18657 var
18658 translate = {
18659 x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
18660 }
18661 ;
18662 return {
18663 transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
18664 };
18665 },
18666
18667 back: function() {
18668 var
18669 translate = {
18670 x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
18671 }
18672 ;
18673 return {
18674 transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
18675 };
18676 }
18677 },
18678
18679 transitionEvent: function() {
18680 var
18681 element = document.createElement('element'),
18682 transitions = {
18683 'transition' :'transitionend',
18684 'OTransition' :'oTransitionEnd',
18685 'MozTransition' :'transitionend',
18686 'WebkitTransition' :'webkitTransitionEnd'
18687 },
18688 transition
18689 ;
18690 for(transition in transitions){
18691 if( element.style[transition] !== undefined ){
18692 return transitions[transition];
18693 }
18694 }
18695 },
18696
18697 nextSide: function() {
18698 return ( $activeSide.next(selector.side).length > 0 )
18699 ? $activeSide.next(selector.side)
18700 : $side.first()
18701 ;
18702 }
18703
18704 },
18705
18706 stage: {
18707
18708 above: function() {
18709 var
18710 box = {
18711 origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
18712 depth : {
18713 active : ($nextSide.outerHeight(true) / 2),
18714 next : ($activeSide.outerHeight(true) / 2)
18715 }
18716 }
18717 ;
18718 module.verbose('Setting the initial animation position as above', $nextSide, box);
18719 $activeSide
18720 .css({
18721 'transform' : 'rotateX(0deg)'
18722 })
18723 ;
18724 $nextSide
18725 .addClass(className.animating)
18726 .css({
18727 'top' : box.origin + 'px',
18728 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px) translateY(-' + box.depth.active + 'px)'
18729 })
18730 ;
18731 },
18732
18733 below: function() {
18734 var
18735 box = {
18736 origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
18737 depth : {
18738 active : ($nextSide.outerHeight(true) / 2),
18739 next : ($activeSide.outerHeight(true) / 2)
18740 }
18741 }
18742 ;
18743 module.verbose('Setting the initial animation position as below', $nextSide, box);
18744 $activeSide
18745 .css({
18746 'transform' : 'rotateX(0deg)'
18747 })
18748 ;
18749 $nextSide
18750 .addClass(className.animating)
18751 .css({
18752 'top' : box.origin + 'px',
18753 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px) translateY(' + box.depth.active + 'px)'
18754 })
18755 ;
18756 },
18757
18758 left: function() {
18759 var
18760 height = {
18761 active : $activeSide.outerWidth(true),
18762 next : $nextSide.outerWidth(true)
18763 },
18764 box = {
18765 origin : ( ( height.active - height.next ) / 2),
18766 depth : {
18767 active : (height.next / 2),
18768 next : (height.active / 2)
18769 }
18770 }
18771 ;
18772 module.verbose('Setting the initial animation position as left', $nextSide, box);
18773 $activeSide
18774 .css({
18775 'transform' : 'rotateY(0deg)'
18776 })
18777 ;
18778 $nextSide
18779 .addClass(className.animating)
18780 .css({
18781 'left' : box.origin + 'px',
18782 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px) translateX(-' + box.depth.active + 'px)'
18783 })
18784 ;
18785 },
18786
18787 right: function() {
18788 var
18789 height = {
18790 active : $activeSide.outerWidth(true),
18791 next : $nextSide.outerWidth(true)
18792 },
18793 box = {
18794 origin : ( ( height.active - height.next ) / 2),
18795 depth : {
18796 active : (height.next / 2),
18797 next : (height.active / 2)
18798 }
18799 }
18800 ;
18801 module.verbose('Setting the initial animation position as right', $nextSide, box);
18802 $activeSide
18803 .css({
18804 'transform' : 'rotateY(0deg)'
18805 })
18806 ;
18807 $nextSide
18808 .addClass(className.animating)
18809 .css({
18810 'left' : box.origin + 'px',
18811 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px) translateX(' + box.depth.active + 'px)'
18812 })
18813 ;
18814 },
18815
18816 behind: function() {
18817 var
18818 height = {
18819 active : $activeSide.outerWidth(true),
18820 next : $nextSide.outerWidth(true)
18821 },
18822 box = {
18823 origin : ( ( height.active - height.next ) / 2),
18824 depth : {
18825 active : (height.next / 2),
18826 next : (height.active / 2)
18827 }
18828 }
18829 ;
18830 module.verbose('Setting the initial animation position as behind', $nextSide, box);
18831 $activeSide
18832 .css({
18833 'transform' : 'rotateY(0deg)'
18834 })
18835 ;
18836 $nextSide
18837 .addClass(className.animating)
18838 .css({
18839 'left' : box.origin + 'px',
18840 'transform' : 'rotateY(-180deg)'
18841 })
18842 ;
18843 }
18844 },
18845 setting: function(name, value) {
18846 module.debug('Changing setting', name, value);
18847 if( $.isPlainObject(name) ) {
18848 $.extend(true, settings, name);
18849 }
18850 else if(value !== undefined) {
18851 if($.isPlainObject(settings[name])) {
18852 $.extend(true, settings[name], value);
18853 }
18854 else {
18855 settings[name] = value;
18856 }
18857 }
18858 else {
18859 return settings[name];
18860 }
18861 },
18862 internal: function(name, value) {
18863 if( $.isPlainObject(name) ) {
18864 $.extend(true, module, name);
18865 }
18866 else if(value !== undefined) {
18867 module[name] = value;
18868 }
18869 else {
18870 return module[name];
18871 }
18872 },
18873 debug: function() {
18874 if(!settings.silent && settings.debug) {
18875 if(settings.performance) {
18876 module.performance.log(arguments);
18877 }
18878 else {
18879 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
18880 module.debug.apply(console, arguments);
18881 }
18882 }
18883 },
18884 verbose: function() {
18885 if(!settings.silent && settings.verbose && settings.debug) {
18886 if(settings.performance) {
18887 module.performance.log(arguments);
18888 }
18889 else {
18890 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
18891 module.verbose.apply(console, arguments);
18892 }
18893 }
18894 },
18895 error: function() {
18896 if(!settings.silent) {
18897 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
18898 module.error.apply(console, arguments);
18899 }
18900 },
18901 performance: {
18902 log: function(message) {
18903 var
18904 currentTime,
18905 executionTime,
18906 previousTime
18907 ;
18908 if(settings.performance) {
18909 currentTime = new Date().getTime();
18910 previousTime = time || currentTime;
18911 executionTime = currentTime - previousTime;
18912 time = currentTime;
18913 performance.push({
18914 'Name' : message[0],
18915 'Arguments' : [].slice.call(message, 1) || '',
18916 'Element' : element,
18917 'Execution Time' : executionTime
18918 });
18919 }
18920 clearTimeout(module.performance.timer);
18921 module.performance.timer = setTimeout(module.performance.display, 500);
18922 },
18923 display: function() {
18924 var
18925 title = settings.name + ':',
18926 totalTime = 0
18927 ;
18928 time = false;
18929 clearTimeout(module.performance.timer);
18930 $.each(performance, function(index, data) {
18931 totalTime += data['Execution Time'];
18932 });
18933 title += ' ' + totalTime + 'ms';
18934 if(moduleSelector) {
18935 title += ' \'' + moduleSelector + '\'';
18936 }
18937 if($allModules.length > 1) {
18938 title += ' ' + '(' + $allModules.length + ')';
18939 }
18940 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
18941 console.groupCollapsed(title);
18942 if(console.table) {
18943 console.table(performance);
18944 }
18945 else {
18946 $.each(performance, function(index, data) {
18947 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
18948 });
18949 }
18950 console.groupEnd();
18951 }
18952 performance = [];
18953 }
18954 },
18955 invoke: function(query, passedArguments, context) {
18956 var
18957 object = instance,
18958 maxDepth,
18959 found,
18960 response
18961 ;
18962 passedArguments = passedArguments || queryArguments;
18963 context = element || context;
18964 if(typeof query == 'string' && object !== undefined) {
18965 query = query.split(/[\. ]/);
18966 maxDepth = query.length - 1;
18967 $.each(query, function(depth, value) {
18968 var camelCaseValue = (depth != maxDepth)
18969 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
18970 : query
18971 ;
18972 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
18973 object = object[camelCaseValue];
18974 }
18975 else if( object[camelCaseValue] !== undefined ) {
18976 found = object[camelCaseValue];
18977 return false;
18978 }
18979 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
18980 object = object[value];
18981 }
18982 else if( object[value] !== undefined ) {
18983 found = object[value];
18984 return false;
18985 }
18986 else {
18987 return false;
18988 }
18989 });
18990 }
18991 if ( $.isFunction( found ) ) {
18992 response = found.apply(context, passedArguments);
18993 }
18994 else if(found !== undefined) {
18995 response = found;
18996 }
18997 if(Array.isArray(returnedValue)) {
18998 returnedValue.push(response);
18999 }
19000 else if(returnedValue !== undefined) {
19001 returnedValue = [returnedValue, response];
19002 }
19003 else if(response !== undefined) {
19004 returnedValue = response;
19005 }
19006 return found;
19007 }
19008 };
19009
19010 if(methodInvoked) {
19011 if(instance === undefined) {
19012 module.initialize();
19013 }
19014 var $inputs = $module.find('input');
19015 if( $inputs.length > 0) {
19016 $inputs.blur();
19017 setTimeout(function(){
19018 module.invoke(query);
19019 }, 150);
19020 } else {
19021 module.invoke(query);
19022 }
19023 }
19024 else {
19025 if(instance !== undefined) {
19026 instance.invoke('destroy');
19027 }
19028 module.initialize();
19029 }
19030 })
19031 ;
19032
19033 return (returnedValue !== undefined)
19034 ? returnedValue
19035 : this
19036 ;
19037};
19038
19039$.fn.shape.settings = {
19040
19041 // module info
19042 name : 'Shape',
19043
19044 // hide all debug content
19045 silent : false,
19046
19047 // debug content outputted to console
19048 debug : false,
19049
19050 // verbose debug output
19051 verbose : false,
19052
19053 // fudge factor in pixels when swapping from 2d to 3d (can be useful to correct rounding errors)
19054 jitter : 0,
19055
19056 // performance data output
19057 performance: true,
19058
19059 // event namespace
19060 namespace : 'shape',
19061
19062 // width during animation, can be set to 'auto', initial', 'next' or pixel amount
19063 width: 'initial',
19064
19065 // height during animation, can be set to 'auto', 'initial', 'next' or pixel amount
19066 height: 'initial',
19067
19068 // callback occurs on side change
19069 beforeChange : function() {},
19070 onChange : function() {},
19071
19072 // allow animation to same side
19073 allowRepeats: false,
19074
19075 // animation duration
19076 duration : false,
19077
19078 // possible errors
19079 error: {
19080 side : 'You tried to switch to a side that does not exist.',
19081 method : 'The method you called is not defined'
19082 },
19083
19084 // classnames used
19085 className : {
19086 animating : 'animating',
19087 hidden : 'hidden',
19088 loading : 'loading',
19089 active : 'active'
19090 },
19091
19092 // selectors used
19093 selector : {
19094 sides : '.sides',
19095 side : '.side'
19096 }
19097
19098};
19099
19100
19101})( jQuery, window, document );
19102
19103/*!
19104 * # Semantic UI 2.7.2 - Sidebar
19105 * http://github.com/semantic-org/semantic-ui/
19106 *
19107 *
19108 * Released under the MIT license
19109 * http://opensource.org/licenses/MIT
19110 *
19111 */
19112
19113;(function ($, window, document, undefined) {
19114
19115'use strict';
19116
19117$.isFunction = $.isFunction || function(obj) {
19118 return typeof obj === "function" && typeof obj.nodeType !== "number";
19119};
19120
19121window = (typeof window != 'undefined' && window.Math == Math)
19122 ? window
19123 : (typeof self != 'undefined' && self.Math == Math)
19124 ? self
19125 : Function('return this')()
19126;
19127
19128$.fn.sidebar = function(parameters) {
19129 var
19130 $allModules = $(this),
19131 $window = $(window),
19132 $document = $(document),
19133 $html = $('html'),
19134 $head = $('head'),
19135
19136 moduleSelector = $allModules.selector || '',
19137
19138 time = new Date().getTime(),
19139 performance = [],
19140
19141 query = arguments[0],
19142 methodInvoked = (typeof query == 'string'),
19143 queryArguments = [].slice.call(arguments, 1),
19144
19145 requestAnimationFrame = window.requestAnimationFrame
19146 || window.mozRequestAnimationFrame
19147 || window.webkitRequestAnimationFrame
19148 || window.msRequestAnimationFrame
19149 || function(callback) { setTimeout(callback, 0); },
19150
19151 returnedValue
19152 ;
19153
19154 $allModules
19155 .each(function() {
19156 var
19157 settings = ( $.isPlainObject(parameters) )
19158 ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
19159 : $.extend({}, $.fn.sidebar.settings),
19160
19161 selector = settings.selector,
19162 className = settings.className,
19163 namespace = settings.namespace,
19164 regExp = settings.regExp,
19165 error = settings.error,
19166
19167 eventNamespace = '.' + namespace,
19168 moduleNamespace = 'module-' + namespace,
19169
19170 $module = $(this),
19171 $context = $(settings.context),
19172
19173 $sidebars = $module.children(selector.sidebar),
19174 $fixed = $context.children(selector.fixed),
19175 $pusher = $context.children(selector.pusher),
19176 $style,
19177
19178 element = this,
19179 instance = $module.data(moduleNamespace),
19180
19181 elementNamespace,
19182 id,
19183 currentScroll,
19184 transitionEvent,
19185
19186 module
19187 ;
19188
19189 module = {
19190
19191 initialize: function() {
19192 module.debug('Initializing sidebar', parameters);
19193
19194 module.create.id();
19195
19196 transitionEvent = module.get.transitionEvent();
19197
19198 // avoids locking rendering if initialized in onReady
19199 if(settings.delaySetup) {
19200 requestAnimationFrame(module.setup.layout);
19201 }
19202 else {
19203 module.setup.layout();
19204 }
19205
19206 requestAnimationFrame(function() {
19207 module.setup.cache();
19208 });
19209
19210 module.instantiate();
19211 },
19212
19213 instantiate: function() {
19214 module.verbose('Storing instance of module', module);
19215 instance = module;
19216 $module
19217 .data(moduleNamespace, module)
19218 ;
19219 },
19220
19221 create: {
19222 id: function() {
19223 id = (Math.random().toString(16) + '000000000').substr(2,8);
19224 elementNamespace = '.' + id;
19225 module.verbose('Creating unique id for element', id);
19226 }
19227 },
19228
19229 destroy: function() {
19230 module.verbose('Destroying previous module for', $module);
19231 $module
19232 .off(eventNamespace)
19233 .removeData(moduleNamespace)
19234 ;
19235 if(module.is.ios()) {
19236 module.remove.ios();
19237 }
19238 // bound by uuid
19239 $context.off(elementNamespace);
19240 $window.off(elementNamespace);
19241 $document.off(elementNamespace);
19242 },
19243
19244 event: {
19245 clickaway: function(event) {
19246 if(settings.closable){
19247 var
19248 clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
19249 clickedContext = ($context.is(event.target))
19250 ;
19251 if(clickedInPusher) {
19252 module.verbose('User clicked on dimmed page');
19253 module.hide();
19254 }
19255 if(clickedContext) {
19256 module.verbose('User clicked on dimmable context (scaled out page)');
19257 module.hide();
19258 }
19259 }
19260 },
19261 touch: function(event) {
19262 //event.stopPropagation();
19263 },
19264 containScroll: function(event) {
19265 if(element.scrollTop <= 0) {
19266 element.scrollTop = 1;
19267 }
19268 if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
19269 element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
19270 }
19271 },
19272 scroll: function(event) {
19273 if( $(event.target).closest(selector.sidebar).length === 0 ) {
19274 event.preventDefault();
19275 }
19276 }
19277 },
19278
19279 bind: {
19280 clickaway: function() {
19281 module.verbose('Adding clickaway events to context', $context);
19282 $context
19283 .on('click' + elementNamespace, module.event.clickaway)
19284 .on('touchend' + elementNamespace, module.event.clickaway)
19285 ;
19286 },
19287 scrollLock: function() {
19288 if(settings.scrollLock) {
19289 module.debug('Disabling page scroll');
19290 $window
19291 .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
19292 ;
19293 }
19294 module.verbose('Adding events to contain sidebar scroll');
19295 $document
19296 .on('touchmove' + elementNamespace, module.event.touch)
19297 ;
19298 $module
19299 .on('scroll' + eventNamespace, module.event.containScroll)
19300 ;
19301 }
19302 },
19303 unbind: {
19304 clickaway: function() {
19305 module.verbose('Removing clickaway events from context', $context);
19306 $context.off(elementNamespace);
19307 },
19308 scrollLock: function() {
19309 module.verbose('Removing scroll lock from page');
19310 $document.off(elementNamespace);
19311 $window.off(elementNamespace);
19312 $module.off('scroll' + eventNamespace);
19313 }
19314 },
19315
19316 add: {
19317 inlineCSS: function() {
19318 var
19319 width = module.cache.width || $module.outerWidth(),
19320 height = module.cache.height || $module.outerHeight(),
19321 isRTL = module.is.rtl(),
19322 direction = module.get.direction(),
19323 distance = {
19324 left : width,
19325 right : -width,
19326 top : height,
19327 bottom : -height
19328 },
19329 style
19330 ;
19331
19332 if(isRTL){
19333 module.verbose('RTL detected, flipping widths');
19334 distance.left = -width;
19335 distance.right = width;
19336 }
19337
19338 style = '<style>';
19339
19340 if(direction === 'left' || direction === 'right') {
19341 module.debug('Adding CSS rules for animation distance', width);
19342 style += ''
19343 + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
19344 + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
19345 + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
19346 + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
19347 + ' }'
19348 ;
19349 }
19350 else if(direction === 'top' || direction == 'bottom') {
19351 style += ''
19352 + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
19353 + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
19354 + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
19355 + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
19356 + ' }'
19357 ;
19358 }
19359
19360 /* IE is only browser not to create context with transforms */
19361 /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
19362 if( module.is.ie() ) {
19363 if(direction === 'left' || direction === 'right') {
19364 module.debug('Adding CSS rules for animation distance', width);
19365 style += ''
19366 + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
19367 + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
19368 + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
19369 + ' }'
19370 ;
19371 }
19372 else if(direction === 'top' || direction == 'bottom') {
19373 style += ''
19374 + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
19375 + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
19376 + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
19377 + ' }'
19378 ;
19379 }
19380 /* opposite sides visible forces content overlay */
19381 style += ''
19382 + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
19383 + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
19384 + ' -webkit-transform: translate3d(0, 0, 0);'
19385 + ' transform: translate3d(0, 0, 0);'
19386 + ' }'
19387 ;
19388 }
19389 style += '</style>';
19390 $style = $(style)
19391 .appendTo($head)
19392 ;
19393 module.debug('Adding sizing css to head', $style);
19394 }
19395 },
19396
19397 refresh: function() {
19398 module.verbose('Refreshing selector cache');
19399 $context = $(settings.context);
19400 $sidebars = $context.children(selector.sidebar);
19401 $pusher = $context.children(selector.pusher);
19402 $fixed = $context.children(selector.fixed);
19403 module.clear.cache();
19404 },
19405
19406 refreshSidebars: function() {
19407 module.verbose('Refreshing other sidebars');
19408 $sidebars = $context.children(selector.sidebar);
19409 },
19410
19411 repaint: function() {
19412 module.verbose('Forcing repaint event');
19413 element.style.display = 'none';
19414 var ignored = element.offsetHeight;
19415 element.scrollTop = element.scrollTop;
19416 element.style.display = '';
19417 },
19418
19419 setup: {
19420 cache: function() {
19421 module.cache = {
19422 width : $module.outerWidth(),
19423 height : $module.outerHeight(),
19424 rtl : ($module.css('direction') == 'rtl')
19425 };
19426 },
19427 layout: function() {
19428 if( $context.children(selector.pusher).length === 0 ) {
19429 module.debug('Adding wrapper element for sidebar');
19430 module.error(error.pusher);
19431 $pusher = $('<div class="pusher" />');
19432 $context
19433 .children()
19434 .not(selector.omitted)
19435 .not($sidebars)
19436 .wrapAll($pusher)
19437 ;
19438 module.refresh();
19439 }
19440 if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
19441 module.debug('Moved sidebar to correct parent element');
19442 module.error(error.movedSidebar, element);
19443 $module.detach().prependTo($context);
19444 module.refresh();
19445 }
19446 module.clear.cache();
19447 module.set.pushable();
19448 module.set.direction();
19449 }
19450 },
19451
19452 attachEvents: function(selector, event) {
19453 var
19454 $toggle = $(selector)
19455 ;
19456 event = $.isFunction(module[event])
19457 ? module[event]
19458 : module.toggle
19459 ;
19460 if($toggle.length > 0) {
19461 module.debug('Attaching sidebar events to element', selector, event);
19462 $toggle
19463 .on('click' + eventNamespace, event)
19464 ;
19465 }
19466 else {
19467 module.error(error.notFound, selector);
19468 }
19469 },
19470
19471 show: function(callback) {
19472 callback = $.isFunction(callback)
19473 ? callback
19474 : function(){}
19475 ;
19476 if(module.is.hidden()) {
19477 module.refreshSidebars();
19478 if(settings.overlay) {
19479 module.error(error.overlay);
19480 settings.transition = 'overlay';
19481 }
19482 module.refresh();
19483 if(module.othersActive()) {
19484 module.debug('Other sidebars currently visible');
19485 if(settings.exclusive) {
19486 // if not overlay queue animation after hide
19487 if(settings.transition != 'overlay') {
19488 module.hideOthers(module.show);
19489 return;
19490 }
19491 else {
19492 module.hideOthers();
19493 }
19494 }
19495 else {
19496 settings.transition = 'overlay';
19497 }
19498 }
19499 module.pushPage(function() {
19500 callback.call(element);
19501 settings.onShow.call(element);
19502 });
19503 settings.onChange.call(element);
19504 settings.onVisible.call(element);
19505 }
19506 else {
19507 module.debug('Sidebar is already visible');
19508 }
19509 },
19510
19511 hide: function(callback) {
19512 callback = $.isFunction(callback)
19513 ? callback
19514 : function(){}
19515 ;
19516 if(module.is.visible() || module.is.animating()) {
19517 module.debug('Hiding sidebar', callback);
19518 module.refreshSidebars();
19519 module.pullPage(function() {
19520 callback.call(element);
19521 settings.onHidden.call(element);
19522 });
19523 settings.onChange.call(element);
19524 settings.onHide.call(element);
19525 }
19526 },
19527
19528 othersAnimating: function() {
19529 return ($sidebars.not($module).filter('.' + className.animating).length > 0);
19530 },
19531 othersVisible: function() {
19532 return ($sidebars.not($module).filter('.' + className.visible).length > 0);
19533 },
19534 othersActive: function() {
19535 return(module.othersVisible() || module.othersAnimating());
19536 },
19537
19538 hideOthers: function(callback) {
19539 var
19540 $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
19541 sidebarCount = $otherSidebars.length,
19542 callbackCount = 0
19543 ;
19544 callback = callback || function(){};
19545 $otherSidebars
19546 .sidebar('hide', function() {
19547 callbackCount++;
19548 if(callbackCount == sidebarCount) {
19549 callback();
19550 }
19551 })
19552 ;
19553 },
19554
19555 toggle: function() {
19556 module.verbose('Determining toggled direction');
19557 if(module.is.hidden()) {
19558 module.show();
19559 }
19560 else {
19561 module.hide();
19562 }
19563 },
19564
19565 pushPage: function(callback) {
19566 var
19567 transition = module.get.transition(),
19568 $transition = (transition === 'overlay' || module.othersActive())
19569 ? $module
19570 : $pusher,
19571 animate,
19572 dim,
19573 transitionEnd
19574 ;
19575 callback = $.isFunction(callback)
19576 ? callback
19577 : function(){}
19578 ;
19579 if(settings.transition == 'scale down') {
19580 module.scrollToTop();
19581 }
19582 module.set.transition(transition);
19583 module.repaint();
19584 animate = function() {
19585 module.bind.clickaway();
19586 module.add.inlineCSS();
19587 module.set.animating();
19588 module.set.visible();
19589 };
19590 dim = function() {
19591 module.set.dimmed();
19592 };
19593 transitionEnd = function(event) {
19594 if( event.target == $transition[0] ) {
19595 $transition.off(transitionEvent + elementNamespace, transitionEnd);
19596 module.remove.animating();
19597 module.bind.scrollLock();
19598 callback.call(element);
19599 }
19600 };
19601 $transition.off(transitionEvent + elementNamespace);
19602 $transition.on(transitionEvent + elementNamespace, transitionEnd);
19603 requestAnimationFrame(animate);
19604 if(settings.dimPage && !module.othersVisible()) {
19605 requestAnimationFrame(dim);
19606 }
19607 },
19608
19609 pullPage: function(callback) {
19610 var
19611 transition = module.get.transition(),
19612 $transition = (transition == 'overlay' || module.othersActive())
19613 ? $module
19614 : $pusher,
19615 animate,
19616 transitionEnd
19617 ;
19618 callback = $.isFunction(callback)
19619 ? callback
19620 : function(){}
19621 ;
19622 module.verbose('Removing context push state', module.get.direction());
19623
19624 module.unbind.clickaway();
19625 module.unbind.scrollLock();
19626
19627 animate = function() {
19628 module.set.transition(transition);
19629 module.set.animating();
19630 module.remove.visible();
19631 if(settings.dimPage && !module.othersVisible()) {
19632 $pusher.removeClass(className.dimmed);
19633 }
19634 };
19635 transitionEnd = function(event) {
19636 if( event.target == $transition[0] ) {
19637 $transition.off(transitionEvent + elementNamespace, transitionEnd);
19638 module.remove.animating();
19639 module.remove.transition();
19640 module.remove.inlineCSS();
19641 if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
19642 module.scrollBack();
19643 }
19644 callback.call(element);
19645 }
19646 };
19647 $transition.off(transitionEvent + elementNamespace);
19648 $transition.on(transitionEvent + elementNamespace, transitionEnd);
19649 requestAnimationFrame(animate);
19650 },
19651
19652 scrollToTop: function() {
19653 module.verbose('Scrolling to top of page to avoid animation issues');
19654 currentScroll = $(window).scrollTop();
19655 $module.scrollTop(0);
19656 window.scrollTo(0, 0);
19657 },
19658
19659 scrollBack: function() {
19660 module.verbose('Scrolling back to original page position');
19661 window.scrollTo(0, currentScroll);
19662 },
19663
19664 clear: {
19665 cache: function() {
19666 module.verbose('Clearing cached dimensions');
19667 module.cache = {};
19668 }
19669 },
19670
19671 set: {
19672
19673 // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
19674 // (This is no longer necessary in latest iOS)
19675 ios: function() {
19676 $html.addClass(className.ios);
19677 },
19678
19679 // container
19680 pushed: function() {
19681 $context.addClass(className.pushed);
19682 },
19683 pushable: function() {
19684 $context.addClass(className.pushable);
19685 },
19686
19687 // pusher
19688 dimmed: function() {
19689 $pusher.addClass(className.dimmed);
19690 },
19691
19692 // sidebar
19693 active: function() {
19694 $module.addClass(className.active);
19695 },
19696 animating: function() {
19697 $module.addClass(className.animating);
19698 },
19699 transition: function(transition) {
19700 transition = transition || module.get.transition();
19701 $module.addClass(transition);
19702 },
19703 direction: function(direction) {
19704 direction = direction || module.get.direction();
19705 $module.addClass(className[direction]);
19706 },
19707 visible: function() {
19708 $module.addClass(className.visible);
19709 },
19710 overlay: function() {
19711 $module.addClass(className.overlay);
19712 }
19713 },
19714 remove: {
19715
19716 inlineCSS: function() {
19717 module.debug('Removing inline css styles', $style);
19718 if($style && $style.length > 0) {
19719 $style.remove();
19720 }
19721 },
19722
19723 // ios scroll on html not document
19724 ios: function() {
19725 $html.removeClass(className.ios);
19726 },
19727
19728 // context
19729 pushed: function() {
19730 $context.removeClass(className.pushed);
19731 },
19732 pushable: function() {
19733 $context.removeClass(className.pushable);
19734 },
19735
19736 // sidebar
19737 active: function() {
19738 $module.removeClass(className.active);
19739 },
19740 animating: function() {
19741 $module.removeClass(className.animating);
19742 },
19743 transition: function(transition) {
19744 transition = transition || module.get.transition();
19745 $module.removeClass(transition);
19746 },
19747 direction: function(direction) {
19748 direction = direction || module.get.direction();
19749 $module.removeClass(className[direction]);
19750 },
19751 visible: function() {
19752 $module.removeClass(className.visible);
19753 },
19754 overlay: function() {
19755 $module.removeClass(className.overlay);
19756 }
19757 },
19758
19759 get: {
19760 direction: function() {
19761 if($module.hasClass(className.top)) {
19762 return className.top;
19763 }
19764 else if($module.hasClass(className.right)) {
19765 return className.right;
19766 }
19767 else if($module.hasClass(className.bottom)) {
19768 return className.bottom;
19769 }
19770 return className.left;
19771 },
19772 transition: function() {
19773 var
19774 direction = module.get.direction(),
19775 transition
19776 ;
19777 transition = ( module.is.mobile() )
19778 ? (settings.mobileTransition == 'auto')
19779 ? settings.defaultTransition.mobile[direction]
19780 : settings.mobileTransition
19781 : (settings.transition == 'auto')
19782 ? settings.defaultTransition.computer[direction]
19783 : settings.transition
19784 ;
19785 module.verbose('Determined transition', transition);
19786 return transition;
19787 },
19788 transitionEvent: function() {
19789 var
19790 element = document.createElement('element'),
19791 transitions = {
19792 'transition' :'transitionend',
19793 'OTransition' :'oTransitionEnd',
19794 'MozTransition' :'transitionend',
19795 'WebkitTransition' :'webkitTransitionEnd'
19796 },
19797 transition
19798 ;
19799 for(transition in transitions){
19800 if( element.style[transition] !== undefined ){
19801 return transitions[transition];
19802 }
19803 }
19804 }
19805 },
19806
19807 is: {
19808
19809 ie: function() {
19810 var
19811 isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
19812 isIE = ('ActiveXObject' in window)
19813 ;
19814 return (isIE11 || isIE);
19815 },
19816
19817 ios: function() {
19818 var
19819 userAgent = navigator.userAgent,
19820 isIOS = userAgent.match(regExp.ios),
19821 isMobileChrome = userAgent.match(regExp.mobileChrome)
19822 ;
19823 if(isIOS && !isMobileChrome) {
19824 module.verbose('Browser was found to be iOS', userAgent);
19825 return true;
19826 }
19827 else {
19828 return false;
19829 }
19830 },
19831 mobile: function() {
19832 var
19833 userAgent = navigator.userAgent,
19834 isMobile = userAgent.match(regExp.mobile)
19835 ;
19836 if(isMobile) {
19837 module.verbose('Browser was found to be mobile', userAgent);
19838 return true;
19839 }
19840 else {
19841 module.verbose('Browser is not mobile, using regular transition', userAgent);
19842 return false;
19843 }
19844 },
19845 hidden: function() {
19846 return !module.is.visible();
19847 },
19848 visible: function() {
19849 return $module.hasClass(className.visible);
19850 },
19851 // alias
19852 open: function() {
19853 return module.is.visible();
19854 },
19855 closed: function() {
19856 return module.is.hidden();
19857 },
19858 vertical: function() {
19859 return $module.hasClass(className.top);
19860 },
19861 animating: function() {
19862 return $context.hasClass(className.animating);
19863 },
19864 rtl: function () {
19865 if(module.cache.rtl === undefined) {
19866 module.cache.rtl = ($module.css('direction') == 'rtl');
19867 }
19868 return module.cache.rtl;
19869 }
19870 },
19871
19872 setting: function(name, value) {
19873 module.debug('Changing setting', name, value);
19874 if( $.isPlainObject(name) ) {
19875 $.extend(true, settings, name);
19876 }
19877 else if(value !== undefined) {
19878 if($.isPlainObject(settings[name])) {
19879 $.extend(true, settings[name], value);
19880 }
19881 else {
19882 settings[name] = value;
19883 }
19884 }
19885 else {
19886 return settings[name];
19887 }
19888 },
19889 internal: function(name, value) {
19890 if( $.isPlainObject(name) ) {
19891 $.extend(true, module, name);
19892 }
19893 else if(value !== undefined) {
19894 module[name] = value;
19895 }
19896 else {
19897 return module[name];
19898 }
19899 },
19900 debug: function() {
19901 if(!settings.silent && settings.debug) {
19902 if(settings.performance) {
19903 module.performance.log(arguments);
19904 }
19905 else {
19906 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
19907 module.debug.apply(console, arguments);
19908 }
19909 }
19910 },
19911 verbose: function() {
19912 if(!settings.silent && settings.verbose && settings.debug) {
19913 if(settings.performance) {
19914 module.performance.log(arguments);
19915 }
19916 else {
19917 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
19918 module.verbose.apply(console, arguments);
19919 }
19920 }
19921 },
19922 error: function() {
19923 if(!settings.silent) {
19924 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
19925 module.error.apply(console, arguments);
19926 }
19927 },
19928 performance: {
19929 log: function(message) {
19930 var
19931 currentTime,
19932 executionTime,
19933 previousTime
19934 ;
19935 if(settings.performance) {
19936 currentTime = new Date().getTime();
19937 previousTime = time || currentTime;
19938 executionTime = currentTime - previousTime;
19939 time = currentTime;
19940 performance.push({
19941 'Name' : message[0],
19942 'Arguments' : [].slice.call(message, 1) || '',
19943 'Element' : element,
19944 'Execution Time' : executionTime
19945 });
19946 }
19947 clearTimeout(module.performance.timer);
19948 module.performance.timer = setTimeout(module.performance.display, 500);
19949 },
19950 display: function() {
19951 var
19952 title = settings.name + ':',
19953 totalTime = 0
19954 ;
19955 time = false;
19956 clearTimeout(module.performance.timer);
19957 $.each(performance, function(index, data) {
19958 totalTime += data['Execution Time'];
19959 });
19960 title += ' ' + totalTime + 'ms';
19961 if(moduleSelector) {
19962 title += ' \'' + moduleSelector + '\'';
19963 }
19964 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
19965 console.groupCollapsed(title);
19966 if(console.table) {
19967 console.table(performance);
19968 }
19969 else {
19970 $.each(performance, function(index, data) {
19971 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
19972 });
19973 }
19974 console.groupEnd();
19975 }
19976 performance = [];
19977 }
19978 },
19979 invoke: function(query, passedArguments, context) {
19980 var
19981 object = instance,
19982 maxDepth,
19983 found,
19984 response
19985 ;
19986 passedArguments = passedArguments || queryArguments;
19987 context = element || context;
19988 if(typeof query == 'string' && object !== undefined) {
19989 query = query.split(/[\. ]/);
19990 maxDepth = query.length - 1;
19991 $.each(query, function(depth, value) {
19992 var camelCaseValue = (depth != maxDepth)
19993 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
19994 : query
19995 ;
19996 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
19997 object = object[camelCaseValue];
19998 }
19999 else if( object[camelCaseValue] !== undefined ) {
20000 found = object[camelCaseValue];
20001 return false;
20002 }
20003 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
20004 object = object[value];
20005 }
20006 else if( object[value] !== undefined ) {
20007 found = object[value];
20008 return false;
20009 }
20010 else {
20011 module.error(error.method, query);
20012 return false;
20013 }
20014 });
20015 }
20016 if ( $.isFunction( found ) ) {
20017 response = found.apply(context, passedArguments);
20018 }
20019 else if(found !== undefined) {
20020 response = found;
20021 }
20022 if(Array.isArray(returnedValue)) {
20023 returnedValue.push(response);
20024 }
20025 else if(returnedValue !== undefined) {
20026 returnedValue = [returnedValue, response];
20027 }
20028 else if(response !== undefined) {
20029 returnedValue = response;
20030 }
20031 return found;
20032 }
20033 }
20034 ;
20035
20036 if(methodInvoked) {
20037 if(instance === undefined) {
20038 module.initialize();
20039 }
20040 module.invoke(query);
20041 }
20042 else {
20043 if(instance !== undefined) {
20044 module.invoke('destroy');
20045 }
20046 module.initialize();
20047 }
20048 });
20049
20050 return (returnedValue !== undefined)
20051 ? returnedValue
20052 : this
20053 ;
20054};
20055
20056$.fn.sidebar.settings = {
20057
20058 name : 'Sidebar',
20059 namespace : 'sidebar',
20060
20061 silent : false,
20062 debug : false,
20063 verbose : false,
20064 performance : true,
20065
20066 transition : 'auto',
20067 mobileTransition : 'auto',
20068
20069 defaultTransition : {
20070 computer: {
20071 left : 'uncover',
20072 right : 'uncover',
20073 top : 'overlay',
20074 bottom : 'overlay'
20075 },
20076 mobile: {
20077 left : 'uncover',
20078 right : 'uncover',
20079 top : 'overlay',
20080 bottom : 'overlay'
20081 }
20082 },
20083
20084 context : 'body',
20085 exclusive : false,
20086 closable : true,
20087 dimPage : true,
20088 scrollLock : false,
20089 returnScroll : false,
20090 delaySetup : false,
20091
20092 duration : 500,
20093
20094 onChange : function(){},
20095 onShow : function(){},
20096 onHide : function(){},
20097
20098 onHidden : function(){},
20099 onVisible : function(){},
20100
20101 className : {
20102 active : 'active',
20103 animating : 'animating',
20104 dimmed : 'dimmed',
20105 ios : 'ios',
20106 pushable : 'pushable',
20107 pushed : 'pushed',
20108 right : 'right',
20109 top : 'top',
20110 left : 'left',
20111 bottom : 'bottom',
20112 visible : 'visible'
20113 },
20114
20115 selector: {
20116 fixed : '.fixed',
20117 omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
20118 pusher : '.pusher',
20119 sidebar : '.ui.sidebar'
20120 },
20121
20122 regExp: {
20123 ios : /(iPad|iPhone|iPod)/g,
20124 mobileChrome : /(CriOS)/g,
20125 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
20126 },
20127
20128 error : {
20129 method : 'The method you called is not defined.',
20130 pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
20131 movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
20132 overlay : 'The overlay setting is no longer supported, use animation: overlay',
20133 notFound : 'There were no elements that matched the specified selector'
20134 }
20135
20136};
20137
20138
20139})( jQuery, window, document );
20140
20141/*!
20142 * # Semantic UI 2.7.2 - Sticky
20143 * http://github.com/semantic-org/semantic-ui/
20144 *
20145 *
20146 * Released under the MIT license
20147 * http://opensource.org/licenses/MIT
20148 *
20149 */
20150
20151;(function ($, window, document, undefined) {
20152
20153'use strict';
20154
20155$.isFunction = $.isFunction || function(obj) {
20156 return typeof obj === "function" && typeof obj.nodeType !== "number";
20157};
20158
20159window = (typeof window != 'undefined' && window.Math == Math)
20160 ? window
20161 : (typeof self != 'undefined' && self.Math == Math)
20162 ? self
20163 : Function('return this')()
20164;
20165
20166$.fn.sticky = function(parameters) {
20167 var
20168 $allModules = $(this),
20169 moduleSelector = $allModules.selector || '',
20170
20171 time = new Date().getTime(),
20172 performance = [],
20173
20174 query = arguments[0],
20175 methodInvoked = (typeof query == 'string'),
20176 queryArguments = [].slice.call(arguments, 1),
20177 returnedValue
20178 ;
20179
20180 $allModules
20181 .each(function() {
20182 var
20183 settings = ( $.isPlainObject(parameters) )
20184 ? $.extend(true, {}, $.fn.sticky.settings, parameters)
20185 : $.extend({}, $.fn.sticky.settings),
20186
20187 className = settings.className,
20188 namespace = settings.namespace,
20189 error = settings.error,
20190
20191 eventNamespace = '.' + namespace,
20192 moduleNamespace = 'module-' + namespace,
20193
20194 $module = $(this),
20195 $window = $(window),
20196 $scroll = $(settings.scrollContext),
20197 $container,
20198 $context,
20199
20200 instance = $module.data(moduleNamespace),
20201
20202 requestAnimationFrame = window.requestAnimationFrame
20203 || window.mozRequestAnimationFrame
20204 || window.webkitRequestAnimationFrame
20205 || window.msRequestAnimationFrame
20206 || function(callback) { setTimeout(callback, 0); },
20207
20208 element = this,
20209
20210 documentObserver,
20211 observer,
20212 module
20213 ;
20214
20215 module = {
20216
20217 initialize: function() {
20218
20219 module.determineContainer();
20220 module.determineContext();
20221 module.verbose('Initializing sticky', settings, $container);
20222
20223 module.save.positions();
20224 module.checkErrors();
20225 module.bind.events();
20226
20227 if(settings.observeChanges) {
20228 module.observeChanges();
20229 }
20230 module.instantiate();
20231 },
20232
20233 instantiate: function() {
20234 module.verbose('Storing instance of module', module);
20235 instance = module;
20236 $module
20237 .data(moduleNamespace, module)
20238 ;
20239 },
20240
20241 destroy: function() {
20242 module.verbose('Destroying previous instance');
20243 module.reset();
20244 if(documentObserver) {
20245 documentObserver.disconnect();
20246 }
20247 if(observer) {
20248 observer.disconnect();
20249 }
20250 $window
20251 .off('load' + eventNamespace, module.event.load)
20252 .off('resize' + eventNamespace, module.event.resize)
20253 ;
20254 $scroll
20255 .off('scrollchange' + eventNamespace, module.event.scrollchange)
20256 ;
20257 $module.removeData(moduleNamespace);
20258 },
20259
20260 observeChanges: function() {
20261 if('MutationObserver' in window) {
20262 documentObserver = new MutationObserver(module.event.documentChanged);
20263 observer = new MutationObserver(module.event.changed);
20264 documentObserver.observe(document, {
20265 childList : true,
20266 subtree : true
20267 });
20268 observer.observe(element, {
20269 childList : true,
20270 subtree : true
20271 });
20272 observer.observe($context[0], {
20273 childList : true,
20274 subtree : true
20275 });
20276 module.debug('Setting up mutation observer', observer);
20277 }
20278 },
20279
20280 determineContainer: function() {
20281 if(settings.container) {
20282 $container = $(settings.container);
20283 }
20284 else {
20285 $container = $module.offsetParent();
20286 }
20287 },
20288
20289 determineContext: function() {
20290 if(settings.context) {
20291 $context = $(settings.context);
20292 }
20293 else {
20294 $context = $container;
20295 }
20296 if($context.length === 0) {
20297 module.error(error.invalidContext, settings.context, $module);
20298 return;
20299 }
20300 },
20301
20302 checkErrors: function() {
20303 if( module.is.hidden() ) {
20304 module.error(error.visible, $module);
20305 }
20306 if(module.cache.element.height > module.cache.context.height) {
20307 module.reset();
20308 module.error(error.elementSize, $module);
20309 return;
20310 }
20311 },
20312
20313 bind: {
20314 events: function() {
20315 $window
20316 .on('load' + eventNamespace, module.event.load)
20317 .on('resize' + eventNamespace, module.event.resize)
20318 ;
20319 // pub/sub pattern
20320 $scroll
20321 .off('scroll' + eventNamespace)
20322 .on('scroll' + eventNamespace, module.event.scroll)
20323 .on('scrollchange' + eventNamespace, module.event.scrollchange)
20324 ;
20325 }
20326 },
20327
20328 event: {
20329 changed: function(mutations) {
20330 clearTimeout(module.timer);
20331 module.timer = setTimeout(function() {
20332 module.verbose('DOM tree modified, updating sticky menu', mutations);
20333 module.refresh();
20334 }, 100);
20335 },
20336 documentChanged: function(mutations) {
20337 [].forEach.call(mutations, function(mutation) {
20338 if(mutation.removedNodes) {
20339 [].forEach.call(mutation.removedNodes, function(node) {
20340 if(node == element || $(node).find(element).length > 0) {
20341 module.debug('Element removed from DOM, tearing down events');
20342 module.destroy();
20343 }
20344 });
20345 }
20346 });
20347 },
20348 load: function() {
20349 module.verbose('Page contents finished loading');
20350 requestAnimationFrame(module.refresh);
20351 },
20352 resize: function() {
20353 module.verbose('Window resized');
20354 requestAnimationFrame(module.refresh);
20355 },
20356 scroll: function() {
20357 requestAnimationFrame(function() {
20358 $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
20359 });
20360 },
20361 scrollchange: function(event, scrollPosition) {
20362 module.stick(scrollPosition);
20363 settings.onScroll.call(element);
20364 }
20365 },
20366
20367 refresh: function(hardRefresh) {
20368 module.reset();
20369 if(!settings.context) {
20370 module.determineContext();
20371 }
20372 if(hardRefresh) {
20373 module.determineContainer();
20374 }
20375 module.save.positions();
20376 module.stick();
20377 settings.onReposition.call(element);
20378 },
20379
20380 supports: {
20381 sticky: function() {
20382 var
20383 $element = $('<div/>')
20384 ;
20385 $element.addClass(className.supported);
20386 return($element.css('position').match('sticky'));
20387 }
20388 },
20389
20390 save: {
20391 lastScroll: function(scroll) {
20392 module.lastScroll = scroll;
20393 },
20394 elementScroll: function(scroll) {
20395 module.elementScroll = scroll;
20396 },
20397 positions: function() {
20398 var
20399 scrollContext = {
20400 height : $scroll.height()
20401 },
20402 element = {
20403 margin: {
20404 top : parseInt($module.css('margin-top'), 10),
20405 bottom : parseInt($module.css('margin-bottom'), 10),
20406 },
20407 offset : $module.offset(),
20408 width : $module.outerWidth(),
20409 height : $module.outerHeight()
20410 },
20411 context = {
20412 offset : $context.offset(),
20413 height : $context.outerHeight()
20414 }
20415 ;
20416 if( !module.is.standardScroll() ) {
20417 module.debug('Non-standard scroll. Removing scroll offset from element offset');
20418
20419 scrollContext.top = $scroll.scrollTop();
20420 scrollContext.left = $scroll.scrollLeft();
20421
20422 element.offset.top += scrollContext.top;
20423 context.offset.top += scrollContext.top;
20424 element.offset.left += scrollContext.left;
20425 context.offset.left += scrollContext.left;
20426 }
20427 module.cache = {
20428 fits : ( (element.height + settings.offset) <= scrollContext.height),
20429 sameHeight : (element.height == context.height),
20430 scrollContext : {
20431 height : scrollContext.height
20432 },
20433 element: {
20434 margin : element.margin,
20435 top : element.offset.top - element.margin.top,
20436 left : element.offset.left,
20437 width : element.width,
20438 height : element.height,
20439 bottom : element.offset.top + element.height
20440 },
20441 context: {
20442 top : context.offset.top,
20443 height : context.height,
20444 bottom : context.offset.top + context.height
20445 }
20446 };
20447 module.set.containerSize();
20448
20449 module.stick();
20450 module.debug('Caching element positions', module.cache);
20451 }
20452 },
20453
20454 get: {
20455 direction: function(scroll) {
20456 var
20457 direction = 'down'
20458 ;
20459 scroll = scroll || $scroll.scrollTop();
20460 if(module.lastScroll !== undefined) {
20461 if(module.lastScroll < scroll) {
20462 direction = 'down';
20463 }
20464 else if(module.lastScroll > scroll) {
20465 direction = 'up';
20466 }
20467 }
20468 return direction;
20469 },
20470 scrollChange: function(scroll) {
20471 scroll = scroll || $scroll.scrollTop();
20472 return (module.lastScroll)
20473 ? (scroll - module.lastScroll)
20474 : 0
20475 ;
20476 },
20477 currentElementScroll: function() {
20478 if(module.elementScroll) {
20479 return module.elementScroll;
20480 }
20481 return ( module.is.top() )
20482 ? Math.abs(parseInt($module.css('top'), 10)) || 0
20483 : Math.abs(parseInt($module.css('bottom'), 10)) || 0
20484 ;
20485 },
20486
20487 elementScroll: function(scroll) {
20488 scroll = scroll || $scroll.scrollTop();
20489 var
20490 element = module.cache.element,
20491 scrollContext = module.cache.scrollContext,
20492 delta = module.get.scrollChange(scroll),
20493 maxScroll = (element.height - scrollContext.height + settings.offset),
20494 elementScroll = module.get.currentElementScroll(),
20495 possibleScroll = (elementScroll + delta)
20496 ;
20497 if(module.cache.fits || possibleScroll < 0) {
20498 elementScroll = 0;
20499 }
20500 else if(possibleScroll > maxScroll ) {
20501 elementScroll = maxScroll;
20502 }
20503 else {
20504 elementScroll = possibleScroll;
20505 }
20506 return elementScroll;
20507 }
20508 },
20509
20510 remove: {
20511 lastScroll: function() {
20512 delete module.lastScroll;
20513 },
20514 elementScroll: function(scroll) {
20515 delete module.elementScroll;
20516 },
20517 minimumSize: function() {
20518 $container
20519 .css('min-height', '')
20520 ;
20521 },
20522 offset: function() {
20523 $module.css('margin-top', '');
20524 }
20525 },
20526
20527 set: {
20528 offset: function() {
20529 module.verbose('Setting offset on element', settings.offset);
20530 $module
20531 .css('margin-top', settings.offset)
20532 ;
20533 },
20534 containerSize: function() {
20535 var
20536 tagName = $container.get(0).tagName
20537 ;
20538 if(tagName === 'HTML' || tagName == 'body') {
20539 // this can trigger for too many reasons
20540 //module.error(error.container, tagName, $module);
20541 module.determineContainer();
20542 }
20543 else {
20544 if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
20545 module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
20546 $container.css({
20547 height: module.cache.context.height
20548 });
20549 }
20550 }
20551 },
20552 minimumSize: function() {
20553 var
20554 element = module.cache.element
20555 ;
20556 $container
20557 .css('min-height', element.height)
20558 ;
20559 },
20560 scroll: function(scroll) {
20561 module.debug('Setting scroll on element', scroll);
20562 if(module.elementScroll == scroll) {
20563 return;
20564 }
20565 if( module.is.top() ) {
20566 $module
20567 .css('bottom', '')
20568 .css('top', -scroll)
20569 ;
20570 }
20571 if( module.is.bottom() ) {
20572 $module
20573 .css('top', '')
20574 .css('bottom', scroll)
20575 ;
20576 }
20577 },
20578 size: function() {
20579 if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
20580 element.style.setProperty('width', module.cache.element.width + 'px', 'important');
20581 element.style.setProperty('height', module.cache.element.height + 'px', 'important');
20582 }
20583 }
20584 },
20585
20586 is: {
20587 standardScroll: function() {
20588 return ($scroll[0] == window);
20589 },
20590 top: function() {
20591 return $module.hasClass(className.top);
20592 },
20593 bottom: function() {
20594 return $module.hasClass(className.bottom);
20595 },
20596 initialPosition: function() {
20597 return (!module.is.fixed() && !module.is.bound());
20598 },
20599 hidden: function() {
20600 return (!$module.is(':visible'));
20601 },
20602 bound: function() {
20603 return $module.hasClass(className.bound);
20604 },
20605 fixed: function() {
20606 return $module.hasClass(className.fixed);
20607 }
20608 },
20609
20610 stick: function(scroll) {
20611 var
20612 cachedPosition = scroll || $scroll.scrollTop(),
20613 cache = module.cache,
20614 fits = cache.fits,
20615 sameHeight = cache.sameHeight,
20616 element = cache.element,
20617 scrollContext = cache.scrollContext,
20618 context = cache.context,
20619 offset = (module.is.bottom() && settings.pushing)
20620 ? settings.bottomOffset
20621 : settings.offset,
20622 scroll = {
20623 top : cachedPosition + offset,
20624 bottom : cachedPosition + offset + scrollContext.height
20625 },
20626 elementScroll = (fits)
20627 ? 0
20628 : module.get.elementScroll(scroll.top),
20629
20630 // shorthand
20631 doesntFit = !fits,
20632 elementVisible = (element.height !== 0)
20633 ;
20634 if(elementVisible && !sameHeight) {
20635
20636 if( module.is.initialPosition() ) {
20637 if(scroll.top >= context.bottom) {
20638 module.debug('Initial element position is bottom of container');
20639 module.bindBottom();
20640 }
20641 else if(scroll.top > element.top) {
20642 if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
20643 module.debug('Initial element position is bottom of container');
20644 module.bindBottom();
20645 }
20646 else {
20647 module.debug('Initial element position is fixed');
20648 module.fixTop();
20649 }
20650 }
20651
20652 }
20653 else if( module.is.fixed() ) {
20654
20655 // currently fixed top
20656 if( module.is.top() ) {
20657 if( scroll.top <= element.top ) {
20658 module.debug('Fixed element reached top of container');
20659 module.setInitialPosition();
20660 }
20661 else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
20662 module.debug('Fixed element reached bottom of container');
20663 module.bindBottom();
20664 }
20665 // scroll element if larger than screen
20666 else if(doesntFit) {
20667 module.set.scroll(elementScroll);
20668 module.save.lastScroll(scroll.top);
20669 module.save.elementScroll(elementScroll);
20670 }
20671 }
20672
20673 // currently fixed bottom
20674 else if(module.is.bottom() ) {
20675
20676 // top edge
20677 if( (scroll.bottom - element.height) <= element.top) {
20678 module.debug('Bottom fixed rail has reached top of container');
20679 module.setInitialPosition();
20680 }
20681 // bottom edge
20682 else if(scroll.bottom >= context.bottom) {
20683 module.debug('Bottom fixed rail has 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 }
20695 else if( module.is.bottom() ) {
20696 if( scroll.top <= element.top ) {
20697 module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
20698 module.setInitialPosition();
20699 }
20700 else {
20701 if(settings.pushing) {
20702 if(module.is.bound() && scroll.bottom <= context.bottom ) {
20703 module.debug('Fixing bottom attached element to bottom of browser.');
20704 module.fixBottom();
20705 }
20706 }
20707 else {
20708 if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
20709 module.debug('Fixing bottom attached element to top of browser.');
20710 module.fixTop();
20711 }
20712 }
20713 }
20714 }
20715 }
20716 },
20717
20718 bindTop: function() {
20719 module.debug('Binding element to top of parent container');
20720 module.remove.offset();
20721 $module
20722 .css({
20723 left : '',
20724 top : '',
20725 marginBottom : ''
20726 })
20727 .removeClass(className.fixed)
20728 .removeClass(className.bottom)
20729 .addClass(className.bound)
20730 .addClass(className.top)
20731 ;
20732 settings.onTop.call(element);
20733 settings.onUnstick.call(element);
20734 },
20735 bindBottom: function() {
20736 module.debug('Binding element to bottom of parent container');
20737 module.remove.offset();
20738 $module
20739 .css({
20740 left : '',
20741 top : ''
20742 })
20743 .removeClass(className.fixed)
20744 .removeClass(className.top)
20745 .addClass(className.bound)
20746 .addClass(className.bottom)
20747 ;
20748 settings.onBottom.call(element);
20749 settings.onUnstick.call(element);
20750 },
20751
20752 setInitialPosition: function() {
20753 module.debug('Returning to initial position');
20754 module.unfix();
20755 module.unbind();
20756 },
20757
20758
20759 fixTop: function() {
20760 module.debug('Fixing element to top of page');
20761 if(settings.setSize) {
20762 module.set.size();
20763 }
20764 module.set.minimumSize();
20765 module.set.offset();
20766 $module
20767 .css({
20768 left : module.cache.element.left,
20769 bottom : '',
20770 marginBottom : ''
20771 })
20772 .removeClass(className.bound)
20773 .removeClass(className.bottom)
20774 .addClass(className.fixed)
20775 .addClass(className.top)
20776 ;
20777 settings.onStick.call(element);
20778 },
20779
20780 fixBottom: function() {
20781 module.debug('Sticking element to bottom 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.top)
20795 .addClass(className.fixed)
20796 .addClass(className.bottom)
20797 ;
20798 settings.onStick.call(element);
20799 },
20800
20801 unbind: function() {
20802 if( module.is.bound() ) {
20803 module.debug('Removing container bound position on element');
20804 module.remove.offset();
20805 $module
20806 .removeClass(className.bound)
20807 .removeClass(className.top)
20808 .removeClass(className.bottom)
20809 ;
20810 }
20811 },
20812
20813 unfix: function() {
20814 if( module.is.fixed() ) {
20815 module.debug('Removing fixed position on element');
20816 module.remove.minimumSize();
20817 module.remove.offset();
20818 $module
20819 .removeClass(className.fixed)
20820 .removeClass(className.top)
20821 .removeClass(className.bottom)
20822 ;
20823 settings.onUnstick.call(element);
20824 }
20825 },
20826
20827 reset: function() {
20828 module.debug('Resetting elements position');
20829 module.unbind();
20830 module.unfix();
20831 module.resetCSS();
20832 module.remove.offset();
20833 module.remove.lastScroll();
20834 },
20835
20836 resetCSS: function() {
20837 $module
20838 .css({
20839 width : '',
20840 height : ''
20841 })
20842 ;
20843 $container
20844 .css({
20845 height: ''
20846 })
20847 ;
20848 },
20849
20850 setting: function(name, value) {
20851 if( $.isPlainObject(name) ) {
20852 $.extend(true, settings, name);
20853 }
20854 else if(value !== undefined) {
20855 settings[name] = value;
20856 }
20857 else {
20858 return settings[name];
20859 }
20860 },
20861 internal: function(name, value) {
20862 if( $.isPlainObject(name) ) {
20863 $.extend(true, module, name);
20864 }
20865 else if(value !== undefined) {
20866 module[name] = value;
20867 }
20868 else {
20869 return module[name];
20870 }
20871 },
20872 debug: function() {
20873 if(!settings.silent && settings.debug) {
20874 if(settings.performance) {
20875 module.performance.log(arguments);
20876 }
20877 else {
20878 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
20879 module.debug.apply(console, arguments);
20880 }
20881 }
20882 },
20883 verbose: function() {
20884 if(!settings.silent && settings.verbose && settings.debug) {
20885 if(settings.performance) {
20886 module.performance.log(arguments);
20887 }
20888 else {
20889 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
20890 module.verbose.apply(console, arguments);
20891 }
20892 }
20893 },
20894 error: function() {
20895 if(!settings.silent) {
20896 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
20897 module.error.apply(console, arguments);
20898 }
20899 },
20900 performance: {
20901 log: function(message) {
20902 var
20903 currentTime,
20904 executionTime,
20905 previousTime
20906 ;
20907 if(settings.performance) {
20908 currentTime = new Date().getTime();
20909 previousTime = time || currentTime;
20910 executionTime = currentTime - previousTime;
20911 time = currentTime;
20912 performance.push({
20913 'Name' : message[0],
20914 'Arguments' : [].slice.call(message, 1) || '',
20915 'Element' : element,
20916 'Execution Time' : executionTime
20917 });
20918 }
20919 clearTimeout(module.performance.timer);
20920 module.performance.timer = setTimeout(module.performance.display, 0);
20921 },
20922 display: function() {
20923 var
20924 title = settings.name + ':',
20925 totalTime = 0
20926 ;
20927 time = false;
20928 clearTimeout(module.performance.timer);
20929 $.each(performance, function(index, data) {
20930 totalTime += data['Execution Time'];
20931 });
20932 title += ' ' + totalTime + 'ms';
20933 if(moduleSelector) {
20934 title += ' \'' + moduleSelector + '\'';
20935 }
20936 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
20937 console.groupCollapsed(title);
20938 if(console.table) {
20939 console.table(performance);
20940 }
20941 else {
20942 $.each(performance, function(index, data) {
20943 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
20944 });
20945 }
20946 console.groupEnd();
20947 }
20948 performance = [];
20949 }
20950 },
20951 invoke: function(query, passedArguments, context) {
20952 var
20953 object = instance,
20954 maxDepth,
20955 found,
20956 response
20957 ;
20958 passedArguments = passedArguments || queryArguments;
20959 context = element || context;
20960 if(typeof query == 'string' && object !== undefined) {
20961 query = query.split(/[\. ]/);
20962 maxDepth = query.length - 1;
20963 $.each(query, function(depth, value) {
20964 var camelCaseValue = (depth != maxDepth)
20965 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
20966 : query
20967 ;
20968 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
20969 object = object[camelCaseValue];
20970 }
20971 else if( object[camelCaseValue] !== undefined ) {
20972 found = object[camelCaseValue];
20973 return false;
20974 }
20975 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
20976 object = object[value];
20977 }
20978 else if( object[value] !== undefined ) {
20979 found = object[value];
20980 return false;
20981 }
20982 else {
20983 return false;
20984 }
20985 });
20986 }
20987 if ( $.isFunction( found ) ) {
20988 response = found.apply(context, passedArguments);
20989 }
20990 else if(found !== undefined) {
20991 response = found;
20992 }
20993 if(Array.isArray(returnedValue)) {
20994 returnedValue.push(response);
20995 }
20996 else if(returnedValue !== undefined) {
20997 returnedValue = [returnedValue, response];
20998 }
20999 else if(response !== undefined) {
21000 returnedValue = response;
21001 }
21002 return found;
21003 }
21004 };
21005
21006 if(methodInvoked) {
21007 if(instance === undefined) {
21008 module.initialize();
21009 }
21010 module.invoke(query);
21011 }
21012 else {
21013 if(instance !== undefined) {
21014 instance.invoke('destroy');
21015 }
21016 module.initialize();
21017 }
21018 })
21019 ;
21020
21021 return (returnedValue !== undefined)
21022 ? returnedValue
21023 : this
21024 ;
21025};
21026
21027$.fn.sticky.settings = {
21028
21029 name : 'Sticky',
21030 namespace : 'sticky',
21031
21032 silent : false,
21033 debug : false,
21034 verbose : true,
21035 performance : true,
21036
21037 // whether to stick in the opposite direction on scroll up
21038 pushing : false,
21039
21040 context : false,
21041 container : false,
21042
21043 // Context to watch scroll events
21044 scrollContext : window,
21045
21046 // Offset to adjust scroll
21047 offset : 0,
21048
21049 // Offset to adjust scroll when attached to bottom of screen
21050 bottomOffset : 0,
21051
21052 // will only set container height if difference between context and container is larger than this number
21053 jitter : 5,
21054
21055 // set width of sticky element when it is fixed to page (used to make sure 100% width is maintained if no fixed size set)
21056 setSize : true,
21057
21058 // Whether to automatically observe changes with Mutation Observers
21059 observeChanges : false,
21060
21061 // Called when position is recalculated
21062 onReposition : function(){},
21063
21064 // Called on each scroll
21065 onScroll : function(){},
21066
21067 // Called when element is stuck to viewport
21068 onStick : function(){},
21069
21070 // Called when element is unstuck from viewport
21071 onUnstick : function(){},
21072
21073 // Called when element reaches top of context
21074 onTop : function(){},
21075
21076 // Called when element reaches bottom of context
21077 onBottom : function(){},
21078
21079 error : {
21080 container : 'Sticky element must be inside a relative container',
21081 visible : 'Element is hidden, you must call refresh after element becomes visible. Use silent setting to surpress this warning in production.',
21082 method : 'The method you called is not defined.',
21083 invalidContext : 'Context specified does not exist',
21084 elementSize : 'Sticky element is larger than its container, cannot create sticky.'
21085 },
21086
21087 className : {
21088 bound : 'bound',
21089 fixed : 'fixed',
21090 supported : 'native',
21091 top : 'top',
21092 bottom : 'bottom'
21093 }
21094
21095};
21096
21097})( jQuery, window, document );
21098
21099/*!
21100 * # Semantic UI 2.7.2 - Tab
21101 * http://github.com/semantic-org/semantic-ui/
21102 *
21103 *
21104 * Released under the MIT license
21105 * http://opensource.org/licenses/MIT
21106 *
21107 */
21108
21109;(function ($, window, document, undefined) {
21110
21111'use strict';
21112
21113$.isWindow = $.isWindow || function(obj) {
21114 return obj != null && obj === obj.window;
21115};
21116$.isFunction = $.isFunction || function(obj) {
21117 return typeof obj === "function" && typeof obj.nodeType !== "number";
21118};
21119
21120window = (typeof window != 'undefined' && window.Math == Math)
21121 ? window
21122 : (typeof self != 'undefined' && self.Math == Math)
21123 ? self
21124 : Function('return this')()
21125;
21126
21127$.fn.tab = function(parameters) {
21128
21129 var
21130 // use window context if none specified
21131 $allModules = $.isFunction(this)
21132 ? $(window)
21133 : $(this),
21134
21135 moduleSelector = $allModules.selector || '',
21136 time = new Date().getTime(),
21137 performance = [],
21138
21139 query = arguments[0],
21140 methodInvoked = (typeof query == 'string'),
21141 queryArguments = [].slice.call(arguments, 1),
21142
21143 initializedHistory = false,
21144 returnedValue
21145 ;
21146
21147 $allModules
21148 .each(function() {
21149 var
21150
21151 settings = ( $.isPlainObject(parameters) )
21152 ? $.extend(true, {}, $.fn.tab.settings, parameters)
21153 : $.extend({}, $.fn.tab.settings),
21154
21155 className = settings.className,
21156 metadata = settings.metadata,
21157 selector = settings.selector,
21158 error = settings.error,
21159 regExp = settings.regExp,
21160
21161 eventNamespace = '.' + settings.namespace,
21162 moduleNamespace = 'module-' + settings.namespace,
21163
21164 $module = $(this),
21165 $context,
21166 $tabs,
21167
21168 cache = {},
21169 firstLoad = true,
21170 recursionDepth = 0,
21171 element = this,
21172 instance = $module.data(moduleNamespace),
21173
21174 activeTabPath,
21175 parameterArray,
21176 module,
21177
21178 historyEvent
21179
21180 ;
21181
21182 module = {
21183
21184 initialize: function() {
21185 module.debug('Initializing tab menu item', $module);
21186 module.fix.callbacks();
21187 module.determineTabs();
21188
21189 module.debug('Determining tabs', settings.context, $tabs);
21190 // set up automatic routing
21191 if(settings.auto) {
21192 module.set.auto();
21193 }
21194 module.bind.events();
21195
21196 if(settings.history && !initializedHistory) {
21197 module.initializeHistory();
21198 initializedHistory = true;
21199 }
21200
21201 module.instantiate();
21202 },
21203
21204 instantiate: function () {
21205 module.verbose('Storing instance of module', module);
21206 instance = module;
21207 $module
21208 .data(moduleNamespace, module)
21209 ;
21210 },
21211
21212 destroy: function() {
21213 module.debug('Destroying tabs', $module);
21214 $module
21215 .removeData(moduleNamespace)
21216 .off(eventNamespace)
21217 ;
21218 },
21219
21220 bind: {
21221 events: function() {
21222 // if using $.tab don't add events
21223 if( !$.isWindow( element ) ) {
21224 module.debug('Attaching tab activation events to element', $module);
21225 $module
21226 .on('click' + eventNamespace, module.event.click)
21227 ;
21228 }
21229 }
21230 },
21231
21232 determineTabs: function() {
21233 var
21234 $reference
21235 ;
21236
21237 // determine tab context
21238 if(settings.context === 'parent') {
21239 if($module.closest(selector.ui).length > 0) {
21240 $reference = $module.closest(selector.ui);
21241 module.verbose('Using closest UI element as parent', $reference);
21242 }
21243 else {
21244 $reference = $module;
21245 }
21246 $context = $reference.parent();
21247 module.verbose('Determined parent element for creating context', $context);
21248 }
21249 else if(settings.context) {
21250 $context = $(settings.context);
21251 module.verbose('Using selector for tab context', settings.context, $context);
21252 }
21253 else {
21254 $context = $('body');
21255 }
21256 // find tabs
21257 if(settings.childrenOnly) {
21258 $tabs = $context.children(selector.tabs);
21259 module.debug('Searching tab context children for tabs', $context, $tabs);
21260 }
21261 else {
21262 $tabs = $context.find(selector.tabs);
21263 module.debug('Searching tab context for tabs', $context, $tabs);
21264 }
21265 },
21266
21267 fix: {
21268 callbacks: function() {
21269 if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
21270 if(parameters.onTabLoad) {
21271 parameters.onLoad = parameters.onTabLoad;
21272 delete parameters.onTabLoad;
21273 module.error(error.legacyLoad, parameters.onLoad);
21274 }
21275 if(parameters.onTabInit) {
21276 parameters.onFirstLoad = parameters.onTabInit;
21277 delete parameters.onTabInit;
21278 module.error(error.legacyInit, parameters.onFirstLoad);
21279 }
21280 settings = $.extend(true, {}, $.fn.tab.settings, parameters);
21281 }
21282 }
21283 },
21284
21285 initializeHistory: function() {
21286 module.debug('Initializing page state');
21287 if( $.address === undefined ) {
21288 module.error(error.state);
21289 return false;
21290 }
21291 else {
21292 if(settings.historyType == 'state') {
21293 module.debug('Using HTML5 to manage state');
21294 if(settings.path !== false) {
21295 $.address
21296 .history(true)
21297 .state(settings.path)
21298 ;
21299 }
21300 else {
21301 module.error(error.path);
21302 return false;
21303 }
21304 }
21305 $.address
21306 .bind('change', module.event.history.change)
21307 ;
21308 }
21309 },
21310
21311 event: {
21312 click: function(event) {
21313 var
21314 tabPath = $(this).data(metadata.tab)
21315 ;
21316 if(tabPath !== undefined) {
21317 if(settings.history) {
21318 module.verbose('Updating page state', event);
21319 $.address.value(tabPath);
21320 }
21321 else {
21322 module.verbose('Changing tab', event);
21323 module.changeTab(tabPath);
21324 }
21325 event.preventDefault();
21326 }
21327 else {
21328 module.debug('No tab specified');
21329 }
21330 },
21331 history: {
21332 change: function(event) {
21333 var
21334 tabPath = event.pathNames.join('/') || module.get.initialPath(),
21335 pageTitle = settings.templates.determineTitle(tabPath) || false
21336 ;
21337 module.performance.display();
21338 module.debug('History change event', tabPath, event);
21339 historyEvent = event;
21340 if(tabPath !== undefined) {
21341 module.changeTab(tabPath);
21342 }
21343 if(pageTitle) {
21344 $.address.title(pageTitle);
21345 }
21346 }
21347 }
21348 },
21349
21350 refresh: function() {
21351 if(activeTabPath) {
21352 module.debug('Refreshing tab', activeTabPath);
21353 module.changeTab(activeTabPath);
21354 }
21355 },
21356
21357 cache: {
21358
21359 read: function(cacheKey) {
21360 return (cacheKey !== undefined)
21361 ? cache[cacheKey]
21362 : false
21363 ;
21364 },
21365 add: function(cacheKey, content) {
21366 cacheKey = cacheKey || activeTabPath;
21367 module.debug('Adding cached content for', cacheKey);
21368 cache[cacheKey] = content;
21369 },
21370 remove: function(cacheKey) {
21371 cacheKey = cacheKey || activeTabPath;
21372 module.debug('Removing cached content for', cacheKey);
21373 delete cache[cacheKey];
21374 }
21375 },
21376
21377 escape: {
21378 string: function(text) {
21379 text = String(text);
21380 return text.replace(regExp.escape, '\\$&');
21381 }
21382 },
21383
21384 set: {
21385 auto: function() {
21386 var
21387 url = (typeof settings.path == 'string')
21388 ? settings.path.replace(/\/$/, '') + '/{$tab}'
21389 : '/{$tab}'
21390 ;
21391 module.verbose('Setting up automatic tab retrieval from server', url);
21392 if($.isPlainObject(settings.apiSettings)) {
21393 settings.apiSettings.url = url;
21394 }
21395 else {
21396 settings.apiSettings = {
21397 url: url
21398 };
21399 }
21400 },
21401 loading: function(tabPath) {
21402 var
21403 $tab = module.get.tabElement(tabPath),
21404 isLoading = $tab.hasClass(className.loading)
21405 ;
21406 if(!isLoading) {
21407 module.verbose('Setting loading state for', $tab);
21408 $tab
21409 .addClass(className.loading)
21410 .siblings($tabs)
21411 .removeClass(className.active + ' ' + className.loading)
21412 ;
21413 if($tab.length > 0) {
21414 settings.onRequest.call($tab[0], tabPath);
21415 }
21416 }
21417 },
21418 state: function(state) {
21419 $.address.value(state);
21420 }
21421 },
21422
21423 changeTab: function(tabPath) {
21424 var
21425 pushStateAvailable = (window.history && window.history.pushState),
21426 shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
21427 remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
21428 // only add default path if not remote content
21429 pathArray = (remoteContent && !shouldIgnoreLoad)
21430 ? module.utilities.pathToArray(tabPath)
21431 : module.get.defaultPathArray(tabPath)
21432 ;
21433 tabPath = module.utilities.arrayToPath(pathArray);
21434 $.each(pathArray, function(index, tab) {
21435 var
21436 currentPathArray = pathArray.slice(0, index + 1),
21437 currentPath = module.utilities.arrayToPath(currentPathArray),
21438
21439 isTab = module.is.tab(currentPath),
21440 isLastIndex = (index + 1 == pathArray.length),
21441
21442 $tab = module.get.tabElement(currentPath),
21443 $anchor,
21444 nextPathArray,
21445 nextPath,
21446 isLastTab
21447 ;
21448 module.verbose('Looking for tab', tab);
21449 if(isTab) {
21450 module.verbose('Tab was found', tab);
21451 // scope up
21452 activeTabPath = currentPath;
21453 parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
21454
21455 if(isLastIndex) {
21456 isLastTab = true;
21457 }
21458 else {
21459 nextPathArray = pathArray.slice(0, index + 2);
21460 nextPath = module.utilities.arrayToPath(nextPathArray);
21461 isLastTab = ( !module.is.tab(nextPath) );
21462 if(isLastTab) {
21463 module.verbose('Tab parameters found', nextPathArray);
21464 }
21465 }
21466 if(isLastTab && remoteContent) {
21467 if(!shouldIgnoreLoad) {
21468 module.activate.navigation(currentPath);
21469 module.fetch.content(currentPath, tabPath);
21470 }
21471 else {
21472 module.debug('Ignoring remote content on first tab load', currentPath);
21473 firstLoad = false;
21474 module.cache.add(tabPath, $tab.html());
21475 module.activate.all(currentPath);
21476 settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21477 settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21478 }
21479 return false;
21480 }
21481 else {
21482 module.debug('Opened local tab', currentPath);
21483 module.activate.all(currentPath);
21484 if( !module.cache.read(currentPath) ) {
21485 module.cache.add(currentPath, true);
21486 module.debug('First time tab loaded calling tab init');
21487 settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21488 }
21489 settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21490 }
21491
21492 }
21493 else if(tabPath.search('/') == -1 && tabPath !== '') {
21494 // look for in page anchor
21495 tabPath = module.escape.string(tabPath);
21496 $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
21497 currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
21498 $tab = module.get.tabElement(currentPath);
21499 // if anchor exists use parent tab
21500 if($anchor && $anchor.length > 0 && currentPath) {
21501 module.debug('Anchor link used, opening parent tab', $tab, $anchor);
21502 if( !$tab.hasClass(className.active) ) {
21503 setTimeout(function() {
21504 module.scrollTo($anchor);
21505 }, 0);
21506 }
21507 module.activate.all(currentPath);
21508 if( !module.cache.read(currentPath) ) {
21509 module.cache.add(currentPath, true);
21510 module.debug('First time tab loaded calling tab init');
21511 settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21512 }
21513 settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
21514 return false;
21515 }
21516 }
21517 else {
21518 module.error(error.missingTab, $module, $context, currentPath);
21519 return false;
21520 }
21521 });
21522 },
21523
21524 scrollTo: function($element) {
21525 var
21526 scrollOffset = ($element && $element.length > 0)
21527 ? $element.offset().top
21528 : false
21529 ;
21530 if(scrollOffset !== false) {
21531 module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
21532 $(document).scrollTop(scrollOffset);
21533 }
21534 },
21535
21536 update: {
21537 content: function(tabPath, html, evaluateScripts) {
21538 var
21539 $tab = module.get.tabElement(tabPath),
21540 tab = $tab[0]
21541 ;
21542 evaluateScripts = (evaluateScripts !== undefined)
21543 ? evaluateScripts
21544 : settings.evaluateScripts
21545 ;
21546 if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') {
21547 $tab
21548 .empty()
21549 .append($(html).clone(true))
21550 ;
21551 }
21552 else {
21553 if(evaluateScripts) {
21554 module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
21555 $tab.html(html);
21556 }
21557 else {
21558 module.debug('Updating HTML', tabPath, html);
21559 tab.innerHTML = html;
21560 }
21561 }
21562 }
21563 },
21564
21565 fetch: {
21566
21567 content: function(tabPath, fullTabPath) {
21568 var
21569 $tab = module.get.tabElement(tabPath),
21570 apiSettings = {
21571 dataType : 'html',
21572 encodeParameters : false,
21573 on : 'now',
21574 cache : settings.alwaysRefresh,
21575 headers : {
21576 'X-Remote': true
21577 },
21578 onSuccess : function(response) {
21579 if(settings.cacheType == 'response') {
21580 module.cache.add(fullTabPath, response);
21581 }
21582 module.update.content(tabPath, response);
21583 if(tabPath == activeTabPath) {
21584 module.debug('Content loaded', tabPath);
21585 module.activate.tab(tabPath);
21586 }
21587 else {
21588 module.debug('Content loaded in background', tabPath);
21589 }
21590 settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
21591 settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
21592
21593 if(settings.loadOnce) {
21594 module.cache.add(fullTabPath, true);
21595 }
21596 else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) {
21597 setTimeout(function() {
21598 var
21599 $clone = $tab.children().clone(true)
21600 ;
21601 $clone = $clone.not('script');
21602 module.cache.add(fullTabPath, $clone);
21603 }, 0);
21604 }
21605 else {
21606 module.cache.add(fullTabPath, $tab.html());
21607 }
21608 },
21609 urlData: {
21610 tab: fullTabPath
21611 }
21612 },
21613 request = $tab.api('get request') || false,
21614 existingRequest = ( request && request.state() === 'pending' ),
21615 requestSettings,
21616 cachedContent
21617 ;
21618
21619 fullTabPath = fullTabPath || tabPath;
21620 cachedContent = module.cache.read(fullTabPath);
21621
21622
21623 if(settings.cache && cachedContent) {
21624 module.activate.tab(tabPath);
21625 module.debug('Adding cached content', fullTabPath);
21626 if(!settings.loadOnce) {
21627 if(settings.evaluateScripts == 'once') {
21628 module.update.content(tabPath, cachedContent, false);
21629 }
21630 else {
21631 module.update.content(tabPath, cachedContent);
21632 }
21633 }
21634 settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
21635 }
21636 else if(existingRequest) {
21637 module.set.loading(tabPath);
21638 module.debug('Content is already loading', fullTabPath);
21639 }
21640 else if($.api !== undefined) {
21641 requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
21642 module.debug('Retrieving remote content', fullTabPath, requestSettings);
21643 module.set.loading(tabPath);
21644 $tab.api(requestSettings);
21645 }
21646 else {
21647 module.error(error.api);
21648 }
21649 }
21650 },
21651
21652 activate: {
21653 all: function(tabPath) {
21654 module.activate.tab(tabPath);
21655 module.activate.navigation(tabPath);
21656 },
21657 tab: function(tabPath) {
21658 var
21659 $tab = module.get.tabElement(tabPath),
21660 $deactiveTabs = (settings.deactivate == 'siblings')
21661 ? $tab.siblings($tabs)
21662 : $tabs.not($tab),
21663 isActive = $tab.hasClass(className.active)
21664 ;
21665 module.verbose('Showing tab content for', $tab);
21666 if(!isActive) {
21667 $tab
21668 .addClass(className.active)
21669 ;
21670 $deactiveTabs
21671 .removeClass(className.active + ' ' + className.loading)
21672 ;
21673 if($tab.length > 0) {
21674 settings.onVisible.call($tab[0], tabPath);
21675 }
21676 }
21677 },
21678 navigation: function(tabPath) {
21679 var
21680 $navigation = module.get.navElement(tabPath),
21681 $deactiveNavigation = (settings.deactivate == 'siblings')
21682 ? $navigation.siblings($allModules)
21683 : $allModules.not($navigation),
21684 isActive = $navigation.hasClass(className.active)
21685 ;
21686 module.verbose('Activating tab navigation for', $navigation, tabPath);
21687 if(!isActive) {
21688 $navigation
21689 .addClass(className.active)
21690 ;
21691 $deactiveNavigation
21692 .removeClass(className.active + ' ' + className.loading)
21693 ;
21694 }
21695 }
21696 },
21697
21698 deactivate: {
21699 all: function() {
21700 module.deactivate.navigation();
21701 module.deactivate.tabs();
21702 },
21703 navigation: function() {
21704 $allModules
21705 .removeClass(className.active)
21706 ;
21707 },
21708 tabs: function() {
21709 $tabs
21710 .removeClass(className.active + ' ' + className.loading)
21711 ;
21712 }
21713 },
21714
21715 is: {
21716 tab: function(tabName) {
21717 return (tabName !== undefined)
21718 ? ( module.get.tabElement(tabName).length > 0 )
21719 : false
21720 ;
21721 }
21722 },
21723
21724 get: {
21725 initialPath: function() {
21726 return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
21727 },
21728 path: function() {
21729 return $.address.value();
21730 },
21731 // adds default tabs to tab path
21732 defaultPathArray: function(tabPath) {
21733 return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
21734 },
21735 defaultPath: function(tabPath) {
21736 var
21737 $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + module.escape.string(tabPath) + '/"]').eq(0),
21738 defaultTab = $defaultNav.data(metadata.tab) || false
21739 ;
21740 if( defaultTab ) {
21741 module.debug('Found default tab', defaultTab);
21742 if(recursionDepth < settings.maxDepth) {
21743 recursionDepth++;
21744 return module.get.defaultPath(defaultTab);
21745 }
21746 module.error(error.recursion);
21747 }
21748 else {
21749 module.debug('No default tabs found for', tabPath, $tabs);
21750 }
21751 recursionDepth = 0;
21752 return tabPath;
21753 },
21754 navElement: function(tabPath) {
21755 tabPath = tabPath || activeTabPath;
21756 return $allModules.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]');
21757 },
21758 tabElement: function(tabPath) {
21759 var
21760 $fullPathTab,
21761 $simplePathTab,
21762 tabPathArray,
21763 lastTab
21764 ;
21765 tabPath = tabPath || activeTabPath;
21766 tabPathArray = module.utilities.pathToArray(tabPath);
21767 lastTab = module.utilities.last(tabPathArray);
21768 $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]');
21769 $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + module.escape.string(lastTab) + '"]');
21770 return ($fullPathTab.length > 0)
21771 ? $fullPathTab
21772 : $simplePathTab
21773 ;
21774 },
21775 tab: function() {
21776 return activeTabPath;
21777 }
21778 },
21779
21780 utilities: {
21781 filterArray: function(keepArray, removeArray) {
21782 return $.grep(keepArray, function(keepValue) {
21783 return ( $.inArray(keepValue, removeArray) == -1);
21784 });
21785 },
21786 last: function(array) {
21787 return Array.isArray(array)
21788 ? array[ array.length - 1]
21789 : false
21790 ;
21791 },
21792 pathToArray: function(pathName) {
21793 if(pathName === undefined) {
21794 pathName = activeTabPath;
21795 }
21796 return typeof pathName == 'string'
21797 ? pathName.split('/')
21798 : [pathName]
21799 ;
21800 },
21801 arrayToPath: function(pathArray) {
21802 return Array.isArray(pathArray)
21803 ? pathArray.join('/')
21804 : false
21805 ;
21806 }
21807 },
21808
21809 setting: function(name, value) {
21810 module.debug('Changing setting', name, value);
21811 if( $.isPlainObject(name) ) {
21812 $.extend(true, settings, name);
21813 }
21814 else if(value !== undefined) {
21815 if($.isPlainObject(settings[name])) {
21816 $.extend(true, settings[name], value);
21817 }
21818 else {
21819 settings[name] = value;
21820 }
21821 }
21822 else {
21823 return settings[name];
21824 }
21825 },
21826 internal: function(name, value) {
21827 if( $.isPlainObject(name) ) {
21828 $.extend(true, module, name);
21829 }
21830 else if(value !== undefined) {
21831 module[name] = value;
21832 }
21833 else {
21834 return module[name];
21835 }
21836 },
21837 debug: function() {
21838 if(!settings.silent && settings.debug) {
21839 if(settings.performance) {
21840 module.performance.log(arguments);
21841 }
21842 else {
21843 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
21844 module.debug.apply(console, arguments);
21845 }
21846 }
21847 },
21848 verbose: function() {
21849 if(!settings.silent && settings.verbose && settings.debug) {
21850 if(settings.performance) {
21851 module.performance.log(arguments);
21852 }
21853 else {
21854 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
21855 module.verbose.apply(console, arguments);
21856 }
21857 }
21858 },
21859 error: function() {
21860 if(!settings.silent) {
21861 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
21862 module.error.apply(console, arguments);
21863 }
21864 },
21865 performance: {
21866 log: function(message) {
21867 var
21868 currentTime,
21869 executionTime,
21870 previousTime
21871 ;
21872 if(settings.performance) {
21873 currentTime = new Date().getTime();
21874 previousTime = time || currentTime;
21875 executionTime = currentTime - previousTime;
21876 time = currentTime;
21877 performance.push({
21878 'Name' : message[0],
21879 'Arguments' : [].slice.call(message, 1) || '',
21880 'Element' : element,
21881 'Execution Time' : executionTime
21882 });
21883 }
21884 clearTimeout(module.performance.timer);
21885 module.performance.timer = setTimeout(module.performance.display, 500);
21886 },
21887 display: function() {
21888 var
21889 title = settings.name + ':',
21890 totalTime = 0
21891 ;
21892 time = false;
21893 clearTimeout(module.performance.timer);
21894 $.each(performance, function(index, data) {
21895 totalTime += data['Execution Time'];
21896 });
21897 title += ' ' + totalTime + 'ms';
21898 if(moduleSelector) {
21899 title += ' \'' + moduleSelector + '\'';
21900 }
21901 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
21902 console.groupCollapsed(title);
21903 if(console.table) {
21904 console.table(performance);
21905 }
21906 else {
21907 $.each(performance, function(index, data) {
21908 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
21909 });
21910 }
21911 console.groupEnd();
21912 }
21913 performance = [];
21914 }
21915 },
21916 invoke: function(query, passedArguments, context) {
21917 var
21918 object = instance,
21919 maxDepth,
21920 found,
21921 response
21922 ;
21923 passedArguments = passedArguments || queryArguments;
21924 context = element || context;
21925 if(typeof query == 'string' && object !== undefined) {
21926 query = query.split(/[\. ]/);
21927 maxDepth = query.length - 1;
21928 $.each(query, function(depth, value) {
21929 var camelCaseValue = (depth != maxDepth)
21930 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
21931 : query
21932 ;
21933 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
21934 object = object[camelCaseValue];
21935 }
21936 else if( object[camelCaseValue] !== undefined ) {
21937 found = object[camelCaseValue];
21938 return false;
21939 }
21940 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
21941 object = object[value];
21942 }
21943 else if( object[value] !== undefined ) {
21944 found = object[value];
21945 return false;
21946 }
21947 else {
21948 module.error(error.method, query);
21949 return false;
21950 }
21951 });
21952 }
21953 if ( $.isFunction( found ) ) {
21954 response = found.apply(context, passedArguments);
21955 }
21956 else if(found !== undefined) {
21957 response = found;
21958 }
21959 if(Array.isArray(returnedValue)) {
21960 returnedValue.push(response);
21961 }
21962 else if(returnedValue !== undefined) {
21963 returnedValue = [returnedValue, response];
21964 }
21965 else if(response !== undefined) {
21966 returnedValue = response;
21967 }
21968 return found;
21969 }
21970 };
21971 if(methodInvoked) {
21972 if(instance === undefined) {
21973 module.initialize();
21974 }
21975 module.invoke(query);
21976 }
21977 else {
21978 if(instance !== undefined) {
21979 instance.invoke('destroy');
21980 }
21981 module.initialize();
21982 }
21983 })
21984 ;
21985 return (returnedValue !== undefined)
21986 ? returnedValue
21987 : this
21988 ;
21989
21990};
21991
21992// shortcut for tabbed content with no defined navigation
21993$.tab = function() {
21994 $(window).tab.apply(this, arguments);
21995};
21996
21997$.fn.tab.settings = {
21998
21999 name : 'Tab',
22000 namespace : 'tab',
22001
22002 silent : false,
22003 debug : false,
22004 verbose : false,
22005 performance : true,
22006
22007 auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
22008 history : false, // use browser history
22009 historyType : 'hash', // #/ or html5 state
22010 path : false, // base path of url
22011
22012 context : false, // specify a context that tabs must appear inside
22013 childrenOnly : false, // use only tabs that are children of context
22014 maxDepth : 25, // max depth a tab can be nested
22015
22016 deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together
22017
22018 alwaysRefresh : false, // load tab content new every tab click
22019 cache : true, // cache the content requests to pull locally
22020 loadOnce : false, // Whether tab data should only be loaded once when using remote content
22021 cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute
22022 ignoreFirstLoad : false, // don't load remote content on first load
22023
22024 apiSettings : false, // settings for api call
22025 evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
22026
22027 onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
22028 onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
22029 onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
22030 onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
22031
22032 templates : {
22033 determineTitle: function(tabArray) {} // returns page title for path
22034 },
22035
22036 error: {
22037 api : 'You attempted to load content without API module',
22038 method : 'The method you called is not defined',
22039 missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
22040 noContent : 'The tab you specified is missing a content url.',
22041 path : 'History enabled, but no path was specified',
22042 recursion : 'Max recursive depth reached',
22043 legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
22044 legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
22045 state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
22046 },
22047
22048 regExp : {
22049 escape : /[-[\]{}()*+?.,\\^$|#\s:=@]/g
22050 },
22051
22052 metadata : {
22053 tab : 'tab',
22054 loaded : 'loaded',
22055 promise: 'promise'
22056 },
22057
22058 className : {
22059 loading : 'loading',
22060 active : 'active'
22061 },
22062
22063 selector : {
22064 tabs : '.ui.tab',
22065 ui : '.ui'
22066 }
22067
22068};
22069
22070})( jQuery, window, document );
22071
22072/*!
22073 * # Semantic UI 2.7.2 - Toast
22074 * http://github.com/semantic-org/semantic-ui/
22075 *
22076 *
22077 * Released under the MIT license
22078 * http://opensource.org/licenses/MIT
22079 *
22080 */
22081
22082;(function ($, window, document, undefined) {
22083
22084'use strict';
22085
22086$.isFunction = $.isFunction || function(obj) {
22087 return typeof obj === "function" && typeof obj.nodeType !== "number";
22088};
22089
22090window = (typeof window != 'undefined' && window.Math == Math)
22091 ? window
22092 : (typeof self != 'undefined' && self.Math == Math)
22093 ? self
22094 : Function('return this')()
22095;
22096
22097$.fn.toast = function(parameters) {
22098 var
22099 $allModules = $(this),
22100 moduleSelector = $allModules.selector || '',
22101
22102 time = new Date().getTime(),
22103 performance = [],
22104
22105 query = arguments[0],
22106 methodInvoked = (typeof query == 'string'),
22107 queryArguments = [].slice.call(arguments, 1),
22108 returnedValue
22109 ;
22110 $allModules
22111 .each(function() {
22112 var
22113 settings = ( $.isPlainObject(parameters) )
22114 ? $.extend(true, {}, $.fn.toast.settings, parameters)
22115 : $.extend({}, $.fn.toast.settings),
22116
22117 className = settings.className,
22118 selector = settings.selector,
22119 error = settings.error,
22120 namespace = settings.namespace,
22121
22122 eventNamespace = '.' + namespace,
22123 moduleNamespace = namespace + '-module',
22124
22125 $module = $(this),
22126 $toastBox = $('<div/>',{'class':settings.className.box}),
22127 $toast = $('<div/>'),
22128 $progress = $('<div/>',{'class':settings.className.progress+' '+settings.class}),
22129 $progressBar = $('<div/>',{'class':'bar'}),
22130
22131 $close = $('<i/>',{'class':'close icon'}),
22132 $context = (settings.context)
22133 ? $(settings.context)
22134 : $('body'),
22135
22136 element = this,
22137 instance = $module.data(moduleNamespace),
22138
22139 module
22140 ;
22141 module = {
22142
22143 initialize: function() {
22144 module.verbose('Initializing element');
22145 if(typeof settings.showProgress !== 'string' || ['top','bottom'].indexOf(settings.showProgress) === -1 ) {
22146 settings.showProgress = false;
22147 }
22148 if (!module.has.container()) {
22149 module.create.container();
22150 }
22151
22152 module.create.toast();
22153
22154 module.bind.events();
22155
22156 if(settings.displayTime > 0) {
22157 module.closeTimer = setTimeout(module.close, settings.displayTime+(!!settings.showProgress ? 300 : 0));
22158 }
22159 module.show();
22160 },
22161
22162 destroy: function() {
22163 module.debug('Removing toast', $toast);
22164 $toast.remove();
22165 $toast = undefined;
22166 settings.onRemove.call($toast, element);
22167 },
22168
22169 show: function(callback) {
22170 callback = callback || function(){};
22171 module.debug('Showing toast');
22172 if(settings.onShow.call($toast, element) === false) {
22173 module.debug('onShow callback returned false, cancelling toast animation');
22174 return;
22175 }
22176 module.animate.show(callback);
22177 },
22178
22179 close: function(callback) {
22180 if(module.closeTimer) {
22181 clearTimeout(module.closeTimer);
22182 }
22183 callback = callback || function(){};
22184 module.remove.visible();
22185 module.unbind.events();
22186 module.animate.close(callback);
22187
22188 },
22189
22190 create: {
22191 container: function() {
22192 module.verbose('Creating container');
22193 $context.append('<div class="ui ' + settings.position + ' ' + className.container + '"></div>');
22194 },
22195 toast: function() {
22196 var $content = $('<div/>').addClass(className.content);
22197 module.verbose('Creating toast');
22198 if(settings.closeIcon) {
22199 $toast.append($close);
22200 $toast.css('cursor','default');
22201 }
22202
22203 var iconClass = typeof settings.showIcon === 'string' ? settings.showIcon : settings.showIcon && settings.icons[settings.class] ? settings.icons[settings.class] : '';
22204 if (iconClass != '') {
22205 var $icon = $('<i/>').addClass(iconClass + ' ' + className.icon);
22206
22207 $toast
22208 .addClass(className.icon)
22209 .append($icon)
22210 ;
22211 }
22212
22213 if (settings.title !== '') {
22214 var
22215 $title = $('<div/>')
22216 .addClass(className.title)
22217 .text(settings.title)
22218 ;
22219
22220 $content.append($title);
22221 }
22222
22223 $content.append($('<div/>').html(settings.message));
22224
22225 $toast
22226 .addClass(settings.class + ' ' + className.toast)
22227 .append($content)
22228 ;
22229 $toast.css('opacity', settings.opacity);
22230 if(settings.compact || $toast.hasClass('compact')) {
22231 $toastBox.addClass('compact');
22232 }
22233 if($toast.hasClass('toast') && !$toast.hasClass('inverted')){
22234 $progress.addClass('inverted');
22235 } else {
22236 $progress.removeClass('inverted');
22237 }
22238 $toast = $toastBox.append($toast);
22239 if(!!settings.showProgress && settings.displayTime > 0){
22240 $progress
22241 .addClass(settings.showProgress)
22242 .append($progressBar);
22243 if ($progress.hasClass('top')) {
22244 $toast.prepend($progress);
22245 } else {
22246 $toast.append($progress);
22247 }
22248 $progressBar.css('transition','width '+(settings.displayTime/1000)+'s linear');
22249 $progressBar.width(settings.progressUp?'0%':'100%');
22250 setTimeout(function() {
22251 if(typeof $progress !== 'undefined'){
22252 $progressBar.width(settings.progressUp?'100%':'0%');
22253 }
22254 },300);
22255 }
22256 if (settings.newestOnTop) {
22257 $toast.prependTo(module.get.container());
22258 }
22259 else {
22260 $toast.appendTo(module.get.container());
22261 }
22262 }
22263 },
22264
22265 bind: {
22266 events: function() {
22267 module.debug('Binding events to toast');
22268 (settings.closeIcon ? $close : $toast)
22269 .on('click' + eventNamespace, module.event.click)
22270 ;
22271 }
22272 },
22273
22274 unbind: {
22275 events: function() {
22276 module.debug('Unbinding events to toast');
22277 (settings.closeIcon ? $close : $toast)
22278 .off('click' + eventNamespace)
22279 ;
22280 }
22281 },
22282
22283 animate: {
22284 show: function(callback) {
22285 callback = $.isFunction(callback) ? callback : function(){};
22286 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
22287 module.set.visible();
22288 $toast
22289 .transition({
22290 animation : settings.transition.showMethod + ' in',
22291 queue : false,
22292 debug : settings.debug,
22293 verbose : settings.verbose,
22294 duration : settings.transition.showDuration,
22295 onComplete : function() {
22296 callback.call($toast, element);
22297 settings.onVisible.call($toast, element);
22298 }
22299 })
22300 ;
22301 }
22302 else {
22303 module.error(error.noTransition);
22304 }
22305 },
22306 close: function(callback) {
22307 callback = $.isFunction(callback) ? callback : function(){};
22308 module.debug('Closing toast');
22309 if(settings.onHide.call($toast, element) === false) {
22310 module.debug('onHide callback returned false, cancelling toast animation');
22311 return;
22312 }
22313 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
22314 $toast
22315 .transition({
22316 animation : settings.transition.hideMethod + ' out',
22317 queue : false,
22318 duration : settings.transition.hideDuration,
22319 debug : settings.debug,
22320 verbose : settings.verbose,
22321
22322 onBeforeHide: function(callback){
22323 callback = $.isFunction(callback)?callback : function(){};
22324 if(settings.transition.closeEasing !== ''){
22325 $toast.css('opacity',0);
22326 $toast.wrap('<div/>').parent().slideUp(500,settings.transition.closeEasing,function(){
22327 $toast.parent().remove();
22328 callback.call($toast);
22329 });
22330 } else {
22331 callback.call($toast);
22332 }
22333 },
22334 onComplete : function() {
22335 module.destroy();
22336 callback.call($toast, element);
22337 settings.onHidden.call($toast, element);
22338 }
22339 })
22340 ;
22341 }
22342 else {
22343 module.error(error.noTransition);
22344 }
22345 }
22346 },
22347
22348 has: {
22349 container: function() {
22350 module.verbose('Determining if there is already a container');
22351 return ($context.find(module.helpers.toClass(settings.position) + selector.container).length > 0);
22352 }
22353 },
22354
22355 get: {
22356 container: function() {
22357 return ($context.find(module.helpers.toClass(settings.position) + selector.container)[0]);
22358 }
22359 },
22360
22361 set: {
22362 visible: function() {
22363 $toast.addClass(className.visible);
22364 }
22365 },
22366
22367 remove: {
22368 visible: function() {
22369 $toast.removeClass(className.visible);
22370 }
22371 },
22372
22373 event: {
22374 click: function() {
22375 settings.onClick.call($toast, element);
22376 module.close();
22377 }
22378 },
22379
22380 helpers: {
22381 toClass: function(selector) {
22382 var
22383 classes = selector.split(' '),
22384 result = ''
22385 ;
22386
22387 classes.forEach(function (element) {
22388 result += '.' + element;
22389 });
22390
22391 return result;
22392 }
22393 },
22394
22395 setting: function(name, value) {
22396 module.debug('Changing setting', name, value);
22397 if( $.isPlainObject(name) ) {
22398 $.extend(true, settings, name);
22399 }
22400 else if(value !== undefined) {
22401 if($.isPlainObject(settings[name])) {
22402 $.extend(true, settings[name], value);
22403 }
22404 else {
22405 settings[name] = value;
22406 }
22407 }
22408 else {
22409 return settings[name];
22410 }
22411 },
22412 internal: function(name, value) {
22413 if( $.isPlainObject(name) ) {
22414 $.extend(true, module, name);
22415 }
22416 else if(value !== undefined) {
22417 module[name] = value;
22418 }
22419 else {
22420 return module[name];
22421 }
22422 },
22423 debug: function() {
22424 if(!settings.silent && settings.debug) {
22425 if(settings.performance) {
22426 module.performance.log(arguments);
22427 }
22428 else {
22429 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
22430 module.debug.apply(console, arguments);
22431 }
22432 }
22433 },
22434 verbose: function() {
22435 if(!settings.silent && settings.verbose && settings.debug) {
22436 if(settings.performance) {
22437 module.performance.log(arguments);
22438 }
22439 else {
22440 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
22441 module.verbose.apply(console, arguments);
22442 }
22443 }
22444 },
22445 error: function() {
22446 if(!settings.silent) {
22447 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
22448 module.error.apply(console, arguments);
22449 }
22450 },
22451 performance: {
22452 log: function(message) {
22453 var
22454 currentTime,
22455 executionTime,
22456 previousTime
22457 ;
22458 if(settings.performance) {
22459 currentTime = new Date().getTime();
22460 previousTime = time || currentTime;
22461 executionTime = currentTime - previousTime;
22462 time = currentTime;
22463 performance.push({
22464 'Name' : message[0],
22465 'Arguments' : [].slice.call(message, 1) || '',
22466 'Element' : element,
22467 'Execution Time' : executionTime
22468 });
22469 }
22470 clearTimeout(module.performance.timer);
22471 module.performance.timer = setTimeout(module.performance.display, 500);
22472 },
22473 display: function() {
22474 var
22475 title = settings.name + ':',
22476 totalTime = 0
22477 ;
22478 time = false;
22479 clearTimeout(module.performance.timer);
22480 $.each(performance, function(index, data) {
22481 totalTime += data['Execution Time'];
22482 });
22483 title += ' ' + totalTime + 'ms';
22484 if(moduleSelector) {
22485 title += ' \'' + moduleSelector + '\'';
22486 }
22487 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
22488 console.groupCollapsed(title);
22489 if(console.table) {
22490 console.table(performance);
22491 }
22492 else {
22493 $.each(performance, function(index, data) {
22494 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
22495 });
22496 }
22497 console.groupEnd();
22498 }
22499 performance = [];
22500 }
22501 },
22502 invoke: function(query, passedArguments, context) {
22503 var
22504 object = instance,
22505 maxDepth,
22506 found,
22507 response
22508 ;
22509 passedArguments = passedArguments || queryArguments;
22510 context = element || context;
22511 if(typeof query == 'string' && object !== undefined) {
22512 query = query.split(/[\. ]/);
22513 maxDepth = query.length - 1;
22514 $.each(query, function(depth, value) {
22515 var camelCaseValue = (depth != maxDepth)
22516 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
22517 : query
22518 ;
22519 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
22520 object = object[camelCaseValue];
22521 }
22522 else if( object[camelCaseValue] !== undefined ) {
22523 found = object[camelCaseValue];
22524 return false;
22525 }
22526 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
22527 object = object[value];
22528 }
22529 else if( object[value] !== undefined ) {
22530 found = object[value];
22531 return false;
22532 }
22533 else {
22534 module.error(error.method, query);
22535 return false;
22536 }
22537 });
22538 }
22539 if ( $.isFunction( found ) ) {
22540 response = found.apply(context, passedArguments);
22541 }
22542 else if(found !== undefined) {
22543 response = found;
22544 }
22545 if(Array.isArray(returnedValue)) {
22546 returnedValue.push(response);
22547 }
22548 else if(returnedValue !== undefined) {
22549 returnedValue = [returnedValue, response];
22550 }
22551 else if(response !== undefined) {
22552 returnedValue = response;
22553 }
22554 return found;
22555 }
22556 };
22557
22558 if(methodInvoked) {
22559 if(instance === undefined) {
22560 module.initialize();
22561 }
22562 module.invoke(query);
22563 }
22564 else {
22565 if(instance !== undefined) {
22566 instance.invoke('destroy');
22567 }
22568 module.initialize();
22569 }
22570 })
22571 ;
22572
22573 return (returnedValue !== undefined)
22574 ? returnedValue
22575 : this
22576 ;
22577};
22578
22579$.fn.toast.settings = {
22580
22581 name : 'Toast',
22582 namespace : 'toast',
22583
22584 silent : false,
22585 debug : false,
22586 verbose : false,
22587 performance : true,
22588
22589 context : 'body',
22590
22591 position : 'top right',
22592 class : 'info',
22593
22594 title : '',
22595 message : '',
22596 displayTime : 3000, // set to zero to require manually dismissal, otherwise hides on its own
22597 showIcon : true,
22598 newestOnTop : false,
22599 showProgress : false,
22600 progressUp : true, //if false, the bar will start at 100% and decrease to 0%
22601 opacity : 1,
22602 compact : true,
22603 closeIcon : false,
22604
22605 // transition settings
22606 transition : {
22607 showMethod : 'scale',
22608 showDuration : 500,
22609 hideMethod : 'scale',
22610 hideDuration : 500,
22611 closeEasing : 'easeOutBounce' //Set to empty string to stack the closed toast area immediately (old behaviour)
22612 },
22613
22614 error: {
22615 method : 'The method you called is not defined.',
22616 noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>'
22617 },
22618
22619 className : {
22620 container : 'toast-container',
22621 box : 'toast-box',
22622 progress : 'ui attached active progress',
22623 toast : 'ui toast',
22624 icon : 'icon',
22625 visible : 'visible',
22626 content : 'content',
22627 title : 'header'
22628 },
22629
22630 icons : {
22631 info : 'info',
22632 success : 'checkmark',
22633 warning : 'warning',
22634 error : 'times'
22635 },
22636
22637 selector : {
22638 container : '.toast-container',
22639 box : '.toast-box',
22640 toast : '.ui.toast'
22641 },
22642
22643 // callbacks
22644 onShow : function(){},
22645 onVisible : function(){},
22646 onClick : function(){},
22647 onHide : function(){},
22648 onHidden : function(){},
22649 onRemove : function(){},
22650};
22651
22652$.extend( $.easing, {
22653 easeOutBounce: function (x, t, b, c, d) {
22654 if ((t/=d) < (1/2.75)) {
22655 return c*(7.5625*t*t) + b;
22656 } else if (t < (2/2.75)) {
22657 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
22658 } else if (t < (2.5/2.75)) {
22659 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
22660 } else {
22661 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
22662 }
22663 }
22664});
22665
22666
22667})( jQuery, window, document );
22668
22669/*!
22670 * # Semantic UI 2.7.2 - Transition
22671 * http://github.com/semantic-org/semantic-ui/
22672 *
22673 *
22674 * Released under the MIT license
22675 * http://opensource.org/licenses/MIT
22676 *
22677 */
22678
22679;(function ($, window, document, undefined) {
22680
22681'use strict';
22682
22683$.isFunction = $.isFunction || function(obj) {
22684 return typeof obj === "function" && typeof obj.nodeType !== "number";
22685};
22686
22687window = (typeof window != 'undefined' && window.Math == Math)
22688 ? window
22689 : (typeof self != 'undefined' && self.Math == Math)
22690 ? self
22691 : Function('return this')()
22692;
22693
22694$.fn.transition = function() {
22695 var
22696 $allModules = $(this),
22697 moduleSelector = $allModules.selector || '',
22698
22699 time = new Date().getTime(),
22700 performance = [],
22701
22702 moduleArguments = arguments,
22703 query = moduleArguments[0],
22704 queryArguments = [].slice.call(arguments, 1),
22705 methodInvoked = (typeof query === 'string'),
22706
22707 returnedValue
22708 ;
22709 $allModules
22710 .each(function(index) {
22711 var
22712 $module = $(this),
22713 element = this,
22714
22715 // set at run time
22716 settings,
22717 instance,
22718
22719 error,
22720 className,
22721 metadata,
22722 animationEnd,
22723
22724 moduleNamespace,
22725 eventNamespace,
22726 module
22727 ;
22728
22729 module = {
22730
22731 initialize: function() {
22732
22733 // get full settings
22734 settings = module.get.settings.apply(element, moduleArguments);
22735
22736 // shorthand
22737 className = settings.className;
22738 error = settings.error;
22739 metadata = settings.metadata;
22740
22741 // define namespace
22742 eventNamespace = '.' + settings.namespace;
22743 moduleNamespace = 'module-' + settings.namespace;
22744 instance = $module.data(moduleNamespace) || module;
22745
22746 // get vendor specific events
22747 animationEnd = module.get.animationEndEvent();
22748
22749 if(methodInvoked) {
22750 methodInvoked = module.invoke(query);
22751 }
22752
22753 // method not invoked, lets run an animation
22754 if(methodInvoked === false) {
22755 module.verbose('Converted arguments into settings object', settings);
22756 if(settings.interval) {
22757 module.delay(settings.animate);
22758 }
22759 else {
22760 module.animate();
22761 }
22762 module.instantiate();
22763 }
22764 },
22765
22766 instantiate: function() {
22767 module.verbose('Storing instance of module', module);
22768 instance = module;
22769 $module
22770 .data(moduleNamespace, instance)
22771 ;
22772 },
22773
22774 destroy: function() {
22775 module.verbose('Destroying previous module for', element);
22776 $module
22777 .removeData(moduleNamespace)
22778 ;
22779 },
22780
22781 refresh: function() {
22782 module.verbose('Refreshing display type on next animation');
22783 delete module.displayType;
22784 },
22785
22786 forceRepaint: function() {
22787 module.verbose('Forcing element repaint');
22788 var
22789 $parentElement = $module.parent(),
22790 $nextElement = $module.next()
22791 ;
22792 if($nextElement.length === 0) {
22793 $module.detach().appendTo($parentElement);
22794 }
22795 else {
22796 $module.detach().insertBefore($nextElement);
22797 }
22798 },
22799
22800 repaint: function() {
22801 module.verbose('Repainting element');
22802 var
22803 fakeAssignment = element.offsetWidth
22804 ;
22805 },
22806
22807 delay: function(interval) {
22808 var
22809 direction = module.get.animationDirection(),
22810 shouldReverse,
22811 delay
22812 ;
22813 if(!direction) {
22814 direction = module.can.transition()
22815 ? module.get.direction()
22816 : 'static'
22817 ;
22818 }
22819 interval = (interval !== undefined)
22820 ? interval
22821 : settings.interval
22822 ;
22823 shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
22824 delay = (shouldReverse || settings.reverse == true)
22825 ? ($allModules.length - index) * settings.interval
22826 : index * settings.interval
22827 ;
22828 module.debug('Delaying animation by', delay);
22829 setTimeout(module.animate, delay);
22830 },
22831
22832 animate: function(overrideSettings) {
22833 settings = overrideSettings || settings;
22834 if(!module.is.supported()) {
22835 module.error(error.support);
22836 return false;
22837 }
22838 module.debug('Preparing animation', settings.animation);
22839 if(module.is.animating()) {
22840 if(settings.queue) {
22841 if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
22842 module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
22843 }
22844 else {
22845 module.queue(settings.animation);
22846 }
22847 return false;
22848 }
22849 else if(!settings.allowRepeats && module.is.occurring()) {
22850 module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
22851 return false;
22852 }
22853 else {
22854 module.debug('New animation started, completing previous early', settings.animation);
22855 instance.complete();
22856 }
22857 }
22858 if( module.can.animate() ) {
22859 module.set.animating(settings.animation);
22860 }
22861 else {
22862 module.error(error.noAnimation, settings.animation, element);
22863 }
22864 },
22865
22866 reset: function() {
22867 module.debug('Resetting animation to beginning conditions');
22868 module.remove.animationCallbacks();
22869 module.restore.conditions();
22870 module.remove.animating();
22871 },
22872
22873 queue: function(animation) {
22874 module.debug('Queueing animation of', animation);
22875 module.queuing = true;
22876 $module
22877 .one(animationEnd + '.queue' + eventNamespace, function() {
22878 module.queuing = false;
22879 module.repaint();
22880 module.animate.apply(this, settings);
22881 })
22882 ;
22883 },
22884
22885 complete: function (event) {
22886 module.debug('Animation complete', settings.animation);
22887 module.remove.completeCallback();
22888 module.remove.failSafe();
22889 if(!module.is.looping()) {
22890 if( module.is.outward() ) {
22891 module.verbose('Animation is outward, hiding element');
22892 module.restore.conditions();
22893 module.hide();
22894 }
22895 else if( module.is.inward() ) {
22896 module.verbose('Animation is outward, showing element');
22897 module.restore.conditions();
22898 module.show();
22899 }
22900 else {
22901 module.verbose('Static animation completed');
22902 module.restore.conditions();
22903 settings.onComplete.call(element);
22904 }
22905 }
22906 },
22907
22908 force: {
22909 visible: function() {
22910 var
22911 style = $module.attr('style'),
22912 userStyle = module.get.userStyle(style),
22913 displayType = module.get.displayType(),
22914 overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
22915 inlineDisplay = $module[0].style.display,
22916 mustStayHidden = !displayType || (inlineDisplay === 'none' && settings.skipInlineHidden) || $module[0].tagName.match(/(script|link|style)/i)
22917 ;
22918 if (mustStayHidden){
22919 module.remove.transition();
22920 return false;
22921 }
22922 module.verbose('Overriding default display to show element', displayType);
22923 $module
22924 .attr('style', overrideStyle)
22925 ;
22926 return true;
22927 },
22928 hidden: function() {
22929 var
22930 style = $module.attr('style'),
22931 currentDisplay = $module.css('display'),
22932 emptyStyle = (style === undefined || style === '')
22933 ;
22934 if(currentDisplay !== 'none' && !module.is.hidden()) {
22935 module.verbose('Overriding default display to hide element');
22936 $module
22937 .css('display', 'none')
22938 ;
22939 }
22940 else if(emptyStyle) {
22941 $module
22942 .removeAttr('style')
22943 ;
22944 }
22945 }
22946 },
22947
22948 has: {
22949 direction: function(animation) {
22950 var
22951 hasDirection = false
22952 ;
22953 animation = animation || settings.animation;
22954 if(typeof animation === 'string') {
22955 animation = animation.split(' ');
22956 $.each(animation, function(index, word){
22957 if(word === className.inward || word === className.outward) {
22958 hasDirection = true;
22959 }
22960 });
22961 }
22962 return hasDirection;
22963 },
22964 inlineDisplay: function() {
22965 var
22966 style = $module.attr('style') || ''
22967 ;
22968 return Array.isArray(style.match(/display.*?;/, ''));
22969 }
22970 },
22971
22972 set: {
22973 animating: function(animation) {
22974 // remove previous callbacks
22975 module.remove.completeCallback();
22976
22977 // determine exact animation
22978 animation = animation || settings.animation;
22979 var animationClass = module.get.animationClass(animation);
22980
22981 // save animation class in cache to restore class names
22982 module.save.animation(animationClass);
22983
22984 if(module.force.visible()) {
22985 module.remove.hidden();
22986 module.remove.direction();
22987
22988 module.start.animation(animationClass);
22989 }
22990 },
22991 duration: function(animationName, duration) {
22992 duration = duration || settings.duration;
22993 duration = (typeof duration == 'number')
22994 ? duration + 'ms'
22995 : duration
22996 ;
22997 if(duration || duration === 0) {
22998 module.verbose('Setting animation duration', duration);
22999 $module
23000 .css({
23001 'animation-duration': duration
23002 })
23003 ;
23004 }
23005 },
23006 direction: function(direction) {
23007 direction = direction || module.get.direction();
23008 if(direction == className.inward) {
23009 module.set.inward();
23010 }
23011 else {
23012 module.set.outward();
23013 }
23014 },
23015 looping: function() {
23016 module.debug('Transition set to loop');
23017 $module
23018 .addClass(className.looping)
23019 ;
23020 },
23021 hidden: function() {
23022 $module
23023 .addClass(className.transition)
23024 .addClass(className.hidden)
23025 ;
23026 },
23027 inward: function() {
23028 module.debug('Setting direction to inward');
23029 $module
23030 .removeClass(className.outward)
23031 .addClass(className.inward)
23032 ;
23033 },
23034 outward: function() {
23035 module.debug('Setting direction to outward');
23036 $module
23037 .removeClass(className.inward)
23038 .addClass(className.outward)
23039 ;
23040 },
23041 visible: function() {
23042 $module
23043 .addClass(className.transition)
23044 .addClass(className.visible)
23045 ;
23046 }
23047 },
23048
23049 start: {
23050 animation: function(animationClass) {
23051 animationClass = animationClass || module.get.animationClass();
23052 module.debug('Starting tween', animationClass);
23053 $module
23054 .addClass(animationClass)
23055 .one(animationEnd + '.complete' + eventNamespace, module.complete)
23056 ;
23057 if(settings.useFailSafe) {
23058 module.add.failSafe();
23059 }
23060 module.set.duration(settings.duration);
23061 settings.onStart.call(element);
23062 }
23063 },
23064
23065 save: {
23066 animation: function(animation) {
23067 if(!module.cache) {
23068 module.cache = {};
23069 }
23070 module.cache.animation = animation;
23071 },
23072 displayType: function(displayType) {
23073 if(displayType !== 'none') {
23074 $module.data(metadata.displayType, displayType);
23075 }
23076 },
23077 transitionExists: function(animation, exists) {
23078 $.fn.transition.exists[animation] = exists;
23079 module.verbose('Saving existence of transition', animation, exists);
23080 }
23081 },
23082
23083 restore: {
23084 conditions: function() {
23085 var
23086 animation = module.get.currentAnimation()
23087 ;
23088 if(animation) {
23089 $module
23090 .removeClass(animation)
23091 ;
23092 module.verbose('Removing animation class', module.cache);
23093 }
23094 module.remove.duration();
23095 }
23096 },
23097
23098 add: {
23099 failSafe: function() {
23100 var
23101 duration = module.get.duration()
23102 ;
23103 module.timer = setTimeout(function() {
23104 $module.triggerHandler(animationEnd);
23105 }, duration + settings.failSafeDelay);
23106 module.verbose('Adding fail safe timer', module.timer);
23107 }
23108 },
23109
23110 remove: {
23111 animating: function() {
23112 $module.removeClass(className.animating);
23113 },
23114 animationCallbacks: function() {
23115 module.remove.queueCallback();
23116 module.remove.completeCallback();
23117 },
23118 queueCallback: function() {
23119 $module.off('.queue' + eventNamespace);
23120 },
23121 completeCallback: function() {
23122 $module.off('.complete' + eventNamespace);
23123 },
23124 display: function() {
23125 $module.css('display', '');
23126 },
23127 direction: function() {
23128 $module
23129 .removeClass(className.inward)
23130 .removeClass(className.outward)
23131 ;
23132 },
23133 duration: function() {
23134 $module
23135 .css('animation-duration', '')
23136 ;
23137 },
23138 failSafe: function() {
23139 module.verbose('Removing fail safe timer', module.timer);
23140 if(module.timer) {
23141 clearTimeout(module.timer);
23142 }
23143 },
23144 hidden: function() {
23145 $module.removeClass(className.hidden);
23146 },
23147 visible: function() {
23148 $module.removeClass(className.visible);
23149 },
23150 looping: function() {
23151 module.debug('Transitions are no longer looping');
23152 if( module.is.looping() ) {
23153 module.reset();
23154 $module
23155 .removeClass(className.looping)
23156 ;
23157 }
23158 },
23159 transition: function() {
23160 $module
23161 .removeClass(className.transition)
23162 .removeClass(className.visible)
23163 .removeClass(className.hidden)
23164 ;
23165 }
23166 },
23167 get: {
23168 settings: function(animation, duration, onComplete) {
23169 // single settings object
23170 if(typeof animation == 'object') {
23171 return $.extend(true, {}, $.fn.transition.settings, animation);
23172 }
23173 // all arguments provided
23174 else if(typeof onComplete == 'function') {
23175 return $.extend({}, $.fn.transition.settings, {
23176 animation : animation,
23177 onComplete : onComplete,
23178 duration : duration
23179 });
23180 }
23181 // only duration provided
23182 else if(typeof duration == 'string' || typeof duration == 'number') {
23183 return $.extend({}, $.fn.transition.settings, {
23184 animation : animation,
23185 duration : duration
23186 });
23187 }
23188 // duration is actually settings object
23189 else if(typeof duration == 'object') {
23190 return $.extend({}, $.fn.transition.settings, duration, {
23191 animation : animation
23192 });
23193 }
23194 // duration is actually callback
23195 else if(typeof duration == 'function') {
23196 return $.extend({}, $.fn.transition.settings, {
23197 animation : animation,
23198 onComplete : duration
23199 });
23200 }
23201 // only animation provided
23202 else {
23203 return $.extend({}, $.fn.transition.settings, {
23204 animation : animation
23205 });
23206 }
23207 },
23208 animationClass: function(animation) {
23209 var
23210 animationClass = animation || settings.animation,
23211 directionClass = (module.can.transition() && !module.has.direction())
23212 ? module.get.direction() + ' '
23213 : ''
23214 ;
23215 return className.animating + ' '
23216 + className.transition + ' '
23217 + directionClass
23218 + animationClass
23219 ;
23220 },
23221 currentAnimation: function() {
23222 return (module.cache && module.cache.animation !== undefined)
23223 ? module.cache.animation
23224 : false
23225 ;
23226 },
23227 currentDirection: function() {
23228 return module.is.inward()
23229 ? className.inward
23230 : className.outward
23231 ;
23232 },
23233 direction: function() {
23234 return module.is.hidden() || !module.is.visible()
23235 ? className.inward
23236 : className.outward
23237 ;
23238 },
23239 animationDirection: function(animation) {
23240 var
23241 direction
23242 ;
23243 animation = animation || settings.animation;
23244 if(typeof animation === 'string') {
23245 animation = animation.split(' ');
23246 // search animation name for out/in class
23247 $.each(animation, function(index, word){
23248 if(word === className.inward) {
23249 direction = className.inward;
23250 }
23251 else if(word === className.outward) {
23252 direction = className.outward;
23253 }
23254 });
23255 }
23256 // return found direction
23257 if(direction) {
23258 return direction;
23259 }
23260 return false;
23261 },
23262 duration: function(duration) {
23263 duration = duration || settings.duration;
23264 if(duration === false) {
23265 duration = $module.css('animation-duration') || 0;
23266 }
23267 return (typeof duration === 'string')
23268 ? (duration.indexOf('ms') > -1)
23269 ? parseFloat(duration)
23270 : parseFloat(duration) * 1000
23271 : duration
23272 ;
23273 },
23274 displayType: function(shouldDetermine) {
23275 shouldDetermine = (shouldDetermine !== undefined)
23276 ? shouldDetermine
23277 : true
23278 ;
23279 if(settings.displayType) {
23280 return settings.displayType;
23281 }
23282 if(shouldDetermine && $module.data(metadata.displayType) === undefined) {
23283 var currentDisplay = $module.css('display');
23284 if(currentDisplay === '' || currentDisplay === 'none'){
23285 // create fake element to determine display state
23286 module.can.transition(true);
23287 } else {
23288 module.save.displayType(currentDisplay);
23289 }
23290 }
23291 return $module.data(metadata.displayType);
23292 },
23293 userStyle: function(style) {
23294 style = style || $module.attr('style') || '';
23295 return style.replace(/display.*?;/, '');
23296 },
23297 transitionExists: function(animation) {
23298 return $.fn.transition.exists[animation];
23299 },
23300 animationStartEvent: function() {
23301 var
23302 element = document.createElement('div'),
23303 animations = {
23304 'animation' :'animationstart',
23305 'OAnimation' :'oAnimationStart',
23306 'MozAnimation' :'mozAnimationStart',
23307 'WebkitAnimation' :'webkitAnimationStart'
23308 },
23309 animation
23310 ;
23311 for(animation in animations){
23312 if( element.style[animation] !== undefined ){
23313 return animations[animation];
23314 }
23315 }
23316 return false;
23317 },
23318 animationEndEvent: function() {
23319 var
23320 element = document.createElement('div'),
23321 animations = {
23322 'animation' :'animationend',
23323 'OAnimation' :'oAnimationEnd',
23324 'MozAnimation' :'mozAnimationEnd',
23325 'WebkitAnimation' :'webkitAnimationEnd'
23326 },
23327 animation
23328 ;
23329 for(animation in animations){
23330 if( element.style[animation] !== undefined ){
23331 return animations[animation];
23332 }
23333 }
23334 return false;
23335 }
23336
23337 },
23338
23339 can: {
23340 transition: function(forced) {
23341 var
23342 animation = settings.animation,
23343 transitionExists = module.get.transitionExists(animation),
23344 displayType = module.get.displayType(false),
23345 elementClass,
23346 tagName,
23347 $clone,
23348 currentAnimation,
23349 inAnimation,
23350 directionExists
23351 ;
23352 if( transitionExists === undefined || forced) {
23353 module.verbose('Determining whether animation exists');
23354 elementClass = $module.attr('class');
23355 tagName = $module.prop('tagName');
23356
23357 $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
23358 currentAnimation = $clone
23359 .addClass(animation)
23360 .removeClass(className.inward)
23361 .removeClass(className.outward)
23362 .addClass(className.animating)
23363 .addClass(className.transition)
23364 .css('animationName')
23365 ;
23366 inAnimation = $clone
23367 .addClass(className.inward)
23368 .css('animationName')
23369 ;
23370 if(!displayType) {
23371 displayType = $clone
23372 .attr('class', elementClass)
23373 .removeAttr('style')
23374 .removeClass(className.hidden)
23375 .removeClass(className.visible)
23376 .show()
23377 .css('display')
23378 ;
23379 module.verbose('Determining final display state', displayType);
23380 module.save.displayType(displayType);
23381 }
23382
23383 $clone.remove();
23384 if(currentAnimation != inAnimation) {
23385 module.debug('Direction exists for animation', animation);
23386 directionExists = true;
23387 }
23388 else if(currentAnimation == 'none' || !currentAnimation) {
23389 module.debug('No animation defined in css', animation);
23390 return;
23391 }
23392 else {
23393 module.debug('Static animation found', animation, displayType);
23394 directionExists = false;
23395 }
23396 module.save.transitionExists(animation, directionExists);
23397 }
23398 return (transitionExists !== undefined)
23399 ? transitionExists
23400 : directionExists
23401 ;
23402 },
23403 animate: function() {
23404 // can transition does not return a value if animation does not exist
23405 return (module.can.transition() !== undefined);
23406 }
23407 },
23408
23409 is: {
23410 animating: function() {
23411 return $module.hasClass(className.animating);
23412 },
23413 inward: function() {
23414 return $module.hasClass(className.inward);
23415 },
23416 outward: function() {
23417 return $module.hasClass(className.outward);
23418 },
23419 looping: function() {
23420 return $module.hasClass(className.looping);
23421 },
23422 occurring: function(animation) {
23423 animation = animation || settings.animation;
23424 animation = '.' + animation.replace(' ', '.');
23425 return ( $module.filter(animation).length > 0 );
23426 },
23427 visible: function() {
23428 return $module.is(':visible');
23429 },
23430 hidden: function() {
23431 return $module.css('visibility') === 'hidden';
23432 },
23433 supported: function() {
23434 return(animationEnd !== false);
23435 }
23436 },
23437
23438 hide: function() {
23439 module.verbose('Hiding element');
23440 if( module.is.animating() ) {
23441 module.reset();
23442 }
23443 element.blur(); // IE will trigger focus change if element is not blurred before hiding
23444 module.remove.display();
23445 module.remove.visible();
23446 if($.isFunction(settings.onBeforeHide)){
23447 settings.onBeforeHide.call(element,function(){
23448 module.hideNow();
23449 });
23450 } else {
23451 module.hideNow();
23452 }
23453
23454 },
23455
23456 hideNow: function() {
23457 module.set.hidden();
23458 module.force.hidden();
23459 settings.onHide.call(element);
23460 settings.onComplete.call(element);
23461 // module.repaint();
23462 },
23463
23464 show: function(display) {
23465 module.verbose('Showing element', display);
23466 if(module.force.visible()) {
23467 module.remove.hidden();
23468 module.set.visible();
23469 settings.onShow.call(element);
23470 settings.onComplete.call(element);
23471 // module.repaint();
23472 }
23473 },
23474
23475 toggle: function() {
23476 if( module.is.visible() ) {
23477 module.hide();
23478 }
23479 else {
23480 module.show();
23481 }
23482 },
23483
23484 stop: function() {
23485 module.debug('Stopping current animation');
23486 $module.triggerHandler(animationEnd);
23487 },
23488
23489 stopAll: function() {
23490 module.debug('Stopping all animation');
23491 module.remove.queueCallback();
23492 $module.triggerHandler(animationEnd);
23493 },
23494
23495 clear: {
23496 queue: function() {
23497 module.debug('Clearing animation queue');
23498 module.remove.queueCallback();
23499 }
23500 },
23501
23502 enable: function() {
23503 module.verbose('Starting animation');
23504 $module.removeClass(className.disabled);
23505 },
23506
23507 disable: function() {
23508 module.debug('Stopping animation');
23509 $module.addClass(className.disabled);
23510 },
23511
23512 setting: function(name, value) {
23513 module.debug('Changing setting', name, value);
23514 if( $.isPlainObject(name) ) {
23515 $.extend(true, settings, name);
23516 }
23517 else if(value !== undefined) {
23518 if($.isPlainObject(settings[name])) {
23519 $.extend(true, settings[name], value);
23520 }
23521 else {
23522 settings[name] = value;
23523 }
23524 }
23525 else {
23526 return settings[name];
23527 }
23528 },
23529 internal: function(name, value) {
23530 if( $.isPlainObject(name) ) {
23531 $.extend(true, module, name);
23532 }
23533 else if(value !== undefined) {
23534 module[name] = value;
23535 }
23536 else {
23537 return module[name];
23538 }
23539 },
23540 debug: function() {
23541 if(!settings.silent && settings.debug) {
23542 if(settings.performance) {
23543 module.performance.log(arguments);
23544 }
23545 else {
23546 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
23547 module.debug.apply(console, arguments);
23548 }
23549 }
23550 },
23551 verbose: function() {
23552 if(!settings.silent && settings.verbose && settings.debug) {
23553 if(settings.performance) {
23554 module.performance.log(arguments);
23555 }
23556 else {
23557 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
23558 module.verbose.apply(console, arguments);
23559 }
23560 }
23561 },
23562 error: function() {
23563 if(!settings.silent) {
23564 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
23565 module.error.apply(console, arguments);
23566 }
23567 },
23568 performance: {
23569 log: function(message) {
23570 var
23571 currentTime,
23572 executionTime,
23573 previousTime
23574 ;
23575 if(settings.performance) {
23576 currentTime = new Date().getTime();
23577 previousTime = time || currentTime;
23578 executionTime = currentTime - previousTime;
23579 time = currentTime;
23580 performance.push({
23581 'Name' : message[0],
23582 'Arguments' : [].slice.call(message, 1) || '',
23583 'Element' : element,
23584 'Execution Time' : executionTime
23585 });
23586 }
23587 clearTimeout(module.performance.timer);
23588 module.performance.timer = setTimeout(module.performance.display, 500);
23589 },
23590 display: function() {
23591 var
23592 title = settings.name + ':',
23593 totalTime = 0
23594 ;
23595 time = false;
23596 clearTimeout(module.performance.timer);
23597 $.each(performance, function(index, data) {
23598 totalTime += data['Execution Time'];
23599 });
23600 title += ' ' + totalTime + 'ms';
23601 if(moduleSelector) {
23602 title += ' \'' + moduleSelector + '\'';
23603 }
23604 if($allModules.length > 1) {
23605 title += ' ' + '(' + $allModules.length + ')';
23606 }
23607 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
23608 console.groupCollapsed(title);
23609 if(console.table) {
23610 console.table(performance);
23611 }
23612 else {
23613 $.each(performance, function(index, data) {
23614 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
23615 });
23616 }
23617 console.groupEnd();
23618 }
23619 performance = [];
23620 }
23621 },
23622 // modified for transition to return invoke success
23623 invoke: function(query, passedArguments, context) {
23624 var
23625 object = instance,
23626 maxDepth,
23627 found,
23628 response
23629 ;
23630 passedArguments = passedArguments || queryArguments;
23631 context = element || context;
23632 if(typeof query == 'string' && object !== undefined) {
23633 query = query.split(/[\. ]/);
23634 maxDepth = query.length - 1;
23635 $.each(query, function(depth, value) {
23636 var camelCaseValue = (depth != maxDepth)
23637 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
23638 : query
23639 ;
23640 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
23641 object = object[camelCaseValue];
23642 }
23643 else if( object[camelCaseValue] !== undefined ) {
23644 found = object[camelCaseValue];
23645 return false;
23646 }
23647 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
23648 object = object[value];
23649 }
23650 else if( object[value] !== undefined ) {
23651 found = object[value];
23652 return false;
23653 }
23654 else {
23655 return false;
23656 }
23657 });
23658 }
23659 if ( $.isFunction( found ) ) {
23660 response = found.apply(context, passedArguments);
23661 }
23662 else if(found !== undefined) {
23663 response = found;
23664 }
23665
23666 if(Array.isArray(returnedValue)) {
23667 returnedValue.push(response);
23668 }
23669 else if(returnedValue !== undefined) {
23670 returnedValue = [returnedValue, response];
23671 }
23672 else if(response !== undefined) {
23673 returnedValue = response;
23674 }
23675 return (found !== undefined)
23676 ? found
23677 : false
23678 ;
23679 }
23680 };
23681 module.initialize();
23682 })
23683 ;
23684 return (returnedValue !== undefined)
23685 ? returnedValue
23686 : this
23687 ;
23688};
23689
23690// Records if CSS transition is available
23691$.fn.transition.exists = {};
23692
23693$.fn.transition.settings = {
23694
23695 // module info
23696 name : 'Transition',
23697
23698 // hide all output from this component regardless of other settings
23699 silent : false,
23700
23701 // debug content outputted to console
23702 debug : false,
23703
23704 // verbose debug output
23705 verbose : false,
23706
23707 // performance data output
23708 performance : true,
23709
23710 // event namespace
23711 namespace : 'transition',
23712
23713 // delay between animations in group
23714 interval : 0,
23715
23716 // whether group animations should be reversed
23717 reverse : 'auto',
23718
23719 // animation callback event
23720 onStart : function() {},
23721 onComplete : function() {},
23722 onShow : function() {},
23723 onHide : function() {},
23724
23725 // whether timeout should be used to ensure callback fires in cases animationend does not
23726 useFailSafe : true,
23727
23728 // delay in ms for fail safe
23729 failSafeDelay : 100,
23730
23731 // whether EXACT animation can occur twice in a row
23732 allowRepeats : false,
23733
23734 // Override final display type on visible
23735 displayType : false,
23736
23737 // animation duration
23738 animation : 'fade',
23739 duration : false,
23740
23741 // new animations will occur after previous ones
23742 queue : true,
23743
23744// whether initially inline hidden objects should be skipped for transition
23745 skipInlineHidden: false,
23746
23747 metadata : {
23748 displayType: 'display'
23749 },
23750
23751 className : {
23752 animating : 'animating',
23753 disabled : 'disabled',
23754 hidden : 'hidden',
23755 inward : 'in',
23756 loading : 'loading',
23757 looping : 'looping',
23758 outward : 'out',
23759 transition : 'transition',
23760 visible : 'visible'
23761 },
23762
23763 // possible errors
23764 error: {
23765 noAnimation : 'Element is no longer attached to DOM. Unable to animate. Use silent setting to surpress this warning in production.',
23766 repeated : 'That animation is already occurring, cancelling repeated animation',
23767 method : 'The method you called is not defined',
23768 support : 'This browser does not support CSS animations'
23769 }
23770
23771};
23772
23773
23774})( jQuery, window, document );
23775
23776/*!
23777 * # Semantic UI 2.7.2 - API
23778 * http://github.com/semantic-org/semantic-ui/
23779 *
23780 *
23781 * Released under the MIT license
23782 * http://opensource.org/licenses/MIT
23783 *
23784 */
23785
23786;(function ($, window, document, undefined) {
23787
23788'use strict';
23789
23790$.isWindow = $.isWindow || function(obj) {
23791 return obj != null && obj === obj.window;
23792};
23793
23794var
23795 window = (typeof window != 'undefined' && window.Math == Math)
23796 ? window
23797 : (typeof self != 'undefined' && self.Math == Math)
23798 ? self
23799 : Function('return this')()
23800;
23801
23802$.api = $.fn.api = function(parameters) {
23803
23804 var
23805 // use window context if none specified
23806 $allModules = $.isFunction(this)
23807 ? $(window)
23808 : $(this),
23809 moduleSelector = $allModules.selector || '',
23810 time = new Date().getTime(),
23811 performance = [],
23812
23813 query = arguments[0],
23814 methodInvoked = (typeof query == 'string'),
23815 queryArguments = [].slice.call(arguments, 1),
23816
23817 returnedValue
23818 ;
23819
23820 $allModules
23821 .each(function() {
23822 var
23823 settings = ( $.isPlainObject(parameters) )
23824 ? $.extend(true, {}, $.fn.api.settings, parameters)
23825 : $.extend({}, $.fn.api.settings),
23826
23827 // internal aliases
23828 namespace = settings.namespace,
23829 metadata = settings.metadata,
23830 selector = settings.selector,
23831 error = settings.error,
23832 className = settings.className,
23833
23834 // define namespaces for modules
23835 eventNamespace = '.' + namespace,
23836 moduleNamespace = 'module-' + namespace,
23837
23838 // element that creates request
23839 $module = $(this),
23840 $form = $module.closest(selector.form),
23841
23842 // context used for state
23843 $context = (settings.stateContext)
23844 ? $(settings.stateContext)
23845 : $module,
23846
23847 // request details
23848 ajaxSettings,
23849 requestSettings,
23850 url,
23851 data,
23852 requestStartTime,
23853
23854 // standard module
23855 element = this,
23856 context = $context[0],
23857 instance = $module.data(moduleNamespace),
23858 module
23859 ;
23860
23861 module = {
23862
23863 initialize: function() {
23864 if(!methodInvoked) {
23865 module.bind.events();
23866 }
23867 module.instantiate();
23868 },
23869
23870 instantiate: function() {
23871 module.verbose('Storing instance of module', module);
23872 instance = module;
23873 $module
23874 .data(moduleNamespace, instance)
23875 ;
23876 },
23877
23878 destroy: function() {
23879 module.verbose('Destroying previous module for', element);
23880 $module
23881 .removeData(moduleNamespace)
23882 .off(eventNamespace)
23883 ;
23884 },
23885
23886 bind: {
23887 events: function() {
23888 var
23889 triggerEvent = module.get.event()
23890 ;
23891 if( triggerEvent ) {
23892 module.verbose('Attaching API events to element', triggerEvent);
23893 $module
23894 .on(triggerEvent + eventNamespace, module.event.trigger)
23895 ;
23896 }
23897 else if(settings.on == 'now') {
23898 module.debug('Querying API endpoint immediately');
23899 module.query();
23900 }
23901 }
23902 },
23903
23904 decode: {
23905 json: function(response) {
23906 if(response !== undefined && typeof response == 'string') {
23907 try {
23908 response = JSON.parse(response);
23909 }
23910 catch(e) {
23911 // isnt json string
23912 }
23913 }
23914 return response;
23915 }
23916 },
23917
23918 read: {
23919 cachedResponse: function(url) {
23920 var
23921 response
23922 ;
23923 if(window.Storage === undefined) {
23924 module.error(error.noStorage);
23925 return;
23926 }
23927 response = sessionStorage.getItem(url);
23928 module.debug('Using cached response', url, response);
23929 response = module.decode.json(response);
23930 return response;
23931 }
23932 },
23933 write: {
23934 cachedResponse: function(url, response) {
23935 if(response && response === '') {
23936 module.debug('Response empty, not caching', response);
23937 return;
23938 }
23939 if(window.Storage === undefined) {
23940 module.error(error.noStorage);
23941 return;
23942 }
23943 if( $.isPlainObject(response) ) {
23944 response = JSON.stringify(response);
23945 }
23946 sessionStorage.setItem(url, response);
23947 module.verbose('Storing cached response for url', url, response);
23948 }
23949 },
23950
23951 query: function() {
23952
23953 if(module.is.disabled()) {
23954 module.debug('Element is disabled API request aborted');
23955 return;
23956 }
23957
23958 if(module.is.loading()) {
23959 if(settings.interruptRequests) {
23960 module.debug('Interrupting previous request');
23961 module.abort();
23962 }
23963 else {
23964 module.debug('Cancelling request, previous request is still pending');
23965 return;
23966 }
23967 }
23968
23969 // pass element metadata to url (value, text)
23970 if(settings.defaultData) {
23971 $.extend(true, settings.urlData, module.get.defaultData());
23972 }
23973
23974 // Add form content
23975 if(settings.serializeForm) {
23976 settings.data = module.add.formData(settings.data);
23977 }
23978
23979 // call beforesend and get any settings changes
23980 requestSettings = module.get.settings();
23981
23982 // check if before send cancelled request
23983 if(requestSettings === false) {
23984 module.cancelled = true;
23985 module.error(error.beforeSend);
23986 return;
23987 }
23988 else {
23989 module.cancelled = false;
23990 }
23991
23992 // get url
23993 url = module.get.templatedURL();
23994
23995 if(!url && !module.is.mocked()) {
23996 module.error(error.missingURL);
23997 return;
23998 }
23999
24000 // replace variables
24001 url = module.add.urlData( url );
24002 // missing url parameters
24003 if( !url && !module.is.mocked()) {
24004 return;
24005 }
24006
24007 requestSettings.url = settings.base + url;
24008
24009 // look for jQuery ajax parameters in settings
24010 ajaxSettings = $.extend(true, {}, settings, {
24011 type : settings.method || settings.type,
24012 data : data,
24013 url : settings.base + url,
24014 beforeSend : settings.beforeXHR,
24015 success : function() {},
24016 failure : function() {},
24017 complete : function() {}
24018 });
24019
24020 module.debug('Querying URL', ajaxSettings.url);
24021 module.verbose('Using AJAX settings', ajaxSettings);
24022 if(settings.cache === 'local' && module.read.cachedResponse(url)) {
24023 module.debug('Response returned from local cache');
24024 module.request = module.create.request();
24025 module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
24026 return;
24027 }
24028
24029 if( !settings.throttle ) {
24030 module.debug('Sending request', data, ajaxSettings.method);
24031 module.send.request();
24032 }
24033 else {
24034 if(!settings.throttleFirstRequest && !module.timer) {
24035 module.debug('Sending request', data, ajaxSettings.method);
24036 module.send.request();
24037 module.timer = setTimeout(function(){}, settings.throttle);
24038 }
24039 else {
24040 module.debug('Throttling request', settings.throttle);
24041 clearTimeout(module.timer);
24042 module.timer = setTimeout(function() {
24043 if(module.timer) {
24044 delete module.timer;
24045 }
24046 module.debug('Sending throttled request', data, ajaxSettings.method);
24047 module.send.request();
24048 }, settings.throttle);
24049 }
24050 }
24051
24052 },
24053
24054 should: {
24055 removeError: function() {
24056 return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
24057 }
24058 },
24059
24060 is: {
24061 disabled: function() {
24062 return ($module.filter(selector.disabled).length > 0);
24063 },
24064 expectingJSON: function() {
24065 return settings.dataType === 'json' || settings.dataType === 'jsonp';
24066 },
24067 form: function() {
24068 return $module.is('form') || $context.is('form');
24069 },
24070 mocked: function() {
24071 return (settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync);
24072 },
24073 input: function() {
24074 return $module.is('input');
24075 },
24076 loading: function() {
24077 return (module.request)
24078 ? (module.request.state() == 'pending')
24079 : false
24080 ;
24081 },
24082 abortedRequest: function(xhr) {
24083 if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
24084 module.verbose('XHR request determined to be aborted');
24085 return true;
24086 }
24087 else {
24088 module.verbose('XHR request was not aborted');
24089 return false;
24090 }
24091 },
24092 validResponse: function(response) {
24093 if( (!module.is.expectingJSON()) || !$.isFunction(settings.successTest) ) {
24094 module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
24095 return true;
24096 }
24097 module.debug('Checking JSON returned success', settings.successTest, response);
24098 if( settings.successTest(response) ) {
24099 module.debug('Response passed success test', response);
24100 return true;
24101 }
24102 else {
24103 module.debug('Response failed success test', response);
24104 return false;
24105 }
24106 }
24107 },
24108
24109 was: {
24110 cancelled: function() {
24111 return (module.cancelled || false);
24112 },
24113 succesful: function() {
24114 return (module.request && module.request.state() == 'resolved');
24115 },
24116 failure: function() {
24117 return (module.request && module.request.state() == 'rejected');
24118 },
24119 complete: function() {
24120 return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
24121 }
24122 },
24123
24124 add: {
24125 urlData: function(url, urlData) {
24126 var
24127 requiredVariables,
24128 optionalVariables
24129 ;
24130 if(url) {
24131 requiredVariables = url.match(settings.regExp.required);
24132 optionalVariables = url.match(settings.regExp.optional);
24133 urlData = urlData || settings.urlData;
24134 if(requiredVariables) {
24135 module.debug('Looking for required URL variables', requiredVariables);
24136 $.each(requiredVariables, function(index, templatedString) {
24137 var
24138 // allow legacy {$var} style
24139 variable = (templatedString.indexOf('$') !== -1)
24140 ? templatedString.substr(2, templatedString.length - 3)
24141 : templatedString.substr(1, templatedString.length - 2),
24142 value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
24143 ? urlData[variable]
24144 : ($module.data(variable) !== undefined)
24145 ? $module.data(variable)
24146 : ($context.data(variable) !== undefined)
24147 ? $context.data(variable)
24148 : urlData[variable]
24149 ;
24150 // remove value
24151 if(value === undefined) {
24152 module.error(error.requiredParameter, variable, url);
24153 url = false;
24154 return false;
24155 }
24156 else {
24157 module.verbose('Found required variable', variable, value);
24158 value = (settings.encodeParameters)
24159 ? module.get.urlEncodedValue(value)
24160 : value
24161 ;
24162 url = url.replace(templatedString, value);
24163 }
24164 });
24165 }
24166 if(optionalVariables) {
24167 module.debug('Looking for optional URL variables', requiredVariables);
24168 $.each(optionalVariables, function(index, templatedString) {
24169 var
24170 // allow legacy {/$var} style
24171 variable = (templatedString.indexOf('$') !== -1)
24172 ? templatedString.substr(3, templatedString.length - 4)
24173 : templatedString.substr(2, templatedString.length - 3),
24174 value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
24175 ? urlData[variable]
24176 : ($module.data(variable) !== undefined)
24177 ? $module.data(variable)
24178 : ($context.data(variable) !== undefined)
24179 ? $context.data(variable)
24180 : urlData[variable]
24181 ;
24182 // optional replacement
24183 if(value !== undefined) {
24184 module.verbose('Optional variable Found', variable, value);
24185 url = url.replace(templatedString, value);
24186 }
24187 else {
24188 module.verbose('Optional variable not found', variable);
24189 // remove preceding slash if set
24190 if(url.indexOf('/' + templatedString) !== -1) {
24191 url = url.replace('/' + templatedString, '');
24192 }
24193 else {
24194 url = url.replace(templatedString, '');
24195 }
24196 }
24197 });
24198 }
24199 }
24200 return url;
24201 },
24202 formData: function(data) {
24203 var
24204 canSerialize = ($.fn.serializeObject !== undefined),
24205 formData = (canSerialize)
24206 ? $form.serializeObject()
24207 : $form.serialize(),
24208 hasOtherData
24209 ;
24210 data = data || settings.data;
24211 hasOtherData = $.isPlainObject(data);
24212
24213 if(hasOtherData) {
24214 if(canSerialize) {
24215 module.debug('Extending existing data with form data', data, formData);
24216 data = $.extend(true, {}, data, formData);
24217 }
24218 else {
24219 module.error(error.missingSerialize);
24220 module.debug('Cant extend data. Replacing data with form data', data, formData);
24221 data = formData;
24222 }
24223 }
24224 else {
24225 module.debug('Adding form data', formData);
24226 data = formData;
24227 }
24228 return data;
24229 }
24230 },
24231
24232 send: {
24233 request: function() {
24234 module.set.loading();
24235 module.request = module.create.request();
24236 if( module.is.mocked() ) {
24237 module.mockedXHR = module.create.mockedXHR();
24238 }
24239 else {
24240 module.xhr = module.create.xhr();
24241 }
24242 settings.onRequest.call(context, module.request, module.xhr);
24243 }
24244 },
24245
24246 event: {
24247 trigger: function(event) {
24248 module.query();
24249 if(event.type == 'submit' || event.type == 'click') {
24250 event.preventDefault();
24251 }
24252 },
24253 xhr: {
24254 always: function() {
24255 // nothing special
24256 },
24257 done: function(response, textStatus, xhr) {
24258 var
24259 context = this,
24260 elapsedTime = (new Date().getTime() - requestStartTime),
24261 timeLeft = (settings.loadingDuration - elapsedTime),
24262 translatedResponse = ( $.isFunction(settings.onResponse) )
24263 ? module.is.expectingJSON() && !settings.rawResponse
24264 ? settings.onResponse.call(context, $.extend(true, {}, response))
24265 : settings.onResponse.call(context, response)
24266 : false
24267 ;
24268 timeLeft = (timeLeft > 0)
24269 ? timeLeft
24270 : 0
24271 ;
24272 if(translatedResponse) {
24273 module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
24274 response = translatedResponse;
24275 }
24276 if(timeLeft > 0) {
24277 module.debug('Response completed early delaying state change by', timeLeft);
24278 }
24279 setTimeout(function() {
24280 if( module.is.validResponse(response) ) {
24281 module.request.resolveWith(context, [response, xhr]);
24282 }
24283 else {
24284 module.request.rejectWith(context, [xhr, 'invalid']);
24285 }
24286 }, timeLeft);
24287 },
24288 fail: function(xhr, status, httpMessage) {
24289 var
24290 context = this,
24291 elapsedTime = (new Date().getTime() - requestStartTime),
24292 timeLeft = (settings.loadingDuration - elapsedTime)
24293 ;
24294 timeLeft = (timeLeft > 0)
24295 ? timeLeft
24296 : 0
24297 ;
24298 if(timeLeft > 0) {
24299 module.debug('Response completed early delaying state change by', timeLeft);
24300 }
24301 setTimeout(function() {
24302 if( module.is.abortedRequest(xhr) ) {
24303 module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
24304 }
24305 else {
24306 module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
24307 }
24308 }, timeLeft);
24309 }
24310 },
24311 request: {
24312 done: function(response, xhr) {
24313 module.debug('Successful API Response', response);
24314 if(settings.cache === 'local' && url) {
24315 module.write.cachedResponse(url, response);
24316 module.debug('Saving server response locally', module.cache);
24317 }
24318 settings.onSuccess.call(context, response, $module, xhr);
24319 },
24320 complete: function(firstParameter, secondParameter) {
24321 var
24322 xhr,
24323 response
24324 ;
24325 // have to guess callback parameters based on request success
24326 if( module.was.succesful() ) {
24327 response = firstParameter;
24328 xhr = secondParameter;
24329 }
24330 else {
24331 xhr = firstParameter;
24332 response = module.get.responseFromXHR(xhr);
24333 }
24334 module.remove.loading();
24335 settings.onComplete.call(context, response, $module, xhr);
24336 },
24337 fail: function(xhr, status, httpMessage) {
24338 var
24339 // pull response from xhr if available
24340 response = module.get.responseFromXHR(xhr),
24341 errorMessage = module.get.errorFromRequest(response, status, httpMessage)
24342 ;
24343 if(status == 'aborted') {
24344 module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
24345 settings.onAbort.call(context, status, $module, xhr);
24346 return true;
24347 }
24348 else if(status == 'invalid') {
24349 module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
24350 }
24351 else if(status == 'error') {
24352 if(xhr !== undefined) {
24353 module.debug('XHR produced a server error', status, httpMessage);
24354 // make sure we have an error to display to console
24355 if( (xhr.status < 200 || xhr.status >= 300) && httpMessage !== undefined && httpMessage !== '') {
24356 module.error(error.statusMessage + httpMessage, ajaxSettings.url);
24357 }
24358 settings.onError.call(context, errorMessage, $module, xhr);
24359 }
24360 }
24361
24362 if(settings.errorDuration && status !== 'aborted') {
24363 module.debug('Adding error state');
24364 module.set.error();
24365 if( module.should.removeError() ) {
24366 setTimeout(module.remove.error, settings.errorDuration);
24367 }
24368 }
24369 module.debug('API Request failed', errorMessage, xhr);
24370 settings.onFailure.call(context, response, $module, xhr);
24371 }
24372 }
24373 },
24374
24375 create: {
24376
24377 request: function() {
24378 // api request promise
24379 return $.Deferred()
24380 .always(module.event.request.complete)
24381 .done(module.event.request.done)
24382 .fail(module.event.request.fail)
24383 ;
24384 },
24385
24386 mockedXHR: function () {
24387 var
24388 // xhr does not simulate these properties of xhr but must return them
24389 textStatus = false,
24390 status = false,
24391 httpMessage = false,
24392 responder = settings.mockResponse || settings.response,
24393 asyncResponder = settings.mockResponseAsync || settings.responseAsync,
24394 asyncCallback,
24395 response,
24396 mockedXHR
24397 ;
24398
24399 mockedXHR = $.Deferred()
24400 .always(module.event.xhr.complete)
24401 .done(module.event.xhr.done)
24402 .fail(module.event.xhr.fail)
24403 ;
24404
24405 if(responder) {
24406 if( $.isFunction(responder) ) {
24407 module.debug('Using specified synchronous callback', responder);
24408 response = responder.call(context, requestSettings);
24409 }
24410 else {
24411 module.debug('Using settings specified response', responder);
24412 response = responder;
24413 }
24414 // simulating response
24415 mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
24416 }
24417 else if( $.isFunction(asyncResponder) ) {
24418 asyncCallback = function(response) {
24419 module.debug('Async callback returned response', response);
24420
24421 if(response) {
24422 mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
24423 }
24424 else {
24425 mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
24426 }
24427 };
24428 module.debug('Using specified async response callback', asyncResponder);
24429 asyncResponder.call(context, requestSettings, asyncCallback);
24430 }
24431 return mockedXHR;
24432 },
24433
24434 xhr: function() {
24435 var
24436 xhr
24437 ;
24438 // ajax request promise
24439 xhr = $.ajax(ajaxSettings)
24440 .always(module.event.xhr.always)
24441 .done(module.event.xhr.done)
24442 .fail(module.event.xhr.fail)
24443 ;
24444 module.verbose('Created server request', xhr, ajaxSettings);
24445 return xhr;
24446 }
24447 },
24448
24449 set: {
24450 error: function() {
24451 module.verbose('Adding error state to element', $context);
24452 $context.addClass(className.error);
24453 },
24454 loading: function() {
24455 module.verbose('Adding loading state to element', $context);
24456 $context.addClass(className.loading);
24457 requestStartTime = new Date().getTime();
24458 }
24459 },
24460
24461 remove: {
24462 error: function() {
24463 module.verbose('Removing error state from element', $context);
24464 $context.removeClass(className.error);
24465 },
24466 loading: function() {
24467 module.verbose('Removing loading state from element', $context);
24468 $context.removeClass(className.loading);
24469 }
24470 },
24471
24472 get: {
24473 responseFromXHR: function(xhr) {
24474 return $.isPlainObject(xhr)
24475 ? (module.is.expectingJSON())
24476 ? module.decode.json(xhr.responseText)
24477 : xhr.responseText
24478 : false
24479 ;
24480 },
24481 errorFromRequest: function(response, status, httpMessage) {
24482 return ($.isPlainObject(response) && response.error !== undefined)
24483 ? response.error // use json error message
24484 : (settings.error[status] !== undefined) // use server error message
24485 ? settings.error[status]
24486 : httpMessage
24487 ;
24488 },
24489 request: function() {
24490 return module.request || false;
24491 },
24492 xhr: function() {
24493 return module.xhr || false;
24494 },
24495 settings: function() {
24496 var
24497 runSettings
24498 ;
24499 runSettings = settings.beforeSend.call(context, settings);
24500 if(runSettings) {
24501 if(runSettings.success !== undefined) {
24502 module.debug('Legacy success callback detected', runSettings);
24503 module.error(error.legacyParameters, runSettings.success);
24504 runSettings.onSuccess = runSettings.success;
24505 }
24506 if(runSettings.failure !== undefined) {
24507 module.debug('Legacy failure callback detected', runSettings);
24508 module.error(error.legacyParameters, runSettings.failure);
24509 runSettings.onFailure = runSettings.failure;
24510 }
24511 if(runSettings.complete !== undefined) {
24512 module.debug('Legacy complete callback detected', runSettings);
24513 module.error(error.legacyParameters, runSettings.complete);
24514 runSettings.onComplete = runSettings.complete;
24515 }
24516 }
24517 if(runSettings === undefined) {
24518 module.error(error.noReturnedValue);
24519 }
24520 if(runSettings === false) {
24521 return runSettings;
24522 }
24523 return (runSettings !== undefined)
24524 ? $.extend(true, {}, runSettings)
24525 : $.extend(true, {}, settings)
24526 ;
24527 },
24528 urlEncodedValue: function(value) {
24529 var
24530 decodedValue = window.decodeURIComponent(value),
24531 encodedValue = window.encodeURIComponent(value),
24532 alreadyEncoded = (decodedValue !== value)
24533 ;
24534 if(alreadyEncoded) {
24535 module.debug('URL value is already encoded, avoiding double encoding', value);
24536 return value;
24537 }
24538 module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
24539 return encodedValue;
24540 },
24541 defaultData: function() {
24542 var
24543 data = {}
24544 ;
24545 if( !$.isWindow(element) ) {
24546 if( module.is.input() ) {
24547 data.value = $module.val();
24548 }
24549 else if( module.is.form() ) {
24550
24551 }
24552 else {
24553 data.text = $module.text();
24554 }
24555 }
24556 return data;
24557 },
24558 event: function() {
24559 if( $.isWindow(element) || settings.on == 'now' ) {
24560 module.debug('API called without element, no events attached');
24561 return false;
24562 }
24563 else if(settings.on == 'auto') {
24564 if( $module.is('input') ) {
24565 return (element.oninput !== undefined)
24566 ? 'input'
24567 : (element.onpropertychange !== undefined)
24568 ? 'propertychange'
24569 : 'keyup'
24570 ;
24571 }
24572 else if( $module.is('form') ) {
24573 return 'submit';
24574 }
24575 else {
24576 return 'click';
24577 }
24578 }
24579 else {
24580 return settings.on;
24581 }
24582 },
24583 templatedURL: function(action) {
24584 action = action || $module.data(metadata.action) || settings.action || false;
24585 url = $module.data(metadata.url) || settings.url || false;
24586 if(url) {
24587 module.debug('Using specified url', url);
24588 return url;
24589 }
24590 if(action) {
24591 module.debug('Looking up url for action', action, settings.api);
24592 if(settings.api[action] === undefined && !module.is.mocked()) {
24593 module.error(error.missingAction, settings.action, settings.api);
24594 return;
24595 }
24596 url = settings.api[action];
24597 }
24598 else if( module.is.form() ) {
24599 url = $module.attr('action') || $context.attr('action') || false;
24600 module.debug('No url or action specified, defaulting to form action', url);
24601 }
24602 return url;
24603 }
24604 },
24605
24606 abort: function() {
24607 var
24608 xhr = module.get.xhr()
24609 ;
24610 if( xhr && xhr.state() !== 'resolved') {
24611 module.debug('Cancelling API request');
24612 xhr.abort();
24613 }
24614 },
24615
24616 // reset state
24617 reset: function() {
24618 module.remove.error();
24619 module.remove.loading();
24620 },
24621
24622 setting: function(name, value) {
24623 module.debug('Changing setting', name, value);
24624 if( $.isPlainObject(name) ) {
24625 $.extend(true, settings, name);
24626 }
24627 else if(value !== undefined) {
24628 if($.isPlainObject(settings[name])) {
24629 $.extend(true, settings[name], value);
24630 }
24631 else {
24632 settings[name] = value;
24633 }
24634 }
24635 else {
24636 return settings[name];
24637 }
24638 },
24639 internal: function(name, value) {
24640 if( $.isPlainObject(name) ) {
24641 $.extend(true, module, name);
24642 }
24643 else if(value !== undefined) {
24644 module[name] = value;
24645 }
24646 else {
24647 return module[name];
24648 }
24649 },
24650 debug: function() {
24651 if(!settings.silent && settings.debug) {
24652 if(settings.performance) {
24653 module.performance.log(arguments);
24654 }
24655 else {
24656 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
24657 module.debug.apply(console, arguments);
24658 }
24659 }
24660 },
24661 verbose: function() {
24662 if(!settings.silent && settings.verbose && settings.debug) {
24663 if(settings.performance) {
24664 module.performance.log(arguments);
24665 }
24666 else {
24667 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
24668 module.verbose.apply(console, arguments);
24669 }
24670 }
24671 },
24672 error: function() {
24673 if(!settings.silent) {
24674 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
24675 module.error.apply(console, arguments);
24676 }
24677 },
24678 performance: {
24679 log: function(message) {
24680 var
24681 currentTime,
24682 executionTime,
24683 previousTime
24684 ;
24685 if(settings.performance) {
24686 currentTime = new Date().getTime();
24687 previousTime = time || currentTime;
24688 executionTime = currentTime - previousTime;
24689 time = currentTime;
24690 performance.push({
24691 'Name' : message[0],
24692 'Arguments' : [].slice.call(message, 1) || '',
24693 //'Element' : element,
24694 'Execution Time' : executionTime
24695 });
24696 }
24697 clearTimeout(module.performance.timer);
24698 module.performance.timer = setTimeout(module.performance.display, 500);
24699 },
24700 display: function() {
24701 var
24702 title = settings.name + ':',
24703 totalTime = 0
24704 ;
24705 time = false;
24706 clearTimeout(module.performance.timer);
24707 $.each(performance, function(index, data) {
24708 totalTime += data['Execution Time'];
24709 });
24710 title += ' ' + totalTime + 'ms';
24711 if(moduleSelector) {
24712 title += ' \'' + moduleSelector + '\'';
24713 }
24714 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
24715 console.groupCollapsed(title);
24716 if(console.table) {
24717 console.table(performance);
24718 }
24719 else {
24720 $.each(performance, function(index, data) {
24721 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
24722 });
24723 }
24724 console.groupEnd();
24725 }
24726 performance = [];
24727 }
24728 },
24729 invoke: function(query, passedArguments, context) {
24730 var
24731 object = instance,
24732 maxDepth,
24733 found,
24734 response
24735 ;
24736 passedArguments = passedArguments || queryArguments;
24737 context = element || context;
24738 if(typeof query == 'string' && object !== undefined) {
24739 query = query.split(/[\. ]/);
24740 maxDepth = query.length - 1;
24741 $.each(query, function(depth, value) {
24742 var camelCaseValue = (depth != maxDepth)
24743 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
24744 : query
24745 ;
24746 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
24747 object = object[camelCaseValue];
24748 }
24749 else if( object[camelCaseValue] !== undefined ) {
24750 found = object[camelCaseValue];
24751 return false;
24752 }
24753 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
24754 object = object[value];
24755 }
24756 else if( object[value] !== undefined ) {
24757 found = object[value];
24758 return false;
24759 }
24760 else {
24761 module.error(error.method, query);
24762 return false;
24763 }
24764 });
24765 }
24766 if ( $.isFunction( found ) ) {
24767 response = found.apply(context, passedArguments);
24768 }
24769 else if(found !== undefined) {
24770 response = found;
24771 }
24772 if(Array.isArray(returnedValue)) {
24773 returnedValue.push(response);
24774 }
24775 else if(returnedValue !== undefined) {
24776 returnedValue = [returnedValue, response];
24777 }
24778 else if(response !== undefined) {
24779 returnedValue = response;
24780 }
24781 return found;
24782 }
24783 };
24784
24785 if(methodInvoked) {
24786 if(instance === undefined) {
24787 module.initialize();
24788 }
24789 module.invoke(query);
24790 }
24791 else {
24792 if(instance !== undefined) {
24793 instance.invoke('destroy');
24794 }
24795 module.initialize();
24796 }
24797 })
24798 ;
24799
24800 return (returnedValue !== undefined)
24801 ? returnedValue
24802 : this
24803 ;
24804};
24805
24806$.api.settings = {
24807
24808 name : 'API',
24809 namespace : 'api',
24810
24811 debug : false,
24812 verbose : false,
24813 performance : true,
24814
24815 // object containing all templates endpoints
24816 api : {},
24817
24818 // whether to cache responses
24819 cache : true,
24820
24821 // whether new requests should abort previous requests
24822 interruptRequests : true,
24823
24824 // event binding
24825 on : 'auto',
24826
24827 // context for applying state classes
24828 stateContext : false,
24829
24830 // duration for loading state
24831 loadingDuration : 0,
24832
24833 // whether to hide errors after a period of time
24834 hideError : 'auto',
24835
24836 // duration for error state
24837 errorDuration : 2000,
24838
24839 // whether parameters should be encoded with encodeURIComponent
24840 encodeParameters : true,
24841
24842 // API action to use
24843 action : false,
24844
24845 // templated URL to use
24846 url : false,
24847
24848 // base URL to apply to all endpoints
24849 base : '',
24850
24851 // data that will
24852 urlData : {},
24853
24854 // whether to add default data to url data
24855 defaultData : true,
24856
24857 // whether to serialize closest form
24858 serializeForm : false,
24859
24860 // how long to wait before request should occur
24861 throttle : 0,
24862
24863 // whether to throttle first request or only repeated
24864 throttleFirstRequest : true,
24865
24866 // standard ajax settings
24867 method : 'get',
24868 data : {},
24869 dataType : 'json',
24870
24871 // mock response
24872 mockResponse : false,
24873 mockResponseAsync : false,
24874
24875 // aliases for mock
24876 response : false,
24877 responseAsync : false,
24878
24879// whether onResponse should work with response value without force converting into an object
24880 rawResponse : false,
24881
24882 // callbacks before request
24883 beforeSend : function(settings) { return settings; },
24884 beforeXHR : function(xhr) {},
24885 onRequest : function(promise, xhr) {},
24886
24887 // after request
24888 onResponse : false, // function(response) { },
24889
24890 // response was successful, if JSON passed validation
24891 onSuccess : function(response, $module) {},
24892
24893 // request finished without aborting
24894 onComplete : function(response, $module) {},
24895
24896 // failed JSON success test
24897 onFailure : function(response, $module) {},
24898
24899 // server error
24900 onError : function(errorMessage, $module) {},
24901
24902 // request aborted
24903 onAbort : function(errorMessage, $module) {},
24904
24905 successTest : false,
24906
24907 // errors
24908 error : {
24909 beforeSend : 'The before send function has aborted the request',
24910 error : 'There was an error with your request',
24911 exitConditions : 'API Request Aborted. Exit conditions met',
24912 JSONParse : 'JSON could not be parsed during error handling',
24913 legacyParameters : 'You are using legacy API success callback names',
24914 method : 'The method you called is not defined',
24915 missingAction : 'API action used but no url was defined',
24916 missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
24917 missingURL : 'No URL specified for api event',
24918 noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
24919 noStorage : 'Caching responses locally requires session storage',
24920 parseError : 'There was an error parsing your request',
24921 requiredParameter : 'Missing a required URL parameter: ',
24922 statusMessage : 'Server gave an error: ',
24923 timeout : 'Your request timed out'
24924 },
24925
24926 regExp : {
24927 required : /\{\$*[A-z0-9]+\}/g,
24928 optional : /\{\/\$*[A-z0-9]+\}/g,
24929 },
24930
24931 className: {
24932 loading : 'loading',
24933 error : 'error'
24934 },
24935
24936 selector: {
24937 disabled : '.disabled',
24938 form : 'form'
24939 },
24940
24941 metadata: {
24942 action : 'action',
24943 url : 'url'
24944 }
24945};
24946
24947
24948
24949})( jQuery, window, document );
24950
24951/*!
24952 * # Semantic UI 2.7.2 - State
24953 * http://github.com/semantic-org/semantic-ui/
24954 *
24955 *
24956 * Released under the MIT license
24957 * http://opensource.org/licenses/MIT
24958 *
24959 */
24960
24961;(function ($, window, document, undefined) {
24962
24963"use strict";
24964
24965$.isFunction = $.isFunction || function(obj) {
24966 return typeof obj === "function" && typeof obj.nodeType !== "number";
24967};
24968
24969window = (typeof window != 'undefined' && window.Math == Math)
24970 ? window
24971 : (typeof self != 'undefined' && self.Math == Math)
24972 ? self
24973 : Function('return this')()
24974;
24975
24976$.fn.state = function(parameters) {
24977 var
24978 $allModules = $(this),
24979
24980 moduleSelector = $allModules.selector || '',
24981
24982 time = new Date().getTime(),
24983 performance = [],
24984
24985 query = arguments[0],
24986 methodInvoked = (typeof query == 'string'),
24987 queryArguments = [].slice.call(arguments, 1),
24988
24989 returnedValue
24990 ;
24991 $allModules
24992 .each(function() {
24993 var
24994 settings = ( $.isPlainObject(parameters) )
24995 ? $.extend(true, {}, $.fn.state.settings, parameters)
24996 : $.extend({}, $.fn.state.settings),
24997
24998 error = settings.error,
24999 metadata = settings.metadata,
25000 className = settings.className,
25001 namespace = settings.namespace,
25002 states = settings.states,
25003 text = settings.text,
25004
25005 eventNamespace = '.' + namespace,
25006 moduleNamespace = namespace + '-module',
25007
25008 $module = $(this),
25009
25010 element = this,
25011 instance = $module.data(moduleNamespace),
25012
25013 module
25014 ;
25015 module = {
25016
25017 initialize: function() {
25018 module.verbose('Initializing module');
25019
25020 // allow module to guess desired state based on element
25021 if(settings.automatic) {
25022 module.add.defaults();
25023 }
25024
25025 // bind events with delegated events
25026 if(settings.context && moduleSelector !== '') {
25027 $(settings.context)
25028 .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text)
25029 .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text)
25030 .on(moduleSelector, 'click' + eventNamespace, module.toggle.state)
25031 ;
25032 }
25033 else {
25034 $module
25035 .on('mouseenter' + eventNamespace, module.change.text)
25036 .on('mouseleave' + eventNamespace, module.reset.text)
25037 .on('click' + eventNamespace, module.toggle.state)
25038 ;
25039 }
25040 module.instantiate();
25041 },
25042
25043 instantiate: function() {
25044 module.verbose('Storing instance of module', module);
25045 instance = module;
25046 $module
25047 .data(moduleNamespace, module)
25048 ;
25049 },
25050
25051 destroy: function() {
25052 module.verbose('Destroying previous module', instance);
25053 $module
25054 .off(eventNamespace)
25055 .removeData(moduleNamespace)
25056 ;
25057 },
25058
25059 refresh: function() {
25060 module.verbose('Refreshing selector cache');
25061 $module = $(element);
25062 },
25063
25064 add: {
25065 defaults: function() {
25066 var
25067 userStates = parameters && $.isPlainObject(parameters.states)
25068 ? parameters.states
25069 : {}
25070 ;
25071 $.each(settings.defaults, function(type, typeStates) {
25072 if( module.is[type] !== undefined && module.is[type]() ) {
25073 module.verbose('Adding default states', type, element);
25074 $.extend(settings.states, typeStates, userStates);
25075 }
25076 });
25077 }
25078 },
25079
25080 is: {
25081
25082 active: function() {
25083 return $module.hasClass(className.active);
25084 },
25085 loading: function() {
25086 return $module.hasClass(className.loading);
25087 },
25088 inactive: function() {
25089 return !( $module.hasClass(className.active) );
25090 },
25091 state: function(state) {
25092 if(className[state] === undefined) {
25093 return false;
25094 }
25095 return $module.hasClass( className[state] );
25096 },
25097
25098 enabled: function() {
25099 return !( $module.is(settings.filter.active) );
25100 },
25101 disabled: function() {
25102 return ( $module.is(settings.filter.active) );
25103 },
25104 textEnabled: function() {
25105 return !( $module.is(settings.filter.text) );
25106 },
25107
25108 // definitions for automatic type detection
25109 button: function() {
25110 return $module.is('.button:not(a, .submit)');
25111 },
25112 input: function() {
25113 return $module.is('input');
25114 },
25115 progress: function() {
25116 return $module.is('.ui.progress');
25117 }
25118 },
25119
25120 allow: function(state) {
25121 module.debug('Now allowing state', state);
25122 states[state] = true;
25123 },
25124 disallow: function(state) {
25125 module.debug('No longer allowing', state);
25126 states[state] = false;
25127 },
25128
25129 allows: function(state) {
25130 return states[state] || false;
25131 },
25132
25133 enable: function() {
25134 $module.removeClass(className.disabled);
25135 },
25136
25137 disable: function() {
25138 $module.addClass(className.disabled);
25139 },
25140
25141 setState: function(state) {
25142 if(module.allows(state)) {
25143 $module.addClass( className[state] );
25144 }
25145 },
25146
25147 removeState: function(state) {
25148 if(module.allows(state)) {
25149 $module.removeClass( className[state] );
25150 }
25151 },
25152
25153 toggle: {
25154 state: function() {
25155 var
25156 apiRequest,
25157 requestCancelled
25158 ;
25159 if( module.allows('active') && module.is.enabled() ) {
25160 module.refresh();
25161 if($.fn.api !== undefined) {
25162 apiRequest = $module.api('get request');
25163 requestCancelled = $module.api('was cancelled');
25164 if( requestCancelled ) {
25165 module.debug('API Request cancelled by beforesend');
25166 settings.activateTest = function(){ return false; };
25167 settings.deactivateTest = function(){ return false; };
25168 }
25169 else if(apiRequest) {
25170 module.listenTo(apiRequest);
25171 return;
25172 }
25173 }
25174 module.change.state();
25175 }
25176 }
25177 },
25178
25179 listenTo: function(apiRequest) {
25180 module.debug('API request detected, waiting for state signal', apiRequest);
25181 if(apiRequest) {
25182 if(text.loading) {
25183 module.update.text(text.loading);
25184 }
25185 $.when(apiRequest)
25186 .then(function() {
25187 if(apiRequest.state() == 'resolved') {
25188 module.debug('API request succeeded');
25189 settings.activateTest = function(){ return true; };
25190 settings.deactivateTest = function(){ return true; };
25191 }
25192 else {
25193 module.debug('API request failed');
25194 settings.activateTest = function(){ return false; };
25195 settings.deactivateTest = function(){ return false; };
25196 }
25197 module.change.state();
25198 })
25199 ;
25200 }
25201 },
25202
25203 // checks whether active/inactive state can be given
25204 change: {
25205
25206 state: function() {
25207 module.debug('Determining state change direction');
25208 // inactive to active change
25209 if( module.is.inactive() ) {
25210 module.activate();
25211 }
25212 else {
25213 module.deactivate();
25214 }
25215 if(settings.sync) {
25216 module.sync();
25217 }
25218 settings.onChange.call(element);
25219 },
25220
25221 text: function() {
25222 if( module.is.textEnabled() ) {
25223 if(module.is.disabled() ) {
25224 module.verbose('Changing text to disabled text', text.hover);
25225 module.update.text(text.disabled);
25226 }
25227 else if( module.is.active() ) {
25228 if(text.hover) {
25229 module.verbose('Changing text to hover text', text.hover);
25230 module.update.text(text.hover);
25231 }
25232 else if(text.deactivate) {
25233 module.verbose('Changing text to deactivating text', text.deactivate);
25234 module.update.text(text.deactivate);
25235 }
25236 }
25237 else {
25238 if(text.hover) {
25239 module.verbose('Changing text to hover text', text.hover);
25240 module.update.text(text.hover);
25241 }
25242 else if(text.activate){
25243 module.verbose('Changing text to activating text', text.activate);
25244 module.update.text(text.activate);
25245 }
25246 }
25247 }
25248 }
25249
25250 },
25251
25252 activate: function() {
25253 if( settings.activateTest.call(element) ) {
25254 module.debug('Setting state to active');
25255 $module
25256 .addClass(className.active)
25257 ;
25258 module.update.text(text.active);
25259 settings.onActivate.call(element);
25260 }
25261 },
25262
25263 deactivate: function() {
25264 if( settings.deactivateTest.call(element) ) {
25265 module.debug('Setting state to inactive');
25266 $module
25267 .removeClass(className.active)
25268 ;
25269 module.update.text(text.inactive);
25270 settings.onDeactivate.call(element);
25271 }
25272 },
25273
25274 sync: function() {
25275 module.verbose('Syncing other buttons to current state');
25276 if( module.is.active() ) {
25277 $allModules
25278 .not($module)
25279 .state('activate');
25280 }
25281 else {
25282 $allModules
25283 .not($module)
25284 .state('deactivate')
25285 ;
25286 }
25287 },
25288
25289 get: {
25290 text: function() {
25291 return (settings.selector.text)
25292 ? $module.find(settings.selector.text).text()
25293 : $module.html()
25294 ;
25295 },
25296 textFor: function(state) {
25297 return text[state] || false;
25298 }
25299 },
25300
25301 flash: {
25302 text: function(text, duration, callback) {
25303 var
25304 previousText = module.get.text()
25305 ;
25306 module.debug('Flashing text message', text, duration);
25307 text = text || settings.text.flash;
25308 duration = duration || settings.flashDuration;
25309 callback = callback || function() {};
25310 module.update.text(text);
25311 setTimeout(function(){
25312 module.update.text(previousText);
25313 callback.call(element);
25314 }, duration);
25315 }
25316 },
25317
25318 reset: {
25319 // on mouseout sets text to previous value
25320 text: function() {
25321 var
25322 activeText = text.active || $module.data(metadata.storedText),
25323 inactiveText = text.inactive || $module.data(metadata.storedText)
25324 ;
25325 if( module.is.textEnabled() ) {
25326 if( module.is.active() && activeText) {
25327 module.verbose('Resetting active text', activeText);
25328 module.update.text(activeText);
25329 }
25330 else if(inactiveText) {
25331 module.verbose('Resetting inactive text', activeText);
25332 module.update.text(inactiveText);
25333 }
25334 }
25335 }
25336 },
25337
25338 update: {
25339 text: function(text) {
25340 var
25341 currentText = module.get.text()
25342 ;
25343 if(text && text !== currentText) {
25344 module.debug('Updating text', text);
25345 if(settings.selector.text) {
25346 $module
25347 .data(metadata.storedText, text)
25348 .find(settings.selector.text)
25349 .text(text)
25350 ;
25351 }
25352 else {
25353 $module
25354 .data(metadata.storedText, text)
25355 .html(text)
25356 ;
25357 }
25358 }
25359 else {
25360 module.debug('Text is already set, ignoring update', text);
25361 }
25362 }
25363 },
25364
25365 setting: function(name, value) {
25366 module.debug('Changing setting', name, value);
25367 if( $.isPlainObject(name) ) {
25368 $.extend(true, settings, name);
25369 }
25370 else if(value !== undefined) {
25371 if($.isPlainObject(settings[name])) {
25372 $.extend(true, settings[name], value);
25373 }
25374 else {
25375 settings[name] = value;
25376 }
25377 }
25378 else {
25379 return settings[name];
25380 }
25381 },
25382 internal: function(name, value) {
25383 if( $.isPlainObject(name) ) {
25384 $.extend(true, module, name);
25385 }
25386 else if(value !== undefined) {
25387 module[name] = value;
25388 }
25389 else {
25390 return module[name];
25391 }
25392 },
25393 debug: function() {
25394 if(!settings.silent && settings.debug) {
25395 if(settings.performance) {
25396 module.performance.log(arguments);
25397 }
25398 else {
25399 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
25400 module.debug.apply(console, arguments);
25401 }
25402 }
25403 },
25404 verbose: function() {
25405 if(!settings.silent && settings.verbose && settings.debug) {
25406 if(settings.performance) {
25407 module.performance.log(arguments);
25408 }
25409 else {
25410 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
25411 module.verbose.apply(console, arguments);
25412 }
25413 }
25414 },
25415 error: function() {
25416 if(!settings.silent) {
25417 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
25418 module.error.apply(console, arguments);
25419 }
25420 },
25421 performance: {
25422 log: function(message) {
25423 var
25424 currentTime,
25425 executionTime,
25426 previousTime
25427 ;
25428 if(settings.performance) {
25429 currentTime = new Date().getTime();
25430 previousTime = time || currentTime;
25431 executionTime = currentTime - previousTime;
25432 time = currentTime;
25433 performance.push({
25434 'Name' : message[0],
25435 'Arguments' : [].slice.call(message, 1) || '',
25436 'Element' : element,
25437 'Execution Time' : executionTime
25438 });
25439 }
25440 clearTimeout(module.performance.timer);
25441 module.performance.timer = setTimeout(module.performance.display, 500);
25442 },
25443 display: function() {
25444 var
25445 title = settings.name + ':',
25446 totalTime = 0
25447 ;
25448 time = false;
25449 clearTimeout(module.performance.timer);
25450 $.each(performance, function(index, data) {
25451 totalTime += data['Execution Time'];
25452 });
25453 title += ' ' + totalTime + 'ms';
25454 if(moduleSelector) {
25455 title += ' \'' + moduleSelector + '\'';
25456 }
25457 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
25458 console.groupCollapsed(title);
25459 if(console.table) {
25460 console.table(performance);
25461 }
25462 else {
25463 $.each(performance, function(index, data) {
25464 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
25465 });
25466 }
25467 console.groupEnd();
25468 }
25469 performance = [];
25470 }
25471 },
25472 invoke: function(query, passedArguments, context) {
25473 var
25474 object = instance,
25475 maxDepth,
25476 found,
25477 response
25478 ;
25479 passedArguments = passedArguments || queryArguments;
25480 context = element || context;
25481 if(typeof query == 'string' && object !== undefined) {
25482 query = query.split(/[\. ]/);
25483 maxDepth = query.length - 1;
25484 $.each(query, function(depth, value) {
25485 var camelCaseValue = (depth != maxDepth)
25486 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
25487 : query
25488 ;
25489 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
25490 object = object[camelCaseValue];
25491 }
25492 else if( object[camelCaseValue] !== undefined ) {
25493 found = object[camelCaseValue];
25494 return false;
25495 }
25496 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
25497 object = object[value];
25498 }
25499 else if( object[value] !== undefined ) {
25500 found = object[value];
25501 return false;
25502 }
25503 else {
25504 module.error(error.method, query);
25505 return false;
25506 }
25507 });
25508 }
25509 if ( $.isFunction( found ) ) {
25510 response = found.apply(context, passedArguments);
25511 }
25512 else if(found !== undefined) {
25513 response = found;
25514 }
25515 if(Array.isArray(returnedValue)) {
25516 returnedValue.push(response);
25517 }
25518 else if(returnedValue !== undefined) {
25519 returnedValue = [returnedValue, response];
25520 }
25521 else if(response !== undefined) {
25522 returnedValue = response;
25523 }
25524 return found;
25525 }
25526 };
25527
25528 if(methodInvoked) {
25529 if(instance === undefined) {
25530 module.initialize();
25531 }
25532 module.invoke(query);
25533 }
25534 else {
25535 if(instance !== undefined) {
25536 instance.invoke('destroy');
25537 }
25538 module.initialize();
25539 }
25540 })
25541 ;
25542
25543 return (returnedValue !== undefined)
25544 ? returnedValue
25545 : this
25546 ;
25547};
25548
25549$.fn.state.settings = {
25550
25551 // module info
25552 name : 'State',
25553
25554 // debug output
25555 debug : false,
25556
25557 // verbose debug output
25558 verbose : false,
25559
25560 // namespace for events
25561 namespace : 'state',
25562
25563 // debug data includes performance
25564 performance : true,
25565
25566 // callback occurs on state change
25567 onActivate : function() {},
25568 onDeactivate : function() {},
25569 onChange : function() {},
25570
25571 // state test functions
25572 activateTest : function() { return true; },
25573 deactivateTest : function() { return true; },
25574
25575 // whether to automatically map default states
25576 automatic : true,
25577
25578 // activate / deactivate changes all elements instantiated at same time
25579 sync : false,
25580
25581 // default flash text duration, used for temporarily changing text of an element
25582 flashDuration : 1000,
25583
25584 // selector filter
25585 filter : {
25586 text : '.loading, .disabled',
25587 active : '.disabled'
25588 },
25589
25590 context : false,
25591
25592 // error
25593 error: {
25594 beforeSend : 'The before send function has cancelled state change',
25595 method : 'The method you called is not defined.'
25596 },
25597
25598 // metadata
25599 metadata: {
25600 promise : 'promise',
25601 storedText : 'stored-text'
25602 },
25603
25604 // change class on state
25605 className: {
25606 active : 'active',
25607 disabled : 'disabled',
25608 error : 'error',
25609 loading : 'loading',
25610 success : 'success',
25611 warning : 'warning'
25612 },
25613
25614 selector: {
25615 // selector for text node
25616 text: false
25617 },
25618
25619 defaults : {
25620 input: {
25621 disabled : true,
25622 loading : true,
25623 active : true
25624 },
25625 button: {
25626 disabled : true,
25627 loading : true,
25628 active : true,
25629 },
25630 progress: {
25631 active : true,
25632 success : true,
25633 warning : true,
25634 error : true
25635 }
25636 },
25637
25638 states : {
25639 active : true,
25640 disabled : true,
25641 error : true,
25642 loading : true,
25643 success : true,
25644 warning : true
25645 },
25646
25647 text : {
25648 disabled : false,
25649 flash : false,
25650 hover : false,
25651 active : false,
25652 inactive : false,
25653 activate : false,
25654 deactivate : false
25655 }
25656
25657};
25658
25659
25660
25661})( jQuery, window, document );
25662
25663/*!
25664 * # Semantic UI 2.7.2 - Visibility
25665 * http://github.com/semantic-org/semantic-ui/
25666 *
25667 *
25668 * Released under the MIT license
25669 * http://opensource.org/licenses/MIT
25670 *
25671 */
25672
25673;(function ($, window, document, undefined) {
25674
25675'use strict';
25676
25677$.isFunction = $.isFunction || function(obj) {
25678 return typeof obj === "function" && typeof obj.nodeType !== "number";
25679};
25680
25681window = (typeof window != 'undefined' && window.Math == Math)
25682 ? window
25683 : (typeof self != 'undefined' && self.Math == Math)
25684 ? self
25685 : Function('return this')()
25686;
25687
25688$.fn.visibility = function(parameters) {
25689 var
25690 $allModules = $(this),
25691 moduleSelector = $allModules.selector || '',
25692
25693 time = new Date().getTime(),
25694 performance = [],
25695
25696 query = arguments[0],
25697 methodInvoked = (typeof query == 'string'),
25698 queryArguments = [].slice.call(arguments, 1),
25699 returnedValue,
25700
25701 moduleCount = $allModules.length,
25702 loadedCount = 0
25703 ;
25704
25705 $allModules
25706 .each(function() {
25707 var
25708 settings = ( $.isPlainObject(parameters) )
25709 ? $.extend(true, {}, $.fn.visibility.settings, parameters)
25710 : $.extend({}, $.fn.visibility.settings),
25711
25712 className = settings.className,
25713 namespace = settings.namespace,
25714 error = settings.error,
25715 metadata = settings.metadata,
25716
25717 eventNamespace = '.' + namespace,
25718 moduleNamespace = 'module-' + namespace,
25719
25720 $window = $(window),
25721
25722 $module = $(this),
25723 $context = $(settings.context),
25724
25725 $placeholder,
25726
25727 instance = $module.data(moduleNamespace),
25728
25729 requestAnimationFrame = window.requestAnimationFrame
25730 || window.mozRequestAnimationFrame
25731 || window.webkitRequestAnimationFrame
25732 || window.msRequestAnimationFrame
25733 || function(callback) { setTimeout(callback, 0); },
25734
25735 element = this,
25736 disabled = false,
25737
25738 contextObserver,
25739 observer,
25740 module
25741 ;
25742
25743 module = {
25744
25745 initialize: function() {
25746 module.debug('Initializing', settings);
25747
25748 module.setup.cache();
25749
25750 if( module.should.trackChanges() ) {
25751
25752 if(settings.type == 'image') {
25753 module.setup.image();
25754 }
25755 if(settings.type == 'fixed') {
25756 module.setup.fixed();
25757 }
25758
25759 if(settings.observeChanges) {
25760 module.observeChanges();
25761 }
25762 module.bind.events();
25763 }
25764
25765 module.save.position();
25766 if( !module.is.visible() ) {
25767 module.error(error.visible, $module);
25768 }
25769
25770 if(settings.initialCheck) {
25771 module.checkVisibility();
25772 }
25773 module.instantiate();
25774 },
25775
25776 instantiate: function() {
25777 module.debug('Storing instance', module);
25778 $module
25779 .data(moduleNamespace, module)
25780 ;
25781 instance = module;
25782 },
25783
25784 destroy: function() {
25785 module.verbose('Destroying previous module');
25786 if(observer) {
25787 observer.disconnect();
25788 }
25789 if(contextObserver) {
25790 contextObserver.disconnect();
25791 }
25792 $window
25793 .off('load' + eventNamespace, module.event.load)
25794 .off('resize' + eventNamespace, module.event.resize)
25795 ;
25796 $context
25797 .off('scroll' + eventNamespace, module.event.scroll)
25798 .off('scrollchange' + eventNamespace, module.event.scrollchange)
25799 ;
25800 if(settings.type == 'fixed') {
25801 module.resetFixed();
25802 module.remove.placeholder();
25803 }
25804 $module
25805 .off(eventNamespace)
25806 .removeData(moduleNamespace)
25807 ;
25808 },
25809
25810 observeChanges: function() {
25811 if('MutationObserver' in window) {
25812 contextObserver = new MutationObserver(module.event.contextChanged);
25813 observer = new MutationObserver(module.event.changed);
25814 contextObserver.observe(document, {
25815 childList : true,
25816 subtree : true
25817 });
25818 observer.observe(element, {
25819 childList : true,
25820 subtree : true
25821 });
25822 module.debug('Setting up mutation observer', observer);
25823 }
25824 },
25825
25826 bind: {
25827 events: function() {
25828 module.verbose('Binding visibility events to scroll and resize');
25829 if(settings.refreshOnLoad) {
25830 $window
25831 .on('load' + eventNamespace, module.event.load)
25832 ;
25833 }
25834 $window
25835 .on('resize' + eventNamespace, module.event.resize)
25836 ;
25837 // pub/sub pattern
25838 $context
25839 .off('scroll' + eventNamespace)
25840 .on('scroll' + eventNamespace, module.event.scroll)
25841 .on('scrollchange' + eventNamespace, module.event.scrollchange)
25842 ;
25843 }
25844 },
25845
25846 event: {
25847 changed: function(mutations) {
25848 module.verbose('DOM tree modified, updating visibility calculations');
25849 module.timer = setTimeout(function() {
25850 module.verbose('DOM tree modified, updating sticky menu');
25851 module.refresh();
25852 }, 100);
25853 },
25854 contextChanged: function(mutations) {
25855 [].forEach.call(mutations, function(mutation) {
25856 if(mutation.removedNodes) {
25857 [].forEach.call(mutation.removedNodes, function(node) {
25858 if(node == element || $(node).find(element).length > 0) {
25859 module.debug('Element removed from DOM, tearing down events');
25860 module.destroy();
25861 }
25862 });
25863 }
25864 });
25865 },
25866 resize: function() {
25867 module.debug('Window resized');
25868 if(settings.refreshOnResize) {
25869 requestAnimationFrame(module.refresh);
25870 }
25871 },
25872 load: function() {
25873 module.debug('Page finished loading');
25874 requestAnimationFrame(module.refresh);
25875 },
25876 // publishes scrollchange event on one scroll
25877 scroll: function() {
25878 if(settings.throttle) {
25879 clearTimeout(module.timer);
25880 module.timer = setTimeout(function() {
25881 $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
25882 }, settings.throttle);
25883 }
25884 else {
25885 requestAnimationFrame(function() {
25886 $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
25887 });
25888 }
25889 },
25890 // subscribes to scrollchange
25891 scrollchange: function(event, scrollPosition) {
25892 module.checkVisibility(scrollPosition);
25893 },
25894 },
25895
25896 precache: function(images, callback) {
25897 if (!(images instanceof Array)) {
25898 images = [images];
25899 }
25900 var
25901 imagesLength = images.length,
25902 loadedCounter = 0,
25903 cache = [],
25904 cacheImage = document.createElement('img'),
25905 handleLoad = function() {
25906 loadedCounter++;
25907 if (loadedCounter >= images.length) {
25908 if ($.isFunction(callback)) {
25909 callback();
25910 }
25911 }
25912 }
25913 ;
25914 while (imagesLength--) {
25915 cacheImage = document.createElement('img');
25916 cacheImage.onload = handleLoad;
25917 cacheImage.onerror = handleLoad;
25918 cacheImage.src = images[imagesLength];
25919 cache.push(cacheImage);
25920 }
25921 },
25922
25923 enableCallbacks: function() {
25924 module.debug('Allowing callbacks to occur');
25925 disabled = false;
25926 },
25927
25928 disableCallbacks: function() {
25929 module.debug('Disabling all callbacks temporarily');
25930 disabled = true;
25931 },
25932
25933 should: {
25934 trackChanges: function() {
25935 if(methodInvoked) {
25936 module.debug('One time query, no need to bind events');
25937 return false;
25938 }
25939 module.debug('Callbacks being attached');
25940 return true;
25941 }
25942 },
25943
25944 setup: {
25945 cache: function() {
25946 module.cache = {
25947 occurred : {},
25948 screen : {},
25949 element : {},
25950 };
25951 },
25952 image: function() {
25953 var
25954 src = $module.data(metadata.src)
25955 ;
25956 if(src) {
25957 module.verbose('Lazy loading image', src);
25958 settings.once = true;
25959 settings.observeChanges = false;
25960
25961 // show when top visible
25962 settings.onOnScreen = function() {
25963 module.debug('Image on screen', element);
25964 module.precache(src, function() {
25965 module.set.image(src, function() {
25966 loadedCount++;
25967 if(loadedCount == moduleCount) {
25968 settings.onAllLoaded.call(this);
25969 }
25970 settings.onLoad.call(this);
25971 });
25972 });
25973 };
25974 }
25975 },
25976 fixed: function() {
25977 module.debug('Setting up fixed');
25978 settings.once = false;
25979 settings.observeChanges = false;
25980 settings.initialCheck = true;
25981 settings.refreshOnLoad = true;
25982 if(!parameters.transition) {
25983 settings.transition = false;
25984 }
25985 module.create.placeholder();
25986 module.debug('Added placeholder', $placeholder);
25987 settings.onTopPassed = function() {
25988 module.debug('Element passed, adding fixed position', $module);
25989 module.show.placeholder();
25990 module.set.fixed();
25991 if(settings.transition) {
25992 if($.fn.transition !== undefined) {
25993 $module.transition(settings.transition, settings.duration);
25994 }
25995 }
25996 };
25997 settings.onTopPassedReverse = function() {
25998 module.debug('Element returned to position, removing fixed', $module);
25999 module.hide.placeholder();
26000 module.remove.fixed();
26001 };
26002 }
26003 },
26004
26005 create: {
26006 placeholder: function() {
26007 module.verbose('Creating fixed position placeholder');
26008 $placeholder = $module
26009 .clone(false)
26010 .css('display', 'none')
26011 .addClass(className.placeholder)
26012 .insertAfter($module)
26013 ;
26014 }
26015 },
26016
26017 show: {
26018 placeholder: function() {
26019 module.verbose('Showing placeholder');
26020 $placeholder
26021 .css('display', 'block')
26022 .css('visibility', 'hidden')
26023 ;
26024 }
26025 },
26026 hide: {
26027 placeholder: function() {
26028 module.verbose('Hiding placeholder');
26029 $placeholder
26030 .css('display', 'none')
26031 .css('visibility', '')
26032 ;
26033 }
26034 },
26035
26036 set: {
26037 fixed: function() {
26038 module.verbose('Setting element to fixed position');
26039 $module
26040 .addClass(className.fixed)
26041 .css({
26042 position : 'fixed',
26043 top : settings.offset + 'px',
26044 left : 'auto',
26045 zIndex : settings.zIndex
26046 })
26047 ;
26048 settings.onFixed.call(element);
26049 },
26050 image: function(src, callback) {
26051 $module
26052 .attr('src', src)
26053 ;
26054 if(settings.transition) {
26055 if( $.fn.transition !== undefined) {
26056 if($module.hasClass(className.visible)) {
26057 module.debug('Transition already occurred on this image, skipping animation');
26058 return;
26059 }
26060 $module.transition(settings.transition, settings.duration, callback);
26061 }
26062 else {
26063 $module.fadeIn(settings.duration, callback);
26064 }
26065 }
26066 else {
26067 $module.show();
26068 }
26069 }
26070 },
26071
26072 is: {
26073 onScreen: function() {
26074 var
26075 calculations = module.get.elementCalculations()
26076 ;
26077 return calculations.onScreen;
26078 },
26079 offScreen: function() {
26080 var
26081 calculations = module.get.elementCalculations()
26082 ;
26083 return calculations.offScreen;
26084 },
26085 visible: function() {
26086 if(module.cache && module.cache.element) {
26087 return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
26088 }
26089 return false;
26090 },
26091 verticallyScrollableContext: function() {
26092 var
26093 overflowY = ($context.get(0) !== window)
26094 ? $context.css('overflow-y')
26095 : false
26096 ;
26097 return (overflowY == 'auto' || overflowY == 'scroll');
26098 },
26099 horizontallyScrollableContext: function() {
26100 var
26101 overflowX = ($context.get(0) !== window)
26102 ? $context.css('overflow-x')
26103 : false
26104 ;
26105 return (overflowX == 'auto' || overflowX == 'scroll');
26106 }
26107 },
26108
26109 refresh: function() {
26110 module.debug('Refreshing constants (width/height)');
26111 if(settings.type == 'fixed') {
26112 module.resetFixed();
26113 }
26114 module.reset();
26115 module.save.position();
26116 if(settings.checkOnRefresh) {
26117 module.checkVisibility();
26118 }
26119 settings.onRefresh.call(element);
26120 },
26121
26122 resetFixed: function () {
26123 module.remove.fixed();
26124 module.remove.occurred();
26125 },
26126
26127 reset: function() {
26128 module.verbose('Resetting all cached values');
26129 if( $.isPlainObject(module.cache) ) {
26130 module.cache.screen = {};
26131 module.cache.element = {};
26132 }
26133 },
26134
26135 checkVisibility: function(scroll) {
26136 module.verbose('Checking visibility of element', module.cache.element);
26137
26138 if( !disabled && module.is.visible() ) {
26139
26140 // save scroll position
26141 module.save.scroll(scroll);
26142
26143 // update calculations derived from scroll
26144 module.save.calculations();
26145
26146 // percentage
26147 module.passed();
26148
26149 // reverse (must be first)
26150 module.passingReverse();
26151 module.topVisibleReverse();
26152 module.bottomVisibleReverse();
26153 module.topPassedReverse();
26154 module.bottomPassedReverse();
26155
26156 // one time
26157 module.onScreen();
26158 module.offScreen();
26159 module.passing();
26160 module.topVisible();
26161 module.bottomVisible();
26162 module.topPassed();
26163 module.bottomPassed();
26164
26165 // on update callback
26166 if(settings.onUpdate) {
26167 settings.onUpdate.call(element, module.get.elementCalculations());
26168 }
26169 }
26170 },
26171
26172 passed: function(amount, newCallback) {
26173 var
26174 calculations = module.get.elementCalculations()
26175 ;
26176 // assign callback
26177 if(amount && newCallback) {
26178 settings.onPassed[amount] = newCallback;
26179 }
26180 else if(amount !== undefined) {
26181 return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
26182 }
26183 else if(calculations.passing) {
26184 $.each(settings.onPassed, function(amount, callback) {
26185 if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
26186 module.execute(callback, amount);
26187 }
26188 else if(!settings.once) {
26189 module.remove.occurred(callback);
26190 }
26191 });
26192 }
26193 },
26194
26195 onScreen: function(newCallback) {
26196 var
26197 calculations = module.get.elementCalculations(),
26198 callback = newCallback || settings.onOnScreen,
26199 callbackName = 'onScreen'
26200 ;
26201 if(newCallback) {
26202 module.debug('Adding callback for onScreen', newCallback);
26203 settings.onOnScreen = newCallback;
26204 }
26205 if(calculations.onScreen) {
26206 module.execute(callback, callbackName);
26207 }
26208 else if(!settings.once) {
26209 module.remove.occurred(callbackName);
26210 }
26211 if(newCallback !== undefined) {
26212 return calculations.onOnScreen;
26213 }
26214 },
26215
26216 offScreen: function(newCallback) {
26217 var
26218 calculations = module.get.elementCalculations(),
26219 callback = newCallback || settings.onOffScreen,
26220 callbackName = 'offScreen'
26221 ;
26222 if(newCallback) {
26223 module.debug('Adding callback for offScreen', newCallback);
26224 settings.onOffScreen = newCallback;
26225 }
26226 if(calculations.offScreen) {
26227 module.execute(callback, callbackName);
26228 }
26229 else if(!settings.once) {
26230 module.remove.occurred(callbackName);
26231 }
26232 if(newCallback !== undefined) {
26233 return calculations.onOffScreen;
26234 }
26235 },
26236
26237 passing: function(newCallback) {
26238 var
26239 calculations = module.get.elementCalculations(),
26240 callback = newCallback || settings.onPassing,
26241 callbackName = 'passing'
26242 ;
26243 if(newCallback) {
26244 module.debug('Adding callback for passing', newCallback);
26245 settings.onPassing = newCallback;
26246 }
26247 if(calculations.passing) {
26248 module.execute(callback, callbackName);
26249 }
26250 else if(!settings.once) {
26251 module.remove.occurred(callbackName);
26252 }
26253 if(newCallback !== undefined) {
26254 return calculations.passing;
26255 }
26256 },
26257
26258
26259 topVisible: function(newCallback) {
26260 var
26261 calculations = module.get.elementCalculations(),
26262 callback = newCallback || settings.onTopVisible,
26263 callbackName = 'topVisible'
26264 ;
26265 if(newCallback) {
26266 module.debug('Adding callback for top visible', newCallback);
26267 settings.onTopVisible = newCallback;
26268 }
26269 if(calculations.topVisible) {
26270 module.execute(callback, callbackName);
26271 }
26272 else if(!settings.once) {
26273 module.remove.occurred(callbackName);
26274 }
26275 if(newCallback === undefined) {
26276 return calculations.topVisible;
26277 }
26278 },
26279
26280 bottomVisible: function(newCallback) {
26281 var
26282 calculations = module.get.elementCalculations(),
26283 callback = newCallback || settings.onBottomVisible,
26284 callbackName = 'bottomVisible'
26285 ;
26286 if(newCallback) {
26287 module.debug('Adding callback for bottom visible', newCallback);
26288 settings.onBottomVisible = newCallback;
26289 }
26290 if(calculations.bottomVisible) {
26291 module.execute(callback, callbackName);
26292 }
26293 else if(!settings.once) {
26294 module.remove.occurred(callbackName);
26295 }
26296 if(newCallback === undefined) {
26297 return calculations.bottomVisible;
26298 }
26299 },
26300
26301 topPassed: function(newCallback) {
26302 var
26303 calculations = module.get.elementCalculations(),
26304 callback = newCallback || settings.onTopPassed,
26305 callbackName = 'topPassed'
26306 ;
26307 if(newCallback) {
26308 module.debug('Adding callback for top passed', newCallback);
26309 settings.onTopPassed = newCallback;
26310 }
26311 if(calculations.topPassed) {
26312 module.execute(callback, callbackName);
26313 }
26314 else if(!settings.once) {
26315 module.remove.occurred(callbackName);
26316 }
26317 if(newCallback === undefined) {
26318 return calculations.topPassed;
26319 }
26320 },
26321
26322 bottomPassed: function(newCallback) {
26323 var
26324 calculations = module.get.elementCalculations(),
26325 callback = newCallback || settings.onBottomPassed,
26326 callbackName = 'bottomPassed'
26327 ;
26328 if(newCallback) {
26329 module.debug('Adding callback for bottom passed', newCallback);
26330 settings.onBottomPassed = newCallback;
26331 }
26332 if(calculations.bottomPassed) {
26333 module.execute(callback, callbackName);
26334 }
26335 else if(!settings.once) {
26336 module.remove.occurred(callbackName);
26337 }
26338 if(newCallback === undefined) {
26339 return calculations.bottomPassed;
26340 }
26341 },
26342
26343 passingReverse: function(newCallback) {
26344 var
26345 calculations = module.get.elementCalculations(),
26346 callback = newCallback || settings.onPassingReverse,
26347 callbackName = 'passingReverse'
26348 ;
26349 if(newCallback) {
26350 module.debug('Adding callback for passing reverse', newCallback);
26351 settings.onPassingReverse = newCallback;
26352 }
26353 if(!calculations.passing) {
26354 if(module.get.occurred('passing')) {
26355 module.execute(callback, callbackName);
26356 }
26357 }
26358 else if(!settings.once) {
26359 module.remove.occurred(callbackName);
26360 }
26361 if(newCallback !== undefined) {
26362 return !calculations.passing;
26363 }
26364 },
26365
26366
26367 topVisibleReverse: function(newCallback) {
26368 var
26369 calculations = module.get.elementCalculations(),
26370 callback = newCallback || settings.onTopVisibleReverse,
26371 callbackName = 'topVisibleReverse'
26372 ;
26373 if(newCallback) {
26374 module.debug('Adding callback for top visible reverse', newCallback);
26375 settings.onTopVisibleReverse = newCallback;
26376 }
26377 if(!calculations.topVisible) {
26378 if(module.get.occurred('topVisible')) {
26379 module.execute(callback, callbackName);
26380 }
26381 }
26382 else if(!settings.once) {
26383 module.remove.occurred(callbackName);
26384 }
26385 if(newCallback === undefined) {
26386 return !calculations.topVisible;
26387 }
26388 },
26389
26390 bottomVisibleReverse: function(newCallback) {
26391 var
26392 calculations = module.get.elementCalculations(),
26393 callback = newCallback || settings.onBottomVisibleReverse,
26394 callbackName = 'bottomVisibleReverse'
26395 ;
26396 if(newCallback) {
26397 module.debug('Adding callback for bottom visible reverse', newCallback);
26398 settings.onBottomVisibleReverse = newCallback;
26399 }
26400 if(!calculations.bottomVisible) {
26401 if(module.get.occurred('bottomVisible')) {
26402 module.execute(callback, callbackName);
26403 }
26404 }
26405 else if(!settings.once) {
26406 module.remove.occurred(callbackName);
26407 }
26408 if(newCallback === undefined) {
26409 return !calculations.bottomVisible;
26410 }
26411 },
26412
26413 topPassedReverse: function(newCallback) {
26414 var
26415 calculations = module.get.elementCalculations(),
26416 callback = newCallback || settings.onTopPassedReverse,
26417 callbackName = 'topPassedReverse'
26418 ;
26419 if(newCallback) {
26420 module.debug('Adding callback for top passed reverse', newCallback);
26421 settings.onTopPassedReverse = newCallback;
26422 }
26423 if(!calculations.topPassed) {
26424 if(module.get.occurred('topPassed')) {
26425 module.execute(callback, callbackName);
26426 }
26427 }
26428 else if(!settings.once) {
26429 module.remove.occurred(callbackName);
26430 }
26431 if(newCallback === undefined) {
26432 return !calculations.onTopPassed;
26433 }
26434 },
26435
26436 bottomPassedReverse: function(newCallback) {
26437 var
26438 calculations = module.get.elementCalculations(),
26439 callback = newCallback || settings.onBottomPassedReverse,
26440 callbackName = 'bottomPassedReverse'
26441 ;
26442 if(newCallback) {
26443 module.debug('Adding callback for bottom passed reverse', newCallback);
26444 settings.onBottomPassedReverse = newCallback;
26445 }
26446 if(!calculations.bottomPassed) {
26447 if(module.get.occurred('bottomPassed')) {
26448 module.execute(callback, callbackName);
26449 }
26450 }
26451 else if(!settings.once) {
26452 module.remove.occurred(callbackName);
26453 }
26454 if(newCallback === undefined) {
26455 return !calculations.bottomPassed;
26456 }
26457 },
26458
26459 execute: function(callback, callbackName) {
26460 var
26461 calculations = module.get.elementCalculations(),
26462 screen = module.get.screenCalculations()
26463 ;
26464 callback = callback || false;
26465 if(callback) {
26466 if(settings.continuous) {
26467 module.debug('Callback being called continuously', callbackName, calculations);
26468 callback.call(element, calculations, screen);
26469 }
26470 else if(!module.get.occurred(callbackName)) {
26471 module.debug('Conditions met', callbackName, calculations);
26472 callback.call(element, calculations, screen);
26473 }
26474 }
26475 module.save.occurred(callbackName);
26476 },
26477
26478 remove: {
26479 fixed: function() {
26480 module.debug('Removing fixed position');
26481 $module
26482 .removeClass(className.fixed)
26483 .css({
26484 position : '',
26485 top : '',
26486 left : '',
26487 zIndex : ''
26488 })
26489 ;
26490 settings.onUnfixed.call(element);
26491 },
26492 placeholder: function() {
26493 module.debug('Removing placeholder content');
26494 if($placeholder) {
26495 $placeholder.remove();
26496 }
26497 },
26498 occurred: function(callback) {
26499 if(callback) {
26500 var
26501 occurred = module.cache.occurred
26502 ;
26503 if(occurred[callback] !== undefined && occurred[callback] === true) {
26504 module.debug('Callback can now be called again', callback);
26505 module.cache.occurred[callback] = false;
26506 }
26507 }
26508 else {
26509 module.cache.occurred = {};
26510 }
26511 }
26512 },
26513
26514 save: {
26515 calculations: function() {
26516 module.verbose('Saving all calculations necessary to determine positioning');
26517 module.save.direction();
26518 module.save.screenCalculations();
26519 module.save.elementCalculations();
26520 },
26521 occurred: function(callback) {
26522 if(callback) {
26523 if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
26524 module.verbose('Saving callback occurred', callback);
26525 module.cache.occurred[callback] = true;
26526 }
26527 }
26528 },
26529 scroll: function(scrollPosition) {
26530 scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
26531 module.cache.scroll = scrollPosition;
26532 },
26533 direction: function() {
26534 var
26535 scroll = module.get.scroll(),
26536 lastScroll = module.get.lastScroll(),
26537 direction
26538 ;
26539 if(scroll > lastScroll && lastScroll) {
26540 direction = 'down';
26541 }
26542 else if(scroll < lastScroll && lastScroll) {
26543 direction = 'up';
26544 }
26545 else {
26546 direction = 'static';
26547 }
26548 module.cache.direction = direction;
26549 return module.cache.direction;
26550 },
26551 elementPosition: function() {
26552 var
26553 element = module.cache.element,
26554 screen = module.get.screenSize()
26555 ;
26556 module.verbose('Saving element position');
26557 // (quicker than $.extend)
26558 element.fits = (element.height < screen.height);
26559 element.offset = $module.offset();
26560 element.width = $module.outerWidth();
26561 element.height = $module.outerHeight();
26562 // compensate for scroll in context
26563 if(module.is.verticallyScrollableContext()) {
26564 element.offset.top += $context.scrollTop() - $context.offset().top;
26565 }
26566 if(module.is.horizontallyScrollableContext()) {
26567 element.offset.left += $context.scrollLeft - $context.offset().left;
26568 }
26569 // store
26570 module.cache.element = element;
26571 return element;
26572 },
26573 elementCalculations: function() {
26574 var
26575 screen = module.get.screenCalculations(),
26576 element = module.get.elementPosition()
26577 ;
26578 // offset
26579 if(settings.includeMargin) {
26580 element.margin = {};
26581 element.margin.top = parseInt($module.css('margin-top'), 10);
26582 element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
26583 element.top = element.offset.top - element.margin.top;
26584 element.bottom = element.offset.top + element.height + element.margin.bottom;
26585 }
26586 else {
26587 element.top = element.offset.top;
26588 element.bottom = element.offset.top + element.height;
26589 }
26590
26591 // visibility
26592 element.topPassed = (screen.top >= element.top);
26593 element.bottomPassed = (screen.top >= element.bottom);
26594 element.topVisible = (screen.bottom >= element.top) && !element.topPassed;
26595 element.bottomVisible = (screen.bottom >= element.bottom) && !element.bottomPassed;
26596 element.pixelsPassed = 0;
26597 element.percentagePassed = 0;
26598
26599 // meta calculations
26600 element.onScreen = ((element.topVisible || element.passing) && !element.bottomPassed);
26601 element.passing = (element.topPassed && !element.bottomPassed);
26602 element.offScreen = (!element.onScreen);
26603
26604 // passing calculations
26605 if(element.passing) {
26606 element.pixelsPassed = (screen.top - element.top);
26607 element.percentagePassed = (screen.top - element.top) / element.height;
26608 }
26609 module.cache.element = element;
26610 module.verbose('Updated element calculations', element);
26611 return element;
26612 },
26613 screenCalculations: function() {
26614 var
26615 scroll = module.get.scroll()
26616 ;
26617 module.save.direction();
26618 module.cache.screen.top = scroll;
26619 module.cache.screen.bottom = scroll + module.cache.screen.height;
26620 return module.cache.screen;
26621 },
26622 screenSize: function() {
26623 module.verbose('Saving window position');
26624 module.cache.screen = {
26625 height: $context.height()
26626 };
26627 },
26628 position: function() {
26629 module.save.screenSize();
26630 module.save.elementPosition();
26631 }
26632 },
26633
26634 get: {
26635 pixelsPassed: function(amount) {
26636 var
26637 element = module.get.elementCalculations()
26638 ;
26639 if(amount.search('%') > -1) {
26640 return ( element.height * (parseInt(amount, 10) / 100) );
26641 }
26642 return parseInt(amount, 10);
26643 },
26644 occurred: function(callback) {
26645 return (module.cache.occurred !== undefined)
26646 ? module.cache.occurred[callback] || false
26647 : false
26648 ;
26649 },
26650 direction: function() {
26651 if(module.cache.direction === undefined) {
26652 module.save.direction();
26653 }
26654 return module.cache.direction;
26655 },
26656 elementPosition: function() {
26657 if(module.cache.element === undefined) {
26658 module.save.elementPosition();
26659 }
26660 return module.cache.element;
26661 },
26662 elementCalculations: function() {
26663 if(module.cache.element === undefined) {
26664 module.save.elementCalculations();
26665 }
26666 return module.cache.element;
26667 },
26668 screenCalculations: function() {
26669 if(module.cache.screen === undefined) {
26670 module.save.screenCalculations();
26671 }
26672 return module.cache.screen;
26673 },
26674 screenSize: function() {
26675 if(module.cache.screen === undefined) {
26676 module.save.screenSize();
26677 }
26678 return module.cache.screen;
26679 },
26680 scroll: function() {
26681 if(module.cache.scroll === undefined) {
26682 module.save.scroll();
26683 }
26684 return module.cache.scroll;
26685 },
26686 lastScroll: function() {
26687 if(module.cache.screen === undefined) {
26688 module.debug('First scroll event, no last scroll could be found');
26689 return false;
26690 }
26691 return module.cache.screen.top;
26692 }
26693 },
26694
26695 setting: function(name, value) {
26696 if( $.isPlainObject(name) ) {
26697 $.extend(true, settings, name);
26698 }
26699 else if(value !== undefined) {
26700 settings[name] = value;
26701 }
26702 else {
26703 return settings[name];
26704 }
26705 },
26706 internal: function(name, value) {
26707 if( $.isPlainObject(name) ) {
26708 $.extend(true, module, name);
26709 }
26710 else if(value !== undefined) {
26711 module[name] = value;
26712 }
26713 else {
26714 return module[name];
26715 }
26716 },
26717 debug: function() {
26718 if(!settings.silent && settings.debug) {
26719 if(settings.performance) {
26720 module.performance.log(arguments);
26721 }
26722 else {
26723 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
26724 module.debug.apply(console, arguments);
26725 }
26726 }
26727 },
26728 verbose: function() {
26729 if(!settings.silent && settings.verbose && settings.debug) {
26730 if(settings.performance) {
26731 module.performance.log(arguments);
26732 }
26733 else {
26734 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
26735 module.verbose.apply(console, arguments);
26736 }
26737 }
26738 },
26739 error: function() {
26740 if(!settings.silent) {
26741 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
26742 module.error.apply(console, arguments);
26743 }
26744 },
26745 performance: {
26746 log: function(message) {
26747 var
26748 currentTime,
26749 executionTime,
26750 previousTime
26751 ;
26752 if(settings.performance) {
26753 currentTime = new Date().getTime();
26754 previousTime = time || currentTime;
26755 executionTime = currentTime - previousTime;
26756 time = currentTime;
26757 performance.push({
26758 'Name' : message[0],
26759 'Arguments' : [].slice.call(message, 1) || '',
26760 'Element' : element,
26761 'Execution Time' : executionTime
26762 });
26763 }
26764 clearTimeout(module.performance.timer);
26765 module.performance.timer = setTimeout(module.performance.display, 500);
26766 },
26767 display: function() {
26768 var
26769 title = settings.name + ':',
26770 totalTime = 0
26771 ;
26772 time = false;
26773 clearTimeout(module.performance.timer);
26774 $.each(performance, function(index, data) {
26775 totalTime += data['Execution Time'];
26776 });
26777 title += ' ' + totalTime + 'ms';
26778 if(moduleSelector) {
26779 title += ' \'' + moduleSelector + '\'';
26780 }
26781 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
26782 console.groupCollapsed(title);
26783 if(console.table) {
26784 console.table(performance);
26785 }
26786 else {
26787 $.each(performance, function(index, data) {
26788 console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
26789 });
26790 }
26791 console.groupEnd();
26792 }
26793 performance = [];
26794 }
26795 },
26796 invoke: function(query, passedArguments, context) {
26797 var
26798 object = instance,
26799 maxDepth,
26800 found,
26801 response
26802 ;
26803 passedArguments = passedArguments || queryArguments;
26804 context = element || context;
26805 if(typeof query == 'string' && object !== undefined) {
26806 query = query.split(/[\. ]/);
26807 maxDepth = query.length - 1;
26808 $.each(query, function(depth, value) {
26809 var camelCaseValue = (depth != maxDepth)
26810 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
26811 : query
26812 ;
26813 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
26814 object = object[camelCaseValue];
26815 }
26816 else if( object[camelCaseValue] !== undefined ) {
26817 found = object[camelCaseValue];
26818 return false;
26819 }
26820 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
26821 object = object[value];
26822 }
26823 else if( object[value] !== undefined ) {
26824 found = object[value];
26825 return false;
26826 }
26827 else {
26828 module.error(error.method, query);
26829 return false;
26830 }
26831 });
26832 }
26833 if ( $.isFunction( found ) ) {
26834 response = found.apply(context, passedArguments);
26835 }
26836 else if(found !== undefined) {
26837 response = found;
26838 }
26839 if(Array.isArray(returnedValue)) {
26840 returnedValue.push(response);
26841 }
26842 else if(returnedValue !== undefined) {
26843 returnedValue = [returnedValue, response];
26844 }
26845 else if(response !== undefined) {
26846 returnedValue = response;
26847 }
26848 return found;
26849 }
26850 };
26851
26852 if(methodInvoked) {
26853 if(instance === undefined) {
26854 module.initialize();
26855 }
26856 instance.save.scroll();
26857 instance.save.calculations();
26858 module.invoke(query);
26859 }
26860 else {
26861 if(instance !== undefined) {
26862 instance.invoke('destroy');
26863 }
26864 module.initialize();
26865 }
26866 })
26867 ;
26868
26869 return (returnedValue !== undefined)
26870 ? returnedValue
26871 : this
26872 ;
26873};
26874
26875$.fn.visibility.settings = {
26876
26877 name : 'Visibility',
26878 namespace : 'visibility',
26879
26880 debug : false,
26881 verbose : false,
26882 performance : true,
26883
26884 // whether to use mutation observers to follow changes
26885 observeChanges : true,
26886
26887 // check position immediately on init
26888 initialCheck : true,
26889
26890 // whether to refresh calculations after all page images load
26891 refreshOnLoad : true,
26892
26893 // whether to refresh calculations after page resize event
26894 refreshOnResize : true,
26895
26896 // should call callbacks on refresh event (resize, etc)
26897 checkOnRefresh : true,
26898
26899 // callback should only occur one time
26900 once : true,
26901
26902 // callback should fire continuously whe evaluates to true
26903 continuous : false,
26904
26905 // offset to use with scroll top
26906 offset : 0,
26907
26908 // whether to include margin in elements position
26909 includeMargin : false,
26910
26911 // scroll context for visibility checks
26912 context : window,
26913
26914 // visibility check delay in ms (defaults to animationFrame)
26915 throttle : false,
26916
26917 // special visibility type (image, fixed)
26918 type : false,
26919
26920 // z-index to use with visibility 'fixed'
26921 zIndex : '10',
26922
26923 // image only animation settings
26924 transition : 'fade in',
26925 duration : 1000,
26926
26927 // array of callbacks for percentage
26928 onPassed : {},
26929
26930 // standard callbacks
26931 onOnScreen : false,
26932 onOffScreen : false,
26933 onPassing : false,
26934 onTopVisible : false,
26935 onBottomVisible : false,
26936 onTopPassed : false,
26937 onBottomPassed : false,
26938
26939 // reverse callbacks
26940 onPassingReverse : false,
26941 onTopVisibleReverse : false,
26942 onBottomVisibleReverse : false,
26943 onTopPassedReverse : false,
26944 onBottomPassedReverse : false,
26945
26946 // special callbacks for image
26947 onLoad : function() {},
26948 onAllLoaded : function() {},
26949
26950 // special callbacks for fixed position
26951 onFixed : function() {},
26952 onUnfixed : function() {},
26953
26954 // utility callbacks
26955 onUpdate : false, // disabled by default for performance
26956 onRefresh : function(){},
26957
26958 metadata : {
26959 src: 'src'
26960 },
26961
26962 className: {
26963 fixed : 'fixed',
26964 placeholder : 'constraint',
26965 visible : 'visible'
26966 },
26967
26968 error : {
26969 method : 'The method you called is not defined.',
26970 visible : 'Element is hidden, you must call refresh after element becomes visible'
26971 }
26972
26973};
26974
26975})( jQuery, window, document );