github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/static/semantic/dist/semantic.js (about) 1 /* 2 * # Semantic UI - x.x 3 * https://github.com/Semantic-Org/Semantic-UI 4 * http://www.semantic-ui.com/ 5 * 6 * Copyright 2014 Contributors 7 * Released under the MIT license 8 * http://opensource.org/licenses/MIT 9 * 10 */ 11 /*! 12 * # Semantic UI x.x - Site 13 * http://github.com/semantic-org/semantic-ui/ 14 * 15 * 16 * Copyright 2014 Contributors 17 * Released under the MIT license 18 * http://opensource.org/licenses/MIT 19 * 20 */ 21 ;(function ( $, window, document, undefined ) { 22 23 $.site = $.fn.site = function(parameters) { 24 var 25 time = new Date().getTime(), 26 performance = [], 27 28 query = arguments[0], 29 methodInvoked = (typeof query == 'string'), 30 queryArguments = [].slice.call(arguments, 1), 31 32 settings = ( $.isPlainObject(parameters) ) 33 ? $.extend(true, {}, $.site.settings, parameters) 34 : $.extend({}, $.site.settings), 35 36 namespace = settings.namespace, 37 error = settings.error, 38 39 eventNamespace = '.' + namespace, 40 moduleNamespace = 'module-' + namespace, 41 42 $document = $(document), 43 $module = $document, 44 element = this, 45 instance = $module.data(moduleNamespace), 46 47 module, 48 returnedValue 49 ; 50 module = { 51 52 initialize: function() { 53 module.instantiate(); 54 }, 55 56 instantiate: function() { 57 module.verbose('Storing instance of site', module); 58 instance = module; 59 $module 60 .data(moduleNamespace, module) 61 ; 62 }, 63 64 normalize: function() { 65 module.fix.console(); 66 module.fix.requestAnimationFrame(); 67 }, 68 69 fix: { 70 console: function() { 71 module.debug('Normalizing window.console'); 72 if (console === undefined || console.log === undefined) { 73 module.verbose('Console not available, normalizing events'); 74 module.disable.console(); 75 } 76 if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') { 77 module.verbose('Console group not available, normalizing events'); 78 window.console.group = function() {}; 79 window.console.groupEnd = function() {}; 80 window.console.groupCollapsed = function() {}; 81 } 82 if (typeof console.markTimeline == 'undefined') { 83 module.verbose('Mark timeline not available, normalizing events'); 84 window.console.markTimeline = function() {}; 85 } 86 }, 87 consoleClear: function() { 88 module.debug('Disabling programmatic console clearing'); 89 window.console.clear = function() {}; 90 }, 91 requestAnimationFrame: function() { 92 module.debug('Normalizing requestAnimationFrame'); 93 if(window.requestAnimationFrame === undefined) { 94 module.debug('RequestAnimationFrame not available, normailizing event'); 95 window.requestAnimationFrame = window.requestAnimationFrame 96 || window.mozRequestAnimationFrame 97 || window.webkitRequestAnimationFrame 98 || window.msRequestAnimationFrame 99 || function(callback) { setTimeout(callback, 0); } 100 ; 101 } 102 } 103 }, 104 105 moduleExists: function(name) { 106 return ($.fn[name] !== undefined && $.fn[name].settings !== undefined); 107 }, 108 109 enabled: { 110 modules: function(modules) { 111 var 112 enabledModules = [] 113 ; 114 modules = modules || settings.modules; 115 $.each(modules, function(index, name) { 116 if(module.moduleExists(name)) { 117 enabledModules.push(name); 118 } 119 }); 120 return enabledModules; 121 } 122 }, 123 124 disabled: { 125 modules: function(modules) { 126 var 127 disabledModules = [] 128 ; 129 modules = modules || settings.modules; 130 $.each(modules, function(index, name) { 131 if(!module.moduleExists(name)) { 132 disabledModules.push(name); 133 } 134 }); 135 return disabledModules; 136 } 137 }, 138 139 change: { 140 setting: function(setting, value, modules, modifyExisting) { 141 modules = (typeof modules === 'string') 142 ? (modules === 'all') 143 ? settings.modules 144 : [modules] 145 : modules || settings.modules 146 ; 147 modifyExisting = (modifyExisting !== undefined) 148 ? modifyExisting 149 : true 150 ; 151 $.each(modules, function(index, name) { 152 var 153 namespace = (module.moduleExists(name)) 154 ? $.fn[name].settings.namespace || false 155 : true, 156 $existingModules 157 ; 158 if(module.moduleExists(name)) { 159 module.verbose('Changing default setting', setting, value, name); 160 $.fn[name].settings[setting] = value; 161 if(modifyExisting && namespace) { 162 $existingModules = $(':data(module-' + namespace + ')'); 163 if($existingModules.length > 0) { 164 module.verbose('Modifying existing settings', $existingModules); 165 $existingModules[name]('setting', setting, value); 166 } 167 } 168 } 169 }); 170 }, 171 settings: function(newSettings, modules, modifyExisting) { 172 modules = (typeof modules === 'string') 173 ? [modules] 174 : modules || settings.modules 175 ; 176 modifyExisting = (modifyExisting !== undefined) 177 ? modifyExisting 178 : true 179 ; 180 $.each(modules, function(index, name) { 181 var 182 $existingModules 183 ; 184 if(module.moduleExists(name)) { 185 module.verbose('Changing default setting', newSettings, name); 186 $.extend(true, $.fn[name].settings, newSettings); 187 if(modifyExisting && namespace) { 188 $existingModules = $(':data(module-' + namespace + ')'); 189 if($existingModules.length > 0) { 190 module.verbose('Modifying existing settings', $existingModules); 191 $existingModules[name]('setting', newSettings); 192 } 193 } 194 } 195 }); 196 } 197 }, 198 199 enable: { 200 console: function() { 201 module.console(true); 202 }, 203 debug: function(modules, modifyExisting) { 204 modules = modules || settings.modules; 205 module.debug('Enabling debug for modules', modules); 206 module.change.setting('debug', true, modules, modifyExisting); 207 }, 208 verbose: function(modules, modifyExisting) { 209 modules = modules || settings.modules; 210 module.debug('Enabling verbose debug for modules', modules); 211 module.change.setting('verbose', true, modules, modifyExisting); 212 } 213 }, 214 disable: { 215 console: function() { 216 module.console(false); 217 }, 218 debug: function(modules, modifyExisting) { 219 modules = modules || settings.modules; 220 module.debug('Disabling debug for modules', modules); 221 module.change.setting('debug', false, modules, modifyExisting); 222 }, 223 verbose: function(modules, modifyExisting) { 224 modules = modules || settings.modules; 225 module.debug('Disabling verbose debug for modules', modules); 226 module.change.setting('verbose', false, modules, modifyExisting); 227 } 228 }, 229 230 console: function(enable) { 231 if(enable) { 232 if(instance.cache.console === undefined) { 233 module.error(error.console); 234 return; 235 } 236 module.debug('Restoring console function'); 237 window.console = instance.cache.console; 238 } 239 else { 240 module.debug('Disabling console function'); 241 instance.cache.console = window.console; 242 window.console = { 243 clear : function(){}, 244 error : function(){}, 245 group : function(){}, 246 groupCollapsed : function(){}, 247 groupEnd : function(){}, 248 info : function(){}, 249 log : function(){}, 250 markTimeline : function(){}, 251 warn : function(){} 252 }; 253 } 254 }, 255 256 destroy: function() { 257 module.verbose('Destroying previous site for', $module); 258 $module 259 .removeData(moduleNamespace) 260 ; 261 }, 262 263 cache: {}, 264 265 setting: function(name, value) { 266 if( $.isPlainObject(name) ) { 267 $.extend(true, settings, name); 268 } 269 else if(value !== undefined) { 270 settings[name] = value; 271 } 272 else { 273 return settings[name]; 274 } 275 }, 276 internal: function(name, value) { 277 if( $.isPlainObject(name) ) { 278 $.extend(true, module, name); 279 } 280 else if(value !== undefined) { 281 module[name] = value; 282 } 283 else { 284 return module[name]; 285 } 286 }, 287 debug: function() { 288 if(settings.debug) { 289 if(settings.performance) { 290 module.performance.log(arguments); 291 } 292 else { 293 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 294 module.debug.apply(console, arguments); 295 } 296 } 297 }, 298 verbose: function() { 299 if(settings.verbose && settings.debug) { 300 if(settings.performance) { 301 module.performance.log(arguments); 302 } 303 else { 304 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 305 module.verbose.apply(console, arguments); 306 } 307 } 308 }, 309 error: function() { 310 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 311 module.error.apply(console, arguments); 312 }, 313 performance: { 314 log: function(message) { 315 var 316 currentTime, 317 executionTime, 318 previousTime 319 ; 320 if(settings.performance) { 321 currentTime = new Date().getTime(); 322 previousTime = time || currentTime; 323 executionTime = currentTime - previousTime; 324 time = currentTime; 325 performance.push({ 326 'Element' : element, 327 'Name' : message[0], 328 'Arguments' : [].slice.call(message, 1) || '', 329 'Execution Time' : executionTime 330 }); 331 } 332 clearTimeout(module.performance.timer); 333 module.performance.timer = setTimeout(module.performance.display, 100); 334 }, 335 display: function() { 336 var 337 title = settings.name + ':', 338 totalTime = 0 339 ; 340 time = false; 341 clearTimeout(module.performance.timer); 342 $.each(performance, function(index, data) { 343 totalTime += data['Execution Time']; 344 }); 345 title += ' ' + totalTime + 'ms'; 346 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 347 console.groupCollapsed(title); 348 if(console.table) { 349 console.table(performance); 350 } 351 else { 352 $.each(performance, function(index, data) { 353 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 354 }); 355 } 356 console.groupEnd(); 357 } 358 performance = []; 359 } 360 }, 361 invoke: function(query, passedArguments, context) { 362 var 363 object = instance, 364 maxDepth, 365 found, 366 response 367 ; 368 passedArguments = passedArguments || queryArguments; 369 context = element || context; 370 if(typeof query == 'string' && object !== undefined) { 371 query = query.split(/[\. ]/); 372 maxDepth = query.length - 1; 373 $.each(query, function(depth, value) { 374 var camelCaseValue = (depth != maxDepth) 375 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 376 : query 377 ; 378 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 379 object = object[camelCaseValue]; 380 } 381 else if( object[camelCaseValue] !== undefined ) { 382 found = object[camelCaseValue]; 383 return false; 384 } 385 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 386 object = object[value]; 387 } 388 else if( object[value] !== undefined ) { 389 found = object[value]; 390 return false; 391 } 392 else { 393 module.error(error.method, query); 394 return false; 395 } 396 }); 397 } 398 if ( $.isFunction( found ) ) { 399 response = found.apply(context, passedArguments); 400 } 401 else if(found !== undefined) { 402 response = found; 403 } 404 if($.isArray(returnedValue)) { 405 returnedValue.push(response); 406 } 407 else if(returnedValue !== undefined) { 408 returnedValue = [returnedValue, response]; 409 } 410 else if(response !== undefined) { 411 returnedValue = response; 412 } 413 return found; 414 } 415 }; 416 417 if(methodInvoked) { 418 if(instance === undefined) { 419 module.initialize(); 420 } 421 module.invoke(query); 422 } 423 else { 424 if(instance !== undefined) { 425 module.destroy(); 426 } 427 module.initialize(); 428 } 429 return (returnedValue !== undefined) 430 ? returnedValue 431 : this 432 ; 433 }; 434 435 $.site.settings = { 436 437 name : 'Site', 438 namespace : 'site', 439 440 error : { 441 console : 'Console cannot be restored, most likely it was overwritten outside of module', 442 method : 'The method you called is not defined.' 443 }, 444 445 debug : false, 446 verbose : true, 447 performance : true, 448 449 modules: [ 450 'accordion', 451 'api', 452 'checkbox', 453 'dimmer', 454 'dropdown', 455 'form', 456 'modal', 457 'nag', 458 'popup', 459 'rating', 460 'shape', 461 'sidebar', 462 'state', 463 'sticky', 464 'tab', 465 'transition', 466 'video', 467 'visit', 468 'visibility' 469 ], 470 471 siteNamespace : 'site', 472 namespaceStub : { 473 cache : {}, 474 config : {}, 475 sections : {}, 476 section : {}, 477 utilities : {} 478 } 479 480 }; 481 482 // allows for selection of elements with data attributes 483 $.extend($.expr[ ":" ], { 484 data: ($.expr.createPseudo) 485 ? $.expr.createPseudo(function(dataName) { 486 return function(elem) { 487 return !!$.data(elem, dataName); 488 }; 489 }) 490 : function(elem, i, match) { 491 // support: jQuery < 1.8 492 return !!$.data(elem, match[ 3 ]); 493 } 494 }); 495 496 497 })( jQuery, window , document ); 498 /*! 499 * # Semantic UI x.x - Form Validation 500 * http://github.com/semantic-org/semantic-ui/ 501 * 502 * 503 * Copyright 2014 Contributors 504 * Released under the MIT license 505 * http://opensource.org/licenses/MIT 506 * 507 */ 508 509 ;(function ( $, window, document, undefined ) { 510 511 "use strict"; 512 513 $.fn.form = function(fields, parameters) { 514 var 515 $allModules = $(this), 516 517 settings = $.extend(true, {}, $.fn.form.settings, parameters), 518 validation = $.extend({}, $.fn.form.settings.defaults, fields), 519 520 namespace = settings.namespace, 521 metadata = settings.metadata, 522 selector = settings.selector, 523 className = settings.className, 524 error = settings.error, 525 526 eventNamespace = '.' + namespace, 527 moduleNamespace = 'module-' + namespace, 528 529 moduleSelector = $allModules.selector || '', 530 531 time = new Date().getTime(), 532 performance = [], 533 534 query = arguments[0], 535 methodInvoked = (typeof query == 'string'), 536 queryArguments = [].slice.call(arguments, 1), 537 returnedValue 538 ; 539 $allModules 540 .each(function() { 541 var 542 $module = $(this), 543 $field = $(this).find(selector.field), 544 $group = $(this).find(selector.group), 545 $message = $(this).find(selector.message), 546 $prompt = $(this).find(selector.prompt), 547 548 $submit = $(this).find(selector.submit), 549 $clear = $(this).find(selector.clear), 550 $reset = $(this).find(selector.reset), 551 552 formErrors = [], 553 keyHeldDown = false, 554 555 element = this, 556 instance = $module.data(moduleNamespace), 557 module 558 ; 559 560 module = { 561 562 initialize: function() { 563 module.verbose('Initializing form validation', $module, validation, settings); 564 module.bindEvents(); 565 module.set.defaults(); 566 module.instantiate(); 567 }, 568 569 instantiate: function() { 570 module.verbose('Storing instance of module', module); 571 instance = module; 572 $module 573 .data(moduleNamespace, module) 574 ; 575 }, 576 577 destroy: function() { 578 module.verbose('Destroying previous module', instance); 579 module.removeEvents(); 580 $module 581 .removeData(moduleNamespace) 582 ; 583 }, 584 585 refresh: function() { 586 module.verbose('Refreshing selector cache'); 587 $field = $module.find(selector.field); 588 }, 589 590 submit: function() { 591 module.verbose('Submitting form', $module); 592 $module 593 .submit() 594 ; 595 }, 596 597 attachEvents: function(selector, action) { 598 action = action || 'submit'; 599 $(selector) 600 .on('click', function(event) { 601 module[action](); 602 event.preventDefault(); 603 }) 604 ; 605 }, 606 607 bindEvents: function() { 608 if(settings.keyboardShortcuts) { 609 $field 610 .on('keydown' + eventNamespace, module.event.field.keydown) 611 ; 612 } 613 $module 614 .on('submit' + eventNamespace, module.validate.form) 615 ; 616 $field 617 .on('blur' + eventNamespace, module.event.field.blur) 618 ; 619 620 // attach events to common elements 621 module.attachEvents($submit, 'submit'); 622 module.attachEvents($reset, 'reset'); 623 module.attachEvents($clear, 'clear'); 624 625 $field 626 .each(function() { 627 var 628 type = $(this).prop('type'), 629 inputEvent = module.get.changeEvent(type) 630 ; 631 $(this) 632 .on(inputEvent + eventNamespace, module.event.field.change) 633 ; 634 }) 635 ; 636 }, 637 638 clear: function() { 639 $field 640 .each(function () { 641 var 642 $field = $(this), 643 $element = $field.parent(), 644 $fieldGroup = $field.closest($group), 645 $prompt = $fieldGroup.find(selector.prompt), 646 defaultValue = $field.data(metadata.defaultValue) || '', 647 isCheckbox = $element.is(selector.uiCheckbox), 648 isDropdown = $element.is(selector.uiDropdown), 649 isErrored = $fieldGroup.hasClass(className.error) 650 ; 651 if(isErrored) { 652 module.verbose('Resetting error on field', $fieldGroup); 653 $fieldGroup.removeClass(className.error); 654 $prompt.remove(); 655 } 656 if(isDropdown) { 657 module.verbose('Resetting dropdown value', $element, defaultValue); 658 $element.dropdown('clear'); 659 } 660 else if(isCheckbox) { 661 $element.checkbox('uncheck'); 662 } 663 else { 664 module.verbose('Resetting field value', $field, defaultValue); 665 $field.val(''); 666 } 667 }) 668 ; 669 }, 670 671 reset: function() { 672 $field 673 .each(function () { 674 var 675 $field = $(this), 676 $element = $field.parent(), 677 $fieldGroup = $field.closest($group), 678 $prompt = $fieldGroup.find(selector.prompt), 679 defaultValue = $field.data(metadata.defaultValue) || '', 680 isCheckbox = $element.is(selector.uiCheckbox), 681 isDropdown = $element.is(selector.uiDropdown), 682 isErrored = $fieldGroup.hasClass(className.error) 683 ; 684 if(isErrored) { 685 module.verbose('Resetting error on field', $fieldGroup); 686 $fieldGroup.removeClass(className.error); 687 $prompt.remove(); 688 } 689 if(isDropdown) { 690 module.verbose('Resetting dropdown value', $element, defaultValue); 691 $element.dropdown('restore defaults'); 692 } 693 else if(isCheckbox) { 694 module.verbose('Resetting checkbox value', $element, defaultValue); 695 if(defaultValue === true) { 696 $element.checkbox('check'); 697 } 698 else { 699 $element.checkbox('uncheck'); 700 } 701 } 702 else { 703 module.verbose('Resetting field value', $field, defaultValue); 704 $field.val(defaultValue); 705 } 706 }) 707 ; 708 }, 709 710 removeEvents: function() { 711 $module 712 .off(eventNamespace) 713 ; 714 $field 715 .off(eventNamespace) 716 ; 717 $submit 718 .off(eventNamespace) 719 ; 720 $field 721 .off(eventNamespace) 722 ; 723 }, 724 725 event: { 726 field: { 727 keydown: function(event) { 728 var 729 $field = $(this), 730 key = event.which, 731 keyCode = { 732 enter : 13, 733 escape : 27 734 } 735 ; 736 if( key == keyCode.escape) { 737 module.verbose('Escape key pressed blurring field'); 738 $field 739 .blur() 740 ; 741 } 742 if(!event.ctrlKey && key == keyCode.enter && $field.is(selector.input) && $field.not(selector.checkbox).length > 0 ) { 743 $submit 744 .addClass(className.pressed) 745 ; 746 if(!keyHeldDown) { 747 $field 748 .one('keyup' + eventNamespace, module.event.field.keyup) 749 ; 750 module.submit(); 751 module.debug('Enter pressed on input submitting form'); 752 } 753 keyHeldDown = true; 754 } 755 }, 756 keyup: function() { 757 keyHeldDown = false; 758 $submit.removeClass(className.pressed); 759 }, 760 blur: function() { 761 var 762 $field = $(this), 763 $fieldGroup = $field.closest($group) 764 ; 765 if( $fieldGroup.hasClass(className.error) ) { 766 module.debug('Revalidating field', $field, module.get.validation($field)); 767 module.validate.field( module.get.validation($field) ); 768 } 769 else if(settings.on == 'blur' || settings.on == 'change') { 770 module.validate.field( module.get.validation($field) ); 771 } 772 }, 773 change: function() { 774 var 775 $field = $(this), 776 $fieldGroup = $field.closest($group) 777 ; 778 if(settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) ) { 779 clearTimeout(module.timer); 780 module.timer = setTimeout(function() { 781 module.debug('Revalidating field', $field, module.get.validation($field)); 782 module.validate.field( module.get.validation($field) ); 783 }, settings.delay); 784 } 785 } 786 } 787 788 }, 789 790 get: { 791 changeEvent: function(type) { 792 if(type == 'checkbox' || type == 'radio' || type == 'hidden') { 793 return 'change'; 794 } 795 else { 796 return module.get.inputEvent(); 797 } 798 }, 799 inputEvent: function() { 800 return (document.createElement('input').oninput !== undefined) 801 ? 'input' 802 : (document.createElement('input').onpropertychange !== undefined) 803 ? 'propertychange' 804 : 'keyup' 805 ; 806 }, 807 field: function(identifier) { 808 module.verbose('Finding field with identifier', identifier); 809 if( $field.filter('#' + identifier).length > 0 ) { 810 return $field.filter('#' + identifier); 811 } 812 else if( $field.filter('[name="' + identifier +'"]').length > 0 ) { 813 return $field.filter('[name="' + identifier +'"]'); 814 } 815 else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) { 816 return $field.filter('[name="' + identifier +'[]"]'); 817 } 818 else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) { 819 return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]'); 820 } 821 return $('<input/>'); 822 }, 823 fields: function(fields) { 824 var 825 $fields = $() 826 ; 827 $.each(fields, function(index, name) { 828 $fields = $fields.add( module.get.field(name) ); 829 }); 830 return $fields; 831 }, 832 validation: function($field) { 833 var 834 rules 835 ; 836 $.each(validation, function(fieldName, field) { 837 if( module.get.field(field.identifier).get(0) == $field.get(0) ) { 838 rules = field; 839 } 840 }); 841 return rules || false; 842 }, 843 value: function (field) { 844 var 845 fields = [], 846 results 847 ; 848 fields.push(field); 849 results = module.get.values.call(element, fields); 850 return results[field]; 851 }, 852 values: function (fields) { 853 var 854 $fields = $.isArray(fields) 855 ? module.get.fields(fields) 856 : $field, 857 values = {} 858 ; 859 $fields.each(function(index, field) { 860 var 861 $field = $(field), 862 type = $field.prop('type'), 863 name = $field.prop('name'), 864 value = $field.val(), 865 isCheckbox = $field.is(selector.checkbox), 866 isRadio = $field.is(selector.radio), 867 isMultiple = (name.indexOf('[]') !== -1), 868 isChecked = (isCheckbox) 869 ? $field.is(':checked') 870 : false 871 ; 872 if(name) { 873 if(isMultiple) { 874 name = name.replace('[]', ''); 875 if(!values[name]) { 876 values[name] = []; 877 } 878 if(isCheckbox) { 879 if(isChecked) { 880 values[name].push(value) 881 } 882 else { 883 module.debug('Omitted unchecked checkbox', $field); 884 return true; 885 } 886 } 887 else { 888 values[name].push(value); 889 } 890 } 891 else { 892 if(isRadio) { 893 if(isChecked) { 894 values[name] = value; 895 } 896 } 897 else if(isCheckbox) { 898 if(isChecked) { 899 values[name] = true; 900 } 901 else { 902 module.debug('Omitted unchecked checkbox', $field); 903 return true; 904 } 905 } 906 else { 907 values[name] = value; 908 } 909 } 910 } 911 }); 912 return values; 913 } 914 }, 915 916 has: { 917 918 field: function(identifier) { 919 module.verbose('Checking for existence of a field with identifier', identifier); 920 if( $field.filter('#' + identifier).length > 0 ) { 921 return true; 922 } 923 else if( $field.filter('[name="' + identifier +'"]').length > 0 ) { 924 return true; 925 } 926 else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) { 927 return true; 928 } 929 return false; 930 } 931 932 }, 933 934 add: { 935 prompt: function(identifier, errors) { 936 var 937 $field = module.get.field(identifier), 938 $fieldGroup = $field.closest($group), 939 $prompt = $fieldGroup.children(selector.prompt), 940 promptExists = ($prompt.length !== 0) 941 ; 942 errors = (typeof errors == 'string') 943 ? [errors] 944 : errors 945 ; 946 module.verbose('Adding field error state', identifier); 947 $fieldGroup 948 .addClass(className.error) 949 ; 950 if(settings.inline) { 951 if(!promptExists) { 952 $prompt = settings.templates.prompt(errors); 953 $prompt 954 .appendTo($fieldGroup) 955 ; 956 } 957 $prompt 958 .html(errors[0]) 959 ; 960 if(!promptExists) { 961 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 962 module.verbose('Displaying error with css transition', settings.transition); 963 $prompt.transition(settings.transition + ' in', settings.duration); 964 } 965 else { 966 module.verbose('Displaying error with fallback javascript animation'); 967 $prompt 968 .fadeIn(settings.duration) 969 ; 970 } 971 } 972 else { 973 module.verbose('Inline errors are disabled, no inline error added', identifier); 974 } 975 } 976 }, 977 errors: function(errors) { 978 module.debug('Adding form error messages', errors); 979 $message 980 .html( settings.templates.error(errors) ) 981 ; 982 } 983 }, 984 985 remove: { 986 prompt: function(field) { 987 var 988 $field = module.get.field(field.identifier), 989 $fieldGroup = $field.closest($group), 990 $prompt = $fieldGroup.children(selector.prompt) 991 ; 992 $fieldGroup 993 .removeClass(className.error) 994 ; 995 if(settings.inline && $prompt.is(':visible')) { 996 module.verbose('Removing prompt for field', field); 997 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 998 $prompt.transition(settings.transition + ' out', settings.duration, function() { 999 $prompt.remove(); 1000 }); 1001 } 1002 else { 1003 $prompt 1004 .fadeOut(settings.duration, function(){ 1005 $prompt.remove(); 1006 }) 1007 ; 1008 } 1009 } 1010 } 1011 }, 1012 1013 set: { 1014 success: function() { 1015 $module 1016 .removeClass(className.error) 1017 .addClass(className.success) 1018 ; 1019 }, 1020 defaults: function () { 1021 $field 1022 .each(function () { 1023 var 1024 $field = $(this), 1025 isCheckbox = ($field.filter(selector.checkbox).length > 0), 1026 value = (isCheckbox) 1027 ? $field.is(':checked') 1028 : $field.val() 1029 ; 1030 $field.data(metadata.defaultValue, value); 1031 }) 1032 ; 1033 }, 1034 error: function() { 1035 $module 1036 .removeClass(className.success) 1037 .addClass(className.error) 1038 ; 1039 }, 1040 value: function (field, value) { 1041 var 1042 fields = {} 1043 ; 1044 fields[field] = value; 1045 return module.set.values.call(element, fields); 1046 }, 1047 values: function (fields) { 1048 if($.isEmptyObject(fields)) { 1049 return; 1050 } 1051 $.each(fields, function(key, value) { 1052 var 1053 $field = module.get.field(key), 1054 $element = $field.parent(), 1055 isMultiple = $.isArray(value), 1056 isCheckbox = $element.is(selector.uiCheckbox), 1057 isDropdown = $element.is(selector.uiDropdown), 1058 isRadio = ($field.is(selector.radio) && isCheckbox), 1059 fieldExists = ($field.length > 0), 1060 $multipleField 1061 ; 1062 if(fieldExists) { 1063 if(isMultiple && isCheckbox) { 1064 module.verbose('Selecting multiple', value, $field); 1065 $element.checkbox('uncheck'); 1066 $.each(value, function(index, value) { 1067 $multipleField = $field.filter('[value="' + value + '"]'); 1068 $element = $multipleField.parent(); 1069 if($multipleField.length > 0) { 1070 $element.checkbox('check'); 1071 } 1072 }); 1073 } 1074 else if(isRadio) { 1075 module.verbose('Selecting radio value', value, $field); 1076 $field.filter('[value="' + value + '"]') 1077 .parent(selector.uiCheckbox) 1078 .checkbox('check') 1079 ; 1080 } 1081 else if(isCheckbox) { 1082 module.verbose('Setting checkbox value', value, $element); 1083 if(value === true) { 1084 $element.checkbox('check'); 1085 } 1086 else { 1087 $element.checkbox('uncheck'); 1088 } 1089 } 1090 else if(isDropdown) { 1091 module.verbose('Setting dropdown value', value, $element); 1092 $element.dropdown('set selected', value); 1093 } 1094 else { 1095 module.verbose('Setting field value', value, $field); 1096 $field.val(value); 1097 } 1098 } 1099 }); 1100 module.validate.form(); 1101 } 1102 }, 1103 1104 validate: { 1105 1106 form: function(event) { 1107 var 1108 allValid = true, 1109 apiRequest 1110 ; 1111 1112 // input keydown event will fire submit repeatedly by browser default 1113 if(keyHeldDown) { 1114 return false; 1115 } 1116 1117 // reset errors 1118 formErrors = []; 1119 $.each(validation, function(fieldName, field) { 1120 if( !( module.validate.field(field) ) ) { 1121 allValid = false; 1122 } 1123 }); 1124 if(allValid) { 1125 module.debug('Form has no validation errors, submitting'); 1126 module.set.success(); 1127 return settings.onSuccess.call(element, event); 1128 } 1129 else { 1130 module.debug('Form has errors'); 1131 module.set.error(); 1132 if(!settings.inline) { 1133 module.add.errors(formErrors); 1134 } 1135 // prevent ajax submit 1136 if($module.data('moduleApi') !== undefined) { 1137 event.stopImmediatePropagation(); 1138 } 1139 return settings.onFailure.call(element, formErrors); 1140 } 1141 }, 1142 1143 // takes a validation object and returns whether field passes validation 1144 field: function(field) { 1145 var 1146 $field = module.get.field(field.identifier), 1147 fieldValid = true, 1148 fieldErrors = [] 1149 ; 1150 if($field.prop('disabled')) { 1151 module.debug('Field is disabled. Skipping', field.identifier); 1152 fieldValid = true; 1153 } 1154 else if(field.optional && $.trim($field.val()) === ''){ 1155 module.debug('Field is optional and empty. Skipping', field.identifier); 1156 fieldValid = true; 1157 } 1158 else if(field.rules !== undefined) { 1159 $.each(field.rules, function(index, rule) { 1160 if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) { 1161 module.debug('Field is invalid', field.identifier, rule.type); 1162 fieldErrors.push(rule.prompt); 1163 fieldValid = false; 1164 } 1165 }); 1166 } 1167 if(fieldValid) { 1168 module.remove.prompt(field, fieldErrors); 1169 settings.onValid.call($field); 1170 } 1171 else { 1172 formErrors = formErrors.concat(fieldErrors); 1173 module.add.prompt(field.identifier, fieldErrors); 1174 settings.onInvalid.call($field, fieldErrors); 1175 return false; 1176 } 1177 return true; 1178 }, 1179 1180 // takes validation rule and returns whether field passes rule 1181 rule: function(field, validation) { 1182 var 1183 $field = module.get.field(field.identifier), 1184 type = validation.type, 1185 value = $.trim($field.val() + ''), 1186 1187 bracketRegExp = /\[(.*)\]/i, 1188 bracket = bracketRegExp.exec(type), 1189 isValid = true, 1190 ancillary, 1191 functionType 1192 ; 1193 // if bracket notation is used, pass in extra parameters 1194 if(bracket !== undefined && bracket !== null) { 1195 ancillary = '' + bracket[1]; 1196 functionType = type.replace(bracket[0], ''); 1197 isValid = settings.rules[functionType].call(element, value, ancillary); 1198 } 1199 // normal notation 1200 else { 1201 isValid = settings.rules[type].call($field, value); 1202 } 1203 return isValid; 1204 } 1205 }, 1206 1207 setting: function(name, value) { 1208 if( $.isPlainObject(name) ) { 1209 $.extend(true, settings, name); 1210 } 1211 else if(value !== undefined) { 1212 settings[name] = value; 1213 } 1214 else { 1215 return settings[name]; 1216 } 1217 }, 1218 internal: function(name, value) { 1219 if( $.isPlainObject(name) ) { 1220 $.extend(true, module, name); 1221 } 1222 else if(value !== undefined) { 1223 module[name] = value; 1224 } 1225 else { 1226 return module[name]; 1227 } 1228 }, 1229 debug: function() { 1230 if(settings.debug) { 1231 if(settings.performance) { 1232 module.performance.log(arguments); 1233 } 1234 else { 1235 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 1236 module.debug.apply(console, arguments); 1237 } 1238 } 1239 }, 1240 verbose: function() { 1241 if(settings.verbose && settings.debug) { 1242 if(settings.performance) { 1243 module.performance.log(arguments); 1244 } 1245 else { 1246 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 1247 module.verbose.apply(console, arguments); 1248 } 1249 } 1250 }, 1251 error: function() { 1252 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 1253 module.error.apply(console, arguments); 1254 }, 1255 performance: { 1256 log: function(message) { 1257 var 1258 currentTime, 1259 executionTime, 1260 previousTime 1261 ; 1262 if(settings.performance) { 1263 currentTime = new Date().getTime(); 1264 previousTime = time || currentTime; 1265 executionTime = currentTime - previousTime; 1266 time = currentTime; 1267 performance.push({ 1268 'Name' : message[0], 1269 'Arguments' : [].slice.call(message, 1) || '', 1270 'Element' : element, 1271 'Execution Time' : executionTime 1272 }); 1273 } 1274 clearTimeout(module.performance.timer); 1275 module.performance.timer = setTimeout(module.performance.display, 100); 1276 }, 1277 display: function() { 1278 var 1279 title = settings.name + ':', 1280 totalTime = 0 1281 ; 1282 time = false; 1283 clearTimeout(module.performance.timer); 1284 $.each(performance, function(index, data) { 1285 totalTime += data['Execution Time']; 1286 }); 1287 title += ' ' + totalTime + 'ms'; 1288 if(moduleSelector) { 1289 title += ' \'' + moduleSelector + '\''; 1290 } 1291 if($allModules.length > 1) { 1292 title += ' ' + '(' + $allModules.length + ')'; 1293 } 1294 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 1295 console.groupCollapsed(title); 1296 if(console.table) { 1297 console.table(performance); 1298 } 1299 else { 1300 $.each(performance, function(index, data) { 1301 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 1302 }); 1303 } 1304 console.groupEnd(); 1305 } 1306 performance = []; 1307 } 1308 }, 1309 invoke: function(query, passedArguments, context) { 1310 var 1311 object = instance, 1312 maxDepth, 1313 found, 1314 response 1315 ; 1316 passedArguments = passedArguments || queryArguments; 1317 context = element || context; 1318 if(typeof query == 'string' && object !== undefined) { 1319 query = query.split(/[\. ]/); 1320 maxDepth = query.length - 1; 1321 $.each(query, function(depth, value) { 1322 var camelCaseValue = (depth != maxDepth) 1323 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 1324 : query 1325 ; 1326 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 1327 object = object[camelCaseValue]; 1328 } 1329 else if( object[camelCaseValue] !== undefined ) { 1330 found = object[camelCaseValue]; 1331 return false; 1332 } 1333 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 1334 object = object[value]; 1335 } 1336 else if( object[value] !== undefined ) { 1337 found = object[value]; 1338 return false; 1339 } 1340 else { 1341 return false; 1342 } 1343 }); 1344 } 1345 if( $.isFunction( found ) ) { 1346 response = found.apply(context, passedArguments); 1347 } 1348 else if(found !== undefined) { 1349 response = found; 1350 } 1351 if($.isArray(returnedValue)) { 1352 returnedValue.push(response); 1353 } 1354 else if(returnedValue !== undefined) { 1355 returnedValue = [returnedValue, response]; 1356 } 1357 else if(response !== undefined) { 1358 returnedValue = response; 1359 } 1360 return found; 1361 } 1362 }; 1363 if(methodInvoked) { 1364 if(instance === undefined) { 1365 module.initialize(); 1366 } 1367 module.invoke(query); 1368 } 1369 else { 1370 if(instance !== undefined) { 1371 instance.invoke('destroy'); 1372 } 1373 module.initialize(); 1374 } 1375 1376 }) 1377 ; 1378 1379 return (returnedValue !== undefined) 1380 ? returnedValue 1381 : this 1382 ; 1383 }; 1384 1385 $.fn.form.settings = { 1386 1387 name : 'Form', 1388 namespace : 'form', 1389 1390 debug : false, 1391 verbose : true, 1392 performance : true, 1393 1394 1395 keyboardShortcuts : true, 1396 on : 'submit', 1397 inline : false, 1398 1399 delay : 200, 1400 revalidate : true, 1401 1402 transition : 'scale', 1403 duration : 200, 1404 1405 onValid : function() {}, 1406 onInvalid : function() {}, 1407 onSuccess : function() { return true; }, 1408 onFailure : function() { return false; }, 1409 1410 metadata : { 1411 defaultValue : 'default', 1412 validate : 'validate' 1413 }, 1414 1415 selector : { 1416 checkbox : 'input[type="checkbox"], input[type="radio"]', 1417 clear : '.clear', 1418 field : 'input, textarea, select', 1419 group : '.field', 1420 input : 'input', 1421 message : '.error.message', 1422 prompt : '.prompt.label', 1423 radio : 'input[type="radio"]', 1424 reset : '.reset', 1425 submit : '.submit', 1426 uiCheckbox : '.ui.checkbox', 1427 uiDropdown : '.ui.dropdown' 1428 }, 1429 1430 className : { 1431 error : 'error', 1432 label : 'ui prompt label', 1433 pressed : 'down', 1434 success : 'success' 1435 }, 1436 1437 error: { 1438 method : 'The method you called is not defined.' 1439 }, 1440 1441 templates: { 1442 1443 // template that produces error message 1444 error: function(errors) { 1445 var 1446 html = '<ul class="list">' 1447 ; 1448 $.each(errors, function(index, value) { 1449 html += '<li>' + value + '</li>'; 1450 }); 1451 html += '</ul>'; 1452 return $(html); 1453 }, 1454 1455 // template that produces label 1456 prompt: function(errors) { 1457 return $('<div/>') 1458 .addClass('ui red pointing prompt label') 1459 .html(errors[0]) 1460 ; 1461 } 1462 }, 1463 1464 rules: { 1465 1466 // checkbox checked 1467 checked: function() { 1468 return ($(this).filter(':checked').length > 0); 1469 }, 1470 1471 // value contains text (insensitive) 1472 contains: function(value, text) { 1473 // escape regex characters 1474 text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 1475 return (value.search( new RegExp(text, 'i') ) !== -1); 1476 }, 1477 1478 // value contains text (case sensitive) 1479 containsExactly: function(value, text) { 1480 // escape regex characters 1481 text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 1482 return (value.search( new RegExp(text) ) !== -1); 1483 }, 1484 1485 // is most likely an email 1486 email: function(value){ 1487 var 1488 emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", "i") 1489 ; 1490 return emailRegExp.test(value); 1491 }, 1492 1493 // is not empty or blank string 1494 empty: function(value) { 1495 return !(value === undefined || '' === value); 1496 }, 1497 1498 // is valid integer 1499 integer: function(value, range) { 1500 var 1501 intRegExp = /^\-?\d+$/, 1502 min, 1503 max, 1504 parts 1505 ; 1506 if(range === undefined || range === '' || range === '..') { 1507 // do nothing 1508 } 1509 else if(range.indexOf('..') == -1) { 1510 if(intRegExp.test(range)) { 1511 min = max = range - 0; 1512 } 1513 } 1514 else { 1515 parts = range.split('..', 2); 1516 if(intRegExp.test(parts[0])) { 1517 min = parts[0] - 0; 1518 } 1519 if(intRegExp.test(parts[1])) { 1520 max = parts[1] - 0; 1521 } 1522 } 1523 return ( 1524 intRegExp.test(value) && 1525 (min === undefined || value >= min) && 1526 (max === undefined || value <= max) 1527 ); 1528 }, 1529 1530 // is value (case insensitive) 1531 is: function(value, text) { 1532 text = (typeof text == 'string') 1533 ? text.toLowerCase() 1534 : text 1535 ; 1536 value = (typeof value == 'string') 1537 ? value.toLowerCase() 1538 : value 1539 ; 1540 return (value == text); 1541 }, 1542 1543 // is value 1544 isExactly: function(value, text) { 1545 return (value == text); 1546 }, 1547 1548 // is at least string length 1549 length: function(value, requiredLength) { 1550 return (value !== undefined) 1551 ? (value.length >= requiredLength) 1552 : false 1553 ; 1554 }, 1555 1556 // matches another field 1557 match: function(value, fieldIdentifier) { 1558 // use either id or name of field 1559 var 1560 $form = $(this), 1561 matchingValue 1562 ; 1563 if($form.find('#' + fieldIdentifier).length > 0) { 1564 matchingValue = $form.find('#' + fieldIdentifier).val(); 1565 } 1566 else if($form.find('[name="' + fieldIdentifier +'"]').length > 0) { 1567 matchingValue = $form.find('[name="' + fieldIdentifier + '"]').val(); 1568 } 1569 else if( $form.find('[data-validate="'+ fieldIdentifier +'"]').length > 0 ) { 1570 matchingValue = $form.find('[data-validate="'+ fieldIdentifier +'"]').val(); 1571 } 1572 return (matchingValue !== undefined) 1573 ? ( value.toString() == matchingValue.toString() ) 1574 : false 1575 ; 1576 }, 1577 1578 // string length is less than max length 1579 maxLength: function(value, maxLength) { 1580 return (value !== undefined) 1581 ? (value.length <= maxLength) 1582 : false 1583 ; 1584 }, 1585 1586 // value is not value (case insensitive) 1587 not: function(value, notValue) { 1588 value = (typeof value == 'string') 1589 ? value.toLowerCase() 1590 : value 1591 ; 1592 notValue = (typeof notValue == 'string') 1593 ? notValue.toLowerCase() 1594 : notValue 1595 ; 1596 return (value != notValue); 1597 }, 1598 1599 // value is not value (case sensitive) 1600 notExactly: function(value, notValue) { 1601 return (value != notValue); 1602 }, 1603 1604 // value is most likely url 1605 url: function(value) { 1606 var 1607 urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ 1608 ; 1609 return urlRegExp.test(value); 1610 } 1611 } 1612 1613 }; 1614 1615 })( jQuery, window , document ); 1616 1617 /*! 1618 * # Semantic UI x.x - Accordion 1619 * http://github.com/semantic-org/semantic-ui/ 1620 * 1621 * 1622 * Copyright 2014 Contributors 1623 * Released under the MIT license 1624 * http://opensource.org/licenses/MIT 1625 * 1626 */ 1627 1628 ;(function ($, window, document, undefined) { 1629 1630 "use strict"; 1631 1632 $.fn.accordion = function(parameters) { 1633 var 1634 $allModules = $(this), 1635 1636 time = new Date().getTime(), 1637 performance = [], 1638 1639 query = arguments[0], 1640 methodInvoked = (typeof query == 'string'), 1641 queryArguments = [].slice.call(arguments, 1), 1642 1643 requestAnimationFrame = window.requestAnimationFrame 1644 || window.mozRequestAnimationFrame 1645 || window.webkitRequestAnimationFrame 1646 || window.msRequestAnimationFrame 1647 || function(callback) { setTimeout(callback, 0); }, 1648 1649 returnedValue 1650 ; 1651 $allModules 1652 .each(function() { 1653 var 1654 settings = ( $.isPlainObject(parameters) ) 1655 ? $.extend(true, {}, $.fn.accordion.settings, parameters) 1656 : $.extend({}, $.fn.accordion.settings), 1657 1658 className = settings.className, 1659 namespace = settings.namespace, 1660 selector = settings.selector, 1661 error = settings.error, 1662 1663 eventNamespace = '.' + namespace, 1664 moduleNamespace = 'module-' + namespace, 1665 moduleSelector = $allModules.selector || '', 1666 1667 $module = $(this), 1668 $title = $module.find(selector.title), 1669 $content = $module.find(selector.content), 1670 1671 element = this, 1672 instance = $module.data(moduleNamespace), 1673 observer, 1674 module 1675 ; 1676 1677 module = { 1678 1679 initialize: function() { 1680 module.debug('Initializing', $module); 1681 module.bind.events(); 1682 module.observeChanges(); 1683 module.instantiate(); 1684 }, 1685 1686 instantiate: function() { 1687 instance = module; 1688 $module 1689 .data(moduleNamespace, module) 1690 ; 1691 }, 1692 1693 destroy: function() { 1694 module.debug('Destroying previous instance', $module); 1695 $module 1696 .off(eventNamespace) 1697 .removeData(moduleNamespace) 1698 ; 1699 }, 1700 1701 refresh: function() { 1702 $title = $module.find(selector.title); 1703 $content = $module.find(selector.content); 1704 }, 1705 1706 observeChanges: function() { 1707 if('MutationObserver' in window) { 1708 observer = new MutationObserver(function(mutations) { 1709 module.debug('DOM tree modified, updating selector cache'); 1710 module.refresh(); 1711 }); 1712 observer.observe(element, { 1713 childList : true, 1714 subtree : true 1715 }); 1716 module.debug('Setting up mutation observer', observer); 1717 } 1718 }, 1719 1720 bind: { 1721 events: function() { 1722 module.debug('Binding delegated events'); 1723 $module 1724 .on('click' + eventNamespace, selector.trigger, module.event.click) 1725 ; 1726 } 1727 }, 1728 1729 event: { 1730 click: function() { 1731 module.toggle.call(this); 1732 } 1733 }, 1734 1735 toggle: function(query) { 1736 var 1737 $activeTitle = (query !== undefined) 1738 ? (typeof query === 'number') 1739 ? $title.eq(query) 1740 : $(query).closest(selector.title) 1741 : $(this).closest(selector.title), 1742 $activeContent = $activeTitle.next($content), 1743 isAnimating = $activeContent.hasClass(className.animating), 1744 isActive = $activeContent.hasClass(className.active), 1745 isOpen = (isActive && !isAnimating), 1746 isOpening = (!isActive && isAnimating) 1747 ; 1748 module.debug('Toggling visibility of content', $activeTitle); 1749 if(isOpen || isOpening) { 1750 if(settings.collapsible) { 1751 module.close.call($activeTitle); 1752 } 1753 else { 1754 module.debug('Cannot close accordion content collapsing is disabled'); 1755 } 1756 } 1757 else { 1758 module.open.call($activeTitle); 1759 } 1760 }, 1761 1762 open: function(query) { 1763 var 1764 $activeTitle = (query !== undefined) 1765 ? (typeof query === 'number') 1766 ? $title.eq(query) 1767 : $(query).closest(selector.title) 1768 : $(this).closest(selector.title), 1769 $activeContent = $activeTitle.next($content), 1770 isAnimating = $activeContent.hasClass(className.animating), 1771 isActive = $activeContent.hasClass(className.active), 1772 isUnopen = (!isActive && !isAnimating) 1773 ; 1774 if(isUnopen) { 1775 module.debug('Opening accordion content', $activeTitle); 1776 if(settings.exclusive) { 1777 module.closeOthers.call($activeTitle); 1778 } 1779 $activeTitle 1780 .addClass(className.active) 1781 ; 1782 $activeContent.addClass(className.animating); 1783 if(settings.animateChildren) { 1784 if($.fn.transition !== undefined && $module.transition('is supported')) { 1785 $activeContent 1786 .children() 1787 .transition({ 1788 animation : 'fade in', 1789 queue : false, 1790 useFailSafe : true, 1791 debug : settings.debug, 1792 verbose : settings.verbose, 1793 duration : settings.duration 1794 }) 1795 ; 1796 } 1797 else { 1798 $activeContent 1799 .children() 1800 .stop(true) 1801 .animate({ 1802 opacity: 1 1803 }, settings.duration, module.resetOpacity) 1804 ; 1805 } 1806 } 1807 $activeContent 1808 .stop(true) 1809 .slideDown(settings.duration, settings.easing, function() { 1810 $activeContent 1811 .removeClass(className.animating) 1812 .addClass(className.active) 1813 ; 1814 module.reset.display.call(this); 1815 settings.onOpen.call(this); 1816 settings.onChange.call(this); 1817 }) 1818 ; 1819 } 1820 }, 1821 1822 close: function(query) { 1823 var 1824 $activeTitle = (query !== undefined) 1825 ? (typeof query === 'number') 1826 ? $title.eq(query) 1827 : $(query).closest(selector.title) 1828 : $(this).closest(selector.title), 1829 $activeContent = $activeTitle.next($content), 1830 isAnimating = $activeContent.hasClass(className.animating), 1831 isActive = $activeContent.hasClass(className.active), 1832 isOpening = (!isActive && isAnimating), 1833 isClosing = (isActive && isAnimating) 1834 ; 1835 if((isActive || isOpening) && !isClosing) { 1836 module.debug('Closing accordion content', $activeContent); 1837 $activeTitle 1838 .removeClass(className.active) 1839 ; 1840 $activeContent 1841 .addClass(className.animating) 1842 ; 1843 if(settings.animateChildren) { 1844 if($.fn.transition !== undefined && $module.transition('is supported')) { 1845 $activeContent 1846 .children() 1847 .transition({ 1848 animation : 'fade out', 1849 queue : false, 1850 useFailSafe : true, 1851 debug : settings.debug, 1852 verbose : settings.verbose, 1853 duration : settings.duration 1854 }) 1855 ; 1856 } 1857 else { 1858 $activeContent 1859 .children() 1860 .stop(true) 1861 .animate({ 1862 opacity: 0 1863 }, settings.duration, module.resetOpacity) 1864 ; 1865 } 1866 } 1867 $activeContent 1868 .stop(true) 1869 .slideUp(settings.duration, settings.easing, function() { 1870 $activeContent 1871 .removeClass(className.animating) 1872 .removeClass(className.active) 1873 ; 1874 module.reset.display.call(this); 1875 settings.onClose.call(this); 1876 settings.onChange.call(this); 1877 }) 1878 ; 1879 } 1880 }, 1881 1882 closeOthers: function(index) { 1883 var 1884 $activeTitle = (index !== undefined) 1885 ? $title.eq(index) 1886 : $(this).closest(selector.title), 1887 $parentTitles = $activeTitle.parents(selector.content).prev(selector.title), 1888 $activeAccordion = $activeTitle.closest(selector.accordion), 1889 activeSelector = selector.title + '.' + className.active + ':visible', 1890 activeContent = selector.content + '.' + className.active + ':visible', 1891 $openTitles, 1892 $nestedTitles, 1893 $openContents 1894 ; 1895 if(settings.closeNested) { 1896 $openTitles = $activeAccordion.find(activeSelector).not($parentTitles); 1897 $openContents = $openTitles.next($content); 1898 } 1899 else { 1900 $openTitles = $activeAccordion.find(activeSelector).not($parentTitles); 1901 $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles); 1902 $openTitles = $openTitles.not($nestedTitles); 1903 $openContents = $openTitles.next($content); 1904 } 1905 if( ($openTitles.length > 0) ) { 1906 module.debug('Exclusive enabled, closing other content', $openTitles); 1907 $openTitles 1908 .removeClass(className.active) 1909 ; 1910 if(settings.animateChildren) { 1911 if($.fn.transition !== undefined && $module.transition('is supported')) { 1912 $openContents 1913 .children() 1914 .transition({ 1915 animation : 'fade out', 1916 useFailSafe : true, 1917 debug : settings.debug, 1918 verbose : settings.verbose, 1919 duration : settings.duration 1920 }) 1921 ; 1922 } 1923 else { 1924 $openContents 1925 .children() 1926 .stop() 1927 .animate({ 1928 opacity: 0 1929 }, settings.duration, module.resetOpacity) 1930 ; 1931 } 1932 } 1933 $openContents 1934 .stop() 1935 .slideUp(settings.duration , settings.easing, function() { 1936 $(this).removeClass(className.active); 1937 module.reset.display.call(this); 1938 }) 1939 ; 1940 } 1941 }, 1942 1943 reset: { 1944 1945 display: function() { 1946 module.verbose('Removing inline display from element', this); 1947 $(this).css('display', ''); 1948 if( $(this).attr('style') === '') { 1949 $(this) 1950 .attr('style', '') 1951 .removeAttr('style') 1952 ; 1953 } 1954 }, 1955 1956 opacity: function() { 1957 module.verbose('Removing inline opacity from element', this); 1958 $(this).css('opacity', ''); 1959 if( $(this).attr('style') === '') { 1960 $(this) 1961 .attr('style', '') 1962 .removeAttr('style') 1963 ; 1964 } 1965 }, 1966 1967 }, 1968 1969 setting: function(name, value) { 1970 module.debug('Changing setting', name, value); 1971 if( $.isPlainObject(name) ) { 1972 $.extend(true, settings, name); 1973 } 1974 else if(value !== undefined) { 1975 settings[name] = value; 1976 } 1977 else { 1978 return settings[name]; 1979 } 1980 }, 1981 internal: function(name, value) { 1982 module.debug('Changing internal', name, value); 1983 if(value !== undefined) { 1984 if( $.isPlainObject(name) ) { 1985 $.extend(true, module, name); 1986 } 1987 else { 1988 module[name] = value; 1989 } 1990 } 1991 else { 1992 return module[name]; 1993 } 1994 }, 1995 debug: function() { 1996 if(settings.debug) { 1997 if(settings.performance) { 1998 module.performance.log(arguments); 1999 } 2000 else { 2001 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 2002 module.debug.apply(console, arguments); 2003 } 2004 } 2005 }, 2006 verbose: function() { 2007 if(settings.verbose && settings.debug) { 2008 if(settings.performance) { 2009 module.performance.log(arguments); 2010 } 2011 else { 2012 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 2013 module.verbose.apply(console, arguments); 2014 } 2015 } 2016 }, 2017 error: function() { 2018 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 2019 module.error.apply(console, arguments); 2020 }, 2021 performance: { 2022 log: function(message) { 2023 var 2024 currentTime, 2025 executionTime, 2026 previousTime 2027 ; 2028 if(settings.performance) { 2029 currentTime = new Date().getTime(); 2030 previousTime = time || currentTime; 2031 executionTime = currentTime - previousTime; 2032 time = currentTime; 2033 performance.push({ 2034 'Name' : message[0], 2035 'Arguments' : [].slice.call(message, 1) || '', 2036 'Element' : element, 2037 'Execution Time' : executionTime 2038 }); 2039 } 2040 clearTimeout(module.performance.timer); 2041 module.performance.timer = setTimeout(module.performance.display, 100); 2042 }, 2043 display: function() { 2044 var 2045 title = settings.name + ':', 2046 totalTime = 0 2047 ; 2048 time = false; 2049 clearTimeout(module.performance.timer); 2050 $.each(performance, function(index, data) { 2051 totalTime += data['Execution Time']; 2052 }); 2053 title += ' ' + totalTime + 'ms'; 2054 if(moduleSelector) { 2055 title += ' \'' + moduleSelector + '\''; 2056 } 2057 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 2058 console.groupCollapsed(title); 2059 if(console.table) { 2060 console.table(performance); 2061 } 2062 else { 2063 $.each(performance, function(index, data) { 2064 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 2065 }); 2066 } 2067 console.groupEnd(); 2068 } 2069 performance = []; 2070 } 2071 }, 2072 invoke: function(query, passedArguments, context) { 2073 var 2074 object = instance, 2075 maxDepth, 2076 found, 2077 response 2078 ; 2079 passedArguments = passedArguments || queryArguments; 2080 context = element || context; 2081 if(typeof query == 'string' && object !== undefined) { 2082 query = query.split(/[\. ]/); 2083 maxDepth = query.length - 1; 2084 $.each(query, function(depth, value) { 2085 var camelCaseValue = (depth != maxDepth) 2086 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 2087 : query 2088 ; 2089 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 2090 object = object[camelCaseValue]; 2091 } 2092 else if( object[camelCaseValue] !== undefined ) { 2093 found = object[camelCaseValue]; 2094 return false; 2095 } 2096 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 2097 object = object[value]; 2098 } 2099 else if( object[value] !== undefined ) { 2100 found = object[value]; 2101 return false; 2102 } 2103 else { 2104 module.error(error.method, query); 2105 return false; 2106 } 2107 }); 2108 } 2109 if ( $.isFunction( found ) ) { 2110 response = found.apply(context, passedArguments); 2111 } 2112 else if(found !== undefined) { 2113 response = found; 2114 } 2115 if($.isArray(returnedValue)) { 2116 returnedValue.push(response); 2117 } 2118 else if(returnedValue !== undefined) { 2119 returnedValue = [returnedValue, response]; 2120 } 2121 else if(response !== undefined) { 2122 returnedValue = response; 2123 } 2124 return found; 2125 } 2126 }; 2127 if(methodInvoked) { 2128 if(instance === undefined) { 2129 module.initialize(); 2130 } 2131 module.invoke(query); 2132 } 2133 else { 2134 if(instance !== undefined) { 2135 instance.invoke('destroy'); 2136 } 2137 module.initialize(); 2138 } 2139 }) 2140 ; 2141 return (returnedValue !== undefined) 2142 ? returnedValue 2143 : this 2144 ; 2145 }; 2146 2147 $.fn.accordion.settings = { 2148 2149 name : 'Accordion', 2150 namespace : 'accordion', 2151 2152 debug : false, 2153 verbose : true, 2154 performance : true, 2155 2156 exclusive : true, 2157 collapsible : true, 2158 closeNested : false, 2159 animateChildren : true, 2160 2161 duration : 350, 2162 easing : 'easeOutQuad', 2163 2164 onOpen : function(){}, 2165 onClose : function(){}, 2166 onChange : function(){}, 2167 2168 error: { 2169 method : 'The method you called is not defined' 2170 }, 2171 2172 className : { 2173 active : 'active', 2174 animating : 'animating' 2175 }, 2176 2177 selector : { 2178 accordion : '.accordion', 2179 title : '.title', 2180 trigger : '.title', 2181 content : '.content' 2182 } 2183 2184 }; 2185 2186 // Adds easing 2187 $.extend( $.easing, { 2188 easeOutQuad: function (x, t, b, c, d) { 2189 return -c *(t/=d)*(t-2) + b; 2190 } 2191 }); 2192 2193 })( jQuery, window , document ); 2194 2195 2196 /*! 2197 * # Semantic UI x.x - Checkbox 2198 * http://github.com/semantic-org/semantic-ui/ 2199 * 2200 * 2201 * Copyright 2014 Contributors 2202 * Released under the MIT license 2203 * http://opensource.org/licenses/MIT 2204 * 2205 */ 2206 2207 ;(function ( $, window, document, undefined ) { 2208 2209 "use strict"; 2210 2211 $.fn.checkbox = function(parameters) { 2212 var 2213 $allModules = $(this), 2214 moduleSelector = $allModules.selector || '', 2215 2216 time = new Date().getTime(), 2217 performance = [], 2218 2219 query = arguments[0], 2220 methodInvoked = (typeof query == 'string'), 2221 queryArguments = [].slice.call(arguments, 1), 2222 returnedValue 2223 ; 2224 2225 $allModules 2226 .each(function() { 2227 var 2228 settings = $.extend(true, {}, $.fn.checkbox.settings, parameters), 2229 2230 className = settings.className, 2231 namespace = settings.namespace, 2232 selector = settings.selector, 2233 error = settings.error, 2234 2235 eventNamespace = '.' + namespace, 2236 moduleNamespace = 'module-' + namespace, 2237 2238 $module = $(this), 2239 $label = $(this).find(selector.label).first(), 2240 $input = $(this).find(selector.input), 2241 2242 instance = $module.data(moduleNamespace), 2243 2244 observer, 2245 element = this, 2246 module 2247 ; 2248 2249 module = { 2250 2251 initialize: function() { 2252 module.verbose('Initializing checkbox', settings); 2253 2254 module.create.label(); 2255 module.add.events(); 2256 2257 if( module.is.checked() ) { 2258 module.set.checked(); 2259 if(settings.fireOnInit) { 2260 settings.onChecked.call($input.get()); 2261 } 2262 } 2263 else { 2264 module.remove.checked(); 2265 if(settings.fireOnInit) { 2266 settings.onUnchecked.call($input.get()); 2267 } 2268 } 2269 module.observeChanges(); 2270 2271 module.instantiate(); 2272 }, 2273 2274 instantiate: function() { 2275 module.verbose('Storing instance of module', module); 2276 instance = module; 2277 $module 2278 .data(moduleNamespace, module) 2279 ; 2280 }, 2281 2282 destroy: function() { 2283 module.verbose('Destroying module'); 2284 module.remove.events(); 2285 $module 2286 .removeData(moduleNamespace) 2287 ; 2288 }, 2289 2290 refresh: function() { 2291 $module = $(this); 2292 $label = $(this).find(selector.label).first(); 2293 $input = $(this).find(selector.input); 2294 }, 2295 2296 observeChanges: function() { 2297 if('MutationObserver' in window) { 2298 observer = new MutationObserver(function(mutations) { 2299 module.debug('DOM tree modified, updating selector cache'); 2300 module.refresh(); 2301 }); 2302 observer.observe(element, { 2303 childList : true, 2304 subtree : true 2305 }); 2306 module.debug('Setting up mutation observer', observer); 2307 } 2308 }, 2309 2310 attachEvents: function(selector, event) { 2311 var 2312 $element = $(selector) 2313 ; 2314 event = $.isFunction(module[event]) 2315 ? module[event] 2316 : module.toggle 2317 ; 2318 if($element.length > 0) { 2319 module.debug('Attaching checkbox events to element', selector, event); 2320 $element 2321 .on('click' + eventNamespace, event) 2322 ; 2323 } 2324 else { 2325 module.error(error.notFound); 2326 } 2327 }, 2328 2329 event: { 2330 keydown: function(event) { 2331 var 2332 key = event.which, 2333 keyCode = { 2334 enter : 13, 2335 space : 32, 2336 escape : 27 2337 } 2338 ; 2339 if( key == keyCode.escape) { 2340 module.verbose('Escape key pressed blurring field'); 2341 $module 2342 .blur() 2343 ; 2344 } 2345 if(!event.ctrlKey && (key == keyCode.enter || key == keyCode.space)) { 2346 module.verbose('Enter key pressed, toggling checkbox'); 2347 module.toggle.call(this); 2348 event.preventDefault(); 2349 } 2350 } 2351 }, 2352 2353 is: { 2354 radio: function() { 2355 return $module.hasClass(className.radio); 2356 }, 2357 checked: function() { 2358 return $input.prop('checked') !== undefined && $input.prop('checked'); 2359 }, 2360 unchecked: function() { 2361 return !module.is.checked(); 2362 } 2363 }, 2364 2365 can: { 2366 change: function() { 2367 return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') ); 2368 }, 2369 uncheck: function() { 2370 return (typeof settings.uncheckable === 'boolean') 2371 ? settings.uncheckable 2372 : !module.is.radio() 2373 ; 2374 } 2375 }, 2376 2377 set: { 2378 checked: function() { 2379 $module.addClass(className.checked); 2380 }, 2381 tab: function() { 2382 if( $input.attr('tabindex') === undefined) { 2383 $input 2384 .attr('tabindex', 0) 2385 ; 2386 } 2387 } 2388 }, 2389 2390 create: { 2391 label: function() { 2392 if($input.prevAll(selector.label).length > 0) { 2393 $input.prev(selector.label).detach().insertAfter($input); 2394 module.debug('Moving existing label', $label); 2395 } 2396 else if( !module.has.label() ) { 2397 $label = $('<label>').insertAfter($input); 2398 module.debug('Creating label', $label); 2399 } 2400 } 2401 }, 2402 2403 has: { 2404 label: function() { 2405 return ($label.length > 0); 2406 } 2407 }, 2408 2409 add: { 2410 events: function() { 2411 module.verbose('Attaching checkbox events'); 2412 $module 2413 .on('click' + eventNamespace, module.toggle) 2414 .on('keydown' + eventNamespace, selector.input, module.event.keydown) 2415 ; 2416 } 2417 }, 2418 2419 remove: { 2420 checked: function() { 2421 $module.removeClass(className.checked); 2422 }, 2423 events: function() { 2424 module.debug('Removing events'); 2425 $module 2426 .off(eventNamespace) 2427 .removeData(moduleNamespace) 2428 ; 2429 $input 2430 .off(eventNamespace, module.event.keydown) 2431 ; 2432 $label 2433 .off(eventNamespace) 2434 ; 2435 } 2436 }, 2437 2438 enable: function() { 2439 module.debug('Enabling checkbox functionality'); 2440 $module.removeClass(className.disabled); 2441 $input.prop('disabled', false); 2442 settings.onEnabled.call($input.get()); 2443 }, 2444 2445 disable: function() { 2446 module.debug('Disabling checkbox functionality'); 2447 $module.addClass(className.disabled); 2448 $input.prop('disabled', 'disabled'); 2449 settings.onDisabled.call($input.get()); 2450 }, 2451 2452 check: function() { 2453 module.debug('Enabling checkbox', $input); 2454 $input 2455 .prop('checked', true) 2456 .trigger('change') 2457 ; 2458 module.set.checked(); 2459 $input.trigger('blur'); 2460 settings.onChange.call($input.get()); 2461 settings.onChecked.call($input.get()); 2462 }, 2463 2464 uncheck: function() { 2465 module.debug('Disabling checkbox'); 2466 $input 2467 .prop('checked', false) 2468 .trigger('change') 2469 ; 2470 module.remove.checked(); 2471 $input.trigger('blur'); 2472 settings.onChange.call($input.get()); 2473 settings.onUnchecked.call($input.get()); 2474 }, 2475 2476 toggle: function(event) { 2477 if( !module.can.change() ) { 2478 console.log(module.can.change()); 2479 module.debug('Checkbox is read-only or disabled, ignoring toggle'); 2480 return; 2481 } 2482 module.verbose('Determining new checkbox state'); 2483 if( module.is.unchecked() ) { 2484 module.check(); 2485 } 2486 else if( module.is.checked() && module.can.uncheck() ) { 2487 module.uncheck(); 2488 } 2489 }, 2490 setting: function(name, value) { 2491 module.debug('Changing setting', name, value); 2492 if( $.isPlainObject(name) ) { 2493 $.extend(true, settings, name); 2494 } 2495 else if(value !== undefined) { 2496 settings[name] = value; 2497 } 2498 else { 2499 return settings[name]; 2500 } 2501 }, 2502 internal: function(name, value) { 2503 if( $.isPlainObject(name) ) { 2504 $.extend(true, module, name); 2505 } 2506 else if(value !== undefined) { 2507 module[name] = value; 2508 } 2509 else { 2510 return module[name]; 2511 } 2512 }, 2513 debug: function() { 2514 if(settings.debug) { 2515 if(settings.performance) { 2516 module.performance.log(arguments); 2517 } 2518 else { 2519 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 2520 module.debug.apply(console, arguments); 2521 } 2522 } 2523 }, 2524 verbose: function() { 2525 if(settings.verbose && settings.debug) { 2526 if(settings.performance) { 2527 module.performance.log(arguments); 2528 } 2529 else { 2530 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 2531 module.verbose.apply(console, arguments); 2532 } 2533 } 2534 }, 2535 error: function() { 2536 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 2537 module.error.apply(console, arguments); 2538 }, 2539 performance: { 2540 log: function(message) { 2541 var 2542 currentTime, 2543 executionTime, 2544 previousTime 2545 ; 2546 if(settings.performance) { 2547 currentTime = new Date().getTime(); 2548 previousTime = time || currentTime; 2549 executionTime = currentTime - previousTime; 2550 time = currentTime; 2551 performance.push({ 2552 'Name' : message[0], 2553 'Arguments' : [].slice.call(message, 1) || '', 2554 'Element' : element, 2555 'Execution Time' : executionTime 2556 }); 2557 } 2558 clearTimeout(module.performance.timer); 2559 module.performance.timer = setTimeout(module.performance.display, 100); 2560 }, 2561 display: function() { 2562 var 2563 title = settings.name + ':', 2564 totalTime = 0 2565 ; 2566 time = false; 2567 clearTimeout(module.performance.timer); 2568 $.each(performance, function(index, data) { 2569 totalTime += data['Execution Time']; 2570 }); 2571 title += ' ' + totalTime + 'ms'; 2572 if(moduleSelector) { 2573 title += ' \'' + moduleSelector + '\''; 2574 } 2575 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 2576 console.groupCollapsed(title); 2577 if(console.table) { 2578 console.table(performance); 2579 } 2580 else { 2581 $.each(performance, function(index, data) { 2582 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 2583 }); 2584 } 2585 console.groupEnd(); 2586 } 2587 performance = []; 2588 } 2589 }, 2590 invoke: function(query, passedArguments, context) { 2591 var 2592 object = instance, 2593 maxDepth, 2594 found, 2595 response 2596 ; 2597 passedArguments = passedArguments || queryArguments; 2598 context = element || context; 2599 if(typeof query == 'string' && object !== undefined) { 2600 query = query.split(/[\. ]/); 2601 maxDepth = query.length - 1; 2602 $.each(query, function(depth, value) { 2603 var camelCaseValue = (depth != maxDepth) 2604 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 2605 : query 2606 ; 2607 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 2608 object = object[camelCaseValue]; 2609 } 2610 else if( object[camelCaseValue] !== undefined ) { 2611 found = object[camelCaseValue]; 2612 return false; 2613 } 2614 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 2615 object = object[value]; 2616 } 2617 else if( object[value] !== undefined ) { 2618 found = object[value]; 2619 return false; 2620 } 2621 else { 2622 module.error(error.method, query); 2623 return false; 2624 } 2625 }); 2626 } 2627 if ( $.isFunction( found ) ) { 2628 response = found.apply(context, passedArguments); 2629 } 2630 else if(found !== undefined) { 2631 response = found; 2632 } 2633 if($.isArray(returnedValue)) { 2634 returnedValue.push(response); 2635 } 2636 else if(returnedValue !== undefined) { 2637 returnedValue = [returnedValue, response]; 2638 } 2639 else if(response !== undefined) { 2640 returnedValue = response; 2641 } 2642 return found; 2643 } 2644 }; 2645 2646 if(methodInvoked) { 2647 if(instance === undefined) { 2648 module.initialize(); 2649 } 2650 module.invoke(query); 2651 } 2652 else { 2653 if(instance !== undefined) { 2654 instance.invoke('destroy'); 2655 } 2656 module.initialize(); 2657 } 2658 }) 2659 ; 2660 2661 return (returnedValue !== undefined) 2662 ? returnedValue 2663 : this 2664 ; 2665 }; 2666 2667 $.fn.checkbox.settings = { 2668 2669 name : 'Checkbox', 2670 namespace : 'checkbox', 2671 2672 debug : false, 2673 verbose : true, 2674 performance : true, 2675 2676 // delegated event context 2677 uncheckable : 'auto', 2678 fireOnInit : true, 2679 2680 onChange : function(){}, 2681 onChecked : function(){}, 2682 onUnchecked : function(){}, 2683 onEnabled : function(){}, 2684 onDisabled : function(){}, 2685 2686 className : { 2687 checked : 'checked', 2688 disabled : 'disabled', 2689 radio : 'radio', 2690 readOnly : 'read-only' 2691 }, 2692 2693 error : { 2694 method : 'The method you called is not defined' 2695 }, 2696 2697 selector : { 2698 input : 'input[type="checkbox"], input[type="radio"]', 2699 label : 'label' 2700 } 2701 2702 }; 2703 2704 })( jQuery, window , document ); 2705 2706 /*! 2707 * # Semantic UI x.x - Dimmer 2708 * http://github.com/semantic-org/semantic-ui/ 2709 * 2710 * 2711 * Copyright 2014 Contributors 2712 * Released under the MIT license 2713 * http://opensource.org/licenses/MIT 2714 * 2715 */ 2716 2717 ;(function ( $, window, document, undefined ) { 2718 2719 "use strict"; 2720 2721 $.fn.dimmer = function(parameters) { 2722 var 2723 $allModules = $(this), 2724 2725 time = new Date().getTime(), 2726 performance = [], 2727 2728 query = arguments[0], 2729 methodInvoked = (typeof query == 'string'), 2730 queryArguments = [].slice.call(arguments, 1), 2731 2732 returnedValue 2733 ; 2734 2735 $allModules 2736 .each(function() { 2737 var 2738 settings = ( $.isPlainObject(parameters) ) 2739 ? $.extend(true, {}, $.fn.dimmer.settings, parameters) 2740 : $.extend({}, $.fn.dimmer.settings), 2741 2742 selector = settings.selector, 2743 namespace = settings.namespace, 2744 className = settings.className, 2745 error = settings.error, 2746 2747 eventNamespace = '.' + namespace, 2748 moduleNamespace = 'module-' + namespace, 2749 moduleSelector = $allModules.selector || '', 2750 2751 clickEvent = ('ontouchstart' in document.documentElement) 2752 ? 'touchstart' 2753 : 'click', 2754 2755 $module = $(this), 2756 $dimmer, 2757 $dimmable, 2758 2759 element = this, 2760 instance = $module.data(moduleNamespace), 2761 module 2762 ; 2763 2764 module = { 2765 2766 preinitialize: function() { 2767 if( module.is.dimmer() ) { 2768 $dimmable = $module.parent(); 2769 $dimmer = $module; 2770 } 2771 else { 2772 $dimmable = $module; 2773 if( module.has.dimmer() ) { 2774 if(settings.dimmerName) { 2775 $dimmer = $dimmable.children(selector.dimmer).filter('.' + settings.dimmerName); 2776 } 2777 else { 2778 $dimmer = $dimmable.children(selector.dimmer); 2779 } 2780 } 2781 else { 2782 $dimmer = module.create(); 2783 } 2784 } 2785 }, 2786 2787 initialize: function() { 2788 module.debug('Initializing dimmer', settings); 2789 if(settings.on == 'hover') { 2790 $dimmable 2791 .on('mouseenter' + eventNamespace, module.show) 2792 .on('mouseleave' + eventNamespace, module.hide) 2793 ; 2794 } 2795 else if(settings.on == 'click') { 2796 $dimmable 2797 .on(clickEvent + eventNamespace, module.toggle) 2798 ; 2799 } 2800 if( module.is.page() ) { 2801 module.debug('Setting as a page dimmer', $dimmable); 2802 module.set.pageDimmer(); 2803 } 2804 2805 if( module.is.closable() ) { 2806 module.verbose('Adding dimmer close event', $dimmer); 2807 $dimmer 2808 .on(clickEvent + eventNamespace, module.event.click) 2809 ; 2810 } 2811 module.set.dimmable(); 2812 module.instantiate(); 2813 }, 2814 2815 instantiate: function() { 2816 module.verbose('Storing instance of module', module); 2817 instance = module; 2818 $module 2819 .data(moduleNamespace, instance) 2820 ; 2821 }, 2822 2823 destroy: function() { 2824 module.verbose('Destroying previous module', $dimmer); 2825 $module 2826 .removeData(moduleNamespace) 2827 ; 2828 $dimmable 2829 .off(eventNamespace) 2830 ; 2831 $dimmer 2832 .off(eventNamespace) 2833 ; 2834 }, 2835 2836 event: { 2837 click: function(event) { 2838 module.verbose('Determining if event occured on dimmer', event); 2839 if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) { 2840 module.hide(); 2841 event.stopImmediatePropagation(); 2842 } 2843 } 2844 }, 2845 2846 addContent: function(element) { 2847 var 2848 $content = $(element) 2849 ; 2850 module.debug('Add content to dimmer', $content); 2851 if($content.parent()[0] !== $dimmer[0]) { 2852 $content.detach().appendTo($dimmer); 2853 } 2854 }, 2855 2856 create: function() { 2857 var 2858 $element = $( settings.template.dimmer() ) 2859 ; 2860 if(settings.variation) { 2861 module.debug('Creating dimmer with variation', settings.variation); 2862 $element.addClass(settings.variation); 2863 } 2864 if(settings.dimmerName) { 2865 module.debug('Creating named dimmer', settings.dimmerName); 2866 $element.addClass(settings.dimmerName); 2867 } 2868 $element 2869 .appendTo($dimmable) 2870 ; 2871 return $element; 2872 }, 2873 2874 show: function(callback) { 2875 callback = $.isFunction(callback) 2876 ? callback 2877 : function(){} 2878 ; 2879 module.debug('Showing dimmer', $dimmer, settings); 2880 if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) { 2881 module.animate.show(callback); 2882 settings.onShow.call(element); 2883 settings.onChange.call(element); 2884 } 2885 else { 2886 module.debug('Dimmer is already shown or disabled'); 2887 } 2888 }, 2889 2890 hide: function(callback) { 2891 callback = $.isFunction(callback) 2892 ? callback 2893 : function(){} 2894 ; 2895 if( module.is.dimmed() || module.is.animating() ) { 2896 module.debug('Hiding dimmer', $dimmer); 2897 module.animate.hide(callback); 2898 settings.onHide.call(element); 2899 settings.onChange.call(element); 2900 } 2901 else { 2902 module.debug('Dimmer is not visible'); 2903 } 2904 }, 2905 2906 toggle: function() { 2907 module.verbose('Toggling dimmer visibility', $dimmer); 2908 if( !module.is.dimmed() ) { 2909 module.show(); 2910 } 2911 else { 2912 module.hide(); 2913 } 2914 }, 2915 2916 animate: { 2917 show: function(callback) { 2918 callback = $.isFunction(callback) 2919 ? callback 2920 : function(){} 2921 ; 2922 if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) { 2923 if(settings.opacity !== 'auto') { 2924 module.set.opacity(); 2925 } 2926 $dimmer 2927 .transition({ 2928 animation : settings.transition + ' in', 2929 queue : false, 2930 duration : module.get.duration(), 2931 useFailSafe : true, 2932 onStart : function() { 2933 module.set.dimmed(); 2934 }, 2935 onComplete : function() { 2936 module.set.active(); 2937 callback(); 2938 } 2939 }) 2940 ; 2941 } 2942 else { 2943 module.verbose('Showing dimmer animation with javascript'); 2944 module.set.dimmed(); 2945 if(settings.opacity == 'auto') { 2946 settings.opacity = 0.8; 2947 } 2948 $dimmer 2949 .stop() 2950 .css({ 2951 opacity : 0, 2952 width : '100%', 2953 height : '100%' 2954 }) 2955 .fadeTo(module.get.duration(), settings.opacity, function() { 2956 $dimmer.removeAttr('style'); 2957 module.set.active(); 2958 callback(); 2959 }) 2960 ; 2961 } 2962 }, 2963 hide: function(callback) { 2964 callback = $.isFunction(callback) 2965 ? callback 2966 : function(){} 2967 ; 2968 if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) { 2969 module.verbose('Hiding dimmer with css'); 2970 $dimmer 2971 .transition({ 2972 animation : settings.transition + ' out', 2973 queue : false, 2974 duration : module.get.duration(), 2975 useFailSafe : true, 2976 onStart : function() { 2977 module.remove.dimmed(); 2978 }, 2979 onComplete : function() { 2980 module.remove.active(); 2981 callback(); 2982 } 2983 }) 2984 ; 2985 } 2986 else { 2987 module.verbose('Hiding dimmer with javascript'); 2988 module.remove.dimmed(); 2989 $dimmer 2990 .stop() 2991 .fadeOut(module.get.duration(), function() { 2992 module.remove.active(); 2993 $dimmer.removeAttr('style'); 2994 callback(); 2995 }) 2996 ; 2997 } 2998 } 2999 }, 3000 3001 get: { 3002 dimmer: function() { 3003 return $dimmer; 3004 }, 3005 duration: function() { 3006 if(typeof settings.duration == 'object') { 3007 if( module.is.active() ) { 3008 return settings.duration.hide; 3009 } 3010 else { 3011 return settings.duration.show; 3012 } 3013 } 3014 return settings.duration; 3015 } 3016 }, 3017 3018 has: { 3019 dimmer: function() { 3020 if(settings.dimmerName) { 3021 return ($module.children(selector.dimmer).filter('.' + settings.dimmerName).length > 0); 3022 } 3023 else { 3024 return ( $module.children(selector.dimmer).length > 0 ); 3025 } 3026 } 3027 }, 3028 3029 is: { 3030 active: function() { 3031 return $dimmer.hasClass(className.active); 3032 }, 3033 animating: function() { 3034 return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) ); 3035 }, 3036 closable: function() { 3037 if(settings.closable == 'auto') { 3038 if(settings.on == 'hover') { 3039 return false; 3040 } 3041 return true; 3042 } 3043 return settings.closable; 3044 }, 3045 dimmer: function() { 3046 return $module.is(selector.dimmer); 3047 }, 3048 dimmable: function() { 3049 return $module.is(selector.dimmable); 3050 }, 3051 dimmed: function() { 3052 return $dimmable.hasClass(className.dimmed); 3053 }, 3054 disabled: function() { 3055 return $dimmable.hasClass(className.disabled); 3056 }, 3057 enabled: function() { 3058 return !module.is.disabled(); 3059 }, 3060 page: function () { 3061 return $dimmable.is('body'); 3062 }, 3063 pageDimmer: function() { 3064 return $dimmer.hasClass(className.pageDimmer); 3065 } 3066 }, 3067 3068 can: { 3069 show: function() { 3070 return !$dimmer.hasClass(className.disabled); 3071 } 3072 }, 3073 3074 set: { 3075 opacity: function(opacity) { 3076 var 3077 opacity = settings.opacity || opacity, 3078 color = $dimmer.css('background-color'), 3079 colorArray = color.split(','), 3080 isRGBA = (colorArray && colorArray.length == 4) 3081 ; 3082 if(isRGBA) { 3083 colorArray[3] = opacity + ')'; 3084 color = colorArray.join(','); 3085 } 3086 else { 3087 color = 'rgba(0, 0, 0, ' + opacity + ')'; 3088 } 3089 module.debug('Setting opacity to', opacity); 3090 $dimmer.css('background-color', color); 3091 }, 3092 active: function() { 3093 $dimmer.addClass(className.active); 3094 }, 3095 dimmable: function() { 3096 $dimmable.addClass(className.dimmable); 3097 }, 3098 dimmed: function() { 3099 $dimmable.addClass(className.dimmed); 3100 }, 3101 pageDimmer: function() { 3102 $dimmer.addClass(className.pageDimmer); 3103 }, 3104 disabled: function() { 3105 $dimmer.addClass(className.disabled); 3106 } 3107 }, 3108 3109 remove: { 3110 active: function() { 3111 $dimmer 3112 .removeClass(className.active) 3113 ; 3114 }, 3115 dimmed: function() { 3116 $dimmable.removeClass(className.dimmed); 3117 }, 3118 disabled: function() { 3119 $dimmer.removeClass(className.disabled); 3120 } 3121 }, 3122 3123 setting: function(name, value) { 3124 module.debug('Changing setting', name, value); 3125 if( $.isPlainObject(name) ) { 3126 $.extend(true, settings, name); 3127 } 3128 else if(value !== undefined) { 3129 settings[name] = value; 3130 } 3131 else { 3132 return settings[name]; 3133 } 3134 }, 3135 internal: function(name, value) { 3136 if( $.isPlainObject(name) ) { 3137 $.extend(true, module, name); 3138 } 3139 else if(value !== undefined) { 3140 module[name] = value; 3141 } 3142 else { 3143 return module[name]; 3144 } 3145 }, 3146 debug: function() { 3147 if(settings.debug) { 3148 if(settings.performance) { 3149 module.performance.log(arguments); 3150 } 3151 else { 3152 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 3153 module.debug.apply(console, arguments); 3154 } 3155 } 3156 }, 3157 verbose: function() { 3158 if(settings.verbose && settings.debug) { 3159 if(settings.performance) { 3160 module.performance.log(arguments); 3161 } 3162 else { 3163 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 3164 module.verbose.apply(console, arguments); 3165 } 3166 } 3167 }, 3168 error: function() { 3169 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 3170 module.error.apply(console, arguments); 3171 }, 3172 performance: { 3173 log: function(message) { 3174 var 3175 currentTime, 3176 executionTime, 3177 previousTime 3178 ; 3179 if(settings.performance) { 3180 currentTime = new Date().getTime(); 3181 previousTime = time || currentTime; 3182 executionTime = currentTime - previousTime; 3183 time = currentTime; 3184 performance.push({ 3185 'Name' : message[0], 3186 'Arguments' : [].slice.call(message, 1) || '', 3187 'Element' : element, 3188 'Execution Time' : executionTime 3189 }); 3190 } 3191 clearTimeout(module.performance.timer); 3192 module.performance.timer = setTimeout(module.performance.display, 100); 3193 }, 3194 display: function() { 3195 var 3196 title = settings.name + ':', 3197 totalTime = 0 3198 ; 3199 time = false; 3200 clearTimeout(module.performance.timer); 3201 $.each(performance, function(index, data) { 3202 totalTime += data['Execution Time']; 3203 }); 3204 title += ' ' + totalTime + 'ms'; 3205 if(moduleSelector) { 3206 title += ' \'' + moduleSelector + '\''; 3207 } 3208 if($allModules.length > 1) { 3209 title += ' ' + '(' + $allModules.length + ')'; 3210 } 3211 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 3212 console.groupCollapsed(title); 3213 if(console.table) { 3214 console.table(performance); 3215 } 3216 else { 3217 $.each(performance, function(index, data) { 3218 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 3219 }); 3220 } 3221 console.groupEnd(); 3222 } 3223 performance = []; 3224 } 3225 }, 3226 invoke: function(query, passedArguments, context) { 3227 var 3228 object = instance, 3229 maxDepth, 3230 found, 3231 response 3232 ; 3233 passedArguments = passedArguments || queryArguments; 3234 context = element || context; 3235 if(typeof query == 'string' && object !== undefined) { 3236 query = query.split(/[\. ]/); 3237 maxDepth = query.length - 1; 3238 $.each(query, function(depth, value) { 3239 var camelCaseValue = (depth != maxDepth) 3240 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 3241 : query 3242 ; 3243 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 3244 object = object[camelCaseValue]; 3245 } 3246 else if( object[camelCaseValue] !== undefined ) { 3247 found = object[camelCaseValue]; 3248 return false; 3249 } 3250 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 3251 object = object[value]; 3252 } 3253 else if( object[value] !== undefined ) { 3254 found = object[value]; 3255 return false; 3256 } 3257 else { 3258 module.error(error.method, query); 3259 return false; 3260 } 3261 }); 3262 } 3263 if ( $.isFunction( found ) ) { 3264 response = found.apply(context, passedArguments); 3265 } 3266 else if(found !== undefined) { 3267 response = found; 3268 } 3269 if($.isArray(returnedValue)) { 3270 returnedValue.push(response); 3271 } 3272 else if(returnedValue !== undefined) { 3273 returnedValue = [returnedValue, response]; 3274 } 3275 else if(response !== undefined) { 3276 returnedValue = response; 3277 } 3278 return found; 3279 } 3280 }; 3281 3282 module.preinitialize(); 3283 3284 if(methodInvoked) { 3285 if(instance === undefined) { 3286 module.initialize(); 3287 } 3288 module.invoke(query); 3289 } 3290 else { 3291 if(instance !== undefined) { 3292 instance.invoke('destroy'); 3293 } 3294 module.initialize(); 3295 } 3296 }) 3297 ; 3298 3299 return (returnedValue !== undefined) 3300 ? returnedValue 3301 : this 3302 ; 3303 }; 3304 3305 $.fn.dimmer.settings = { 3306 3307 name : 'Dimmer', 3308 namespace : 'dimmer', 3309 3310 debug : false, 3311 verbose : true, 3312 performance : true, 3313 3314 // name to distinguish between multiple dimmers in context 3315 dimmerName : false, 3316 3317 // whether to add a variation type 3318 variation : false, 3319 3320 // whether to bind close events 3321 closable : 'auto', 3322 3323 // whether to use css animations 3324 useCSS : true, 3325 3326 // css animation to use 3327 transition : 'fade', 3328 3329 // event to bind to 3330 on : false, 3331 3332 // overriding opacity value 3333 opacity : 'auto', 3334 3335 // transition durations 3336 duration : { 3337 show : 500, 3338 hide : 500 3339 }, 3340 3341 onChange : function(){}, 3342 onShow : function(){}, 3343 onHide : function(){}, 3344 3345 error : { 3346 method : 'The method you called is not defined.' 3347 }, 3348 3349 selector: { 3350 dimmable : '.dimmable', 3351 dimmer : '.ui.dimmer', 3352 content : '.ui.dimmer > .content, .ui.dimmer > .content > .center' 3353 }, 3354 3355 template: { 3356 dimmer: function() { 3357 return $('<div />').attr('class', 'ui dimmer'); 3358 } 3359 }, 3360 3361 className : { 3362 active : 'active', 3363 animating : 'animating', 3364 dimmable : 'dimmable', 3365 dimmed : 'dimmed', 3366 disabled : 'disabled', 3367 hide : 'hide', 3368 pageDimmer : 'page', 3369 show : 'show' 3370 } 3371 3372 }; 3373 3374 })( jQuery, window , document ); 3375 /*! 3376 * # Semantic UI x.x - Dropdown 3377 * http://github.com/semantic-org/semantic-ui/ 3378 * 3379 * 3380 * Copyright 2014 Contributors 3381 * Released under the MIT license 3382 * http://opensource.org/licenses/MIT 3383 * 3384 */ 3385 3386 ;(function ( $, window, document, undefined ) { 3387 3388 "use strict"; 3389 3390 $.fn.dropdown = function(parameters) { 3391 var 3392 $allModules = $(this), 3393 $document = $(document), 3394 3395 moduleSelector = $allModules.selector || '', 3396 3397 hasTouch = ('ontouchstart' in document.documentElement), 3398 time = new Date().getTime(), 3399 performance = [], 3400 3401 query = arguments[0], 3402 methodInvoked = (typeof query == 'string'), 3403 queryArguments = [].slice.call(arguments, 1), 3404 returnedValue 3405 ; 3406 3407 $allModules 3408 .each(function() { 3409 var 3410 settings = ( $.isPlainObject(parameters) ) 3411 ? $.extend(true, {}, $.fn.dropdown.settings, parameters) 3412 : $.extend({}, $.fn.dropdown.settings), 3413 3414 className = settings.className, 3415 metadata = settings.metadata, 3416 namespace = settings.namespace, 3417 selector = settings.selector, 3418 error = settings.error, 3419 3420 eventNamespace = '.' + namespace, 3421 moduleNamespace = 'module-' + namespace, 3422 3423 $module = $(this), 3424 $text = $module.find(selector.text), 3425 $search = $module.find(selector.search), 3426 $input = $module.find(selector.input), 3427 3428 $combo = ($module.prev().find(selector.text).length > 0) 3429 ? $module.prev().find(selector.text) 3430 : $module.prev(), 3431 3432 $menu = $module.children(selector.menu), 3433 $item = $menu.find(selector.item), 3434 3435 activated = false, 3436 itemActivated = false, 3437 element = this, 3438 instance = $module.data(moduleNamespace), 3439 3440 elementNamespace, 3441 id, 3442 observer, 3443 module 3444 ; 3445 3446 module = { 3447 3448 initialize: function() { 3449 module.debug('Initializing dropdown', settings); 3450 3451 if( module.is.alreadySetup() ) { 3452 module.setup.reference(); 3453 } 3454 else { 3455 module.setup.layout(); 3456 3457 module.save.defaults(); 3458 module.set.selected(); 3459 3460 module.create.id(); 3461 3462 if(hasTouch) { 3463 module.bind.touchEvents(); 3464 } 3465 module.bind.mouseEvents(); 3466 module.bind.keyboardEvents(); 3467 3468 module.observeChanges(); 3469 module.instantiate(); 3470 } 3471 }, 3472 3473 instantiate: function() { 3474 module.verbose('Storing instance of dropdown', module); 3475 instance = module; 3476 $module 3477 .data(moduleNamespace, module) 3478 ; 3479 }, 3480 3481 destroy: function() { 3482 module.verbose('Destroying previous dropdown for', $module); 3483 module.remove.tabbable(); 3484 $module 3485 .off(eventNamespace) 3486 .removeData(moduleNamespace) 3487 ; 3488 $menu 3489 .off(eventNamespace) 3490 ; 3491 $document 3492 .off(elementNamespace) 3493 ; 3494 }, 3495 3496 observeChanges: function() { 3497 if('MutationObserver' in window) { 3498 observer = new MutationObserver(function(mutations) { 3499 if( module.is.selectMutation(mutations) ) { 3500 module.debug('<select> modified, recreating menu'); 3501 module.setup.select(); 3502 } 3503 else { 3504 module.debug('DOM tree modified, updating selector cache'); 3505 module.refresh(); 3506 } 3507 }); 3508 observer.observe(element, { 3509 childList : true, 3510 subtree : true 3511 }); 3512 module.debug('Setting up mutation observer', observer); 3513 } 3514 }, 3515 3516 create: { 3517 id: function() { 3518 id = (Math.random().toString(16) + '000000000').substr(2,8); 3519 elementNamespace = '.' + id; 3520 module.verbose('Creating unique id for element', id); 3521 } 3522 }, 3523 3524 search: function() { 3525 var 3526 query 3527 ; 3528 query = $search.val(); 3529 3530 module.verbose('Searching for query', query); 3531 module.filter(query); 3532 if(module.is.searchSelection() && module.can.show() ) { 3533 module.show(); 3534 } 3535 }, 3536 3537 setup: { 3538 layout: function() { 3539 if( $module.is('select') ) { 3540 module.setup.select(); 3541 } 3542 if( module.is.search() && !module.is.searchable() ) { 3543 $search = $('<input />') 3544 .addClass(className.search) 3545 .insertBefore($text) 3546 ; 3547 } 3548 if(settings.allowTab) { 3549 module.set.tabbable(); 3550 } 3551 }, 3552 select: function() { 3553 var 3554 selectValues = module.get.selectValues() 3555 ; 3556 module.debug('Dropdown initialized on a select', selectValues); 3557 if( $module.is('select') ) { 3558 $input = $module; 3559 } 3560 // see if select is placed correctly already 3561 if($input.parent(selector.dropdown).length > 0) { 3562 module.debug('UI dropdown already exists. Creating dropdown menu only'); 3563 $module = $input.closest(selector.dropdown); 3564 $menu = $module.children(selector.menu); 3565 if($menu.length === 0) { 3566 $menu = $('<div />') 3567 .addClass(className.menu) 3568 .appendTo($module) 3569 ; 3570 } 3571 $menu.html( settings.templates.menu( selectValues )); 3572 } 3573 else { 3574 module.debug('Creating entire dropdown from select'); 3575 $module = $('<div />') 3576 .attr('class', $input.attr('class') ) 3577 .addClass(className.selection) 3578 .addClass(className.dropdown) 3579 .html( settings.templates.dropdown(selectValues) ) 3580 .insertBefore($input) 3581 ; 3582 $input 3583 .removeAttr('class') 3584 .prependTo($module) 3585 ; 3586 } 3587 module.refresh(); 3588 }, 3589 reference: function() { 3590 var 3591 index = $allModules.index($module), 3592 $firstModules, 3593 $lastModules 3594 ; 3595 module.debug('Dropdown behavior was called on select, replacing with closest dropdown'); 3596 // replace module reference 3597 $module = $module.parent(selector.dropdown); 3598 module.refresh(); 3599 // adjust all modules 3600 $firstModules = $allModules.slice(0, index); 3601 $lastModules = $allModules.slice(index + 1); 3602 $allModules = $firstModules.add($module).add($lastModules); 3603 } 3604 }, 3605 3606 refresh: function() { 3607 module.verbose('Refreshing selector cache'); 3608 $text = $module.find(selector.text); 3609 $search = $module.find(selector.search); 3610 $input = $module.find(selector.input); 3611 $combo = ($module.prev().find(selector.text).length > 0) 3612 ? $module.prev().find(selector.text) 3613 : $module.prev() 3614 ; 3615 $menu = $module.children(selector.menu); 3616 $item = $menu.find(selector.item); 3617 }, 3618 3619 toggle: function() { 3620 module.verbose('Toggling menu visibility'); 3621 if( !module.is.active() ) { 3622 module.show(); 3623 } 3624 else { 3625 module.hide(); 3626 } 3627 }, 3628 3629 show: function(callback) { 3630 callback = $.isFunction(callback) 3631 ? callback 3632 : function(){} 3633 ; 3634 if( module.is.searchSelection() && module.is.allFiltered() ) { 3635 return; 3636 } 3637 if( module.can.show() && !module.is.active() ) { 3638 module.debug('Showing dropdown'); 3639 module.animate.show(function() { 3640 if( module.can.click() ) { 3641 module.bind.intent(); 3642 } 3643 module.set.visible(); 3644 callback.call(element); 3645 }); 3646 settings.onShow.call(element); 3647 } 3648 }, 3649 3650 hide: function(callback) { 3651 callback = $.isFunction(callback) 3652 ? callback 3653 : function(){} 3654 ; 3655 if( module.is.active() ) { 3656 module.debug('Hiding dropdown'); 3657 module.animate.hide(function() { 3658 module.remove.visible(); 3659 callback.call(element); 3660 }); 3661 settings.onHide.call(element); 3662 } 3663 }, 3664 3665 hideOthers: function() { 3666 module.verbose('Finding other dropdowns to hide'); 3667 $allModules 3668 .not($module) 3669 .has(selector.menu + ':visible:not(.' + className.animating + ')') 3670 .dropdown('hide') 3671 ; 3672 }, 3673 3674 hideSubMenus: function() { 3675 var 3676 $subMenus = $menu.find(selector.menu) 3677 ; 3678 $subMenus.transition('hide'); 3679 }, 3680 3681 bind: { 3682 keyboardEvents: function() { 3683 module.debug('Binding keyboard events'); 3684 $module 3685 .on('keydown' + eventNamespace, module.event.keydown) 3686 ; 3687 if( module.is.searchable() ) { 3688 $module 3689 .on(module.get.inputEvent(), selector.search, module.event.input) 3690 ; 3691 } 3692 }, 3693 touchEvents: function() { 3694 module.debug('Touch device detected binding additional touch events'); 3695 if( module.is.searchSelection() ) { 3696 // do nothing special yet 3697 } 3698 else { 3699 $module 3700 .on('touchstart' + eventNamespace, module.event.test.toggle) 3701 ; 3702 } 3703 $menu 3704 .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter) 3705 ; 3706 }, 3707 mouseEvents: function() { 3708 module.verbose('Mouse detected binding mouse events'); 3709 if( module.is.searchSelection() ) { 3710 $module 3711 .on('mousedown' + eventNamespace, selector.menu, module.event.menu.activate) 3712 .on('mouseup' + eventNamespace, selector.menu, module.event.menu.deactivate) 3713 .on('click' + eventNamespace, selector.search, module.show) 3714 .on('focus' + eventNamespace, selector.search, module.event.searchFocus) 3715 .on('blur' + eventNamespace, selector.search, module.event.searchBlur) 3716 .on('click' + eventNamespace, selector.text, module.event.searchTextFocus) 3717 ; 3718 } 3719 else { 3720 if(settings.on == 'click') { 3721 $module 3722 .on('click' + eventNamespace, module.event.test.toggle) 3723 ; 3724 } 3725 else if(settings.on == 'hover') { 3726 $module 3727 .on('mouseenter' + eventNamespace, module.delay.show) 3728 .on('mouseleave' + eventNamespace, module.delay.hide) 3729 ; 3730 } 3731 else { 3732 $module 3733 .on(settings.on + eventNamespace, module.toggle) 3734 ; 3735 } 3736 $module 3737 .on('mousedown' + eventNamespace, module.event.mousedown) 3738 .on('mouseup' + eventNamespace, module.event.mouseup) 3739 .on('focus' + eventNamespace, module.event.focus) 3740 .on('blur' + eventNamespace, module.event.blur) 3741 ; 3742 } 3743 $menu 3744 .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter) 3745 .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave) 3746 .on('click' + eventNamespace, selector.item, module.event.item.click) 3747 ; 3748 }, 3749 intent: function() { 3750 module.verbose('Binding hide intent event to document'); 3751 if(hasTouch) { 3752 $document 3753 .on('touchstart' + elementNamespace, module.event.test.touch) 3754 .on('touchmove' + elementNamespace, module.event.test.touch) 3755 ; 3756 } 3757 $document 3758 .on('click' + elementNamespace, module.event.test.hide) 3759 ; 3760 } 3761 }, 3762 3763 unbind: { 3764 intent: function() { 3765 module.verbose('Removing hide intent event from document'); 3766 if(hasTouch) { 3767 $document 3768 .off('touchstart' + elementNamespace) 3769 .off('touchmove' + elementNamespace) 3770 ; 3771 } 3772 $document 3773 .off('click' + elementNamespace) 3774 ; 3775 } 3776 }, 3777 3778 filter: function(searchTerm) { 3779 var 3780 $results = $(), 3781 escapedTerm = module.escape.regExp(searchTerm), 3782 exactRegExp = new RegExp('^' + escapedTerm, 'igm'), 3783 fullTextRegExp = new RegExp(escapedTerm, 'ig'), 3784 allItemsFiltered 3785 ; 3786 module.verbose('Searching for matching values'); 3787 $item 3788 .each(function(){ 3789 var 3790 $choice = $(this), 3791 text = String(module.get.choiceText($choice, false)), 3792 value = String(module.get.choiceValue($choice, text)) 3793 ; 3794 if( text.match(exactRegExp) || value.match(exactRegExp) ) { 3795 $results = $results.add($choice); 3796 } 3797 else if(settings.fullTextSearch) { 3798 if( text.match(fullTextRegExp) || value.match(fullTextRegExp) ) { 3799 $results = $results.add($choice); 3800 } 3801 } 3802 }) 3803 ; 3804 3805 module.debug('Setting filter', searchTerm); 3806 module.remove.filteredItem(); 3807 $item 3808 .not($results) 3809 .addClass(className.filtered) 3810 ; 3811 3812 module.verbose('Selecting first non-filtered element'); 3813 module.remove.selectedItem(); 3814 $item 3815 .not('.' + className.filtered) 3816 .eq(0) 3817 .addClass(className.selected) 3818 ; 3819 if( module.is.allFiltered() ) { 3820 module.debug('All items filtered, hiding dropdown', searchTerm); 3821 if(module.is.searchSelection()) { 3822 module.hide(); 3823 } 3824 settings.onNoResults.call(element, searchTerm); 3825 } 3826 }, 3827 3828 focusSearch: function() { 3829 if( module.is.search() ) { 3830 $search 3831 .focus() 3832 ; 3833 } 3834 }, 3835 3836 forceSelection: function() { 3837 var 3838 $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0), 3839 $activeItem = $item.filter('.' + className.active).eq(0), 3840 $selectedItem = ($currentlySelected.length > 0) 3841 ? $currentlySelected 3842 : $activeItem, 3843 hasSelected = ($selectedItem.size() > 0) 3844 ; 3845 if(hasSelected) { 3846 module.event.item.click.call($selectedItem); 3847 module.remove.filteredItem(); 3848 } 3849 else { 3850 module.hide(); 3851 } 3852 }, 3853 3854 event: { 3855 // prevents focus callback from occuring on mousedown 3856 mousedown: function() { 3857 activated = true; 3858 }, 3859 mouseup: function() { 3860 activated = false; 3861 }, 3862 focus: function() { 3863 if(!activated && module.is.hidden()) { 3864 module.show(); 3865 } 3866 }, 3867 blur: function(event) { 3868 var 3869 pageLostFocus = (document.activeElement === this) 3870 ; 3871 if(!activated && !pageLostFocus) { 3872 module.hide(); 3873 } 3874 }, 3875 searchFocus: function() { 3876 activated = true; 3877 module.show(); 3878 }, 3879 searchBlur: function(event) { 3880 var 3881 pageLostFocus = (document.activeElement === this) 3882 ; 3883 if(!itemActivated && !pageLostFocus) { 3884 if(settings.forceSelection) { 3885 module.forceSelection(); 3886 } 3887 else { 3888 module.hide(); 3889 } 3890 } 3891 }, 3892 searchTextFocus: function(event) { 3893 activated = true; 3894 $search.focus(); 3895 }, 3896 input: function(event) { 3897 if(module.is.searchSelection()) { 3898 module.set.filtered(); 3899 } 3900 clearTimeout(module.timer); 3901 module.timer = setTimeout(module.search, settings.delay.search); 3902 }, 3903 keydown: function(event) { 3904 var 3905 $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0), 3906 $activeItem = $menu.children('.' + className.active).eq(0), 3907 $selectedItem = ($currentlySelected.length > 0) 3908 ? $currentlySelected 3909 : $activeItem, 3910 $visibleItems = ($selectedItem.length > 0) 3911 ? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf() 3912 : $menu.children(':not(.' + className.filtered +')'), 3913 $subMenu = $selectedItem.children(selector.menu), 3914 $parentMenu = $selectedItem.closest(selector.menu), 3915 isSubMenuItem = $parentMenu[0] !== $menu[0], 3916 inVisibleMenu = $parentMenu.is(':visible'), 3917 pressedKey = event.which, 3918 keys = { 3919 enter : 13, 3920 escape : 27, 3921 leftArrow : 37, 3922 upArrow : 38, 3923 rightArrow : 39, 3924 downArrow : 40 3925 }, 3926 hasSubMenu = ($subMenu.length> 0), 3927 hasSelectedItem = ($selectedItem.length > 0), 3928 lastVisibleIndex = ($visibleItems.size() - 1), 3929 $nextItem, 3930 newIndex 3931 ; 3932 // visible menu keyboard shortcuts 3933 if(module.is.visible()) { 3934 // enter (select or sub-menu) 3935 if(pressedKey == keys.enter && hasSelectedItem) { 3936 if(hasSubMenu && !settings.allowCategorySelection) { 3937 module.verbose('Pressed enter on unselectable category, opening sub menu'); 3938 pressedKey = keys.rightArrow; 3939 } 3940 else { 3941 module.verbose('Enter key pressed, choosing selected item'); 3942 module.event.item.click.call($selectedItem, event); 3943 } 3944 } 3945 // left arrow (hide sub-menu) 3946 if(pressedKey == keys.leftArrow) { 3947 if(isSubMenuItem) { 3948 module.verbose('Left key pressed, closing sub-menu'); 3949 module.animate.hide(false, $parentMenu); 3950 $selectedItem 3951 .removeClass(className.selected) 3952 ; 3953 $parentMenu 3954 .closest(selector.item) 3955 .addClass(className.selected) 3956 ; 3957 } 3958 event.preventDefault(); 3959 } 3960 // right arrow (show sub-menu) 3961 if(pressedKey == keys.rightArrow) { 3962 if(hasSubMenu) { 3963 module.verbose('Right key pressed, opening sub-menu'); 3964 module.animate.show(false, $subMenu); 3965 $selectedItem 3966 .removeClass(className.selected) 3967 ; 3968 $subMenu 3969 .find(selector.item).eq(0) 3970 .addClass(className.selected) 3971 ; 3972 } 3973 event.preventDefault(); 3974 } 3975 // up arrow (traverse menu up) 3976 if(pressedKey == keys.upArrow) { 3977 $nextItem = (hasSelectedItem && inVisibleMenu) 3978 ? $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0) 3979 : $item.eq(0) 3980 ; 3981 if($visibleItems.index( $nextItem ) < 0) { 3982 module.verbose('Up key pressed but reached top of current menu'); 3983 return; 3984 } 3985 else { 3986 module.verbose('Up key pressed, changing active item'); 3987 $selectedItem 3988 .removeClass(className.selected) 3989 ; 3990 $nextItem 3991 .addClass(className.selected) 3992 ; 3993 module.set.scrollPosition($nextItem); 3994 } 3995 event.preventDefault(); 3996 } 3997 // down arrow (traverse menu down) 3998 if(pressedKey == keys.downArrow) { 3999 $nextItem = (hasSelectedItem && inVisibleMenu) 4000 ? $nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0) 4001 : $item.eq(0) 4002 ; 4003 if($nextItem.length === 0) { 4004 module.verbose('Down key pressed but reached bottom of current menu'); 4005 return; 4006 } 4007 else { 4008 module.verbose('Down key pressed, changing active item'); 4009 $item 4010 .removeClass(className.selected) 4011 ; 4012 $nextItem 4013 .addClass(className.selected) 4014 ; 4015 module.set.scrollPosition($nextItem); 4016 } 4017 event.preventDefault(); 4018 } 4019 } 4020 else { 4021 // enter (open menu) 4022 if(pressedKey == keys.enter) { 4023 module.verbose('Enter key pressed, showing dropdown'); 4024 module.show(); 4025 } 4026 // escape (close menu) 4027 if(pressedKey == keys.escape) { 4028 module.verbose('Escape key pressed, closing dropdown'); 4029 module.hide(); 4030 } 4031 // down arrow (open menu) 4032 if(pressedKey == keys.downArrow) { 4033 module.verbose('Down key pressed, showing dropdown'); 4034 module.show(); 4035 } 4036 } 4037 }, 4038 test: { 4039 toggle: function(event) { 4040 if( module.determine.eventInMenu(event, module.toggle) ) { 4041 event.preventDefault(); 4042 } 4043 }, 4044 touch: function(event) { 4045 module.determine.eventInMenu(event, function() { 4046 if(event.type == 'touchstart') { 4047 module.timer = setTimeout(module.hide, settings.delay.touch); 4048 } 4049 else if(event.type == 'touchmove') { 4050 clearTimeout(module.timer); 4051 } 4052 }); 4053 event.stopPropagation(); 4054 }, 4055 hide: function(event) { 4056 module.determine.eventInModule(event, module.hide); 4057 } 4058 }, 4059 4060 menu: { 4061 activate: function() { 4062 itemActivated = true; 4063 }, 4064 deactivate: function() { 4065 itemActivated = false; 4066 } 4067 }, 4068 item: { 4069 mouseenter: function(event) { 4070 var 4071 $subMenu = $(this).children(selector.menu), 4072 $otherMenus = $(this).siblings(selector.item).children(selector.menu) 4073 ; 4074 if( $subMenu.length > 0 ) { 4075 clearTimeout(module.itemTimer); 4076 module.itemTimer = setTimeout(function() { 4077 module.verbose('Showing sub-menu', $subMenu); 4078 $.each($otherMenus, function() { 4079 module.animate.hide(false, $(this)); 4080 }); 4081 module.animate.show(false, $subMenu); 4082 }, settings.delay.show); 4083 event.preventDefault(); 4084 } 4085 }, 4086 mouseleave: function(event) { 4087 var 4088 $subMenu = $(this).children(selector.menu) 4089 ; 4090 if($subMenu.length > 0) { 4091 clearTimeout(module.itemTimer); 4092 module.itemTimer = setTimeout(function() { 4093 module.verbose('Hiding sub-menu', $subMenu); 4094 module.animate.hide(false, $subMenu); 4095 }, settings.delay.hide); 4096 } 4097 }, 4098 click: function (event) { 4099 var 4100 $choice = $(this), 4101 $target = (event) 4102 ? $(event.target) 4103 : $(''), 4104 $subMenu = $choice.find(selector.menu), 4105 text = module.get.choiceText($choice), 4106 value = module.get.choiceValue($choice, text), 4107 callback = function() { 4108 module.remove.searchTerm(); 4109 module.determine.selectAction(text, value); 4110 }, 4111 hasSubMenu = ($subMenu.length > 0), 4112 isBubbledEvent = ($subMenu.find($target).length > 0) 4113 ; 4114 if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) { 4115 callback(); 4116 } 4117 } 4118 }, 4119 resetStyle: function() { 4120 $(this).removeAttr('style'); 4121 } 4122 }, 4123 4124 determine: { 4125 selectAction: function(text, value) { 4126 module.verbose('Determining action', settings.action); 4127 if( $.isFunction( module.action[settings.action] ) ) { 4128 module.verbose('Triggering preset action', settings.action, text, value); 4129 module.action[ settings.action ](text, value); 4130 } 4131 else if( $.isFunction(settings.action) ) { 4132 module.verbose('Triggering user action', settings.action, text, value); 4133 settings.action(text, value); 4134 } 4135 else { 4136 module.error(error.action, settings.action); 4137 } 4138 }, 4139 eventInModule: function(event, callback) { 4140 callback = $.isFunction(callback) 4141 ? callback 4142 : function(){} 4143 ; 4144 if( $(event.target).closest($module).length === 0 ) { 4145 module.verbose('Triggering event', callback); 4146 callback(); 4147 return true; 4148 } 4149 else { 4150 module.verbose('Event occurred in dropdown, canceling callback'); 4151 return false; 4152 } 4153 }, 4154 eventInMenu: function(event, callback) { 4155 callback = $.isFunction(callback) 4156 ? callback 4157 : function(){} 4158 ; 4159 if( $(event.target).closest($menu).length === 0 ) { 4160 module.verbose('Triggering event', callback); 4161 callback(); 4162 return true; 4163 } 4164 else { 4165 module.verbose('Event occurred in dropdown menu, canceling callback'); 4166 return false; 4167 } 4168 } 4169 }, 4170 4171 action: { 4172 4173 nothing: function() {}, 4174 4175 activate: function(text, value) { 4176 value = (value !== undefined) 4177 ? value 4178 : text 4179 ; 4180 module.set.selected(value); 4181 module.hide(function() { 4182 module.remove.filteredItem(); 4183 }); 4184 }, 4185 4186 select: function(text, value) { 4187 value = (value !== undefined) 4188 ? value 4189 : text 4190 ; 4191 module.set.selected(value); 4192 module.hide(function() { 4193 module.remove.filteredItem(); 4194 }); 4195 }, 4196 4197 combo: function(text, value) { 4198 value = (value !== undefined) 4199 ? value 4200 : text 4201 ; 4202 module.set.selected(value); 4203 module.hide(function() { 4204 module.remove.filteredItem(); 4205 }); 4206 }, 4207 4208 hide: function() { 4209 module.hide(function() { 4210 module.remove.filteredItem(); 4211 }); 4212 } 4213 4214 }, 4215 4216 get: { 4217 id: function() { 4218 return id; 4219 }, 4220 text: function() { 4221 return $text.text(); 4222 }, 4223 value: function() { 4224 return ($input.length > 0) 4225 ? $input.val() 4226 : $module.data(metadata.value) 4227 ; 4228 }, 4229 choiceText: function($choice, preserveHTML) { 4230 preserveHTML = (preserveHTML !== undefined) 4231 ? preserveHTML 4232 : settings.preserveHTML 4233 ; 4234 if($choice !== undefined) { 4235 if($choice.find(selector.menu).length > 0) { 4236 module.verbose('Retreiving text of element with sub-menu'); 4237 $choice = $choice.clone(); 4238 $choice.find(selector.menu).remove(); 4239 $choice.find(selector.menuIcon).remove(); 4240 } 4241 return ($choice.data(metadata.text) !== undefined) 4242 ? $choice.data(metadata.text) 4243 : (preserveHTML) 4244 ? $choice.html().trim() 4245 : $choice.text().trim() 4246 ; 4247 } 4248 }, 4249 choiceValue: function($choice, choiceText) { 4250 choiceText = choiceText || module.get.choiceText($choice); 4251 return ($choice.data(metadata.value) !== undefined) 4252 ? $choice.data(metadata.value) 4253 : (typeof choiceText === 'string') 4254 ? choiceText.toLowerCase().trim() 4255 : choiceText.trim() 4256 ; 4257 }, 4258 inputEvent: function() { 4259 var 4260 input = $search[0] 4261 ; 4262 if(input) { 4263 return (input.oninput !== undefined) 4264 ? 'input' 4265 : (input.onpropertychange !== undefined) 4266 ? 'propertychange' 4267 : 'keyup' 4268 ; 4269 } 4270 return false; 4271 }, 4272 selectValues: function() { 4273 var 4274 select = {} 4275 ; 4276 select.values = (settings.sortSelect) 4277 ? {} // properties will be sorted in object when re-accessed 4278 : [] // properties will keep original order in array 4279 ; 4280 $module 4281 .find('option') 4282 .each(function() { 4283 var 4284 name = $(this).html(), 4285 value = ( $(this).attr('value') !== undefined ) 4286 ? $(this).attr('value') 4287 : name 4288 ; 4289 if(value === '') { 4290 select.placeholder = name; 4291 } 4292 else { 4293 if(settings.sortSelect) { 4294 select.values[value] = { 4295 name : name, 4296 value : value 4297 }; 4298 } 4299 else { 4300 select.values.push({ 4301 name: name, 4302 value: value 4303 }); 4304 } 4305 } 4306 }) 4307 ; 4308 if(settings.sortSelect) { 4309 module.debug('Retrieved and sorted values from select', select); 4310 } 4311 else { 4312 module.debug('Retreived values from select', select); 4313 } 4314 return select; 4315 }, 4316 activeItem: function() { 4317 return $item.filter('.' + className.active); 4318 }, 4319 item: function(value, strict) { 4320 var 4321 $selectedItem = false 4322 ; 4323 value = (value !== undefined) 4324 ? value 4325 : ( module.get.value() !== undefined) 4326 ? module.get.value() 4327 : module.get.text() 4328 ; 4329 strict = (value === '' || value === 0) 4330 ? true 4331 : strict || false 4332 ; 4333 if(value !== undefined) { 4334 $item 4335 .each(function() { 4336 var 4337 $choice = $(this), 4338 optionText = module.get.choiceText($choice), 4339 optionValue = module.get.choiceValue($choice, optionText) 4340 ; 4341 if(strict) { 4342 module.verbose('Ambiguous dropdown value using strict type check', $choice, value); 4343 if( optionValue === value ) { 4344 $selectedItem = $(this); 4345 return true; 4346 } 4347 else if( !$selectedItem && optionText === value ) { 4348 $selectedItem = $(this); 4349 return true; 4350 } 4351 } 4352 else { 4353 if( optionValue == value ) { 4354 module.verbose('Found select item by value', optionValue, value); 4355 $selectedItem = $(this); 4356 return true; 4357 } 4358 else if( !$selectedItem && optionText == value ) { 4359 module.verbose('Found select item by text', optionText, value); 4360 $selectedItem = $(this); 4361 return true; 4362 } 4363 } 4364 }) 4365 ; 4366 } 4367 else { 4368 value = module.get.text(); 4369 } 4370 return $selectedItem || false; 4371 } 4372 }, 4373 4374 restore: { 4375 defaults: function() { 4376 module.restore.defaultText(); 4377 module.restore.defaultValue(); 4378 }, 4379 defaultText: function() { 4380 var 4381 defaultText = $module.data(metadata.defaultText) 4382 ; 4383 module.debug('Restoring default text', defaultText); 4384 module.set.text(defaultText); 4385 $text.addClass(className.placeholder); 4386 }, 4387 defaultValue: function() { 4388 var 4389 defaultValue = $module.data(metadata.defaultValue) 4390 ; 4391 if(defaultValue !== undefined) { 4392 module.debug('Restoring default value', defaultValue); 4393 if(defaultValue.length) { 4394 module.set.selected(defaultValue); 4395 } 4396 else { 4397 module.remove.activeItem(); 4398 module.remove.selectedItem(); 4399 } 4400 } 4401 } 4402 }, 4403 4404 save: { 4405 defaults: function() { 4406 module.save.defaultText(); 4407 module.save.placeholderText(); 4408 module.save.defaultValue(); 4409 }, 4410 defaultValue: function() { 4411 $module.data(metadata.defaultValue, module.get.value() ); 4412 }, 4413 defaultText: function() { 4414 $module.data(metadata.defaultText, $text.text() ); 4415 }, 4416 placeholderText: function() { 4417 if($text.hasClass(className.placeholder)) { 4418 $module.data(metadata.placeholderText, $text.text()); 4419 } 4420 } 4421 }, 4422 4423 clear: function() { 4424 var 4425 placeholderText = $module.data(metadata.placeholderText) 4426 ; 4427 module.set.text(placeholderText); 4428 module.set.value(''); 4429 module.remove.activeItem(); 4430 module.remove.selectedItem(); 4431 $text.addClass(className.placeholder); 4432 }, 4433 4434 set: { 4435 filtered: function() { 4436 var 4437 searchValue = $search.val(), 4438 hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0) 4439 ; 4440 if(hasSearchValue) { 4441 $text.addClass(className.filtered); 4442 } 4443 else { 4444 $text.removeClass(className.filtered); 4445 } 4446 }, 4447 tabbable: function() { 4448 if( module.is.searchable() ) { 4449 module.debug('Searchable dropdown initialized'); 4450 $search 4451 .val('') 4452 .attr('tabindex', 0) 4453 ; 4454 $menu 4455 .attr('tabindex', '-1') 4456 ; 4457 } 4458 else { 4459 module.debug('Simple selection dropdown initialized'); 4460 if(!$module.attr('tabindex') ) { 4461 $module 4462 .attr('tabindex', 0) 4463 ; 4464 $menu 4465 .attr('tabindex', '-1') 4466 ; 4467 } 4468 } 4469 }, 4470 scrollPosition: function($item, forceScroll) { 4471 var 4472 edgeTolerance = 5, 4473 hasActive, 4474 offset, 4475 itemHeight, 4476 itemOffset, 4477 menuOffset, 4478 menuScroll, 4479 menuHeight, 4480 abovePage, 4481 belowPage 4482 ; 4483 4484 $item = $item || module.get.activeItem(); 4485 hasActive = ($item && $item.length > 0); 4486 forceScroll = (forceScroll !== undefined) 4487 ? forceScroll 4488 : false 4489 ; 4490 4491 if($item && hasActive) { 4492 4493 if(!$menu.hasClass(className.visible)) { 4494 $menu.addClass(className.loading); 4495 } 4496 4497 menuHeight = $menu.height(); 4498 itemHeight = $item.height(); 4499 menuScroll = $menu.scrollTop(); 4500 menuOffset = $menu.offset().top; 4501 itemOffset = $item.offset().top; 4502 offset = menuScroll - menuOffset + itemOffset; 4503 belowPage = menuScroll + menuHeight < (offset + edgeTolerance); 4504 abovePage = ((offset - edgeTolerance) < menuScroll); 4505 module.debug('Scrolling to active item', offset); 4506 if(abovePage || belowPage || forceScroll) { 4507 $menu 4508 .scrollTop(offset) 4509 .removeClass(className.loading) 4510 ; 4511 } 4512 } 4513 }, 4514 text: function(text) { 4515 if(settings.action == 'combo') { 4516 module.debug('Changing combo button text', text, $combo); 4517 if(settings.preserveHTML) { 4518 $combo.html(text); 4519 } 4520 else { 4521 $combo.text(text); 4522 } 4523 } 4524 else if(settings.action !== 'select') { 4525 module.debug('Changing text', text, $text); 4526 $text 4527 .removeClass(className.filtered) 4528 .removeClass(className.placeholder) 4529 ; 4530 if(settings.preserveHTML) { 4531 $text.html(text); 4532 } 4533 else { 4534 $text.text(text); 4535 } 4536 } 4537 }, 4538 value: function(value) { 4539 module.debug('Adding selected value to hidden input', value, $input); 4540 if($input.length > 0) { 4541 $input 4542 .val(value) 4543 .trigger('change') 4544 ; 4545 } 4546 else { 4547 $module.data(metadata.value, value); 4548 } 4549 }, 4550 active: function() { 4551 $module 4552 .addClass(className.active) 4553 ; 4554 }, 4555 visible: function() { 4556 $module.addClass(className.visible); 4557 }, 4558 selected: function(value) { 4559 var 4560 $selectedItem = module.get.item(value), 4561 selectedText, 4562 selectedValue 4563 ; 4564 if($selectedItem && !$selectedItem.hasClass(className.active) ) { 4565 module.debug('Setting selected menu item to', $selectedItem); 4566 module.remove.activeItem(); 4567 module.remove.selectedItem(); 4568 $selectedItem 4569 .addClass(className.active) 4570 .addClass(className.selected) 4571 ; 4572 selectedText = module.get.choiceText($selectedItem); 4573 selectedValue = module.get.choiceValue($selectedItem, selectedText); 4574 module.set.text(selectedText); 4575 module.set.value(selectedValue); 4576 settings.onChange.call(element, value, selectedText, $selectedItem); 4577 } 4578 } 4579 }, 4580 4581 remove: { 4582 active: function() { 4583 $module.removeClass(className.active); 4584 }, 4585 visible: function() { 4586 $module.removeClass(className.visible); 4587 }, 4588 activeItem: function() { 4589 $item.removeClass(className.active); 4590 }, 4591 filteredItem: function() { 4592 $item.removeClass(className.filtered); 4593 }, 4594 searchTerm: function() { 4595 $search.val(''); 4596 }, 4597 selectedItem: function() { 4598 $item.removeClass(className.selected); 4599 }, 4600 tabbable: function() { 4601 if( module.is.searchable() ) { 4602 module.debug('Searchable dropdown initialized'); 4603 $search 4604 .attr('tabindex', '-1') 4605 ; 4606 $menu 4607 .attr('tabindex', '-1') 4608 ; 4609 } 4610 else { 4611 module.debug('Simple selection dropdown initialized'); 4612 $module 4613 .attr('tabindex', '-1') 4614 ; 4615 $menu 4616 .attr('tabindex', '-1') 4617 ; 4618 } 4619 } 4620 }, 4621 4622 is: { 4623 active: function() { 4624 return $module.hasClass(className.active); 4625 }, 4626 alreadySetup: function() { 4627 return ($module.is('select') && $module.parent(selector.dropdown).length > 0); 4628 }, 4629 animating: function($subMenu) { 4630 return ($subMenu) 4631 ? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating') 4632 : $menu.is(':animated') || $menu.transition && $menu.transition('is animating') 4633 ; 4634 }, 4635 allFiltered: function() { 4636 return ($item.filter('.' + className.filtered).length === $item.length); 4637 }, 4638 hidden: function($subMenu) { 4639 return ($subMenu) 4640 ? $subMenu.is(':hidden') 4641 : $menu.is(':hidden') 4642 ; 4643 }, 4644 selectMutation: function(mutations) { 4645 var 4646 selectChanged = false 4647 ; 4648 $.each(mutations, function(index, mutation) { 4649 if(mutation.target && $(mutation.target).is('select')) { 4650 selectChanged = true; 4651 return true; 4652 } 4653 }); 4654 return selectChanged; 4655 }, 4656 search: function() { 4657 return $module.hasClass(className.search); 4658 }, 4659 searchable: function() { 4660 return ($search.length > 0); 4661 }, 4662 searchSelection: function() { 4663 return ( module.is.searchable() && $search.parent().is($module) ); 4664 }, 4665 selection: function() { 4666 return $module.hasClass(className.selection); 4667 }, 4668 upward: function() { 4669 return $module.hasClass(className.upward); 4670 }, 4671 visible: function($subMenu) { 4672 return ($subMenu) 4673 ? $subMenu.is(':visible') 4674 : $menu.is(':visible') 4675 ; 4676 } 4677 }, 4678 4679 can: { 4680 click: function() { 4681 return (hasTouch || settings.on == 'click'); 4682 }, 4683 show: function() { 4684 return !$module.hasClass(className.disabled); 4685 } 4686 }, 4687 4688 animate: { 4689 show: function(callback, $subMenu) { 4690 var 4691 $currentMenu = $subMenu || $menu, 4692 start = ($subMenu) 4693 ? function() {} 4694 : function() { 4695 module.hideSubMenus(); 4696 module.hideOthers(); 4697 module.set.active(); 4698 } 4699 ; 4700 callback = $.isFunction(callback) 4701 ? callback 4702 : function(){} 4703 ; 4704 module.set.scrollPosition(module.get.activeItem(), true); 4705 module.verbose('Doing menu show animation', $currentMenu); 4706 if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) { 4707 4708 if(settings.transition == 'auto') { 4709 settings.transition = module.is.upward() 4710 ? 'slide up' 4711 : 'slide down' 4712 ; 4713 module.verbose('Automatically determining animation based on animation direction', settings.transition); 4714 } 4715 if(settings.transition == 'none') { 4716 callback.call(element); 4717 } 4718 else if($.fn.transition !== undefined && $module.transition('is supported')) { 4719 $currentMenu 4720 .transition({ 4721 animation : settings.transition + ' in', 4722 debug : settings.debug, 4723 verbose : settings.verbose, 4724 duration : settings.duration, 4725 queue : true, 4726 onStart : start, 4727 onComplete : function() { 4728 callback.call(element); 4729 } 4730 }) 4731 ; 4732 } 4733 else if(settings.transition == 'slide down') { 4734 start(); 4735 $currentMenu 4736 .hide() 4737 .clearQueue() 4738 .children() 4739 .clearQueue() 4740 .css('opacity', 0) 4741 .delay(50) 4742 .animate({ 4743 opacity : 1 4744 }, settings.duration, 'easeOutQuad', module.event.resetStyle) 4745 .end() 4746 .slideDown(100, 'easeOutQuad', function() { 4747 module.event.resetStyle.call(this); 4748 callback.call(element); 4749 }) 4750 ; 4751 } 4752 else if(settings.transition == 'fade') { 4753 start(); 4754 $currentMenu 4755 .hide() 4756 .clearQueue() 4757 .fadeIn(settings.duration, function() { 4758 module.event.resetStyle.call(this); 4759 callback.call(element); 4760 }) 4761 ; 4762 } 4763 else { 4764 module.error(error.transition, settings.transition); 4765 } 4766 } 4767 }, 4768 hide: function(callback, $subMenu) { 4769 var 4770 $currentMenu = $subMenu || $menu, 4771 duration = ($subMenu) 4772 ? (settings.duration * 0.9) 4773 : settings.duration, 4774 start = ($subMenu) 4775 ? function() {} 4776 : function() { 4777 if( module.can.click() ) { 4778 module.unbind.intent(); 4779 } 4780 module.focusSearch(); 4781 module.remove.active(); 4782 } 4783 ; 4784 callback = $.isFunction(callback) 4785 ? callback 4786 : function(){} 4787 ; 4788 if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) { 4789 module.verbose('Doing menu hide animation', $currentMenu); 4790 4791 if(settings.transition == 'auto') { 4792 settings.transition = module.is.upward() 4793 ? 'slide up' 4794 : 'slide down' 4795 ; 4796 } 4797 4798 $input.trigger('blur'); 4799 4800 if(settings.transition == 'none') { 4801 callback.call(element); 4802 } 4803 else if($.fn.transition !== undefined && $module.transition('is supported')) { 4804 $currentMenu 4805 .transition({ 4806 animation : settings.transition + ' out', 4807 duration : settings.duration, 4808 debug : settings.debug, 4809 verbose : settings.verbose, 4810 queue : true, 4811 onStart : start, 4812 onComplete : function() { 4813 callback.call(element); 4814 } 4815 }) 4816 ; 4817 } 4818 else if(settings.transition == 'slide down') { 4819 start(); 4820 $currentMenu 4821 .show() 4822 .clearQueue() 4823 .children() 4824 .clearQueue() 4825 .css('opacity', 1) 4826 .animate({ 4827 opacity : 0 4828 }, 100, 'easeOutQuad', module.event.resetStyle) 4829 .end() 4830 .delay(50) 4831 .slideUp(100, 'easeOutQuad', function() { 4832 module.event.resetStyle.call(this); 4833 callback.call(element); 4834 }) 4835 ; 4836 } 4837 else if(settings.transition == 'fade') { 4838 start(); 4839 $currentMenu 4840 .show() 4841 .clearQueue() 4842 .fadeOut(150, function() { 4843 module.event.resetStyle.call(this); 4844 callback.call(element); 4845 }) 4846 ; 4847 } 4848 else { 4849 module.error(error.transition); 4850 } 4851 } 4852 } 4853 }, 4854 4855 delay: { 4856 show: function() { 4857 module.verbose('Delaying show event to ensure user intent'); 4858 clearTimeout(module.timer); 4859 module.timer = setTimeout(module.show, settings.delay.show); 4860 }, 4861 hide: function() { 4862 module.verbose('Delaying hide event to ensure user intent'); 4863 clearTimeout(module.timer); 4864 module.timer = setTimeout(module.hide, settings.delay.hide); 4865 } 4866 }, 4867 4868 escape: { 4869 regExp: function(text) { 4870 text = String(text); 4871 return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); 4872 } 4873 }, 4874 4875 setting: function(name, value) { 4876 module.debug('Changing setting', name, value); 4877 if( $.isPlainObject(name) ) { 4878 $.extend(true, settings, name); 4879 } 4880 else if(value !== undefined) { 4881 settings[name] = value; 4882 } 4883 else { 4884 return settings[name]; 4885 } 4886 }, 4887 internal: function(name, value) { 4888 if( $.isPlainObject(name) ) { 4889 $.extend(true, module, name); 4890 } 4891 else if(value !== undefined) { 4892 module[name] = value; 4893 } 4894 else { 4895 return module[name]; 4896 } 4897 }, 4898 debug: function() { 4899 if(settings.debug) { 4900 if(settings.performance) { 4901 module.performance.log(arguments); 4902 } 4903 else { 4904 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 4905 module.debug.apply(console, arguments); 4906 } 4907 } 4908 }, 4909 verbose: function() { 4910 if(settings.verbose && settings.debug) { 4911 if(settings.performance) { 4912 module.performance.log(arguments); 4913 } 4914 else { 4915 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 4916 module.verbose.apply(console, arguments); 4917 } 4918 } 4919 }, 4920 error: function() { 4921 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 4922 module.error.apply(console, arguments); 4923 }, 4924 performance: { 4925 log: function(message) { 4926 var 4927 currentTime, 4928 executionTime, 4929 previousTime 4930 ; 4931 if(settings.performance) { 4932 currentTime = new Date().getTime(); 4933 previousTime = time || currentTime; 4934 executionTime = currentTime - previousTime; 4935 time = currentTime; 4936 performance.push({ 4937 'Name' : message[0], 4938 'Arguments' : [].slice.call(message, 1) || '', 4939 'Element' : element, 4940 'Execution Time' : executionTime 4941 }); 4942 } 4943 clearTimeout(module.performance.timer); 4944 module.performance.timer = setTimeout(module.performance.display, 500); 4945 }, 4946 display: function() { 4947 var 4948 title = settings.name + ':', 4949 totalTime = 0 4950 ; 4951 time = false; 4952 clearTimeout(module.performance.timer); 4953 $.each(performance, function(index, data) { 4954 totalTime += data['Execution Time']; 4955 }); 4956 title += ' ' + totalTime + 'ms'; 4957 if(moduleSelector) { 4958 title += ' \'' + moduleSelector + '\''; 4959 } 4960 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 4961 console.groupCollapsed(title); 4962 if(console.table) { 4963 console.table(performance); 4964 } 4965 else { 4966 $.each(performance, function(index, data) { 4967 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 4968 }); 4969 } 4970 console.groupEnd(); 4971 } 4972 performance = []; 4973 } 4974 }, 4975 invoke: function(query, passedArguments, context) { 4976 var 4977 object = instance, 4978 maxDepth, 4979 found, 4980 response 4981 ; 4982 passedArguments = passedArguments || queryArguments; 4983 context = element || context; 4984 if(typeof query == 'string' && object !== undefined) { 4985 query = query.split(/[\. ]/); 4986 maxDepth = query.length - 1; 4987 $.each(query, function(depth, value) { 4988 var camelCaseValue = (depth != maxDepth) 4989 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 4990 : query 4991 ; 4992 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 4993 object = object[camelCaseValue]; 4994 } 4995 else if( object[camelCaseValue] !== undefined ) { 4996 found = object[camelCaseValue]; 4997 return false; 4998 } 4999 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 5000 object = object[value]; 5001 } 5002 else if( object[value] !== undefined ) { 5003 found = object[value]; 5004 return false; 5005 } 5006 else { 5007 module.error(error.method, query); 5008 return false; 5009 } 5010 }); 5011 } 5012 if ( $.isFunction( found ) ) { 5013 response = found.apply(context, passedArguments); 5014 } 5015 else if(found !== undefined) { 5016 response = found; 5017 } 5018 if($.isArray(returnedValue)) { 5019 returnedValue.push(response); 5020 } 5021 else if(returnedValue !== undefined) { 5022 returnedValue = [returnedValue, response]; 5023 } 5024 else if(response !== undefined) { 5025 returnedValue = response; 5026 } 5027 return found; 5028 } 5029 }; 5030 5031 if(methodInvoked) { 5032 if(instance === undefined) { 5033 module.initialize(); 5034 } 5035 module.invoke(query); 5036 } 5037 else { 5038 if(instance !== undefined) { 5039 instance.invoke('destroy'); 5040 } 5041 module.initialize(); 5042 } 5043 }) 5044 ; 5045 return (returnedValue !== undefined) 5046 ? returnedValue 5047 : $allModules 5048 ; 5049 }; 5050 5051 $.fn.dropdown.settings = { 5052 5053 debug : false, 5054 verbose : true, 5055 performance : true, 5056 5057 on : 'click', 5058 action : 'activate', 5059 5060 allowTab : true, 5061 fullTextSearch : false, 5062 preserveHTML : true, 5063 sortSelect : false, 5064 5065 allowCategorySelection : false, 5066 5067 delay : { 5068 hide : 300, 5069 show : 200, 5070 search : 50, 5071 touch : 50 5072 }, 5073 5074 forceSelection: true, 5075 5076 transition : 'auto', 5077 duration : 250, 5078 5079 /* Callbacks */ 5080 onNoResults : function(searchTerm){}, 5081 onChange : function(value, text){}, 5082 onShow : function(){}, 5083 onHide : function(){}, 5084 5085 /* Component */ 5086 5087 name : 'Dropdown', 5088 namespace : 'dropdown', 5089 5090 error : { 5091 action : 'You called a dropdown action that was not defined', 5092 alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown', 5093 method : 'The method you called is not defined.', 5094 transition : 'The requested transition was not found' 5095 }, 5096 5097 metadata: { 5098 defaultText : 'defaultText', 5099 defaultValue : 'defaultValue', 5100 placeholderText : 'placeholderText', 5101 text : 'text', 5102 value : 'value' 5103 }, 5104 5105 selector : { 5106 dropdown : '.ui.dropdown', 5107 input : '> input[type="hidden"], > select', 5108 item : '.item', 5109 menu : '.menu', 5110 menuIcon : '.dropdown.icon', 5111 search : '> input.search, .menu > .search > input, .menu > input.search', 5112 text : '> .text:not(.icon)' 5113 }, 5114 5115 className : { 5116 active : 'active', 5117 animating : 'animating', 5118 disabled : 'disabled', 5119 dropdown : 'ui dropdown', 5120 filtered : 'filtered', 5121 loading : 'loading', 5122 menu : 'menu', 5123 placeholder : 'default', 5124 search : 'search', 5125 selected : 'selected', 5126 selection : 'selection', 5127 upward : 'upward', 5128 visible : 'visible' 5129 } 5130 5131 }; 5132 5133 /* Templates */ 5134 $.fn.dropdown.settings.templates = { 5135 menu: function(select) { 5136 var 5137 placeholder = select.placeholder || false, 5138 values = select.values || {}, 5139 html = '' 5140 ; 5141 $.each(select.values, function(index, option) { 5142 html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'; 5143 }); 5144 return html; 5145 }, 5146 dropdown: function(select) { 5147 var 5148 placeholder = select.placeholder || false, 5149 values = select.values || {}, 5150 html = '' 5151 ; 5152 html += '<i class="dropdown icon"></i>'; 5153 if(select.placeholder) { 5154 html += '<div class="default text">' + placeholder + '</div>'; 5155 } 5156 else { 5157 html += '<div class="text"></div>'; 5158 } 5159 html += '<div class="menu">'; 5160 $.each(select.values, function(index, option) { 5161 html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'; 5162 }); 5163 html += '</div>'; 5164 return html; 5165 } 5166 }; 5167 5168 5169 /* Dependencies */ 5170 $.extend( $.easing, { 5171 easeOutQuad: function (x, t, b, c, d) { 5172 return -c *(t/=d)*(t-2) + b; 5173 }, 5174 }); 5175 5176 5177 })( jQuery, window , document ); 5178 5179 /*! 5180 * # Semantic UI x.x - Modal 5181 * http://github.com/semantic-org/semantic-ui/ 5182 * 5183 * 5184 * Copyright 2014 Contributors 5185 * Released under the MIT license 5186 * http://opensource.org/licenses/MIT 5187 * 5188 */ 5189 5190 ;(function ( $, window, document, undefined ) { 5191 5192 "use strict"; 5193 5194 $.fn.modal = function(parameters) { 5195 var 5196 $allModules = $(this), 5197 $window = $(window), 5198 $document = $(document), 5199 $body = $('body'), 5200 5201 moduleSelector = $allModules.selector || '', 5202 5203 time = new Date().getTime(), 5204 performance = [], 5205 5206 query = arguments[0], 5207 methodInvoked = (typeof query == 'string'), 5208 queryArguments = [].slice.call(arguments, 1), 5209 5210 requestAnimationFrame = window.requestAnimationFrame 5211 || window.mozRequestAnimationFrame 5212 || window.webkitRequestAnimationFrame 5213 || window.msRequestAnimationFrame 5214 || function(callback) { setTimeout(callback, 0); }, 5215 5216 returnedValue 5217 ; 5218 5219 $allModules 5220 .each(function() { 5221 var 5222 settings = ( $.isPlainObject(parameters) ) 5223 ? $.extend(true, {}, $.fn.modal.settings, parameters) 5224 : $.extend({}, $.fn.modal.settings), 5225 5226 selector = settings.selector, 5227 className = settings.className, 5228 namespace = settings.namespace, 5229 error = settings.error, 5230 5231 eventNamespace = '.' + namespace, 5232 moduleNamespace = 'module-' + namespace, 5233 5234 $module = $(this), 5235 $context = $(settings.context), 5236 $close = $module.find(selector.close), 5237 5238 $allModals, 5239 $otherModals, 5240 $focusedElement, 5241 $dimmable, 5242 $dimmer, 5243 5244 element = this, 5245 instance = $module.data(moduleNamespace), 5246 5247 elementNamespace, 5248 id, 5249 observer, 5250 module 5251 ; 5252 module = { 5253 5254 initialize: function() { 5255 module.verbose('Initializing dimmer', $context); 5256 5257 module.create.id(); 5258 module.create.dimmer(); 5259 module.refreshModals(); 5260 5261 module.verbose('Attaching close events', $close); 5262 module.bind.events(); 5263 module.observeChanges(); 5264 module.instantiate(); 5265 }, 5266 5267 instantiate: function() { 5268 module.verbose('Storing instance of modal'); 5269 instance = module; 5270 $module 5271 .data(moduleNamespace, instance) 5272 ; 5273 }, 5274 5275 create: { 5276 dimmer: function() { 5277 var 5278 defaultSettings = { 5279 debug : settings.debug, 5280 dimmerName : 'modals', 5281 duration : { 5282 show : settings.duration, 5283 hide : settings.duration 5284 } 5285 }, 5286 dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings) 5287 ; 5288 if($.fn.dimmer === undefined) { 5289 module.error(error.dimmer); 5290 return; 5291 } 5292 module.debug('Creating dimmer with settings', dimmerSettings); 5293 $dimmable = $context.dimmer(dimmerSettings); 5294 if(settings.detachable) { 5295 module.verbose('Modal is detachable, moving content into dimmer'); 5296 $dimmable.dimmer('add content', $module); 5297 } 5298 $dimmer = $dimmable.dimmer('get dimmer'); 5299 }, 5300 id: function() { 5301 id = (Math.random().toString(16) + '000000000').substr(2,8); 5302 elementNamespace = '.' + id; 5303 module.verbose('Creating unique id for element', id); 5304 } 5305 }, 5306 5307 destroy: function() { 5308 module.verbose('Destroying previous modal'); 5309 $module 5310 .removeData(moduleNamespace) 5311 .off(eventNamespace) 5312 ; 5313 $window.off(elementNamespace); 5314 $close.off(eventNamespace); 5315 $context.dimmer('destroy'); 5316 }, 5317 5318 observeChanges: function() { 5319 if('MutationObserver' in window) { 5320 observer = new MutationObserver(function(mutations) { 5321 module.debug('DOM tree modified, refreshing'); 5322 module.refresh(); 5323 }); 5324 observer.observe(element, { 5325 childList : true, 5326 subtree : true 5327 }); 5328 module.debug('Setting up mutation observer', observer); 5329 } 5330 }, 5331 5332 refresh: function() { 5333 module.remove.scrolling(); 5334 module.cacheSizes(); 5335 module.set.screenHeight(); 5336 module.set.type(); 5337 module.set.position(); 5338 }, 5339 5340 refreshModals: function() { 5341 $otherModals = $module.siblings(selector.modal); 5342 $allModals = $otherModals.add($module); 5343 }, 5344 5345 attachEvents: function(selector, event) { 5346 var 5347 $toggle = $(selector) 5348 ; 5349 event = $.isFunction(module[event]) 5350 ? module[event] 5351 : module.toggle 5352 ; 5353 if($toggle.length > 0) { 5354 module.debug('Attaching modal events to element', selector, event); 5355 $toggle 5356 .off(eventNamespace) 5357 .on('click' + eventNamespace, event) 5358 ; 5359 } 5360 else { 5361 module.error(error.notFound, selector); 5362 } 5363 }, 5364 5365 bind: { 5366 events: function() { 5367 $close.on('click' + eventNamespace, module.event.close); 5368 $window.on('resize' + elementNamespace, module.event.resize); 5369 } 5370 }, 5371 5372 get: { 5373 id: function() { 5374 return (Math.random().toString(16) + '000000000').substr(2,8); 5375 } 5376 }, 5377 5378 event: { 5379 close: function() { 5380 module.verbose('Closing element pressed'); 5381 if( $(this).is(selector.approve) ) { 5382 if(settings.onApprove.call(element) !== false) { 5383 module.hide(); 5384 } 5385 else { 5386 module.verbose('Approve callback returned false cancelling hide'); 5387 } 5388 } 5389 else if( $(this).is(selector.deny) ) { 5390 if(settings.onDeny.call(element) !== false) { 5391 module.hide(); 5392 } 5393 else { 5394 module.verbose('Deny callback returned false cancelling hide'); 5395 } 5396 } 5397 else { 5398 module.hide(); 5399 } 5400 }, 5401 click: function(event) { 5402 if( $(event.target).closest($module).length === 0 ) { 5403 module.debug('Dimmer clicked, hiding all modals'); 5404 if( module.is.active() ) { 5405 module.remove.clickaway(); 5406 if(settings.allowMultiple) { 5407 module.hide(); 5408 } 5409 else { 5410 module.hideAll(); 5411 } 5412 } 5413 } 5414 }, 5415 debounce: function(method, delay) { 5416 clearTimeout(module.timer); 5417 module.timer = setTimeout(method, delay); 5418 }, 5419 keyboard: function(event) { 5420 var 5421 keyCode = event.which, 5422 escapeKey = 27 5423 ; 5424 if(keyCode == escapeKey) { 5425 if(settings.closable) { 5426 module.debug('Escape key pressed hiding modal'); 5427 module.hide(); 5428 } 5429 else { 5430 module.debug('Escape key pressed, but closable is set to false'); 5431 } 5432 event.preventDefault(); 5433 } 5434 }, 5435 resize: function() { 5436 if( $dimmable.dimmer('is active') ) { 5437 requestAnimationFrame(module.refresh); 5438 } 5439 } 5440 }, 5441 5442 toggle: function() { 5443 if( module.is.active() || module.is.animating() ) { 5444 module.hide(); 5445 } 5446 else { 5447 module.show(); 5448 } 5449 }, 5450 5451 show: function(callback) { 5452 callback = $.isFunction(callback) 5453 ? callback 5454 : function(){} 5455 ; 5456 module.refreshModals(); 5457 module.showModal(callback); 5458 }, 5459 5460 hide: function(callback) { 5461 callback = $.isFunction(callback) 5462 ? callback 5463 : function(){} 5464 ; 5465 module.refreshModals(); 5466 module.hideModal(callback); 5467 }, 5468 5469 showModal: function(callback) { 5470 callback = $.isFunction(callback) 5471 ? callback 5472 : function(){} 5473 ; 5474 if( module.is.animating() || !module.is.active() ) { 5475 5476 module.showDimmer(); 5477 module.cacheSizes(); 5478 module.set.position(); 5479 module.set.screenHeight(); 5480 module.set.type(); 5481 module.set.clickaway(); 5482 5483 if( !settings.allowMultiple && $otherModals.filter('.' + className.active).length > 0) { 5484 module.debug('Other modals visible, queueing show animation'); 5485 module.hideOthers(module.showModal); 5486 } 5487 else { 5488 settings.onShow.call(element); 5489 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 5490 module.debug('Showing modal with css animations'); 5491 $module 5492 .transition({ 5493 debug : settings.debug, 5494 animation : settings.transition + ' in', 5495 queue : settings.queue, 5496 duration : settings.duration, 5497 useFailSafe : true, 5498 onComplete : function() { 5499 settings.onVisible.apply(element); 5500 module.add.keyboardShortcuts(); 5501 module.save.focus(); 5502 module.set.active(); 5503 module.set.autofocus(); 5504 callback(); 5505 } 5506 }) 5507 ; 5508 } 5509 else { 5510 module.debug('Showing modal with javascript'); 5511 $module 5512 .fadeIn(settings.duration, settings.easing, function() { 5513 settings.onVisible.apply(element); 5514 module.add.keyboardShortcuts(); 5515 module.save.focus(); 5516 module.set.active(); 5517 callback(); 5518 }) 5519 ; 5520 } 5521 } 5522 } 5523 else { 5524 module.debug('Modal is already visible'); 5525 } 5526 }, 5527 5528 hideModal: function(callback, keepDimmed) { 5529 callback = $.isFunction(callback) 5530 ? callback 5531 : function(){} 5532 ; 5533 module.debug('Hiding modal'); 5534 settings.onHide.call(element); 5535 5536 if( module.is.animating() || module.is.active() ) { 5537 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 5538 module.remove.active(); 5539 $module 5540 .transition({ 5541 debug : settings.debug, 5542 animation : settings.transition + ' out', 5543 queue : settings.queue, 5544 duration : settings.duration, 5545 useFailSafe : true, 5546 onStart : function() { 5547 if(!module.othersActive() && !keepDimmed) { 5548 module.hideDimmer(); 5549 } 5550 module.remove.keyboardShortcuts(); 5551 }, 5552 onComplete : function() { 5553 settings.onHidden.call(element); 5554 module.restore.focus(); 5555 callback(); 5556 } 5557 }) 5558 ; 5559 } 5560 else { 5561 module.remove.active(); 5562 if( !module.othersActive() ) { 5563 module.hideDimmer(); 5564 } 5565 module.remove.keyboardShortcuts(); 5566 $module 5567 .fadeOut(settings.duration, settings.easing, function() { 5568 settings.onHidden.call(element); 5569 module.restore.focus(); 5570 callback(); 5571 }) 5572 ; 5573 } 5574 } 5575 }, 5576 5577 showDimmer: function() { 5578 if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) { 5579 module.debug('Showing dimmer'); 5580 $dimmable.dimmer('show'); 5581 } 5582 else { 5583 module.debug('Dimmer already visible'); 5584 } 5585 }, 5586 5587 hideDimmer: function() { 5588 if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) { 5589 $dimmable.dimmer('hide', function() { 5590 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 5591 module.remove.clickaway(); 5592 module.remove.screenHeight(); 5593 } 5594 }); 5595 } 5596 else { 5597 module.debug('Dimmer is not visible cannot hide'); 5598 return; 5599 } 5600 }, 5601 5602 hideAll: function(callback) { 5603 var 5604 $visibleModals = $allModals.filter(':visible') 5605 ; 5606 callback = $.isFunction(callback) 5607 ? callback 5608 : function(){} 5609 ; 5610 if( $visibleModals.length > 0 ) { 5611 module.debug('Hiding all visible modals'); 5612 module.hideDimmer(); 5613 $visibleModals 5614 .modal('hide modal', callback) 5615 ; 5616 } 5617 }, 5618 5619 hideOthers: function(callback) { 5620 var 5621 $visibleModals = $otherModals.filter(':visible') 5622 ; 5623 callback = $.isFunction(callback) 5624 ? callback 5625 : function(){} 5626 ; 5627 if( $visibleModals.length > 0 ) { 5628 module.debug('Hiding other modals', $otherModals); 5629 $visibleModals 5630 .modal('hide modal', callback, true) 5631 ; 5632 } 5633 }, 5634 5635 othersActive: function() { 5636 return ($otherModals.filter('.' + className.active).length > 0); 5637 }, 5638 5639 add: { 5640 keyboardShortcuts: function() { 5641 module.verbose('Adding keyboard shortcuts'); 5642 $document 5643 .on('keyup' + eventNamespace, module.event.keyboard) 5644 ; 5645 } 5646 }, 5647 5648 save: { 5649 focus: function() { 5650 $focusedElement = $(document.activeElement).blur(); 5651 } 5652 }, 5653 5654 restore: { 5655 focus: function() { 5656 if($focusedElement && $focusedElement.length > 0) { 5657 $focusedElement.focus(); 5658 } 5659 } 5660 }, 5661 5662 remove: { 5663 active: function() { 5664 $module.removeClass(className.active); 5665 }, 5666 clickaway: function() { 5667 if(settings.closable) { 5668 $dimmer 5669 .off('click' + elementNamespace) 5670 ; 5671 } 5672 }, 5673 screenHeight: function() { 5674 if(module.cache.height > module.cache.pageHeight) { 5675 module.debug('Removing page height'); 5676 $body 5677 .css('height', '') 5678 ; 5679 } 5680 }, 5681 keyboardShortcuts: function() { 5682 module.verbose('Removing keyboard shortcuts'); 5683 $document 5684 .off('keyup' + eventNamespace) 5685 ; 5686 }, 5687 scrolling: function() { 5688 $dimmable.removeClass(className.scrolling); 5689 $module.removeClass(className.scrolling); 5690 } 5691 }, 5692 5693 cacheSizes: function() { 5694 var 5695 modalHeight = $module.outerHeight() 5696 ; 5697 if(module.cache === undefined || modalHeight !== 0) { 5698 module.cache = { 5699 pageHeight : $(document).outerHeight(), 5700 height : modalHeight + settings.offset, 5701 contextHeight : (settings.context == 'body') 5702 ? $(window).height() 5703 : $dimmable.height() 5704 }; 5705 } 5706 module.debug('Caching modal and container sizes', module.cache); 5707 }, 5708 5709 can: { 5710 fit: function() { 5711 return ( ( module.cache.height + (settings.padding * 2) ) < module.cache.contextHeight); 5712 } 5713 }, 5714 5715 is: { 5716 active: function() { 5717 return $module.hasClass(className.active); 5718 }, 5719 animating: function() { 5720 return $module.transition('is supported') 5721 ? $module.transition('is animating') 5722 : $module.is(':visible') 5723 ; 5724 }, 5725 scrolling: function() { 5726 return $dimmable.hasClass(className.scrolling); 5727 }, 5728 modernBrowser: function() { 5729 // appName for IE11 reports 'Netscape' can no longer use 5730 return !(window.ActiveXObject || "ActiveXObject" in window); 5731 } 5732 }, 5733 5734 set: { 5735 autofocus: function() { 5736 if(settings.autofocus) { 5737 var 5738 $inputs = $module.find(':input:visible'), 5739 $autofocus = $inputs.filter('[autofocus]'), 5740 $input = ($autofocus.length > 0) 5741 ? $autofocus 5742 : $inputs 5743 ; 5744 $input.first().focus(); 5745 } 5746 }, 5747 clickaway: function() { 5748 if(settings.closable) { 5749 $dimmer 5750 .on('click' + elementNamespace, module.event.click) 5751 ; 5752 } 5753 }, 5754 screenHeight: function() { 5755 if( module.can.fit() ) { 5756 $body.css('height', ''); 5757 } 5758 else { 5759 module.debug('Modal is taller than page content, resizing page height'); 5760 $body 5761 .css('height', module.cache.height + (settings.padding / 2) ) 5762 ; 5763 } 5764 }, 5765 active: function() { 5766 $module.addClass(className.active); 5767 }, 5768 scrolling: function() { 5769 $dimmable.addClass(className.scrolling); 5770 $module.addClass(className.scrolling); 5771 }, 5772 type: function() { 5773 if(module.can.fit()) { 5774 module.verbose('Modal fits on screen'); 5775 if(!module.othersActive) { 5776 module.remove.scrolling(); 5777 } 5778 } 5779 else { 5780 module.verbose('Modal cannot fit on screen setting to scrolling'); 5781 module.set.scrolling(); 5782 } 5783 }, 5784 position: function() { 5785 module.verbose('Centering modal on page', module.cache); 5786 if(module.can.fit()) { 5787 $module 5788 .css({ 5789 top: '', 5790 marginTop: -(module.cache.height / 2) 5791 }) 5792 ; 5793 } 5794 else { 5795 $module 5796 .css({ 5797 marginTop : '', 5798 top : $document.scrollTop() 5799 }) 5800 ; 5801 } 5802 } 5803 }, 5804 5805 setting: function(name, value) { 5806 module.debug('Changing setting', name, value); 5807 if( $.isPlainObject(name) ) { 5808 $.extend(true, settings, name); 5809 } 5810 else if(value !== undefined) { 5811 settings[name] = value; 5812 } 5813 else { 5814 return settings[name]; 5815 } 5816 }, 5817 internal: function(name, value) { 5818 if( $.isPlainObject(name) ) { 5819 $.extend(true, module, name); 5820 } 5821 else if(value !== undefined) { 5822 module[name] = value; 5823 } 5824 else { 5825 return module[name]; 5826 } 5827 }, 5828 debug: function() { 5829 if(settings.debug) { 5830 if(settings.performance) { 5831 module.performance.log(arguments); 5832 } 5833 else { 5834 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 5835 module.debug.apply(console, arguments); 5836 } 5837 } 5838 }, 5839 verbose: function() { 5840 if(settings.verbose && settings.debug) { 5841 if(settings.performance) { 5842 module.performance.log(arguments); 5843 } 5844 else { 5845 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 5846 module.verbose.apply(console, arguments); 5847 } 5848 } 5849 }, 5850 error: function() { 5851 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 5852 module.error.apply(console, arguments); 5853 }, 5854 performance: { 5855 log: function(message) { 5856 var 5857 currentTime, 5858 executionTime, 5859 previousTime 5860 ; 5861 if(settings.performance) { 5862 currentTime = new Date().getTime(); 5863 previousTime = time || currentTime; 5864 executionTime = currentTime - previousTime; 5865 time = currentTime; 5866 performance.push({ 5867 'Name' : message[0], 5868 'Arguments' : [].slice.call(message, 1) || '', 5869 'Element' : element, 5870 'Execution Time' : executionTime 5871 }); 5872 } 5873 clearTimeout(module.performance.timer); 5874 module.performance.timer = setTimeout(module.performance.display, 100); 5875 }, 5876 display: function() { 5877 var 5878 title = settings.name + ':', 5879 totalTime = 0 5880 ; 5881 time = false; 5882 clearTimeout(module.performance.timer); 5883 $.each(performance, function(index, data) { 5884 totalTime += data['Execution Time']; 5885 }); 5886 title += ' ' + totalTime + 'ms'; 5887 if(moduleSelector) { 5888 title += ' \'' + moduleSelector + '\''; 5889 } 5890 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 5891 console.groupCollapsed(title); 5892 if(console.table) { 5893 console.table(performance); 5894 } 5895 else { 5896 $.each(performance, function(index, data) { 5897 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 5898 }); 5899 } 5900 console.groupEnd(); 5901 } 5902 performance = []; 5903 } 5904 }, 5905 invoke: function(query, passedArguments, context) { 5906 var 5907 object = instance, 5908 maxDepth, 5909 found, 5910 response 5911 ; 5912 passedArguments = passedArguments || queryArguments; 5913 context = element || context; 5914 if(typeof query == 'string' && object !== undefined) { 5915 query = query.split(/[\. ]/); 5916 maxDepth = query.length - 1; 5917 $.each(query, function(depth, value) { 5918 var camelCaseValue = (depth != maxDepth) 5919 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 5920 : query 5921 ; 5922 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 5923 object = object[camelCaseValue]; 5924 } 5925 else if( object[camelCaseValue] !== undefined ) { 5926 found = object[camelCaseValue]; 5927 return false; 5928 } 5929 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 5930 object = object[value]; 5931 } 5932 else if( object[value] !== undefined ) { 5933 found = object[value]; 5934 return false; 5935 } 5936 else { 5937 return false; 5938 } 5939 }); 5940 } 5941 if ( $.isFunction( found ) ) { 5942 response = found.apply(context, passedArguments); 5943 } 5944 else if(found !== undefined) { 5945 response = found; 5946 } 5947 if($.isArray(returnedValue)) { 5948 returnedValue.push(response); 5949 } 5950 else if(returnedValue !== undefined) { 5951 returnedValue = [returnedValue, response]; 5952 } 5953 else if(response !== undefined) { 5954 returnedValue = response; 5955 } 5956 return found; 5957 } 5958 }; 5959 5960 if(methodInvoked) { 5961 if(instance === undefined) { 5962 module.initialize(); 5963 } 5964 module.invoke(query); 5965 } 5966 else { 5967 if(instance !== undefined) { 5968 instance.invoke('destroy'); 5969 } 5970 module.initialize(); 5971 } 5972 }) 5973 ; 5974 5975 return (returnedValue !== undefined) 5976 ? returnedValue 5977 : this 5978 ; 5979 }; 5980 5981 $.fn.modal.settings = { 5982 5983 name : 'Modal', 5984 namespace : 'modal', 5985 5986 debug : false, 5987 verbose : true, 5988 performance : true, 5989 5990 allowMultiple : false, 5991 detachable : true, 5992 closable : true, 5993 autofocus : true, 5994 5995 dimmerSettings : { 5996 closable : false, 5997 useCSS : true 5998 }, 5999 6000 context : 'body', 6001 6002 queue : false, 6003 duration : 500, 6004 easing : 'easeOutExpo', 6005 offset : 0, 6006 transition : 'scale', 6007 6008 padding : 50, 6009 6010 onShow : function(){}, 6011 onHide : function(){}, 6012 6013 onVisible : function(){}, 6014 onHidden : function(){}, 6015 6016 onApprove : function(){ return true; }, 6017 onDeny : function(){ return true; }, 6018 6019 selector : { 6020 close : '.close, .actions .button', 6021 approve : '.actions .positive, .actions .approve, .actions .ok', 6022 deny : '.actions .negative, .actions .deny, .actions .cancel', 6023 modal : '.ui.modal' 6024 }, 6025 error : { 6026 dimmer : 'UI Dimmer, a required component is not included in this page', 6027 method : 'The method you called is not defined.', 6028 notFound : 'The element you specified could not be found' 6029 }, 6030 className : { 6031 active : 'active', 6032 animating : 'animating', 6033 scrolling : 'scrolling' 6034 } 6035 }; 6036 6037 6038 })( jQuery, window , document ); 6039 6040 /*! 6041 * # Semantic UI x.x - Nag 6042 * http://github.com/semantic-org/semantic-ui/ 6043 * 6044 * 6045 * Copyright 2014 Contributors 6046 * Released under the MIT license 6047 * http://opensource.org/licenses/MIT 6048 * 6049 */ 6050 6051 ;(function ($, window, document, undefined) { 6052 6053 "use strict"; 6054 6055 $.fn.nag = function(parameters) { 6056 var 6057 $allModules = $(this), 6058 moduleSelector = $allModules.selector || '', 6059 6060 time = new Date().getTime(), 6061 performance = [], 6062 6063 query = arguments[0], 6064 methodInvoked = (typeof query == 'string'), 6065 queryArguments = [].slice.call(arguments, 1), 6066 returnedValue 6067 ; 6068 $allModules 6069 .each(function() { 6070 var 6071 settings = ( $.isPlainObject(parameters) ) 6072 ? $.extend(true, {}, $.fn.nag.settings, parameters) 6073 : $.extend({}, $.fn.nag.settings), 6074 6075 className = settings.className, 6076 selector = settings.selector, 6077 error = settings.error, 6078 namespace = settings.namespace, 6079 6080 eventNamespace = '.' + namespace, 6081 moduleNamespace = namespace + '-module', 6082 6083 $module = $(this), 6084 6085 $close = $module.find(selector.close), 6086 $context = (settings.context) 6087 ? $(settings.context) 6088 : $('body'), 6089 6090 element = this, 6091 instance = $module.data(moduleNamespace), 6092 6093 moduleOffset, 6094 moduleHeight, 6095 6096 contextWidth, 6097 contextHeight, 6098 contextOffset, 6099 6100 yOffset, 6101 yPosition, 6102 6103 timer, 6104 module, 6105 6106 requestAnimationFrame = window.requestAnimationFrame 6107 || window.mozRequestAnimationFrame 6108 || window.webkitRequestAnimationFrame 6109 || window.msRequestAnimationFrame 6110 || function(callback) { setTimeout(callback, 0); } 6111 ; 6112 module = { 6113 6114 initialize: function() { 6115 module.verbose('Initializing element'); 6116 6117 $module 6118 .data(moduleNamespace, module) 6119 ; 6120 $close 6121 .on('click' + eventNamespace, module.dismiss) 6122 ; 6123 6124 if(settings.detachable && $module.parent()[0] !== $context[0]) { 6125 $module 6126 .detach() 6127 .prependTo($context) 6128 ; 6129 } 6130 6131 if(settings.displayTime > 0) { 6132 setTimeout(module.hide, settings.displayTime); 6133 } 6134 module.show(); 6135 }, 6136 6137 destroy: function() { 6138 module.verbose('Destroying instance'); 6139 $module 6140 .removeData(moduleNamespace) 6141 .off(eventNamespace) 6142 ; 6143 }, 6144 6145 show: function() { 6146 if( module.should.show() && !$module.is(':visible') ) { 6147 module.debug('Showing nag', settings.animation.show); 6148 if(settings.animation.show == 'fade') { 6149 $module 6150 .fadeIn(settings.duration, settings.easing) 6151 ; 6152 } 6153 else { 6154 $module 6155 .slideDown(settings.duration, settings.easing) 6156 ; 6157 } 6158 } 6159 }, 6160 6161 hide: function() { 6162 module.debug('Showing nag', settings.animation.hide); 6163 if(settings.animation.show == 'fade') { 6164 $module 6165 .fadeIn(settings.duration, settings.easing) 6166 ; 6167 } 6168 else { 6169 $module 6170 .slideUp(settings.duration, settings.easing) 6171 ; 6172 } 6173 }, 6174 6175 onHide: function() { 6176 module.debug('Removing nag', settings.animation.hide); 6177 $module.remove(); 6178 if (settings.onHide) { 6179 settings.onHide(); 6180 } 6181 }, 6182 6183 dismiss: function(event) { 6184 if(settings.storageMethod) { 6185 module.storage.set(settings.key, settings.value); 6186 } 6187 module.hide(); 6188 event.stopImmediatePropagation(); 6189 event.preventDefault(); 6190 }, 6191 6192 should: { 6193 show: function() { 6194 if(settings.persist) { 6195 module.debug('Persistent nag is set, can show nag'); 6196 return true; 6197 } 6198 if( module.storage.get(settings.key) != settings.value.toString() ) { 6199 module.debug('Stored value is not set, can show nag', module.storage.get(settings.key)); 6200 return true; 6201 } 6202 module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key)); 6203 return false; 6204 } 6205 }, 6206 6207 get: { 6208 storageOptions: function() { 6209 var 6210 options = {} 6211 ; 6212 if(settings.expires) { 6213 options.expires = settings.expires; 6214 } 6215 if(settings.domain) { 6216 options.domain = settings.domain; 6217 } 6218 if(settings.path) { 6219 options.path = settings.path; 6220 } 6221 return options; 6222 } 6223 }, 6224 6225 clear: function() { 6226 module.storage.remove(settings.key); 6227 }, 6228 6229 storage: { 6230 set: function(key, value) { 6231 var 6232 options = module.get.storageOptions() 6233 ; 6234 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) { 6235 window.localStorage.setItem(key, value); 6236 module.debug('Value stored using local storage', key, value); 6237 } 6238 else if($.cookie !== undefined) { 6239 $.cookie(key, value, options); 6240 module.debug('Value stored using cookie', key, value, options); 6241 } 6242 else { 6243 module.error(error.noCookieStorage); 6244 return; 6245 } 6246 }, 6247 get: function(key, value) { 6248 var 6249 storedValue 6250 ; 6251 if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) { 6252 storedValue = window.localStorage.getItem(key); 6253 } 6254 // get by cookie 6255 else if($.cookie !== undefined) { 6256 storedValue = $.cookie(key); 6257 } 6258 else { 6259 module.error(error.noCookieStorage); 6260 } 6261 if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) { 6262 storedValue = undefined; 6263 } 6264 return storedValue; 6265 }, 6266 remove: function(key) { 6267 var 6268 options = module.get.storageOptions() 6269 ; 6270 if(settings.storageMethod == 'local' && window.store !== undefined) { 6271 window.localStorage.removeItem(key); 6272 } 6273 // store by cookie 6274 else if($.cookie !== undefined) { 6275 $.removeCookie(key, options); 6276 } 6277 else { 6278 module.error(error.noStorage); 6279 } 6280 } 6281 }, 6282 6283 setting: function(name, value) { 6284 module.debug('Changing setting', name, value); 6285 if( $.isPlainObject(name) ) { 6286 $.extend(true, settings, name); 6287 } 6288 else if(value !== undefined) { 6289 settings[name] = value; 6290 } 6291 else { 6292 return settings[name]; 6293 } 6294 }, 6295 internal: function(name, value) { 6296 if( $.isPlainObject(name) ) { 6297 $.extend(true, module, name); 6298 } 6299 else if(value !== undefined) { 6300 module[name] = value; 6301 } 6302 else { 6303 return module[name]; 6304 } 6305 }, 6306 debug: function() { 6307 if(settings.debug) { 6308 if(settings.performance) { 6309 module.performance.log(arguments); 6310 } 6311 else { 6312 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 6313 module.debug.apply(console, arguments); 6314 } 6315 } 6316 }, 6317 verbose: function() { 6318 if(settings.verbose && settings.debug) { 6319 if(settings.performance) { 6320 module.performance.log(arguments); 6321 } 6322 else { 6323 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 6324 module.verbose.apply(console, arguments); 6325 } 6326 } 6327 }, 6328 error: function() { 6329 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 6330 module.error.apply(console, arguments); 6331 }, 6332 performance: { 6333 log: function(message) { 6334 var 6335 currentTime, 6336 executionTime, 6337 previousTime 6338 ; 6339 if(settings.performance) { 6340 currentTime = new Date().getTime(); 6341 previousTime = time || currentTime; 6342 executionTime = currentTime - previousTime; 6343 time = currentTime; 6344 performance.push({ 6345 'Name' : message[0], 6346 'Arguments' : [].slice.call(message, 1) || '', 6347 'Element' : element, 6348 'Execution Time' : executionTime 6349 }); 6350 } 6351 clearTimeout(module.performance.timer); 6352 module.performance.timer = setTimeout(module.performance.display, 100); 6353 }, 6354 display: function() { 6355 var 6356 title = settings.name + ':', 6357 totalTime = 0 6358 ; 6359 time = false; 6360 clearTimeout(module.performance.timer); 6361 $.each(performance, function(index, data) { 6362 totalTime += data['Execution Time']; 6363 }); 6364 title += ' ' + totalTime + 'ms'; 6365 if(moduleSelector) { 6366 title += ' \'' + moduleSelector + '\''; 6367 } 6368 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 6369 console.groupCollapsed(title); 6370 if(console.table) { 6371 console.table(performance); 6372 } 6373 else { 6374 $.each(performance, function(index, data) { 6375 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 6376 }); 6377 } 6378 console.groupEnd(); 6379 } 6380 performance = []; 6381 } 6382 }, 6383 invoke: function(query, passedArguments, context) { 6384 var 6385 object = instance, 6386 maxDepth, 6387 found, 6388 response 6389 ; 6390 passedArguments = passedArguments || queryArguments; 6391 context = element || context; 6392 if(typeof query == 'string' && object !== undefined) { 6393 query = query.split(/[\. ]/); 6394 maxDepth = query.length - 1; 6395 $.each(query, function(depth, value) { 6396 var camelCaseValue = (depth != maxDepth) 6397 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 6398 : query 6399 ; 6400 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 6401 object = object[camelCaseValue]; 6402 } 6403 else if( object[camelCaseValue] !== undefined ) { 6404 found = object[camelCaseValue]; 6405 return false; 6406 } 6407 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 6408 object = object[value]; 6409 } 6410 else if( object[value] !== undefined ) { 6411 found = object[value]; 6412 return false; 6413 } 6414 else { 6415 module.error(error.method, query); 6416 return false; 6417 } 6418 }); 6419 } 6420 if ( $.isFunction( found ) ) { 6421 response = found.apply(context, passedArguments); 6422 } 6423 else if(found !== undefined) { 6424 response = found; 6425 } 6426 if($.isArray(returnedValue)) { 6427 returnedValue.push(response); 6428 } 6429 else if(returnedValue !== undefined) { 6430 returnedValue = [returnedValue, response]; 6431 } 6432 else if(response !== undefined) { 6433 returnedValue = response; 6434 } 6435 return found; 6436 } 6437 }; 6438 6439 if(methodInvoked) { 6440 if(instance === undefined) { 6441 module.initialize(); 6442 } 6443 module.invoke(query); 6444 } 6445 else { 6446 if(instance !== undefined) { 6447 instance.invoke('destroy'); 6448 } 6449 module.initialize(); 6450 } 6451 }) 6452 ; 6453 6454 return (returnedValue !== undefined) 6455 ? returnedValue 6456 : this 6457 ; 6458 }; 6459 6460 $.fn.nag.settings = { 6461 6462 name : 'Nag', 6463 6464 debug : false, 6465 verbose : true, 6466 performance : true, 6467 6468 namespace : 'Nag', 6469 6470 // allows cookie to be overriden 6471 persist : false, 6472 6473 // set to zero to require manually dismissal, otherwise hides on its own 6474 displayTime : 0, 6475 6476 animation : { 6477 show : 'slide', 6478 hide : 'slide' 6479 }, 6480 6481 context : false, 6482 detachable : false, 6483 6484 expires : 30, 6485 domain : false, 6486 path : '/', 6487 6488 // type of storage to use 6489 storageMethod : 'cookie', 6490 6491 // value to store in dismissed localstorage/cookie 6492 key : 'nag', 6493 value : 'dismiss', 6494 6495 error: { 6496 noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state', 6497 method : 'The method you called is not defined.' 6498 }, 6499 6500 className : { 6501 bottom : 'bottom', 6502 fixed : 'fixed' 6503 }, 6504 6505 selector : { 6506 close : '.close.icon' 6507 }, 6508 6509 speed : 500, 6510 easing : 'easeOutQuad', 6511 6512 onHide: function() {} 6513 6514 }; 6515 6516 })( jQuery, window , document ); 6517 6518 /*! 6519 * # Semantic UI x.x - Popup 6520 * http://github.com/semantic-org/semantic-ui/ 6521 * 6522 * 6523 * Copyright 2014 Contributors 6524 * Released under the MIT license 6525 * http://opensource.org/licenses/MIT 6526 * 6527 */ 6528 6529 ;(function ($, window, document, undefined) { 6530 6531 "use strict"; 6532 6533 $.fn.popup = function(parameters) { 6534 var 6535 $allModules = $(this), 6536 $document = $(document), 6537 6538 moduleSelector = $allModules.selector || '', 6539 6540 hasTouch = ('ontouchstart' in document.documentElement), 6541 time = new Date().getTime(), 6542 performance = [], 6543 6544 query = arguments[0], 6545 methodInvoked = (typeof query == 'string'), 6546 queryArguments = [].slice.call(arguments, 1), 6547 6548 returnedValue 6549 ; 6550 $allModules 6551 .each(function() { 6552 var 6553 settings = ( $.isPlainObject(parameters) ) 6554 ? $.extend(true, {}, $.fn.popup.settings, parameters) 6555 : $.extend({}, $.fn.popup.settings), 6556 6557 selector = settings.selector, 6558 className = settings.className, 6559 error = settings.error, 6560 metadata = settings.metadata, 6561 namespace = settings.namespace, 6562 6563 eventNamespace = '.' + settings.namespace, 6564 moduleNamespace = 'module-' + namespace, 6565 6566 $module = $(this), 6567 $context = $(settings.context), 6568 $target = (settings.target) 6569 ? $(settings.target) 6570 : $module, 6571 6572 $window = $(window), 6573 $body = $('body'), 6574 $popup, 6575 $offsetParent, 6576 6577 searchDepth = 0, 6578 triedPositions = false, 6579 6580 element = this, 6581 instance = $module.data(moduleNamespace), 6582 6583 elementNamespace, 6584 id, 6585 module 6586 ; 6587 6588 module = { 6589 6590 // binds events 6591 initialize: function() { 6592 module.debug('Initializing', $module); 6593 module.createID(); 6594 module.bind.events(); 6595 if( !module.exists() && settings.preserve) { 6596 module.create(); 6597 } 6598 module.instantiate(); 6599 }, 6600 6601 instantiate: function() { 6602 module.verbose('Storing instance', module); 6603 instance = module; 6604 $module 6605 .data(moduleNamespace, instance) 6606 ; 6607 }, 6608 6609 refresh: function() { 6610 if(settings.popup) { 6611 $popup = $(settings.popup).eq(0); 6612 } 6613 else { 6614 if(settings.inline) { 6615 $popup = $target.next(selector.popup).eq(0); 6616 } 6617 } 6618 if(settings.popup) { 6619 $popup.addClass(className.loading); 6620 $offsetParent = module.get.offsetParent(); 6621 $popup.removeClass(className.loading); 6622 if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) { 6623 module.debug('Moving popup to the same offset parent as activating element'); 6624 $popup 6625 .detach() 6626 .appendTo($offsetParent) 6627 ; 6628 } 6629 } 6630 else { 6631 $offsetParent = (settings.inline) 6632 ? module.get.offsetParent($target) 6633 : module.has.popup() 6634 ? module.get.offsetParent($popup) 6635 : $body 6636 ; 6637 } 6638 if( $offsetParent.is('html') ) { 6639 module.debug('Setting page as offset parent'); 6640 $offsetParent = $body; 6641 } 6642 }, 6643 6644 reposition: function() { 6645 module.refresh(); 6646 module.set.position(); 6647 }, 6648 6649 destroy: function() { 6650 module.debug('Destroying previous module'); 6651 // remove element only if was created dynamically 6652 if($popup && !settings.preserve) { 6653 module.removePopup(); 6654 } 6655 // clear all timeouts 6656 clearTimeout(module.hideTimer); 6657 clearTimeout(module.showTimer); 6658 // remove events 6659 $window.off(elementNamespace); 6660 $module 6661 .off(eventNamespace) 6662 .removeData(moduleNamespace) 6663 ; 6664 }, 6665 6666 event: { 6667 start: function(event) { 6668 var 6669 delay = ($.isPlainObject(settings.delay)) 6670 ? settings.delay.show 6671 : settings.delay 6672 ; 6673 clearTimeout(module.hideTimer); 6674 module.showTimer = setTimeout(function() { 6675 if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) { 6676 module.show(); 6677 } 6678 }, delay); 6679 }, 6680 end: function() { 6681 var 6682 delay = ($.isPlainObject(settings.delay)) 6683 ? settings.delay.hide 6684 : settings.delay 6685 ; 6686 clearTimeout(module.showTimer); 6687 module.hideTimer = setTimeout(function() { 6688 if(module.is.visible() ) { 6689 module.hide(); 6690 } 6691 }, delay); 6692 }, 6693 resize: function() { 6694 if( module.is.visible() ) { 6695 module.set.position(); 6696 } 6697 } 6698 }, 6699 6700 // generates popup html from metadata 6701 create: function() { 6702 var 6703 html = $module.data(metadata.html) || settings.html, 6704 variation = $module.data(metadata.variation) || settings.variation, 6705 title = $module.data(metadata.title) || settings.title, 6706 content = $module.data(metadata.content) || $module.attr('title') || settings.content 6707 ; 6708 if(html || content || title) { 6709 module.debug('Creating pop-up html'); 6710 if(!html) { 6711 html = settings.templates.popup({ 6712 title : title, 6713 content : content 6714 }); 6715 } 6716 $popup = $('<div/>') 6717 .addClass(className.popup) 6718 .addClass(variation) 6719 .data(metadata.activator, $module) 6720 .html(html) 6721 ; 6722 if(variation) { 6723 $popup 6724 .addClass(variation) 6725 ; 6726 } 6727 if(settings.inline) { 6728 module.verbose('Inserting popup element inline', $popup); 6729 $popup 6730 .insertAfter($module) 6731 ; 6732 } 6733 else { 6734 module.verbose('Appending popup element to body', $popup); 6735 $popup 6736 .appendTo( $context ) 6737 ; 6738 } 6739 module.refresh(); 6740 if(settings.hoverable) { 6741 module.bind.popup(); 6742 } 6743 settings.onCreate.call($popup, element); 6744 } 6745 else if($target.next(selector.popup).length !== 0) { 6746 module.verbose('Pre-existing popup found'); 6747 settings.inline = true; 6748 settings.popup = $target.next(selector.popup).data(metadata.activator, $module); 6749 module.refresh(); 6750 if(settings.hoverable) { 6751 module.bind.popup(); 6752 } 6753 } 6754 else if(settings.popup) { 6755 settings.popup.data(metadata.activator, $module); 6756 module.verbose('Used popup specified in settings'); 6757 module.refresh(); 6758 if(settings.hoverable) { 6759 module.bind.popup(); 6760 } 6761 } 6762 else { 6763 module.debug('No content specified skipping display', element); 6764 } 6765 }, 6766 6767 createID: function() { 6768 id = (Math.random().toString(16) + '000000000').substr(2,8); 6769 elementNamespace = '.' + id; 6770 module.verbose('Creating unique id for element', id); 6771 }, 6772 6773 // determines popup state 6774 toggle: function() { 6775 module.debug('Toggling pop-up'); 6776 if( module.is.hidden() ) { 6777 module.debug('Popup is hidden, showing pop-up'); 6778 module.unbind.close(); 6779 module.show(); 6780 } 6781 else { 6782 module.debug('Popup is visible, hiding pop-up'); 6783 module.hide(); 6784 } 6785 }, 6786 6787 show: function(callback) { 6788 callback = $.isFunction(callback) ? callback : function(){}; 6789 module.debug('Showing pop-up', settings.transition); 6790 if( !module.exists() ) { 6791 module.create(); 6792 } 6793 else if(!settings.preserve && !settings.popup) { 6794 module.refresh(); 6795 } 6796 if( $popup && module.set.position() ) { 6797 module.save.conditions(); 6798 if(settings.exclusive) { 6799 module.hideAll(); 6800 } 6801 module.animate.show(callback); 6802 } 6803 }, 6804 6805 6806 hide: function(callback) { 6807 callback = $.isFunction(callback) ? callback : function(){}; 6808 module.remove.visible(); 6809 module.unbind.close(); 6810 if( module.is.visible() ) { 6811 module.restore.conditions(); 6812 module.animate.hide(callback); 6813 } 6814 }, 6815 6816 hideAll: function() { 6817 $(selector.popup) 6818 .filter('.' + className.visible) 6819 .each(function() { 6820 $(this) 6821 .data(metadata.activator) 6822 .popup('hide') 6823 ; 6824 }) 6825 ; 6826 }, 6827 6828 hideGracefully: function(event) { 6829 // don't close on clicks inside popup 6830 if(event && $(event.target).closest(selector.popup).length === 0) { 6831 module.debug('Click occurred outside popup hiding popup'); 6832 module.hide(); 6833 } 6834 else { 6835 module.debug('Click was inside popup, keeping popup open'); 6836 } 6837 }, 6838 6839 exists: function() { 6840 if(!$popup) { 6841 return false; 6842 } 6843 if(settings.inline || settings.popup) { 6844 return ( module.has.popup() ); 6845 } 6846 else { 6847 return ( $popup.closest($context).length >= 1 ) 6848 ? true 6849 : false 6850 ; 6851 } 6852 }, 6853 6854 removePopup: function() { 6855 module.debug('Removing popup', $popup); 6856 if( module.has.popup() && !settings.popup) { 6857 $popup.remove(); 6858 $popup = undefined; 6859 } 6860 settings.onRemove.call($popup, element); 6861 }, 6862 6863 save: { 6864 conditions: function() { 6865 module.cache = { 6866 title: $module.attr('title') 6867 }; 6868 if (module.cache.title) { 6869 $module.removeAttr('title'); 6870 } 6871 module.verbose('Saving original attributes', module.cache.title); 6872 } 6873 }, 6874 restore: { 6875 conditions: function() { 6876 if(module.cache && module.cache.title) { 6877 $module.attr('title', module.cache.title); 6878 module.verbose('Restoring original attributes', module.cache.title); 6879 } 6880 return true; 6881 } 6882 }, 6883 animate: { 6884 show: function(callback) { 6885 callback = $.isFunction(callback) ? callback : function(){}; 6886 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 6887 module.set.visible(); 6888 $popup 6889 .transition({ 6890 animation : settings.transition + ' in', 6891 queue : false, 6892 debug : settings.debug, 6893 verbose : settings.verbose, 6894 duration : settings.duration, 6895 onComplete : function() { 6896 module.bind.close(); 6897 callback.call($popup, element); 6898 settings.onVisible.call($popup, element); 6899 } 6900 }) 6901 ; 6902 } 6903 else { 6904 module.set.visible(); 6905 $popup 6906 .stop() 6907 .fadeIn(settings.duration, settings.easing, function() { 6908 module.bind.close(); 6909 callback.call($popup, element); 6910 settings.onVisible.call($popup, element); 6911 }) 6912 ; 6913 } 6914 settings.onShow.call($popup, element); 6915 }, 6916 hide: function(callback) { 6917 callback = $.isFunction(callback) ? callback : function(){}; 6918 module.debug('Hiding pop-up'); 6919 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 6920 $popup 6921 .transition({ 6922 animation : settings.transition + ' out', 6923 queue : false, 6924 duration : settings.duration, 6925 debug : settings.debug, 6926 verbose : settings.verbose, 6927 onComplete : function() { 6928 module.reset(); 6929 callback.call($popup, element); 6930 settings.onHidden.call($popup, element); 6931 } 6932 }) 6933 ; 6934 } 6935 else { 6936 $popup 6937 .stop() 6938 .fadeOut(settings.duration, settings.easing, function() { 6939 module.reset(); 6940 callback.call($popup, element); 6941 settings.onHidden.call($popup, element); 6942 }) 6943 ; 6944 } 6945 settings.onHide.call($popup, element); 6946 } 6947 }, 6948 6949 get: { 6950 id: function() { 6951 return id; 6952 }, 6953 startEvent: function() { 6954 if(settings.on == 'hover') { 6955 return (hasTouch) 6956 ? 'touchstart mouseenter' 6957 : 'mouseenter' 6958 ; 6959 } 6960 else if(settings.on == 'focus') { 6961 return 'focus'; 6962 } 6963 return false; 6964 }, 6965 scrollEvent: function() { 6966 return (hasTouch) 6967 ? 'touchmove scroll' 6968 : 'scroll' 6969 ; 6970 }, 6971 endEvent: function() { 6972 if(settings.on == 'hover') { 6973 return 'mouseleave'; 6974 } 6975 else if(settings.on == 'focus') { 6976 return 'blur'; 6977 } 6978 return false; 6979 }, 6980 offsetParent: function($target) { 6981 var 6982 element = ($target !== undefined) 6983 ? $target[0] 6984 : $module[0], 6985 parentNode = element.parentNode, 6986 $node = $(parentNode) 6987 ; 6988 if(parentNode) { 6989 var 6990 is2D = ($node.css('transform') === 'none'), 6991 isStatic = ($node.css('position') === 'static'), 6992 isHTML = $node.is('html') 6993 ; 6994 while(parentNode && !isHTML && isStatic && is2D) { 6995 parentNode = parentNode.parentNode; 6996 $node = $(parentNode); 6997 is2D = ($node.css('transform') === 'none'); 6998 isStatic = ($node.css('position') === 'static'); 6999 isHTML = $node.is('html'); 7000 } 7001 } 7002 return ($node && $node.length > 0) 7003 ? $node 7004 : $() 7005 ; 7006 }, 7007 offstagePosition: function(position) { 7008 var 7009 boundary = { 7010 top : $(window).scrollTop(), 7011 bottom : $(window).scrollTop() + $(window).height(), 7012 left : 0, 7013 right : $(window).width() 7014 }, 7015 popup = { 7016 width : $popup.width(), 7017 height : $popup.height(), 7018 offset : $popup.offset() 7019 }, 7020 offstage = {}, 7021 offstagePositions = [] 7022 ; 7023 position = position || false; 7024 if(popup.offset && position) { 7025 module.verbose('Checking if outside viewable area', popup.offset); 7026 offstage = { 7027 top : (popup.offset.top < boundary.top), 7028 bottom : (popup.offset.top + popup.height > boundary.bottom), 7029 right : (popup.offset.left + popup.width > boundary.right), 7030 left : (popup.offset.left < boundary.left) 7031 }; 7032 } 7033 // return only boundaries that have been surpassed 7034 $.each(offstage, function(direction, isOffstage) { 7035 if(isOffstage) { 7036 offstagePositions.push(direction); 7037 } 7038 }); 7039 return (offstagePositions.length > 0) 7040 ? offstagePositions.join(' ') 7041 : false 7042 ; 7043 }, 7044 positions: function() { 7045 return { 7046 'top left' : false, 7047 'top center' : false, 7048 'top right' : false, 7049 'bottom left' : false, 7050 'bottom center' : false, 7051 'bottom right' : false, 7052 'left center' : false, 7053 'right center' : false 7054 }; 7055 }, 7056 nextPosition: function(position) { 7057 var 7058 positions = position.split(' '), 7059 verticalPosition = positions[0], 7060 horizontalPosition = positions[1], 7061 opposite = { 7062 top : 'bottom', 7063 bottom : 'top', 7064 left : 'right', 7065 right : 'left' 7066 }, 7067 adjacent = { 7068 left : 'center', 7069 center : 'right', 7070 right : 'left' 7071 }, 7072 backup = { 7073 'top left' : 'top center', 7074 'top center' : 'top right', 7075 'top right' : 'right center', 7076 'right center' : 'bottom right', 7077 'bottom right' : 'bottom center', 7078 'bottom center' : 'bottom left', 7079 'bottom left' : 'left center', 7080 'left center' : 'top left' 7081 }, 7082 adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'), 7083 oppositeTried = false, 7084 adjacentTried = false, 7085 nextPosition = false 7086 ; 7087 if(!triedPositions) { 7088 module.verbose('All available positions available'); 7089 triedPositions = module.get.positions(); 7090 } 7091 7092 module.debug('Recording last position tried', position); 7093 triedPositions[position] = true; 7094 7095 if(settings.prefer === 'opposite') { 7096 nextPosition = [opposite[verticalPosition], horizontalPosition]; 7097 nextPosition = nextPosition.join(' '); 7098 oppositeTried = (triedPositions[nextPosition] === true); 7099 module.debug('Trying opposite strategy', nextPosition); 7100 } 7101 if((settings.prefer === 'adjacent') && adjacentsAvailable ) { 7102 nextPosition = [verticalPosition, adjacent[horizontalPosition]]; 7103 nextPosition = nextPosition.join(' '); 7104 adjacentTried = (triedPositions[nextPosition] === true); 7105 module.debug('Trying adjacent strategy', nextPosition); 7106 } 7107 if(adjacentTried || oppositeTried) { 7108 module.debug('Using backup position', nextPosition); 7109 nextPosition = backup[position]; 7110 } 7111 return nextPosition; 7112 } 7113 }, 7114 7115 set: { 7116 position: function(position, arrowOffset) { 7117 var 7118 windowWidth = $(window).width(), 7119 windowHeight = $(window).height(), 7120 7121 targetWidth = $target.outerWidth(), 7122 targetHeight = $target.outerHeight(), 7123 7124 popupWidth = $popup.outerWidth(), 7125 popupHeight = $popup.outerHeight(), 7126 7127 parentWidth = $offsetParent.outerWidth(), 7128 parentHeight = $offsetParent.outerHeight(), 7129 7130 distanceAway = settings.distanceAway, 7131 7132 targetElement = $target[0], 7133 7134 marginTop = (settings.inline) 7135 ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10) 7136 : 0, 7137 marginLeft = (settings.inline) 7138 ? parseInt( window.getComputedStyle(targetElement).getPropertyValue(module.is.rtl() ? 'margin-right' : 'margin-left'), 10) 7139 : 0, 7140 7141 target = (settings.inline || settings.popup) 7142 ? $target.position() 7143 : $target.offset(), 7144 7145 computedPosition, 7146 positioning, 7147 offstagePosition 7148 ; 7149 position = position || $module.data(metadata.position) || settings.position; 7150 arrowOffset = arrowOffset || $module.data(metadata.offset) || settings.offset; 7151 7152 if(searchDepth == settings.maxSearchDepth && settings.lastResort) { 7153 module.debug('Using last resort position to display', settings.lastResort); 7154 position = settings.lastResort; 7155 } 7156 7157 if(settings.inline) { 7158 module.debug('Adding targets margin to calculation'); 7159 if(position == 'left center' || position == 'right center') { 7160 arrowOffset += marginTop; 7161 distanceAway += -marginLeft; 7162 } 7163 else if (position == 'top left' || position == 'top center' || position == 'top right') { 7164 arrowOffset += marginLeft; 7165 distanceAway -= marginTop; 7166 } 7167 else { 7168 arrowOffset += marginLeft; 7169 distanceAway += marginTop; 7170 } 7171 } 7172 module.debug('Calculating popup positioning', position); 7173 7174 computedPosition = position; 7175 if (module.is.rtl()) { 7176 computedPosition = computedPosition.replace(/left|right/g, function (match) { 7177 return (match == 'left') 7178 ? 'right' 7179 : 'left' 7180 ; 7181 }); 7182 module.debug('RTL: Popup positioning updated', computedPosition); 7183 } 7184 switch (computedPosition) { 7185 case 'top left': 7186 positioning = { 7187 top : 'auto', 7188 bottom : parentHeight - target.top + distanceAway, 7189 left : target.left + arrowOffset, 7190 right : 'auto' 7191 }; 7192 break; 7193 case 'top center': 7194 positioning = { 7195 bottom : parentHeight - target.top + distanceAway, 7196 left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset, 7197 top : 'auto', 7198 right : 'auto' 7199 }; 7200 break; 7201 case 'top right': 7202 positioning = { 7203 bottom : parentHeight - target.top + distanceAway, 7204 right : parentWidth - target.left - targetWidth - arrowOffset, 7205 top : 'auto', 7206 left : 'auto' 7207 }; 7208 break; 7209 case 'left center': 7210 positioning = { 7211 top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset, 7212 right : parentWidth - target.left + distanceAway, 7213 left : 'auto', 7214 bottom : 'auto' 7215 }; 7216 break; 7217 case 'right center': 7218 positioning = { 7219 top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset, 7220 left : target.left + targetWidth + distanceAway, 7221 bottom : 'auto', 7222 right : 'auto' 7223 }; 7224 break; 7225 case 'bottom left': 7226 positioning = { 7227 top : target.top + targetHeight + distanceAway, 7228 left : target.left + arrowOffset, 7229 bottom : 'auto', 7230 right : 'auto' 7231 }; 7232 break; 7233 case 'bottom center': 7234 positioning = { 7235 top : target.top + targetHeight + distanceAway, 7236 left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset, 7237 bottom : 'auto', 7238 right : 'auto' 7239 }; 7240 break; 7241 case 'bottom right': 7242 positioning = { 7243 top : target.top + targetHeight + distanceAway, 7244 right : parentWidth - target.left - targetWidth - arrowOffset, 7245 left : 'auto', 7246 bottom : 'auto' 7247 }; 7248 break; 7249 } 7250 if(positioning === undefined) { 7251 module.error(error.invalidPosition, position); 7252 } 7253 7254 module.debug('Calculated popup positioning values', positioning); 7255 7256 // tentatively place on stage 7257 $popup 7258 .css(positioning) 7259 .removeClass(className.position) 7260 .addClass(position) 7261 .addClass(className.loading) 7262 ; 7263 // check if is offstage 7264 offstagePosition = module.get.offstagePosition(position); 7265 7266 // recursively find new positioning 7267 if(offstagePosition) { 7268 module.debug('Popup cant fit into viewport', offstagePosition); 7269 if(searchDepth < settings.maxSearchDepth) { 7270 searchDepth++; 7271 position = module.get.nextPosition(position); 7272 module.debug('Trying new position', position); 7273 return ($popup) 7274 ? module.set.position(position) 7275 : false 7276 ; 7277 } 7278 else if(!settings.lastResort) { 7279 module.debug('Popup could not find a position in view', $popup); 7280 module.error(error.cannotPlace, element); 7281 module.remove.attempts(); 7282 module.remove.loading(); 7283 module.reset(); 7284 return false; 7285 } 7286 } 7287 7288 module.debug('Position is on stage', position); 7289 module.remove.attempts(); 7290 module.set.fluidWidth(); 7291 module.remove.loading(); 7292 return true; 7293 }, 7294 7295 fluidWidth: function() { 7296 if( settings.setFluidWidth && $popup.hasClass(className.fluid) ) { 7297 $popup.css('width', $offsetParent.width()); 7298 } 7299 }, 7300 7301 visible: function() { 7302 $module.addClass(className.visible); 7303 } 7304 }, 7305 7306 remove: { 7307 loading: function() { 7308 $popup.removeClass(className.loading); 7309 }, 7310 visible: function() { 7311 $module.removeClass(className.visible); 7312 }, 7313 attempts: function() { 7314 module.verbose('Resetting all searched positions'); 7315 searchDepth = 0; 7316 triedPositions = false; 7317 } 7318 }, 7319 7320 bind: { 7321 events: function() { 7322 module.debug('Binding popup events to module'); 7323 if(settings.on == 'click') { 7324 $module 7325 .on('click' + eventNamespace, module.toggle) 7326 ; 7327 } 7328 else if( module.get.startEvent() ) { 7329 $module 7330 .on(module.get.startEvent() + eventNamespace, module.event.start) 7331 .on(module.get.endEvent() + eventNamespace, module.event.end) 7332 ; 7333 } 7334 if(settings.target) { 7335 module.debug('Target set to element', $target); 7336 } 7337 $window.on('resize' + elementNamespace, module.event.resize); 7338 }, 7339 popup: function() { 7340 module.verbose('Allowing hover events on popup to prevent closing'); 7341 if( $popup && module.has.popup() ) { 7342 $popup 7343 .on('mouseenter' + eventNamespace, module.event.start) 7344 .on('mouseleave' + eventNamespace, module.event.end) 7345 ; 7346 } 7347 }, 7348 close:function() { 7349 if(settings.hideOnScroll === true || settings.hideOnScroll == 'auto' && settings.on != 'click') { 7350 $document 7351 .one(module.get.scrollEvent() + elementNamespace, module.hideGracefully) 7352 ; 7353 $context 7354 .one(module.get.scrollEvent() + elementNamespace, module.hideGracefully) 7355 ; 7356 } 7357 if(settings.on == 'click' && settings.closable) { 7358 module.verbose('Binding popup close event to document'); 7359 $document 7360 .on('click' + elementNamespace, function(event) { 7361 module.verbose('Pop-up clickaway intent detected'); 7362 module.hideGracefully.call(element, event); 7363 }) 7364 ; 7365 } 7366 } 7367 }, 7368 7369 unbind: { 7370 close: function() { 7371 if(settings.hideOnScroll === true || settings.hideOnScroll == 'auto' && settings.on != 'click') { 7372 $document 7373 .off('scroll' + elementNamespace, module.hide) 7374 ; 7375 $context 7376 .off('scroll' + elementNamespace, module.hide) 7377 ; 7378 } 7379 if(settings.on == 'click' && settings.closable) { 7380 module.verbose('Removing close event from document'); 7381 $document 7382 .off('click' + elementNamespace) 7383 ; 7384 } 7385 } 7386 }, 7387 7388 has: { 7389 popup: function() { 7390 return ($popup && $popup.length > 0); 7391 } 7392 }, 7393 7394 is: { 7395 active: function() { 7396 return $module.hasClass(className.active); 7397 }, 7398 animating: function() { 7399 return ( $popup && $popup.is(':animated') || $popup.hasClass(className.animating) ); 7400 }, 7401 visible: function() { 7402 return $popup && $popup.is(':visible'); 7403 }, 7404 dropdown: function() { 7405 return $module.hasClass(className.dropdown); 7406 }, 7407 hidden: function() { 7408 return !module.is.visible(); 7409 }, 7410 rtl: function () { 7411 return $module.css('direction') == 'rtl'; 7412 } 7413 }, 7414 7415 reset: function() { 7416 module.remove.visible(); 7417 if(settings.preserve) { 7418 if($.fn.transition !== undefined) { 7419 $popup 7420 .transition('remove transition') 7421 ; 7422 } 7423 } 7424 else { 7425 module.removePopup(); 7426 } 7427 }, 7428 7429 setting: function(name, value) { 7430 if( $.isPlainObject(name) ) { 7431 $.extend(true, settings, name); 7432 } 7433 else if(value !== undefined) { 7434 settings[name] = value; 7435 } 7436 else { 7437 return settings[name]; 7438 } 7439 }, 7440 internal: function(name, value) { 7441 if( $.isPlainObject(name) ) { 7442 $.extend(true, module, name); 7443 } 7444 else if(value !== undefined) { 7445 module[name] = value; 7446 } 7447 else { 7448 return module[name]; 7449 } 7450 }, 7451 debug: function() { 7452 if(settings.debug) { 7453 if(settings.performance) { 7454 module.performance.log(arguments); 7455 } 7456 else { 7457 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 7458 module.debug.apply(console, arguments); 7459 } 7460 } 7461 }, 7462 verbose: function() { 7463 if(settings.verbose && settings.debug) { 7464 if(settings.performance) { 7465 module.performance.log(arguments); 7466 } 7467 else { 7468 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 7469 module.verbose.apply(console, arguments); 7470 } 7471 } 7472 }, 7473 error: function() { 7474 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 7475 module.error.apply(console, arguments); 7476 }, 7477 performance: { 7478 log: function(message) { 7479 var 7480 currentTime, 7481 executionTime, 7482 previousTime 7483 ; 7484 if(settings.performance) { 7485 currentTime = new Date().getTime(); 7486 previousTime = time || currentTime; 7487 executionTime = currentTime - previousTime; 7488 time = currentTime; 7489 performance.push({ 7490 'Name' : message[0], 7491 'Arguments' : [].slice.call(message, 1) || '', 7492 'Element' : element, 7493 'Execution Time' : executionTime 7494 }); 7495 } 7496 clearTimeout(module.performance.timer); 7497 module.performance.timer = setTimeout(module.performance.display, 100); 7498 }, 7499 display: function() { 7500 var 7501 title = settings.name + ':', 7502 totalTime = 0 7503 ; 7504 time = false; 7505 clearTimeout(module.performance.timer); 7506 $.each(performance, function(index, data) { 7507 totalTime += data['Execution Time']; 7508 }); 7509 title += ' ' + totalTime + 'ms'; 7510 if(moduleSelector) { 7511 title += ' \'' + moduleSelector + '\''; 7512 } 7513 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 7514 console.groupCollapsed(title); 7515 if(console.table) { 7516 console.table(performance); 7517 } 7518 else { 7519 $.each(performance, function(index, data) { 7520 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 7521 }); 7522 } 7523 console.groupEnd(); 7524 } 7525 performance = []; 7526 } 7527 }, 7528 invoke: function(query, passedArguments, context) { 7529 var 7530 object = instance, 7531 maxDepth, 7532 found, 7533 response 7534 ; 7535 passedArguments = passedArguments || queryArguments; 7536 context = element || context; 7537 if(typeof query == 'string' && object !== undefined) { 7538 query = query.split(/[\. ]/); 7539 maxDepth = query.length - 1; 7540 $.each(query, function(depth, value) { 7541 var camelCaseValue = (depth != maxDepth) 7542 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 7543 : query 7544 ; 7545 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 7546 object = object[camelCaseValue]; 7547 } 7548 else if( object[camelCaseValue] !== undefined ) { 7549 found = object[camelCaseValue]; 7550 return false; 7551 } 7552 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 7553 object = object[value]; 7554 } 7555 else if( object[value] !== undefined ) { 7556 found = object[value]; 7557 return false; 7558 } 7559 else { 7560 return false; 7561 } 7562 }); 7563 } 7564 if ( $.isFunction( found ) ) { 7565 response = found.apply(context, passedArguments); 7566 } 7567 else if(found !== undefined) { 7568 response = found; 7569 } 7570 if($.isArray(returnedValue)) { 7571 returnedValue.push(response); 7572 } 7573 else if(returnedValue !== undefined) { 7574 returnedValue = [returnedValue, response]; 7575 } 7576 else if(response !== undefined) { 7577 returnedValue = response; 7578 } 7579 return found; 7580 } 7581 }; 7582 7583 if(methodInvoked) { 7584 if(instance === undefined) { 7585 module.initialize(); 7586 } 7587 module.invoke(query); 7588 } 7589 else { 7590 if(instance !== undefined) { 7591 instance.invoke('destroy'); 7592 } 7593 module.initialize(); 7594 } 7595 }) 7596 ; 7597 7598 return (returnedValue !== undefined) 7599 ? returnedValue 7600 : this 7601 ; 7602 }; 7603 7604 $.fn.popup.settings = { 7605 7606 name : 'Popup', 7607 7608 debug : false, 7609 verbose : true, 7610 performance : true, 7611 namespace : 'popup', 7612 7613 onCreate : function(){}, 7614 onRemove : function(){}, 7615 7616 onShow : function(){}, 7617 onVisible : function(){}, 7618 onHide : function(){}, 7619 onHidden : function(){}, 7620 7621 variation : '', 7622 content : false, 7623 html : false, 7624 title : false, 7625 7626 on : 'hover', 7627 closable : true, 7628 hideOnScroll : 'auto', 7629 exclusive : true, 7630 7631 context : 'body', 7632 7633 position : 'top left', 7634 prefer : 'opposite', 7635 lastResort : false, 7636 7637 delay : { 7638 show : 30, 7639 hide : 0 7640 }, 7641 7642 setFluidWidth : true, 7643 movePopup : true, 7644 7645 target : false, 7646 popup : false, 7647 inline : false, 7648 preserve : false, 7649 hoverable : false, 7650 7651 duration : 200, 7652 easing : 'easeOutQuint', 7653 transition : 'scale', 7654 7655 distanceAway : 0, 7656 offset : 0, 7657 maxSearchDepth : 20, 7658 7659 error: { 7660 invalidPosition : 'The position you specified is not a valid position', 7661 cannotPlace : 'No visible position could be found for the popup', 7662 method : 'The method you called is not defined.' 7663 }, 7664 7665 metadata: { 7666 activator : 'activator', 7667 content : 'content', 7668 html : 'html', 7669 offset : 'offset', 7670 position : 'position', 7671 title : 'title', 7672 variation : 'variation' 7673 }, 7674 7675 className : { 7676 active : 'active', 7677 animating : 'animating', 7678 dropdown : 'dropdown', 7679 fluid : 'fluid', 7680 loading : 'loading', 7681 popup : 'ui popup', 7682 position : 'top left center bottom right', 7683 visible : 'visible' 7684 }, 7685 7686 selector : { 7687 popup : '.ui.popup' 7688 }, 7689 7690 templates: { 7691 escape: function(string) { 7692 var 7693 badChars = /[&<>"'`]/g, 7694 shouldEscape = /[&<>"'`]/, 7695 escape = { 7696 "&": "&", 7697 "<": "<", 7698 ">": ">", 7699 '"': """, 7700 "'": "'", 7701 "`": "`" 7702 }, 7703 escapedChar = function(chr) { 7704 return escape[chr]; 7705 } 7706 ; 7707 if(shouldEscape.test(string)) { 7708 return string.replace(badChars, escapedChar); 7709 } 7710 return string; 7711 }, 7712 popup: function(text) { 7713 var 7714 html = '', 7715 escape = $.fn.popup.settings.templates.escape 7716 ; 7717 if(typeof text !== undefined) { 7718 if(typeof text.title !== undefined && text.title) { 7719 text.title = escape(text.title); 7720 html += '<div class="header">' + text.title + '</div>'; 7721 } 7722 if(typeof text.content !== undefined && text.content) { 7723 text.content = escape(text.content); 7724 html += '<div class="content">' + text.content + '</div>'; 7725 } 7726 } 7727 return html; 7728 } 7729 } 7730 7731 }; 7732 7733 // Adds easing 7734 $.extend( $.easing, { 7735 easeOutQuad: function (x, t, b, c, d) { 7736 return -c *(t/=d)*(t-2) + b; 7737 } 7738 }); 7739 7740 7741 })( jQuery, window , document ); 7742 7743 /*! 7744 * # Semantic UI x.x - Progress 7745 * http://github.com/semantic-org/semantic-ui/ 7746 * 7747 * 7748 * Copyright 2014 Contributors 7749 * Released under the MIT license 7750 * http://opensource.org/licenses/MIT 7751 * 7752 */ 7753 7754 ;(function ( $, window, document, undefined ) { 7755 7756 "use strict"; 7757 7758 $.fn.progress = function(parameters) { 7759 var 7760 $allModules = $(this), 7761 7762 moduleSelector = $allModules.selector || '', 7763 7764 time = new Date().getTime(), 7765 performance = [], 7766 7767 query = arguments[0], 7768 methodInvoked = (typeof query == 'string'), 7769 queryArguments = [].slice.call(arguments, 1), 7770 7771 returnedValue 7772 ; 7773 7774 $allModules 7775 .each(function() { 7776 var 7777 settings = ( $.isPlainObject(parameters) ) 7778 ? $.extend(true, {}, $.fn.progress.settings, parameters) 7779 : $.extend({}, $.fn.progress.settings), 7780 7781 className = settings.className, 7782 metadata = settings.metadata, 7783 namespace = settings.namespace, 7784 selector = settings.selector, 7785 error = settings.error, 7786 7787 eventNamespace = '.' + namespace, 7788 moduleNamespace = 'module-' + namespace, 7789 7790 $module = $(this), 7791 $bar = $(this).find(selector.bar), 7792 $progress = $(this).find(selector.progress), 7793 $label = $(this).find(selector.label), 7794 7795 element = this, 7796 instance = $module.data(moduleNamespace), 7797 7798 animating = false, 7799 transitionEnd, 7800 module 7801 ; 7802 7803 module = { 7804 7805 initialize: function() { 7806 module.debug('Initializing progress bar', settings); 7807 7808 transitionEnd = module.get.transitionEnd(); 7809 7810 module.read.metadata(); 7811 module.set.duration(); 7812 module.set.initials(); 7813 module.instantiate(); 7814 }, 7815 7816 instantiate: function() { 7817 module.verbose('Storing instance of progress', module); 7818 instance = module; 7819 $module 7820 .data(moduleNamespace, module) 7821 ; 7822 }, 7823 destroy: function() { 7824 module.verbose('Destroying previous progress for', $module); 7825 clearInterval(instance.interval); 7826 module.remove.state(); 7827 $module.removeData(moduleNamespace); 7828 instance = undefined; 7829 }, 7830 7831 reset: function() { 7832 module.set.percent(0); 7833 }, 7834 7835 complete: function() { 7836 if(module.percent === undefined || module.percent < 100) { 7837 module.set.percent(100); 7838 } 7839 }, 7840 7841 read: { 7842 metadata: function() { 7843 if( $module.data(metadata.percent) ) { 7844 module.verbose('Current percent value set from metadata'); 7845 module.percent = $module.data(metadata.percent); 7846 } 7847 if( $module.data(metadata.total) ) { 7848 module.verbose('Total value set from metadata'); 7849 module.total = $module.data(metadata.total); 7850 } 7851 if( $module.data(metadata.value) ) { 7852 module.verbose('Current value set from metadata'); 7853 module.value = $module.data(metadata.value); 7854 } 7855 }, 7856 currentValue: function() { 7857 return (module.value !== undefined) 7858 ? module.value 7859 : false 7860 ; 7861 } 7862 }, 7863 7864 increment: function(incrementValue) { 7865 var 7866 total = module.total || false, 7867 edgeValue, 7868 startValue, 7869 newValue 7870 ; 7871 if(total) { 7872 startValue = module.value || 0; 7873 incrementValue = incrementValue || 1; 7874 newValue = startValue + incrementValue; 7875 edgeValue = module.total; 7876 module.debug('Incrementing value by', incrementValue, startValue, edgeValue); 7877 if(newValue > edgeValue ) { 7878 module.debug('Value cannot increment above total', edgeValue); 7879 newValue = edgeValue; 7880 } 7881 module.set.progress(newValue); 7882 } 7883 else { 7884 startValue = module.percent || 0; 7885 incrementValue = incrementValue || module.get.randomValue(); 7886 newValue = startValue + incrementValue; 7887 edgeValue = 100; 7888 module.debug('Incrementing percentage by', incrementValue, startValue); 7889 if(newValue > edgeValue ) { 7890 module.debug('Value cannot increment above 100 percent'); 7891 newValue = edgeValue; 7892 } 7893 module.set.progress(newValue); 7894 } 7895 }, 7896 decrement: function(decrementValue) { 7897 var 7898 total = module.total || false, 7899 edgeValue = 0, 7900 startValue, 7901 newValue 7902 ; 7903 if(total) { 7904 startValue = module.value || 0; 7905 decrementValue = decrementValue || 1; 7906 newValue = startValue - decrementValue; 7907 module.debug('Decrementing value by', decrementValue, startValue); 7908 } 7909 else { 7910 startValue = module.percent || 0; 7911 decrementValue = decrementValue || module.get.randomValue(); 7912 newValue = startValue - decrementValue; 7913 module.debug('Decrementing percentage by', decrementValue, startValue); 7914 } 7915 7916 if(newValue < edgeValue) { 7917 module.debug('Value cannot decrement below 0'); 7918 newValue = 0; 7919 } 7920 module.set.progress(newValue); 7921 }, 7922 7923 get: { 7924 text: function(templateText) { 7925 var 7926 value = module.value || 0, 7927 total = module.total || 0, 7928 percent = (module.is.visible() && animating) 7929 ? module.get.displayPercent() 7930 : module.percent || 0, 7931 left = (module.total > 0) 7932 ? (total - value) 7933 : (100 - percent) 7934 ; 7935 templateText = templateText || ''; 7936 templateText = templateText 7937 .replace('{value}', value) 7938 .replace('{total}', total) 7939 .replace('{left}', left) 7940 .replace('{percent}', percent) 7941 ; 7942 module.debug('Adding variables to progress bar text', templateText); 7943 return templateText; 7944 }, 7945 randomValue: function() { 7946 module.debug('Generating random increment percentage'); 7947 return Math.floor((Math.random() * settings.random.max) + settings.random.min); 7948 }, 7949 7950 transitionEnd: function() { 7951 var 7952 element = document.createElement('element'), 7953 transitions = { 7954 'transition' :'transitionend', 7955 'OTransition' :'oTransitionEnd', 7956 'MozTransition' :'transitionend', 7957 'WebkitTransition' :'webkitTransitionEnd' 7958 }, 7959 transition 7960 ; 7961 for(transition in transitions){ 7962 if( element.style[transition] !== undefined ){ 7963 return transitions[transition]; 7964 } 7965 } 7966 }, 7967 7968 // gets current displayed percentage (if animating values this is the intermediary value) 7969 displayPercent: function() { 7970 var 7971 barWidth = $bar.width(), 7972 totalWidth = $module.width(), 7973 minDisplay = parseInt($bar.css('min-width'), 10), 7974 displayPercent = (barWidth > minDisplay) 7975 ? (barWidth / totalWidth * 100) 7976 : module.percent 7977 ; 7978 if(settings.precision === 0) { 7979 return Math.round(displayPercent); 7980 } 7981 return Math.round(displayPercent * (10 * settings.precision) / (10 * settings.precision) ); 7982 }, 7983 7984 percent: function() { 7985 return module.percent || 0; 7986 }, 7987 value: function() { 7988 return module.value || false; 7989 }, 7990 total: function() { 7991 return module.total || false; 7992 } 7993 }, 7994 7995 is: { 7996 success: function() { 7997 return $module.hasClass(className.success); 7998 }, 7999 warning: function() { 8000 return $module.hasClass(className.warning); 8001 }, 8002 error: function() { 8003 return $module.hasClass(className.error); 8004 }, 8005 active: function() { 8006 return $module.hasClass(className.active); 8007 }, 8008 visible: function() { 8009 return $module.is(':visible'); 8010 } 8011 }, 8012 8013 remove: { 8014 state: function() { 8015 module.verbose('Removing stored state'); 8016 delete module.total; 8017 delete module.percent; 8018 delete module.value; 8019 }, 8020 active: function() { 8021 module.verbose('Removing active state'); 8022 $module.removeClass(className.active); 8023 }, 8024 success: function() { 8025 module.verbose('Removing success state'); 8026 $module.removeClass(className.success); 8027 }, 8028 warning: function() { 8029 module.verbose('Removing warning state'); 8030 $module.removeClass(className.warning); 8031 }, 8032 error: function() { 8033 module.verbose('Removing error state'); 8034 $module.removeClass(className.error); 8035 } 8036 }, 8037 8038 set: { 8039 barWidth: function(value) { 8040 if(value > 100) { 8041 module.error(error.tooHigh, value); 8042 } 8043 else if (value < 0) { 8044 module.error(error.tooLow, value); 8045 } 8046 else { 8047 $bar 8048 .css('width', value + '%') 8049 ; 8050 $module 8051 .attr('data-percent', parseInt(value, 10)) 8052 ; 8053 } 8054 }, 8055 duration: function(duration) { 8056 duration = duration || settings.duration; 8057 duration = (typeof duration == 'number') 8058 ? duration + 'ms' 8059 : duration 8060 ; 8061 module.verbose('Setting progress bar transition duration', duration); 8062 $bar 8063 .css({ 8064 '-webkit-transition-duration': duration, 8065 '-moz-transition-duration': duration, 8066 '-ms-transition-duration': duration, 8067 '-o-transition-duration': duration, 8068 'transition-duration': duration 8069 }) 8070 ; 8071 }, 8072 initials: function() { 8073 if(settings.total !== false) { 8074 module.verbose('Current total set in settings', settings.total); 8075 module.total = settings.total; 8076 } 8077 if(settings.value !== false) { 8078 module.verbose('Current value set in settings', settings.value); 8079 module.value = settings.value; 8080 } 8081 if(settings.percent !== false) { 8082 module.verbose('Current percent set in settings', settings.percent); 8083 module.percent = settings.percent; 8084 } 8085 if(module.percent !== undefined) { 8086 module.set.percent(module.percent); 8087 } 8088 else if(module.value !== undefined) { 8089 module.set.progress(module.value); 8090 } 8091 }, 8092 percent: function(percent) { 8093 percent = (typeof percent == 'string') 8094 ? +(percent.replace('%', '')) 8095 : percent 8096 ; 8097 if(percent > 0 && percent < 1) { 8098 module.verbose('Module percentage passed as decimal, converting'); 8099 percent = percent * 100; 8100 } 8101 // round percentage 8102 if(settings.precision === 0) { 8103 percent = Math.round(percent); 8104 } 8105 else { 8106 percent = Math.round(percent * (10 * settings.precision) / (10 * settings.precision) ); 8107 } 8108 module.percent = percent; 8109 if(module.total) { 8110 module.value = Math.round( (percent / 100) * module.total); 8111 } 8112 else if(settings.limitValues) { 8113 module.value = (module.value > 100) 8114 ? 100 8115 : (module.value < 0) 8116 ? 0 8117 : module.value 8118 ; 8119 } 8120 module.set.barWidth(percent); 8121 if( module.is.visible() ) { 8122 module.set.labelInterval(); 8123 } 8124 module.set.labels(); 8125 settings.onChange.call(element, percent, module.value, module.total); 8126 }, 8127 labelInterval: function() { 8128 var 8129 animationCallback = function() { 8130 module.verbose('Bar finished animating, removing continuous label updates'); 8131 clearInterval(module.interval); 8132 animating = false; 8133 module.set.labels(); 8134 } 8135 ; 8136 clearInterval(module.interval); 8137 $bar.one(transitionEnd + eventNamespace, animationCallback); 8138 module.timer = setTimeout(animationCallback, settings.duration + 100); 8139 animating = true; 8140 module.interval = setInterval(module.set.labels, settings.framerate); 8141 }, 8142 labels: function() { 8143 module.verbose('Setting both bar progress and outer label text'); 8144 module.set.barLabel(); 8145 module.set.state(); 8146 }, 8147 label: function(text) { 8148 text = text || ''; 8149 if(text) { 8150 text = module.get.text(text); 8151 module.debug('Setting label to text', text); 8152 $label.text(text); 8153 } 8154 }, 8155 state: function(percent) { 8156 percent = (percent !== undefined) 8157 ? percent 8158 : module.percent 8159 ; 8160 if(percent === 100) { 8161 if(settings.autoSuccess && !(module.is.warning() || module.is.error())) { 8162 module.set.success(); 8163 module.debug('Automatically triggering success at 100%'); 8164 } 8165 else { 8166 module.verbose('Reached 100% removing active state'); 8167 module.remove.active(); 8168 } 8169 } 8170 else if(percent > 0) { 8171 module.verbose('Adjusting active progress bar label', percent); 8172 module.set.active(); 8173 } 8174 else { 8175 module.remove.active(); 8176 module.set.label(settings.text.active); 8177 } 8178 }, 8179 barLabel: function(text) { 8180 if(text !== undefined) { 8181 $progress.text( module.get.text(text) ); 8182 } 8183 else if(settings.label == 'ratio' && module.total) { 8184 module.debug('Adding ratio to bar label'); 8185 $progress.text( module.get.text(settings.text.ratio) ); 8186 } 8187 else if(settings.label == 'percent') { 8188 module.debug('Adding percentage to bar label'); 8189 $progress.text( module.get.text(settings.text.percent) ); 8190 } 8191 }, 8192 active: function(text) { 8193 text = text || settings.text.active; 8194 module.debug('Setting active state'); 8195 if(settings.showActivity && !module.is.active() ) { 8196 $module.addClass(className.active); 8197 } 8198 module.remove.warning(); 8199 module.remove.error(); 8200 module.remove.success(); 8201 if(text) { 8202 module.set.label(text); 8203 } 8204 settings.onActive.call(element, module.value, module.total); 8205 }, 8206 success : function(text) { 8207 text = text || settings.text.success; 8208 module.debug('Setting success state'); 8209 $module.addClass(className.success); 8210 module.remove.active(); 8211 module.remove.warning(); 8212 module.remove.error(); 8213 module.complete(); 8214 if(text) { 8215 module.set.label(text); 8216 } 8217 settings.onSuccess.call(element, module.total); 8218 }, 8219 warning : function(text) { 8220 text = text || settings.text.warning; 8221 module.debug('Setting warning state'); 8222 $module.addClass(className.warning); 8223 module.remove.active(); 8224 module.remove.success(); 8225 module.remove.error(); 8226 module.complete(); 8227 if(text) { 8228 module.set.label(text); 8229 } 8230 settings.onWarning.call(element, module.value, module.total); 8231 }, 8232 error : function(text) { 8233 text = text || settings.text.error; 8234 module.debug('Setting error state'); 8235 $module.addClass(className.error); 8236 module.remove.active(); 8237 module.remove.success(); 8238 module.remove.warning(); 8239 module.complete(); 8240 if(text) { 8241 module.set.label(text); 8242 } 8243 settings.onError.call(element, module.value, module.total); 8244 }, 8245 total: function(totalValue) { 8246 module.total = totalValue; 8247 }, 8248 progress: function(value) { 8249 var 8250 numericValue = (typeof value === 'string') 8251 ? (value.replace(/[^\d.]/g, '') !== '') 8252 ? +(value.replace(/[^\d.]/g, '')) 8253 : false 8254 : value, 8255 percentComplete 8256 ; 8257 if(numericValue === false) { 8258 module.error(error.nonNumeric, value); 8259 } 8260 if(module.total) { 8261 module.value = numericValue; 8262 percentComplete = (numericValue / module.total) * 100; 8263 module.debug('Calculating percent complete from total', percentComplete); 8264 module.set.percent( percentComplete ); 8265 } 8266 else { 8267 percentComplete = numericValue; 8268 module.debug('Setting value to exact percentage value', percentComplete); 8269 module.set.percent( percentComplete ); 8270 } 8271 } 8272 }, 8273 8274 setting: function(name, value) { 8275 module.debug('Changing setting', name, value); 8276 if( $.isPlainObject(name) ) { 8277 $.extend(true, settings, name); 8278 } 8279 else if(value !== undefined) { 8280 settings[name] = value; 8281 } 8282 else { 8283 return settings[name]; 8284 } 8285 }, 8286 internal: function(name, value) { 8287 if( $.isPlainObject(name) ) { 8288 $.extend(true, module, name); 8289 } 8290 else if(value !== undefined) { 8291 module[name] = value; 8292 } 8293 else { 8294 return module[name]; 8295 } 8296 }, 8297 debug: function() { 8298 if(settings.debug) { 8299 if(settings.performance) { 8300 module.performance.log(arguments); 8301 } 8302 else { 8303 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 8304 module.debug.apply(console, arguments); 8305 } 8306 } 8307 }, 8308 verbose: function() { 8309 if(settings.verbose && settings.debug) { 8310 if(settings.performance) { 8311 module.performance.log(arguments); 8312 } 8313 else { 8314 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 8315 module.verbose.apply(console, arguments); 8316 } 8317 } 8318 }, 8319 error: function() { 8320 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 8321 module.error.apply(console, arguments); 8322 }, 8323 performance: { 8324 log: function(message) { 8325 var 8326 currentTime, 8327 executionTime, 8328 previousTime 8329 ; 8330 if(settings.performance) { 8331 currentTime = new Date().getTime(); 8332 previousTime = time || currentTime; 8333 executionTime = currentTime - previousTime; 8334 time = currentTime; 8335 performance.push({ 8336 'Name' : message[0], 8337 'Arguments' : [].slice.call(message, 1) || '', 8338 'Element' : element, 8339 'Execution Time' : executionTime 8340 }); 8341 } 8342 clearTimeout(module.performance.timer); 8343 module.performance.timer = setTimeout(module.performance.display, 100); 8344 }, 8345 display: function() { 8346 var 8347 title = settings.name + ':', 8348 totalTime = 0 8349 ; 8350 time = false; 8351 clearTimeout(module.performance.timer); 8352 $.each(performance, function(index, data) { 8353 totalTime += data['Execution Time']; 8354 }); 8355 title += ' ' + totalTime + 'ms'; 8356 if(moduleSelector) { 8357 title += ' \'' + moduleSelector + '\''; 8358 } 8359 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 8360 console.groupCollapsed(title); 8361 if(console.table) { 8362 console.table(performance); 8363 } 8364 else { 8365 $.each(performance, function(index, data) { 8366 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 8367 }); 8368 } 8369 console.groupEnd(); 8370 } 8371 performance = []; 8372 } 8373 }, 8374 invoke: function(query, passedArguments, context) { 8375 var 8376 object = instance, 8377 maxDepth, 8378 found, 8379 response 8380 ; 8381 passedArguments = passedArguments || queryArguments; 8382 context = element || context; 8383 if(typeof query == 'string' && object !== undefined) { 8384 query = query.split(/[\. ]/); 8385 maxDepth = query.length - 1; 8386 $.each(query, function(depth, value) { 8387 var camelCaseValue = (depth != maxDepth) 8388 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 8389 : query 8390 ; 8391 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 8392 object = object[camelCaseValue]; 8393 } 8394 else if( object[camelCaseValue] !== undefined ) { 8395 found = object[camelCaseValue]; 8396 return false; 8397 } 8398 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 8399 object = object[value]; 8400 } 8401 else if( object[value] !== undefined ) { 8402 found = object[value]; 8403 return false; 8404 } 8405 else { 8406 module.error(error.method, query); 8407 return false; 8408 } 8409 }); 8410 } 8411 if ( $.isFunction( found ) ) { 8412 response = found.apply(context, passedArguments); 8413 } 8414 else if(found !== undefined) { 8415 response = found; 8416 } 8417 if($.isArray(returnedValue)) { 8418 returnedValue.push(response); 8419 } 8420 else if(returnedValue !== undefined) { 8421 returnedValue = [returnedValue, response]; 8422 } 8423 else if(response !== undefined) { 8424 returnedValue = response; 8425 } 8426 return found; 8427 } 8428 }; 8429 8430 if(methodInvoked) { 8431 if(instance === undefined) { 8432 module.initialize(); 8433 } 8434 module.invoke(query); 8435 } 8436 else { 8437 if(instance !== undefined) { 8438 instance.invoke('destroy'); 8439 } 8440 module.initialize(); 8441 } 8442 }) 8443 ; 8444 8445 return (returnedValue !== undefined) 8446 ? returnedValue 8447 : this 8448 ; 8449 }; 8450 8451 $.fn.progress.settings = { 8452 8453 name : 'Progress', 8454 namespace : 'progress', 8455 8456 debug : false, 8457 verbose : true, 8458 performance : true, 8459 8460 random : { 8461 min : 2, 8462 max : 5 8463 }, 8464 8465 duration : 300, 8466 8467 autoSuccess : true, 8468 showActivity : true, 8469 limitValues : true, 8470 8471 label : 'percent', 8472 precision : 1, 8473 framerate : (1000 / 30), /// 30 fps 8474 8475 percent : false, 8476 total : false, 8477 value : false, 8478 8479 onChange : function(percent, value, total){}, 8480 onSuccess : function(total){}, 8481 onActive : function(value, total){}, 8482 onError : function(value, total){}, 8483 onWarning : function(value, total){}, 8484 8485 error : { 8486 method : 'The method you called is not defined.', 8487 nonNumeric : 'Progress value is non numeric', 8488 tooHigh : 'Value specified is above 100%', 8489 tooLow : 'Value specified is below 0%' 8490 }, 8491 8492 regExp: { 8493 variable: /\{\$*[A-z0-9]+\}/g 8494 }, 8495 8496 metadata: { 8497 percent : 'percent', 8498 total : 'total', 8499 value : 'value' 8500 }, 8501 8502 selector : { 8503 bar : '> .bar', 8504 label : '> .label', 8505 progress : '.bar > .progress' 8506 }, 8507 8508 text : { 8509 active : false, 8510 error : false, 8511 success : false, 8512 warning : false, 8513 percent : '{percent}%', 8514 ratio : '{value} of {total}' 8515 }, 8516 8517 className : { 8518 active : 'active', 8519 error : 'error', 8520 success : 'success', 8521 warning : 'warning' 8522 } 8523 8524 }; 8525 8526 8527 })( jQuery, window , document ); 8528 /*! 8529 * # Semantic UI x.x - Rating 8530 * http://github.com/semantic-org/semantic-ui/ 8531 * 8532 * 8533 * Copyright 2014 Contributors 8534 * Released under the MIT license 8535 * http://opensource.org/licenses/MIT 8536 * 8537 */ 8538 8539 ;(function ($, window, document, undefined) { 8540 8541 "use strict"; 8542 8543 $.fn.rating = function(parameters) { 8544 var 8545 $allModules = $(this), 8546 moduleSelector = $allModules.selector || '', 8547 8548 time = new Date().getTime(), 8549 performance = [], 8550 8551 query = arguments[0], 8552 methodInvoked = (typeof query == 'string'), 8553 queryArguments = [].slice.call(arguments, 1), 8554 returnedValue 8555 ; 8556 $allModules 8557 .each(function() { 8558 var 8559 settings = ( $.isPlainObject(parameters) ) 8560 ? $.extend(true, {}, $.fn.rating.settings, parameters) 8561 : $.extend({}, $.fn.rating.settings), 8562 8563 namespace = settings.namespace, 8564 className = settings.className, 8565 metadata = settings.metadata, 8566 selector = settings.selector, 8567 error = settings.error, 8568 8569 eventNamespace = '.' + namespace, 8570 moduleNamespace = 'module-' + namespace, 8571 8572 element = this, 8573 instance = $(this).data(moduleNamespace), 8574 8575 $module = $(this), 8576 $icon = $module.find(selector.icon), 8577 8578 module 8579 ; 8580 8581 module = { 8582 8583 initialize: function() { 8584 module.verbose('Initializing rating module', settings); 8585 8586 if($icon.length === 0) { 8587 module.setup.layout(); 8588 } 8589 8590 if(settings.interactive) { 8591 module.enable(); 8592 } 8593 else { 8594 module.disable(); 8595 } 8596 if(settings.initialRating) { 8597 module.debug('Setting initial rating'); 8598 module.setRating(settings.initialRating); 8599 } 8600 if( $module.data(metadata.rating) ) { 8601 module.debug('Rating found in metadata'); 8602 module.setRating( $module.data(metadata.rating) ); 8603 } 8604 module.instantiate(); 8605 }, 8606 8607 instantiate: function() { 8608 module.verbose('Instantiating module', settings); 8609 instance = module; 8610 $module 8611 .data(moduleNamespace, module) 8612 ; 8613 }, 8614 8615 destroy: function() { 8616 module.verbose('Destroying previous instance', instance); 8617 $module 8618 .removeData(moduleNamespace) 8619 ; 8620 $icon 8621 .off(eventNamespace) 8622 ; 8623 }, 8624 8625 refresh: function() { 8626 $icon = $module.find(selector.icon); 8627 }, 8628 8629 setup: { 8630 layout: function() { 8631 var 8632 maxRating = $module.data(metadata.maxRating) || settings.maxRating 8633 ; 8634 module.debug('Generating icon html dynamically'); 8635 $module 8636 .html($.fn.rating.settings.templates.icon(maxRating)) 8637 ; 8638 module.refresh(); 8639 } 8640 }, 8641 8642 event: { 8643 mouseenter: function() { 8644 var 8645 $activeIcon = $(this) 8646 ; 8647 $activeIcon 8648 .nextAll() 8649 .removeClass(className.selected) 8650 ; 8651 $module 8652 .addClass(className.selected) 8653 ; 8654 $activeIcon 8655 .addClass(className.selected) 8656 .prevAll() 8657 .addClass(className.selected) 8658 ; 8659 }, 8660 mouseleave: function() { 8661 $module 8662 .removeClass(className.selected) 8663 ; 8664 $icon 8665 .removeClass(className.selected) 8666 ; 8667 }, 8668 click: function() { 8669 var 8670 $activeIcon = $(this), 8671 currentRating = module.getRating(), 8672 rating = $icon.index($activeIcon) + 1, 8673 canClear = (settings.clearable == 'auto') 8674 ? ($icon.length === 1) 8675 : settings.clearable 8676 ; 8677 if(canClear && currentRating == rating) { 8678 module.clearRating(); 8679 } 8680 else { 8681 module.setRating( rating ); 8682 } 8683 } 8684 }, 8685 8686 clearRating: function() { 8687 module.debug('Clearing current rating'); 8688 module.setRating(0); 8689 }, 8690 8691 getRating: function() { 8692 var 8693 currentRating = $icon.filter('.' + className.active).length 8694 ; 8695 module.verbose('Current rating retrieved', currentRating); 8696 return currentRating; 8697 }, 8698 8699 enable: function() { 8700 module.debug('Setting rating to interactive mode'); 8701 $icon 8702 .on('mouseenter' + eventNamespace, module.event.mouseenter) 8703 .on('mouseleave' + eventNamespace, module.event.mouseleave) 8704 .on('click' + eventNamespace, module.event.click) 8705 ; 8706 $module 8707 .removeClass(className.disabled) 8708 ; 8709 }, 8710 8711 disable: function() { 8712 module.debug('Setting rating to read-only mode'); 8713 $icon 8714 .off(eventNamespace) 8715 ; 8716 $module 8717 .addClass(className.disabled) 8718 ; 8719 }, 8720 8721 setRating: function(rating) { 8722 var 8723 ratingIndex = (rating - 1 >= 0) 8724 ? (rating - 1) 8725 : 0, 8726 $activeIcon = $icon.eq(ratingIndex) 8727 ; 8728 $module 8729 .removeClass(className.selected) 8730 ; 8731 $icon 8732 .removeClass(className.selected) 8733 .removeClass(className.active) 8734 ; 8735 if(rating > 0) { 8736 module.verbose('Setting current rating to', rating); 8737 $activeIcon 8738 .prevAll() 8739 .andSelf() 8740 .addClass(className.active) 8741 ; 8742 } 8743 settings.onRate.call(element, rating); 8744 }, 8745 8746 setting: function(name, value) { 8747 module.debug('Changing setting', name, value); 8748 if( $.isPlainObject(name) ) { 8749 $.extend(true, settings, name); 8750 } 8751 else if(value !== undefined) { 8752 settings[name] = value; 8753 } 8754 else { 8755 return settings[name]; 8756 } 8757 }, 8758 internal: function(name, value) { 8759 if( $.isPlainObject(name) ) { 8760 $.extend(true, module, name); 8761 } 8762 else if(value !== undefined) { 8763 module[name] = value; 8764 } 8765 else { 8766 return module[name]; 8767 } 8768 }, 8769 debug: function() { 8770 if(settings.debug) { 8771 if(settings.performance) { 8772 module.performance.log(arguments); 8773 } 8774 else { 8775 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 8776 module.debug.apply(console, arguments); 8777 } 8778 } 8779 }, 8780 verbose: function() { 8781 if(settings.verbose && settings.debug) { 8782 if(settings.performance) { 8783 module.performance.log(arguments); 8784 } 8785 else { 8786 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 8787 module.verbose.apply(console, arguments); 8788 } 8789 } 8790 }, 8791 error: function() { 8792 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 8793 module.error.apply(console, arguments); 8794 }, 8795 performance: { 8796 log: function(message) { 8797 var 8798 currentTime, 8799 executionTime, 8800 previousTime 8801 ; 8802 if(settings.performance) { 8803 currentTime = new Date().getTime(); 8804 previousTime = time || currentTime; 8805 executionTime = currentTime - previousTime; 8806 time = currentTime; 8807 performance.push({ 8808 'Name' : message[0], 8809 'Arguments' : [].slice.call(message, 1) || '', 8810 'Element' : element, 8811 'Execution Time' : executionTime 8812 }); 8813 } 8814 clearTimeout(module.performance.timer); 8815 module.performance.timer = setTimeout(module.performance.display, 100); 8816 }, 8817 display: function() { 8818 var 8819 title = settings.name + ':', 8820 totalTime = 0 8821 ; 8822 time = false; 8823 clearTimeout(module.performance.timer); 8824 $.each(performance, function(index, data) { 8825 totalTime += data['Execution Time']; 8826 }); 8827 title += ' ' + totalTime + 'ms'; 8828 if(moduleSelector) { 8829 title += ' \'' + moduleSelector + '\''; 8830 } 8831 if($allModules.length > 1) { 8832 title += ' ' + '(' + $allModules.length + ')'; 8833 } 8834 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 8835 console.groupCollapsed(title); 8836 if(console.table) { 8837 console.table(performance); 8838 } 8839 else { 8840 $.each(performance, function(index, data) { 8841 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 8842 }); 8843 } 8844 console.groupEnd(); 8845 } 8846 performance = []; 8847 } 8848 }, 8849 invoke: function(query, passedArguments, context) { 8850 var 8851 object = instance, 8852 maxDepth, 8853 found, 8854 response 8855 ; 8856 passedArguments = passedArguments || queryArguments; 8857 context = element || context; 8858 if(typeof query == 'string' && object !== undefined) { 8859 query = query.split(/[\. ]/); 8860 maxDepth = query.length - 1; 8861 $.each(query, function(depth, value) { 8862 var camelCaseValue = (depth != maxDepth) 8863 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 8864 : query 8865 ; 8866 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 8867 object = object[camelCaseValue]; 8868 } 8869 else if( object[camelCaseValue] !== undefined ) { 8870 found = object[camelCaseValue]; 8871 return false; 8872 } 8873 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 8874 object = object[value]; 8875 } 8876 else if( object[value] !== undefined ) { 8877 found = object[value]; 8878 return false; 8879 } 8880 else { 8881 return false; 8882 } 8883 }); 8884 } 8885 if ( $.isFunction( found ) ) { 8886 response = found.apply(context, passedArguments); 8887 } 8888 else if(found !== undefined) { 8889 response = found; 8890 } 8891 if($.isArray(returnedValue)) { 8892 returnedValue.push(response); 8893 } 8894 else if(returnedValue !== undefined) { 8895 returnedValue = [returnedValue, response]; 8896 } 8897 else if(response !== undefined) { 8898 returnedValue = response; 8899 } 8900 return found; 8901 } 8902 }; 8903 if(methodInvoked) { 8904 if(instance === undefined) { 8905 module.initialize(); 8906 } 8907 module.invoke(query); 8908 } 8909 else { 8910 if(instance !== undefined) { 8911 instance.invoke('destroy'); 8912 } 8913 module.initialize(); 8914 } 8915 }) 8916 ; 8917 8918 return (returnedValue !== undefined) 8919 ? returnedValue 8920 : this 8921 ; 8922 }; 8923 8924 $.fn.rating.settings = { 8925 8926 name : 'Rating', 8927 namespace : 'rating', 8928 8929 debug : false, 8930 verbose : true, 8931 performance : true, 8932 8933 initialRating : 0, 8934 interactive : true, 8935 maxRating : 4, 8936 clearable : 'auto', 8937 8938 onRate : function(rating){}, 8939 8940 error : { 8941 method : 'The method you called is not defined', 8942 noMaximum : 'No maximum rating specified. Cannot generate HTML automatically' 8943 }, 8944 8945 8946 metadata: { 8947 rating : 'rating', 8948 maxRating : 'maxRating' 8949 }, 8950 8951 className : { 8952 active : 'active', 8953 disabled : 'disabled', 8954 selected : 'selected', 8955 loading : 'loading' 8956 }, 8957 8958 selector : { 8959 icon : '.icon' 8960 }, 8961 8962 templates: { 8963 icon: function(maxRating) { 8964 var 8965 icon = 1, 8966 html = '' 8967 ; 8968 while(icon <= maxRating) { 8969 html += '<i class="icon"></i>'; 8970 icon++; 8971 } 8972 return html; 8973 } 8974 } 8975 8976 }; 8977 8978 })( jQuery, window , document ); 8979 8980 /*! 8981 * # Semantic UI x.x - Search 8982 * http://github.com/semantic-org/semantic-ui/ 8983 * 8984 * 8985 * Copyright 2014 Contributors 8986 * Released under the MIT license 8987 * http://opensource.org/licenses/MIT 8988 * 8989 */ 8990 8991 ;(function ($, window, document, undefined) { 8992 8993 "use strict"; 8994 8995 $.fn.search = function(parameters) { 8996 var 8997 $allModules = $(this), 8998 moduleSelector = $allModules.selector || '', 8999 9000 time = new Date().getTime(), 9001 performance = [], 9002 9003 query = arguments[0], 9004 methodInvoked = (typeof query == 'string'), 9005 queryArguments = [].slice.call(arguments, 1), 9006 returnedValue 9007 ; 9008 $(this) 9009 .each(function() { 9010 var 9011 settings = $.extend(true, {}, $.fn.search.settings, parameters), 9012 9013 className = settings.className, 9014 metadata = settings.metadata, 9015 regExp = settings.regExp, 9016 selector = settings.selector, 9017 error = settings.error, 9018 namespace = settings.namespace, 9019 9020 eventNamespace = '.' + namespace, 9021 moduleNamespace = namespace + '-module', 9022 9023 $module = $(this), 9024 $prompt = $module.find(selector.prompt), 9025 $searchButton = $module.find(selector.searchButton), 9026 $results = $module.find(selector.results), 9027 $result = $module.find(selector.result), 9028 $category = $module.find(selector.category), 9029 9030 element = this, 9031 instance = $module.data(moduleNamespace), 9032 9033 module 9034 ; 9035 module = { 9036 9037 initialize: function() { 9038 module.verbose('Initializing module'); 9039 var 9040 prompt = $prompt[0], 9041 inputEvent = (prompt !== undefined && prompt.oninput !== undefined) 9042 ? 'input' 9043 : (prompt !== undefined && prompt.onpropertychange !== undefined) 9044 ? 'propertychange' 9045 : 'keyup' 9046 ; 9047 if(settings.automatic) { 9048 $prompt 9049 .on(inputEvent + eventNamespace, module.throttle) 9050 .attr('autocomplete', 'off') 9051 ; 9052 } 9053 $prompt 9054 .on('focus' + eventNamespace, module.event.focus) 9055 .on('blur' + eventNamespace, module.event.blur) 9056 .on('keydown' + eventNamespace, module.handleKeyboard) 9057 ; 9058 $searchButton 9059 .on('click' + eventNamespace, module.query) 9060 ; 9061 $results 9062 .on('mousedown' + eventNamespace, module.event.result.mousedown) 9063 .on('mouseup' + eventNamespace, module.event.result.mouseup) 9064 .on('click' + eventNamespace, selector.result, module.event.result.click) 9065 ; 9066 module.instantiate(); 9067 }, 9068 instantiate: function() { 9069 module.verbose('Storing instance of module', module); 9070 instance = module; 9071 $module 9072 .data(moduleNamespace, module) 9073 ; 9074 }, 9075 destroy: function() { 9076 module.verbose('Destroying instance'); 9077 $module 9078 .removeData(moduleNamespace) 9079 ; 9080 $prompt 9081 .off(eventNamespace) 9082 ; 9083 $searchButton 9084 .off(eventNamespace) 9085 ; 9086 $results 9087 .off(eventNamespace) 9088 ; 9089 }, 9090 event: { 9091 focus: function() { 9092 module.set.focus(); 9093 clearTimeout(module.timer); 9094 module.throttle(); 9095 if( module.has.minimumCharacters() ) { 9096 module.showResults(); 9097 } 9098 }, 9099 blur: function(event) { 9100 var 9101 pageLostFocus = (document.activeElement === this) 9102 ; 9103 if(!pageLostFocus && !module.resultsClicked) { 9104 module.cancel.query(); 9105 module.remove.focus(); 9106 module.timer = setTimeout(module.hideResults, settings.hideDelay); 9107 } 9108 }, 9109 result: { 9110 mousedown: function() { 9111 module.resultsClicked = true; 9112 }, 9113 mouseup: function() { 9114 module.resultsClicked = false; 9115 }, 9116 click: function(event) { 9117 module.debug('Search result selected'); 9118 var 9119 $result = $(this), 9120 $title = $result.find(selector.title).eq(0), 9121 $link = $result.find('a[href]').eq(0), 9122 href = $link.attr('href') || false, 9123 target = $link.attr('target') || false, 9124 title = $title.html(), 9125 name = ($title.length > 0) 9126 ? $title.text() 9127 : false, 9128 results = module.get.results(), 9129 result = module.get.result(name, results), 9130 returnedValue 9131 ; 9132 if( $.isFunction(settings.onSelect) ) { 9133 if(settings.onSelect.call(element, result, results) === false) { 9134 module.debug('Custom onSelect callback cancelled default select action'); 9135 return; 9136 } 9137 } 9138 module.hideResults(); 9139 if(name) { 9140 module.set.value(name); 9141 } 9142 if(href) { 9143 module.verbose('Opening search link found in result', $link); 9144 if(target == '_blank' || event.ctrlKey) { 9145 window.open(href); 9146 } 9147 else { 9148 window.location.href = (href); 9149 } 9150 } 9151 } 9152 } 9153 }, 9154 handleKeyboard: function(event) { 9155 var 9156 // force selector refresh 9157 $result = $module.find(selector.result), 9158 $category = $module.find(selector.category), 9159 currentIndex = $result.index( $result.filter('.' + className.active) ), 9160 resultSize = $result.length, 9161 9162 keyCode = event.which, 9163 keys = { 9164 backspace : 8, 9165 enter : 13, 9166 escape : 27, 9167 upArrow : 38, 9168 downArrow : 40 9169 }, 9170 newIndex 9171 ; 9172 // search shortcuts 9173 if(keyCode == keys.escape) { 9174 module.verbose('Escape key pressed, blurring search field'); 9175 $prompt 9176 .trigger('blur') 9177 ; 9178 } 9179 if( module.is.visible() ) { 9180 if(keyCode == keys.enter) { 9181 module.verbose('Enter key pressed, selecting active result'); 9182 if( $result.filter('.' + className.active).length > 0 ) { 9183 module.event.result.click.call($result.filter('.' + className.active), event); 9184 event.preventDefault(); 9185 return false; 9186 } 9187 } 9188 else if(keyCode == keys.upArrow) { 9189 module.verbose('Up key pressed, changing active result'); 9190 newIndex = (currentIndex - 1 < 0) 9191 ? currentIndex 9192 : currentIndex - 1 9193 ; 9194 $category 9195 .removeClass(className.active) 9196 ; 9197 $result 9198 .removeClass(className.active) 9199 .eq(newIndex) 9200 .addClass(className.active) 9201 .closest($category) 9202 .addClass(className.active) 9203 ; 9204 event.preventDefault(); 9205 } 9206 else if(keyCode == keys.downArrow) { 9207 module.verbose('Down key pressed, changing active result'); 9208 newIndex = (currentIndex + 1 >= resultSize) 9209 ? currentIndex 9210 : currentIndex + 1 9211 ; 9212 $category 9213 .removeClass(className.active) 9214 ; 9215 $result 9216 .removeClass(className.active) 9217 .eq(newIndex) 9218 .addClass(className.active) 9219 .closest($category) 9220 .addClass(className.active) 9221 ; 9222 event.preventDefault(); 9223 } 9224 } 9225 else { 9226 // query shortcuts 9227 if(keyCode == keys.enter) { 9228 module.verbose('Enter key pressed, executing query'); 9229 module.query(); 9230 module.set.buttonPressed(); 9231 $prompt.one('keyup', module.remove.buttonFocus); 9232 } 9233 } 9234 }, 9235 9236 setup: { 9237 api: function() { 9238 var 9239 apiSettings = { 9240 on : false, 9241 action : 'search', 9242 onFailure : module.error 9243 }, 9244 searchHTML 9245 ; 9246 module.verbose('First request, initializing API'); 9247 $module.api(apiSettings); 9248 } 9249 }, 9250 9251 can: { 9252 useAPI: function() { 9253 return $.fn.api !== undefined; 9254 }, 9255 transition: function() { 9256 return settings.transition && $.fn.transition !== undefined && $module.transition('is supported'); 9257 } 9258 }, 9259 9260 is: { 9261 empty: function() { 9262 return ($results.html() === ''); 9263 }, 9264 visible: function() { 9265 return ($results.filter(':visible').length > 0); 9266 }, 9267 focused: function() { 9268 return ($prompt.filter(':focus').length > 0); 9269 } 9270 }, 9271 9272 get: { 9273 value: function() { 9274 return $prompt.val(); 9275 }, 9276 results: function() { 9277 var 9278 results = $module.data(metadata.results) 9279 ; 9280 return results; 9281 }, 9282 result: function(value, results) { 9283 var 9284 result = false 9285 ; 9286 value = value || module.get.value(); 9287 results = results || module.get.results(); 9288 if(settings.type === 'category') { 9289 module.debug('Finding result that matches', value); 9290 $.each(results, function(index, category) { 9291 if($.isArray(category.results)) { 9292 result = module.search.object(value, category.results)[0]; 9293 if(result && result.length > 0) { 9294 return true; 9295 } 9296 } 9297 }); 9298 } 9299 else { 9300 module.debug('Finding result in results object', value); 9301 result = module.search.object(value, results)[0]; 9302 } 9303 return result; 9304 }, 9305 }, 9306 9307 set: { 9308 focus: function() { 9309 $module.addClass(className.focus); 9310 }, 9311 loading: function() { 9312 $module.addClass(className.loading); 9313 }, 9314 value: function(value) { 9315 module.verbose('Setting search input value', value); 9316 $prompt.val(value); 9317 module.query(); 9318 }, 9319 buttonPressed: function() { 9320 $searchButton.addClass(className.pressed); 9321 } 9322 }, 9323 9324 remove: { 9325 loading: function() { 9326 $module.removeClass(className.loading); 9327 }, 9328 focus: function() { 9329 $module.removeClass(className.focus); 9330 }, 9331 buttonPressed: function() { 9332 $searchButton.removeClass(className.pressed); 9333 } 9334 }, 9335 9336 query: function() { 9337 var 9338 searchTerm = module.get.value(), 9339 cache = module.read.cache(searchTerm) 9340 ; 9341 if(cache) { 9342 module.debug('Reading result for ' + searchTerm + ' from cache'); 9343 module.save.results(cache.results); 9344 module.addResults(cache.html); 9345 } 9346 else { 9347 module.debug('Querying for ' + searchTerm); 9348 if($.isPlainObject(settings.source) || $.isArray(settings.source)) { 9349 module.search.local(searchTerm); 9350 } 9351 else if( module.can.useAPI() ) { 9352 if(settings.apiSettings) { 9353 module.debug('Searching with specified API settings', settings.apiSettings); 9354 module.search.remote(searchTerm); 9355 } 9356 else if($.api.settings.api.search !== undefined) { 9357 module.debug('Searching with default search API endpoint'); 9358 module.search.remote(searchTerm); 9359 } 9360 else { 9361 module.error(error.noEndpoint); 9362 } 9363 } 9364 else { 9365 module.error(error.source); 9366 } 9367 settings.onSearchQuery.call(element, searchTerm); 9368 } 9369 }, 9370 9371 search: { 9372 local: function(searchTerm) { 9373 var 9374 searchResults = module.search.object(searchTerm, settings.content), 9375 searchHTML 9376 ; 9377 module.set.loading(); 9378 module.save.results(searchResults); 9379 module.debug('Returned local search results', searchResults); 9380 9381 searchHTML = module.generateResults({ 9382 results: searchResults 9383 }); 9384 module.remove.loading(); 9385 module.write.cache(searchTerm, { 9386 html : searchHTML, 9387 results : searchResults 9388 }); 9389 module.addResults(searchHTML); 9390 }, 9391 remote: function(searchTerm) { 9392 var 9393 apiSettings = { 9394 onSuccess : function(response) { 9395 module.parse.response.call(element, response, searchTerm); 9396 }, 9397 urlData: { 9398 query: searchTerm 9399 } 9400 } 9401 ; 9402 if( !$module.api('get request') ) { 9403 module.setup.api(); 9404 } 9405 $.extend(true, apiSettings, settings.apiSettings); 9406 module.debug('Executing search', apiSettings); 9407 module.cancel.query(); 9408 $module 9409 .api('setting', apiSettings) 9410 .api('query') 9411 ; 9412 }, 9413 object: function(searchTerm, source) { 9414 var 9415 results = [], 9416 fullTextResults = [], 9417 searchFields = $.isArray(settings.searchFields) 9418 ? settings.searchFields 9419 : [settings.searchFields], 9420 searchExp = searchTerm.replace(regExp.escape, '\\$&'), 9421 searchRegExp = new RegExp(regExp.exact + searchExp, 'i') 9422 ; 9423 9424 source = source || settings.source; 9425 9426 // exit conditions on no source 9427 if(source === undefined) { 9428 module.error(error.source); 9429 return []; 9430 } 9431 9432 // iterate through search fields in array order 9433 $.each(searchFields, function(index, field) { 9434 $.each(source, function(label, content) { 9435 var 9436 fieldExists = (typeof content[field] == 'string'), 9437 notAlreadyResult = ($.inArray(content, results) == -1 && $.inArray(content, fullTextResults) == -1) 9438 ; 9439 if(fieldExists && notAlreadyResult) { 9440 if( content[field].match(searchRegExp) ) { 9441 results.push(content); 9442 } 9443 else if(settings.searchFullText && module.fuzzySearch(searchTerm, content[field]) ) { 9444 fullTextResults.push(content); 9445 } 9446 } 9447 }); 9448 }); 9449 return $.merge(results, fullTextResults); 9450 } 9451 }, 9452 9453 fuzzySearch: function(query, term) { 9454 var 9455 termLength = term.length, 9456 queryLength = query.length 9457 ; 9458 query = query.toLowerCase(); 9459 term = term.toLowerCase(); 9460 if(queryLength > termLength) { 9461 return false; 9462 } 9463 if(queryLength === termLength) { 9464 return (query === term); 9465 } 9466 search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) { 9467 var 9468 queryCharacter = query.charCodeAt(characterIndex) 9469 ; 9470 while(nextCharacterIndex < termLength) { 9471 if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) { 9472 continue search; 9473 } 9474 } 9475 return false; 9476 } 9477 return true; 9478 }, 9479 9480 parse: { 9481 response: function(response, searchTerm) { 9482 var 9483 searchHTML = module.generateResults(response) 9484 ; 9485 module.verbose('Parsing server response', response); 9486 if(response !== undefined) { 9487 if(searchTerm !== undefined && response.results !== undefined) { 9488 module.write.cache(searchTerm, { 9489 html : searchHTML, 9490 results : response.results 9491 }); 9492 module.save.results(response.results); 9493 module.addResults(searchHTML); 9494 } 9495 } 9496 } 9497 }, 9498 9499 throttle: function() { 9500 clearTimeout(module.timer); 9501 if(module.has.minimumCharacters()) { 9502 module.timer = setTimeout(module.query, settings.searchDelay); 9503 } 9504 else { 9505 module.hideResults(); 9506 } 9507 }, 9508 9509 cancel: { 9510 query: function() { 9511 if( module.can.useAPI() ) { 9512 $module.api('abort'); 9513 } 9514 } 9515 }, 9516 9517 has: { 9518 minimumCharacters: function() { 9519 var 9520 searchTerm = module.get.value(), 9521 numCharacters = searchTerm.length 9522 ; 9523 return (numCharacters >= settings.minCharacters); 9524 } 9525 }, 9526 9527 read: { 9528 cache: function(name) { 9529 var 9530 cache = $module.data(metadata.cache) 9531 ; 9532 if(settings.cache) { 9533 module.verbose('Checking cache for generated html for query', name); 9534 return (typeof cache == 'object') && (cache[name] !== undefined) 9535 ? cache[name] 9536 : false 9537 ; 9538 } 9539 return false; 9540 } 9541 }, 9542 9543 save: { 9544 results: function(results) { 9545 module.verbose('Saving current search results to metadata', results); 9546 $module.data(metadata.results, results); 9547 } 9548 }, 9549 9550 write: { 9551 cache: function(name, value) { 9552 var 9553 cache = ($module.data(metadata.cache) !== undefined) 9554 ? $module.data(metadata.cache) 9555 : {} 9556 ; 9557 if(settings.cache) { 9558 module.verbose('Writing generated html to cache', name, value); 9559 cache[name] = value; 9560 $module 9561 .data(metadata.cache, cache) 9562 ; 9563 } 9564 } 9565 }, 9566 9567 addResults: function(html) { 9568 if( $.isFunction(settings.onResultsAdd) ) { 9569 if( settings.onResultsAdd.call($results, html) === false ) { 9570 module.debug('onResultsAdd callback cancelled default action'); 9571 return false; 9572 } 9573 } 9574 $results 9575 .html(html) 9576 ; 9577 module.showResults(); 9578 }, 9579 9580 showResults: function() { 9581 if( !module.is.visible() && module.is.focused() && !module.is.empty() ) { 9582 if( module.can.transition() ) { 9583 module.debug('Showing results with css animations'); 9584 $results 9585 .transition({ 9586 animation : settings.transition + ' in', 9587 duration : settings.duration, 9588 queue : true 9589 }) 9590 ; 9591 } 9592 else { 9593 module.debug('Showing results with javascript'); 9594 $results 9595 .stop() 9596 .fadeIn(settings.duration, settings.easing) 9597 ; 9598 } 9599 settings.onResultsOpen.call($results); 9600 } 9601 }, 9602 hideResults: function() { 9603 if( module.is.visible() ) { 9604 if( module.can.transition() ) { 9605 module.debug('Hiding results with css animations'); 9606 $results 9607 .transition({ 9608 animation : settings.transition + ' out', 9609 duration : settings.duration, 9610 queue : true 9611 }) 9612 ; 9613 } 9614 else { 9615 module.debug('Hiding results with javascript'); 9616 $results 9617 .stop() 9618 .fadeOut(settings.duration, settings.easing) 9619 ; 9620 } 9621 settings.onResultsClose.call($results); 9622 } 9623 }, 9624 9625 generateResults: function(response) { 9626 module.debug('Generating html from response', response); 9627 var 9628 template = settings.templates[settings.type], 9629 isProperObject = ($.isPlainObject(response.results) && !$.isEmptyObject(response.results)), 9630 isProperArray = ($.isArray(response.results) && response.results.length > 0), 9631 html = '' 9632 ; 9633 if(isProperObject || isProperArray ) { 9634 if(settings.maxResults > 0) { 9635 if(isProperObject) { 9636 if(settings.type == 'standard') { 9637 module.error(error.maxResults); 9638 } 9639 } 9640 else { 9641 response.results = response.results.slice(0, settings.maxResults); 9642 } 9643 } 9644 if($.isFunction(template)) { 9645 html = template(response); 9646 } 9647 else { 9648 module.error(error.noTemplate, false); 9649 } 9650 } 9651 else { 9652 html = module.displayMessage(error.noResults, 'empty'); 9653 } 9654 settings.onResults.call(element, response); 9655 return html; 9656 }, 9657 9658 displayMessage: function(text, type) { 9659 type = type || 'standard'; 9660 module.debug('Displaying message', text, type); 9661 module.addResults( settings.templates.message(text, type) ); 9662 return settings.templates.message(text, type); 9663 }, 9664 9665 setting: function(name, value) { 9666 if( $.isPlainObject(name) ) { 9667 $.extend(true, settings, name); 9668 } 9669 else if(value !== undefined) { 9670 settings[name] = value; 9671 } 9672 else { 9673 return settings[name]; 9674 } 9675 }, 9676 internal: function(name, value) { 9677 if( $.isPlainObject(name) ) { 9678 $.extend(true, module, name); 9679 } 9680 else if(value !== undefined) { 9681 module[name] = value; 9682 } 9683 else { 9684 return module[name]; 9685 } 9686 }, 9687 debug: function() { 9688 if(settings.debug) { 9689 if(settings.performance) { 9690 module.performance.log(arguments); 9691 } 9692 else { 9693 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 9694 module.debug.apply(console, arguments); 9695 } 9696 } 9697 }, 9698 verbose: function() { 9699 if(settings.verbose && settings.debug) { 9700 if(settings.performance) { 9701 module.performance.log(arguments); 9702 } 9703 else { 9704 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 9705 module.verbose.apply(console, arguments); 9706 } 9707 } 9708 }, 9709 error: function() { 9710 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 9711 module.error.apply(console, arguments); 9712 }, 9713 performance: { 9714 log: function(message) { 9715 var 9716 currentTime, 9717 executionTime, 9718 previousTime 9719 ; 9720 if(settings.performance) { 9721 currentTime = new Date().getTime(); 9722 previousTime = time || currentTime; 9723 executionTime = currentTime - previousTime; 9724 time = currentTime; 9725 performance.push({ 9726 'Name' : message[0], 9727 'Arguments' : [].slice.call(message, 1) || '', 9728 'Element' : element, 9729 'Execution Time' : executionTime 9730 }); 9731 } 9732 clearTimeout(module.performance.timer); 9733 module.performance.timer = setTimeout(module.performance.display, 100); 9734 }, 9735 display: function() { 9736 var 9737 title = settings.name + ':', 9738 totalTime = 0 9739 ; 9740 time = false; 9741 clearTimeout(module.performance.timer); 9742 $.each(performance, function(index, data) { 9743 totalTime += data['Execution Time']; 9744 }); 9745 title += ' ' + totalTime + 'ms'; 9746 if(moduleSelector) { 9747 title += ' \'' + moduleSelector + '\''; 9748 } 9749 if($allModules.length > 1) { 9750 title += ' ' + '(' + $allModules.length + ')'; 9751 } 9752 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 9753 console.groupCollapsed(title); 9754 if(console.table) { 9755 console.table(performance); 9756 } 9757 else { 9758 $.each(performance, function(index, data) { 9759 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 9760 }); 9761 } 9762 console.groupEnd(); 9763 } 9764 performance = []; 9765 } 9766 }, 9767 invoke: function(query, passedArguments, context) { 9768 var 9769 object = instance, 9770 maxDepth, 9771 found, 9772 response 9773 ; 9774 passedArguments = passedArguments || queryArguments; 9775 context = element || context; 9776 if(typeof query == 'string' && object !== undefined) { 9777 query = query.split(/[\. ]/); 9778 maxDepth = query.length - 1; 9779 $.each(query, function(depth, value) { 9780 var camelCaseValue = (depth != maxDepth) 9781 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 9782 : query 9783 ; 9784 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 9785 object = object[camelCaseValue]; 9786 } 9787 else if( object[camelCaseValue] !== undefined ) { 9788 found = object[camelCaseValue]; 9789 return false; 9790 } 9791 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 9792 object = object[value]; 9793 } 9794 else if( object[value] !== undefined ) { 9795 found = object[value]; 9796 return false; 9797 } 9798 else { 9799 return false; 9800 } 9801 }); 9802 } 9803 if( $.isFunction( found ) ) { 9804 response = found.apply(context, passedArguments); 9805 } 9806 else if(found !== undefined) { 9807 response = found; 9808 } 9809 if($.isArray(returnedValue)) { 9810 returnedValue.push(response); 9811 } 9812 else if(returnedValue !== undefined) { 9813 returnedValue = [returnedValue, response]; 9814 } 9815 else if(response !== undefined) { 9816 returnedValue = response; 9817 } 9818 return found; 9819 } 9820 }; 9821 if(methodInvoked) { 9822 if(instance === undefined) { 9823 module.initialize(); 9824 } 9825 module.invoke(query); 9826 } 9827 else { 9828 if(instance !== undefined) { 9829 instance.invoke('destroy'); 9830 } 9831 module.initialize(); 9832 } 9833 9834 }) 9835 ; 9836 9837 return (returnedValue !== undefined) 9838 ? returnedValue 9839 : this 9840 ; 9841 }; 9842 9843 $.fn.search.settings = { 9844 9845 name : 'Search Module', 9846 namespace : 'search', 9847 9848 debug : false, 9849 verbose : true, 9850 performance : true, 9851 9852 type : 'standard', 9853 minCharacters : 1, 9854 9855 // api config 9856 apiSettings : false, 9857 9858 source : false, 9859 searchFields : [ 9860 'title', 9861 'description' 9862 ], 9863 searchFullText : true, 9864 9865 automatic : 'true', 9866 hideDelay : 0, 9867 searchDelay : 100, 9868 maxResults : 7, 9869 cache : true, 9870 9871 transition : 'scale', 9872 duration : 300, 9873 easing : 'easeOutExpo', 9874 9875 onSelect : false, 9876 onResultsAdd : false, 9877 9878 onSearchQuery : function(){}, 9879 onResults : function(response){}, 9880 9881 onResultsOpen : function(){}, 9882 onResultsClose : function(){}, 9883 9884 className: { 9885 active : 'active', 9886 empty : 'empty', 9887 focus : 'focus', 9888 loading : 'loading', 9889 pressed : 'down' 9890 }, 9891 9892 error : { 9893 source : 'Cannot search. No source used, and Semantic API module was not included', 9894 noResults : 'Your search returned no results', 9895 logging : 'Error in debug logging, exiting.', 9896 noEndpoint : 'No search endpoint was specified', 9897 noTemplate : 'A valid template name was not specified.', 9898 serverError : 'There was an issue with querying the server.', 9899 maxResults : 'Results must be an array to use maxResults setting', 9900 method : 'The method you called is not defined.' 9901 }, 9902 9903 metadata: { 9904 cache : 'cache', 9905 results : 'results' 9906 }, 9907 9908 regExp: { 9909 escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, 9910 exact : '(?:\s|^)' 9911 }, 9912 9913 selector : { 9914 prompt : '.prompt', 9915 searchButton : '.search.button', 9916 results : '.results', 9917 category : '.category', 9918 result : '.result', 9919 title : '.title, .name' 9920 }, 9921 9922 templates: { 9923 escape: function(string) { 9924 var 9925 badChars = /[&<>"'`]/g, 9926 shouldEscape = /[&<>"'`]/, 9927 escape = { 9928 "&": "&", 9929 "<": "<", 9930 ">": ">", 9931 '"': """, 9932 "'": "'", 9933 "`": "`" 9934 }, 9935 escapedChar = function(chr) { 9936 return escape[chr]; 9937 } 9938 ; 9939 if(shouldEscape.test(string)) { 9940 return string.replace(badChars, escapedChar); 9941 } 9942 return string; 9943 }, 9944 message: function(message, type) { 9945 var 9946 html = '' 9947 ; 9948 if(message !== undefined && type !== undefined) { 9949 html += '' 9950 + '<div class="message ' + type + '">' 9951 ; 9952 // message type 9953 if(type == 'empty') { 9954 html += '' 9955 + '<div class="header">No Results</div class="header">' 9956 + '<div class="description">' + message + '</div class="description">' 9957 ; 9958 } 9959 else { 9960 html += ' <div class="description">' + message + '</div>'; 9961 } 9962 html += '</div>'; 9963 } 9964 return html; 9965 }, 9966 category: function(response) { 9967 var 9968 html = '', 9969 escape = $.fn.search.settings.templates.escape 9970 ; 9971 if(response.results !== undefined) { 9972 // each category 9973 $.each(response.results, function(index, category) { 9974 if(category.results !== undefined && category.results.length > 0) { 9975 html += '' 9976 + '<div class="category">' 9977 + '<div class="name">' + category.name + '</div>' 9978 ; 9979 // each item inside category 9980 $.each(category.results, function(index, result) { 9981 html += '<div class="result">'; 9982 if(result.url) { 9983 html += '<a href="' + result.url + '"></a>'; 9984 } 9985 if(result.image !== undefined) { 9986 result.image = escape(result.image); 9987 html += '' 9988 + '<div class="image">' 9989 + ' <img src="' + result.image + '" alt="">' 9990 + '</div>' 9991 ; 9992 } 9993 html += '<div class="content">'; 9994 if(result.price !== undefined) { 9995 result.price = escape(result.price); 9996 html += '<div class="price">' + result.price + '</div>'; 9997 } 9998 if(result.title !== undefined) { 9999 result.title = escape(result.title); 10000 html += '<div class="title">' + result.title + '</div>'; 10001 } 10002 if(result.description !== undefined) { 10003 html += '<div class="description">' + result.description + '</div>'; 10004 } 10005 html += '' 10006 + '</div>' 10007 + '</div>' 10008 ; 10009 }); 10010 html += '' 10011 + '</div>' 10012 ; 10013 } 10014 }); 10015 if(response.action) { 10016 html += '' 10017 + '<a href="' + response.action.url + '" class="action">' 10018 + response.action.text 10019 + '</a>'; 10020 } 10021 return html; 10022 } 10023 return false; 10024 }, 10025 standard: function(response) { 10026 var 10027 html = '' 10028 ; 10029 if(response.results !== undefined) { 10030 10031 // each result 10032 $.each(response.results, function(index, result) { 10033 if(result.url) { 10034 html += '<a class="result" href="' + result.url + '">'; 10035 } 10036 else { 10037 html += '<a class="result">'; 10038 } 10039 if(result.image !== undefined) { 10040 html += '' 10041 + '<div class="image">' 10042 + ' <img src="' + result.image + '">' 10043 + '</div>' 10044 ; 10045 } 10046 html += '<div class="content">'; 10047 if(result.price !== undefined) { 10048 html += '<div class="price">' + result.price + '</div>'; 10049 } 10050 if(result.title !== undefined) { 10051 html += '<div class="title">' + result.title + '</div>'; 10052 } 10053 if(result.description !== undefined) { 10054 html += '<div class="description">' + result.description + '</div>'; 10055 } 10056 html += '' 10057 + '</div>' 10058 ; 10059 html += '</a>'; 10060 }); 10061 10062 if(response.action) { 10063 html += '' 10064 + '<a href="' + response.action.url + '" class="action">' 10065 + response.action.text 10066 + '</a>'; 10067 } 10068 return html; 10069 } 10070 return false; 10071 } 10072 } 10073 }; 10074 10075 })( jQuery, window , document ); 10076 10077 /*! 10078 * # Semantic UI x.x - Shape 10079 * http://github.com/semantic-org/semantic-ui/ 10080 * 10081 * 10082 * Copyright 2014 Contributors 10083 * Released under the MIT license 10084 * http://opensource.org/licenses/MIT 10085 * 10086 */ 10087 10088 ;(function ( $, window, document, undefined ) { 10089 10090 "use strict"; 10091 10092 $.fn.shape = function(parameters) { 10093 var 10094 $allModules = $(this), 10095 $body = $('body'), 10096 10097 time = new Date().getTime(), 10098 performance = [], 10099 10100 query = arguments[0], 10101 methodInvoked = (typeof query == 'string'), 10102 queryArguments = [].slice.call(arguments, 1), 10103 10104 requestAnimationFrame = window.requestAnimationFrame 10105 || window.mozRequestAnimationFrame 10106 || window.webkitRequestAnimationFrame 10107 || window.msRequestAnimationFrame 10108 || function(callback) { setTimeout(callback, 0); }, 10109 10110 returnedValue 10111 ; 10112 10113 $allModules 10114 .each(function() { 10115 var 10116 moduleSelector = $allModules.selector || '', 10117 settings = $.extend(true, {}, $.fn.shape.settings, parameters), 10118 10119 // internal aliases 10120 namespace = settings.namespace, 10121 selector = settings.selector, 10122 error = settings.error, 10123 className = settings.className, 10124 10125 // define namespaces for modules 10126 eventNamespace = '.' + namespace, 10127 moduleNamespace = 'module-' + namespace, 10128 10129 // selector cache 10130 $module = $(this), 10131 $sides = $module.find(selector.sides), 10132 $side = $module.find(selector.side), 10133 10134 // private variables 10135 nextIndex = false, 10136 $activeSide, 10137 $nextSide, 10138 10139 // standard module 10140 element = this, 10141 instance = $module.data(moduleNamespace), 10142 module 10143 ; 10144 10145 module = { 10146 10147 initialize: function() { 10148 module.verbose('Initializing module for', element); 10149 module.set.defaultSide(); 10150 module.instantiate(); 10151 }, 10152 10153 instantiate: function() { 10154 module.verbose('Storing instance of module', module); 10155 instance = module; 10156 $module 10157 .data(moduleNamespace, instance) 10158 ; 10159 }, 10160 10161 destroy: function() { 10162 module.verbose('Destroying previous module for', element); 10163 $module 10164 .removeData(moduleNamespace) 10165 .off(eventNamespace) 10166 ; 10167 }, 10168 10169 refresh: function() { 10170 module.verbose('Refreshing selector cache for', element); 10171 $module = $(element); 10172 $sides = $(this).find(selector.shape); 10173 $side = $(this).find(selector.side); 10174 }, 10175 10176 repaint: function() { 10177 module.verbose('Forcing repaint event'); 10178 var 10179 shape = $sides.get(0) || document.createElement('div'), 10180 fakeAssignment = shape.offsetWidth 10181 ; 10182 }, 10183 10184 animate: function(propertyObject, callback) { 10185 module.verbose('Animating box with properties', propertyObject); 10186 callback = callback || function(event) { 10187 module.verbose('Executing animation callback'); 10188 if(event !== undefined) { 10189 event.stopPropagation(); 10190 } 10191 module.reset(); 10192 module.set.active(); 10193 }; 10194 settings.beforeChange.call($nextSide.get()); 10195 if(module.get.transitionEvent()) { 10196 module.verbose('Starting CSS animation'); 10197 $module 10198 .addClass(className.animating) 10199 ; 10200 $sides 10201 .css(propertyObject) 10202 .one(module.get.transitionEvent(), callback) 10203 ; 10204 module.set.duration(settings.duration); 10205 requestAnimationFrame(function() { 10206 $module 10207 .addClass(className.animating) 10208 ; 10209 $activeSide 10210 .addClass(className.hidden) 10211 ; 10212 }); 10213 } 10214 else { 10215 callback(); 10216 } 10217 }, 10218 10219 queue: function(method) { 10220 module.debug('Queueing animation of', method); 10221 $sides 10222 .one(module.get.transitionEvent(), function() { 10223 module.debug('Executing queued animation'); 10224 setTimeout(function(){ 10225 $module.shape(method); 10226 }, 0); 10227 }) 10228 ; 10229 }, 10230 10231 reset: function() { 10232 module.verbose('Animating states reset'); 10233 $module 10234 .removeClass(className.animating) 10235 .attr('style', '') 10236 .removeAttr('style') 10237 ; 10238 // removeAttr style does not consistently work in safari 10239 $sides 10240 .attr('style', '') 10241 .removeAttr('style') 10242 ; 10243 $side 10244 .attr('style', '') 10245 .removeAttr('style') 10246 .removeClass(className.hidden) 10247 ; 10248 $nextSide 10249 .removeClass(className.animating) 10250 .attr('style', '') 10251 .removeAttr('style') 10252 ; 10253 }, 10254 10255 is: { 10256 complete: function() { 10257 return ($side.filter('.' + className.active)[0] == $nextSide[0]); 10258 }, 10259 animating: function() { 10260 return $module.hasClass(className.animating); 10261 } 10262 }, 10263 10264 set: { 10265 10266 defaultSide: function() { 10267 $activeSide = $module.find('.' + settings.className.active); 10268 $nextSide = ( $activeSide.next(selector.side).length > 0 ) 10269 ? $activeSide.next(selector.side) 10270 : $module.find(selector.side).first() 10271 ; 10272 nextIndex = false; 10273 module.verbose('Active side set to', $activeSide); 10274 module.verbose('Next side set to', $nextSide); 10275 }, 10276 10277 duration: function(duration) { 10278 duration = duration || settings.duration; 10279 duration = (typeof duration == 'number') 10280 ? duration + 'ms' 10281 : duration 10282 ; 10283 module.verbose('Setting animation duration', duration); 10284 $sides.add($side) 10285 .css({ 10286 '-webkit-transition-duration': duration, 10287 '-moz-transition-duration': duration, 10288 '-ms-transition-duration': duration, 10289 '-o-transition-duration': duration, 10290 'transition-duration': duration 10291 }) 10292 ; 10293 }, 10294 10295 stageSize: function() { 10296 var 10297 $clone = $module.clone().addClass(className.loading), 10298 $activeSide = $clone.find('.' + settings.className.active), 10299 $nextSide = (nextIndex) 10300 ? $clone.find(selector.side).eq(nextIndex) 10301 : ( $activeSide.next(selector.side).length > 0 ) 10302 ? $activeSide.next(selector.side) 10303 : $clone.find(selector.side).first(), 10304 newSize = {} 10305 ; 10306 $activeSide.removeClass(className.active); 10307 $nextSide.addClass(className.active); 10308 $clone.insertAfter($module); 10309 newSize = { 10310 width : $nextSide.outerWidth(), 10311 height : $nextSide.outerHeight() 10312 }; 10313 $clone.remove(); 10314 $module 10315 .css(newSize) 10316 ; 10317 module.verbose('Resizing stage to fit new content', newSize); 10318 }, 10319 10320 nextSide: function(selector) { 10321 nextIndex = selector; 10322 $nextSide = $side.filter(selector); 10323 nextIndex = $side.index($nextSide); 10324 if($nextSide.length === 0) { 10325 module.set.defaultSide(); 10326 module.error(error.side); 10327 } 10328 module.verbose('Next side manually set to', $nextSide); 10329 }, 10330 10331 active: function() { 10332 module.verbose('Setting new side to active', $nextSide); 10333 $side 10334 .removeClass(className.active) 10335 ; 10336 $nextSide 10337 .addClass(className.active) 10338 ; 10339 settings.onChange.call($nextSide.get()); 10340 module.set.defaultSide(); 10341 } 10342 }, 10343 10344 flip: { 10345 10346 up: function() { 10347 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) { 10348 module.debug('Side already visible', $nextSide); 10349 return; 10350 } 10351 if( !module.is.animating()) { 10352 module.debug('Flipping up', $nextSide); 10353 module.set.stageSize(); 10354 module.stage.above(); 10355 module.animate( module.get.transform.up() ); 10356 } 10357 else { 10358 module.queue('flip up'); 10359 } 10360 }, 10361 10362 down: function() { 10363 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) { 10364 module.debug('Side already visible', $nextSide); 10365 return; 10366 } 10367 if( !module.is.animating()) { 10368 module.debug('Flipping down', $nextSide); 10369 module.set.stageSize(); 10370 module.stage.below(); 10371 module.animate( module.get.transform.down() ); 10372 } 10373 else { 10374 module.queue('flip down'); 10375 } 10376 }, 10377 10378 left: function() { 10379 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) { 10380 module.debug('Side already visible', $nextSide); 10381 return; 10382 } 10383 if( !module.is.animating()) { 10384 module.debug('Flipping left', $nextSide); 10385 module.set.stageSize(); 10386 module.stage.left(); 10387 module.animate(module.get.transform.left() ); 10388 } 10389 else { 10390 module.queue('flip left'); 10391 } 10392 }, 10393 10394 right: function() { 10395 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) { 10396 module.debug('Side already visible', $nextSide); 10397 return; 10398 } 10399 if( !module.is.animating()) { 10400 module.debug('Flipping right', $nextSide); 10401 module.set.stageSize(); 10402 module.stage.right(); 10403 module.animate(module.get.transform.right() ); 10404 } 10405 else { 10406 module.queue('flip right'); 10407 } 10408 }, 10409 10410 over: function() { 10411 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) { 10412 module.debug('Side already visible', $nextSide); 10413 return; 10414 } 10415 if( !module.is.animating()) { 10416 module.debug('Flipping over', $nextSide); 10417 module.set.stageSize(); 10418 module.stage.behind(); 10419 module.animate(module.get.transform.over() ); 10420 } 10421 else { 10422 module.queue('flip over'); 10423 } 10424 }, 10425 10426 back: function() { 10427 if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) { 10428 module.debug('Side already visible', $nextSide); 10429 return; 10430 } 10431 if( !module.is.animating()) { 10432 module.debug('Flipping back', $nextSide); 10433 module.set.stageSize(); 10434 module.stage.behind(); 10435 module.animate(module.get.transform.back() ); 10436 } 10437 else { 10438 module.queue('flip back'); 10439 } 10440 } 10441 10442 }, 10443 10444 get: { 10445 10446 transform: { 10447 up: function() { 10448 var 10449 translate = { 10450 y: -(($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), 10451 z: -($activeSide.outerHeight() / 2) 10452 } 10453 ; 10454 return { 10455 transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)' 10456 }; 10457 }, 10458 10459 down: function() { 10460 var 10461 translate = { 10462 y: -(($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), 10463 z: -($activeSide.outerHeight() / 2) 10464 } 10465 ; 10466 return { 10467 transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)' 10468 }; 10469 }, 10470 10471 left: function() { 10472 var 10473 translate = { 10474 x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2), 10475 z : -($activeSide.outerWidth() / 2) 10476 } 10477 ; 10478 return { 10479 transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)' 10480 }; 10481 }, 10482 10483 right: function() { 10484 var 10485 translate = { 10486 x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2), 10487 z : -($activeSide.outerWidth() / 2) 10488 } 10489 ; 10490 return { 10491 transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)' 10492 }; 10493 }, 10494 10495 over: function() { 10496 var 10497 translate = { 10498 x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2) 10499 } 10500 ; 10501 return { 10502 transform: 'translateX(' + translate.x + 'px) rotateY(180deg)' 10503 }; 10504 }, 10505 10506 back: function() { 10507 var 10508 translate = { 10509 x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2) 10510 } 10511 ; 10512 return { 10513 transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)' 10514 }; 10515 } 10516 }, 10517 10518 transitionEvent: function() { 10519 var 10520 element = document.createElement('element'), 10521 transitions = { 10522 'transition' :'transitionend', 10523 'OTransition' :'oTransitionEnd', 10524 'MozTransition' :'transitionend', 10525 'WebkitTransition' :'webkitTransitionEnd' 10526 }, 10527 transition 10528 ; 10529 for(transition in transitions){ 10530 if( element.style[transition] !== undefined ){ 10531 return transitions[transition]; 10532 } 10533 } 10534 }, 10535 10536 nextSide: function() { 10537 return ( $activeSide.next(selector.side).length > 0 ) 10538 ? $activeSide.next(selector.side) 10539 : $module.find(selector.side).first() 10540 ; 10541 } 10542 10543 }, 10544 10545 stage: { 10546 10547 above: function() { 10548 var 10549 box = { 10550 origin : (($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), 10551 depth : { 10552 active : ($nextSide.outerHeight() / 2), 10553 next : ($activeSide.outerHeight() / 2) 10554 } 10555 } 10556 ; 10557 module.verbose('Setting the initial animation position as above', $nextSide, box); 10558 $activeSide 10559 .css({ 10560 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' 10561 }) 10562 ; 10563 $nextSide 10564 .addClass(className.animating) 10565 .css({ 10566 'display' : 'block', 10567 'top' : box.origin + 'px', 10568 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)' 10569 }) 10570 ; 10571 }, 10572 10573 below: function() { 10574 var 10575 box = { 10576 origin : (($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), 10577 depth : { 10578 active : ($nextSide.outerHeight() / 2), 10579 next : ($activeSide.outerHeight() / 2) 10580 } 10581 } 10582 ; 10583 module.verbose('Setting the initial animation position as below', $nextSide, box); 10584 $activeSide 10585 .css({ 10586 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' 10587 }) 10588 ; 10589 $nextSide 10590 .addClass(className.animating) 10591 .css({ 10592 'display' : 'block', 10593 'top' : box.origin + 'px', 10594 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)' 10595 }) 10596 ; 10597 }, 10598 10599 left: function() { 10600 var 10601 box = { 10602 origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), 10603 depth : { 10604 active : ($nextSide.outerWidth() / 2), 10605 next : ($activeSide.outerWidth() / 2) 10606 } 10607 } 10608 ; 10609 module.verbose('Setting the initial animation position as left', $nextSide, box); 10610 $activeSide 10611 .css({ 10612 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' 10613 }) 10614 ; 10615 $nextSide 10616 .addClass(className.animating) 10617 .css({ 10618 'display' : 'block', 10619 'left' : box.origin + 'px', 10620 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)' 10621 }) 10622 ; 10623 }, 10624 10625 right: function() { 10626 var 10627 box = { 10628 origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), 10629 depth : { 10630 active : ($nextSide.outerWidth() / 2), 10631 next : ($activeSide.outerWidth() / 2) 10632 } 10633 } 10634 ; 10635 module.verbose('Setting the initial animation position as left', $nextSide, box); 10636 $activeSide 10637 .css({ 10638 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' 10639 }) 10640 ; 10641 $nextSide 10642 .addClass(className.animating) 10643 .css({ 10644 'display' : 'block', 10645 'left' : box.origin + 'px', 10646 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)' 10647 }) 10648 ; 10649 }, 10650 10651 behind: function() { 10652 var 10653 box = { 10654 origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), 10655 depth : { 10656 active : ($nextSide.outerWidth() / 2), 10657 next : ($activeSide.outerWidth() / 2) 10658 } 10659 } 10660 ; 10661 module.verbose('Setting the initial animation position as behind', $nextSide, box); 10662 $activeSide 10663 .css({ 10664 'transform' : 'rotateY(0deg)' 10665 }) 10666 ; 10667 $nextSide 10668 .addClass(className.animating) 10669 .css({ 10670 'display' : 'block', 10671 'left' : box.origin + 'px', 10672 'transform' : 'rotateY(-180deg)' 10673 }) 10674 ; 10675 } 10676 }, 10677 setting: function(name, value) { 10678 module.debug('Changing setting', name, value); 10679 if( $.isPlainObject(name) ) { 10680 $.extend(true, settings, name); 10681 } 10682 else if(value !== undefined) { 10683 settings[name] = value; 10684 } 10685 else { 10686 return settings[name]; 10687 } 10688 }, 10689 internal: function(name, value) { 10690 if( $.isPlainObject(name) ) { 10691 $.extend(true, module, name); 10692 } 10693 else if(value !== undefined) { 10694 module[name] = value; 10695 } 10696 else { 10697 return module[name]; 10698 } 10699 }, 10700 debug: function() { 10701 if(settings.debug) { 10702 if(settings.performance) { 10703 module.performance.log(arguments); 10704 } 10705 else { 10706 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 10707 module.debug.apply(console, arguments); 10708 } 10709 } 10710 }, 10711 verbose: function() { 10712 if(settings.verbose && settings.debug) { 10713 if(settings.performance) { 10714 module.performance.log(arguments); 10715 } 10716 else { 10717 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 10718 module.verbose.apply(console, arguments); 10719 } 10720 } 10721 }, 10722 error: function() { 10723 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 10724 module.error.apply(console, arguments); 10725 }, 10726 performance: { 10727 log: function(message) { 10728 var 10729 currentTime, 10730 executionTime, 10731 previousTime 10732 ; 10733 if(settings.performance) { 10734 currentTime = new Date().getTime(); 10735 previousTime = time || currentTime; 10736 executionTime = currentTime - previousTime; 10737 time = currentTime; 10738 performance.push({ 10739 'Name' : message[0], 10740 'Arguments' : [].slice.call(message, 1) || '', 10741 'Element' : element, 10742 'Execution Time' : executionTime 10743 }); 10744 } 10745 clearTimeout(module.performance.timer); 10746 module.performance.timer = setTimeout(module.performance.display, 100); 10747 }, 10748 display: function() { 10749 var 10750 title = settings.name + ':', 10751 totalTime = 0 10752 ; 10753 time = false; 10754 clearTimeout(module.performance.timer); 10755 $.each(performance, function(index, data) { 10756 totalTime += data['Execution Time']; 10757 }); 10758 title += ' ' + totalTime + 'ms'; 10759 if(moduleSelector) { 10760 title += ' \'' + moduleSelector + '\''; 10761 } 10762 if($allModules.length > 1) { 10763 title += ' ' + '(' + $allModules.length + ')'; 10764 } 10765 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 10766 console.groupCollapsed(title); 10767 if(console.table) { 10768 console.table(performance); 10769 } 10770 else { 10771 $.each(performance, function(index, data) { 10772 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 10773 }); 10774 } 10775 console.groupEnd(); 10776 } 10777 performance = []; 10778 } 10779 }, 10780 invoke: function(query, passedArguments, context) { 10781 var 10782 object = instance, 10783 maxDepth, 10784 found, 10785 response 10786 ; 10787 passedArguments = passedArguments || queryArguments; 10788 context = element || context; 10789 if(typeof query == 'string' && object !== undefined) { 10790 query = query.split(/[\. ]/); 10791 maxDepth = query.length - 1; 10792 $.each(query, function(depth, value) { 10793 var camelCaseValue = (depth != maxDepth) 10794 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 10795 : query 10796 ; 10797 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 10798 object = object[camelCaseValue]; 10799 } 10800 else if( object[camelCaseValue] !== undefined ) { 10801 found = object[camelCaseValue]; 10802 return false; 10803 } 10804 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 10805 object = object[value]; 10806 } 10807 else if( object[value] !== undefined ) { 10808 found = object[value]; 10809 return false; 10810 } 10811 else { 10812 return false; 10813 } 10814 }); 10815 } 10816 if ( $.isFunction( found ) ) { 10817 response = found.apply(context, passedArguments); 10818 } 10819 else if(found !== undefined) { 10820 response = found; 10821 } 10822 if($.isArray(returnedValue)) { 10823 returnedValue.push(response); 10824 } 10825 else if(returnedValue !== undefined) { 10826 returnedValue = [returnedValue, response]; 10827 } 10828 else if(response !== undefined) { 10829 returnedValue = response; 10830 } 10831 return found; 10832 } 10833 }; 10834 10835 if(methodInvoked) { 10836 if(instance === undefined) { 10837 module.initialize(); 10838 } 10839 module.invoke(query); 10840 } 10841 else { 10842 if(instance !== undefined) { 10843 instance.invoke('destroy'); 10844 } 10845 module.initialize(); 10846 } 10847 }) 10848 ; 10849 10850 return (returnedValue !== undefined) 10851 ? returnedValue 10852 : this 10853 ; 10854 }; 10855 10856 $.fn.shape.settings = { 10857 10858 // module info 10859 name : 'Shape', 10860 10861 // debug content outputted to console 10862 debug : false, 10863 10864 // verbose debug output 10865 verbose : true, 10866 10867 // performance data output 10868 performance: true, 10869 10870 // event namespace 10871 namespace : 'shape', 10872 10873 // callback occurs on side change 10874 beforeChange : function() {}, 10875 onChange : function() {}, 10876 10877 // allow animation to same side 10878 allowRepeats: false, 10879 10880 // animation duration 10881 duration : 700, 10882 10883 // possible errors 10884 error: { 10885 side : 'You tried to switch to a side that does not exist.', 10886 method : 'The method you called is not defined' 10887 }, 10888 10889 // classnames used 10890 className : { 10891 animating : 'animating', 10892 hidden : 'hidden', 10893 loading : 'loading', 10894 active : 'active' 10895 }, 10896 10897 // selectors used 10898 selector : { 10899 sides : '.sides', 10900 side : '.side' 10901 } 10902 10903 }; 10904 10905 10906 })( jQuery, window , document ); 10907 /*! 10908 * # Semantic UI x.x - Sidebar 10909 * http://github.com/semantic-org/semantic-ui/ 10910 * 10911 * 10912 * Copyright 2014 Contributors 10913 * Released under the MIT license 10914 * http://opensource.org/licenses/MIT 10915 * 10916 */ 10917 10918 ;(function ( $, window, document, undefined ) { 10919 10920 "use strict"; 10921 10922 $.fn.sidebar = function(parameters) { 10923 var 10924 $allModules = $(this), 10925 $window = $(window), 10926 $document = $(document), 10927 $html = $('html'), 10928 $head = $('head'), 10929 10930 moduleSelector = $allModules.selector || '', 10931 10932 time = new Date().getTime(), 10933 performance = [], 10934 10935 query = arguments[0], 10936 methodInvoked = (typeof query == 'string'), 10937 queryArguments = [].slice.call(arguments, 1), 10938 10939 requestAnimationFrame = window.requestAnimationFrame 10940 || window.mozRequestAnimationFrame 10941 || window.webkitRequestAnimationFrame 10942 || window.msRequestAnimationFrame 10943 || function(callback) { setTimeout(callback, 0); }, 10944 10945 returnedValue 10946 ; 10947 10948 $allModules 10949 .each(function() { 10950 var 10951 settings = ( $.isPlainObject(parameters) ) 10952 ? $.extend(true, {}, $.fn.sidebar.settings, parameters) 10953 : $.extend({}, $.fn.sidebar.settings), 10954 10955 selector = settings.selector, 10956 className = settings.className, 10957 namespace = settings.namespace, 10958 regExp = settings.regExp, 10959 error = settings.error, 10960 10961 eventNamespace = '.' + namespace, 10962 moduleNamespace = 'module-' + namespace, 10963 10964 $module = $(this), 10965 $context = $(settings.context), 10966 10967 $sidebars = $module.children(selector.sidebar), 10968 $fixed = $context.children(selector.fixed), 10969 $pusher = $context.children(selector.pusher), 10970 $style, 10971 10972 element = this, 10973 instance = $module.data(moduleNamespace), 10974 10975 elementNamespace, 10976 id, 10977 currentScroll, 10978 transitionEvent, 10979 10980 module 10981 ; 10982 10983 module = { 10984 10985 initialize: function() { 10986 module.debug('Initializing sidebar', parameters); 10987 10988 module.create.id(); 10989 10990 transitionEvent = module.get.transitionEvent(); 10991 10992 // cache on initialize 10993 if( ( settings.useLegacy == 'auto' && module.is.legacy() ) || settings.useLegacy === true) { 10994 settings.transition = 'overlay'; 10995 settings.useLegacy = true; 10996 } 10997 10998 if(module.is.ios()) { 10999 module.set.ios(); 11000 } 11001 11002 // avoids locking rendering if initialized in onReady 11003 if(settings.delaySetup) { 11004 requestAnimationFrame(module.setup.layout); 11005 } 11006 else { 11007 module.setup.layout(); 11008 } 11009 11010 module.instantiate(); 11011 }, 11012 11013 instantiate: function() { 11014 module.verbose('Storing instance of module', module); 11015 instance = module; 11016 $module 11017 .data(moduleNamespace, module) 11018 ; 11019 }, 11020 11021 create: { 11022 id: function() { 11023 id = (Math.random().toString(16) + '000000000').substr(2,8); 11024 elementNamespace = '.' + id; 11025 module.verbose('Creating unique id for element', id); 11026 } 11027 }, 11028 11029 destroy: function() { 11030 module.verbose('Destroying previous module for', $module); 11031 module.remove.direction(); 11032 $module 11033 .off(eventNamespace) 11034 .removeData(moduleNamespace) 11035 ; 11036 // bound by uuid 11037 $context.off(elementNamespace); 11038 $window.off(elementNamespace); 11039 $document.off(elementNamespace); 11040 }, 11041 11042 event: { 11043 clickaway: function(event) { 11044 var 11045 clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)), 11046 clickedContext = ($context.is(event.target)) 11047 ; 11048 if(clickedInPusher) { 11049 module.verbose('User clicked on dimmed page'); 11050 module.hide(); 11051 } 11052 if(clickedContext) { 11053 module.verbose('User clicked on dimmable context (scaled out page)'); 11054 module.hide(); 11055 } 11056 }, 11057 touch: function(event) { 11058 //event.stopPropagation(); 11059 }, 11060 containScroll: function(event) { 11061 if(element.scrollTop <= 0) { 11062 element.scrollTop = 1; 11063 } 11064 if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) { 11065 element.scrollTop = element.scrollHeight - element.offsetHeight - 1; 11066 } 11067 }, 11068 scroll: function(event) { 11069 if( $(event.target).closest(selector.sidebar).length === 0 ) { 11070 event.preventDefault(); 11071 } 11072 } 11073 }, 11074 11075 bind: { 11076 clickaway: function() { 11077 module.verbose('Adding clickaway events to context', $context); 11078 if(settings.closable) { 11079 $context 11080 .on('click' + elementNamespace, module.event.clickaway) 11081 .on('touchend' + elementNamespace, module.event.clickaway) 11082 ; 11083 } 11084 }, 11085 scrollLock: function() { 11086 if(settings.scrollLock) { 11087 module.debug('Disabling page scroll'); 11088 $window 11089 .on('DOMMouseScroll' + elementNamespace, module.event.scroll) 11090 ; 11091 } 11092 module.verbose('Adding events to contain sidebar scroll'); 11093 $document 11094 .on('touchmove' + elementNamespace, module.event.touch) 11095 ; 11096 $module 11097 .on('scroll' + eventNamespace, module.event.containScroll) 11098 ; 11099 } 11100 }, 11101 unbind: { 11102 clickaway: function() { 11103 module.verbose('Removing clickaway events from context', $context); 11104 $context.off(elementNamespace); 11105 }, 11106 scrollLock: function() { 11107 module.verbose('Removing scroll lock from page'); 11108 $document.off(elementNamespace); 11109 $window.off(elementNamespace); 11110 $module.off('scroll' + eventNamespace); 11111 } 11112 }, 11113 11114 add: { 11115 bodyCSS: function() { 11116 var 11117 width = $module.outerWidth(), 11118 height = $module.outerHeight(), 11119 direction = module.get.direction(), 11120 distance = { 11121 left : width, 11122 right : -width, 11123 top : height, 11124 bottom : -height 11125 }, 11126 style 11127 ; 11128 if( module.is.rtl() ){ 11129 module.verbose('RTL detected, flipping widths'); 11130 distance.left = -width; 11131 distance.right = width; 11132 } 11133 11134 style = '<style title="' + namespace + '">'; 11135 11136 if(direction === 'left' || direction === 'right') { 11137 module.debug('Adding CSS rules for animation distance', width); 11138 style += '' 11139 + ' .ui.visible.' + direction + '.sidebar ~ .fixed,' 11140 + ' .ui.visible.' + direction + '.sidebar ~ .pusher {' 11141 + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);' 11142 + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);' 11143 + ' }' 11144 ; 11145 } 11146 else if(direction === 'top' || direction == 'bottom') { 11147 style += '' 11148 + ' .ui.visible.' + direction + '.sidebar ~ .fixed,' 11149 + ' .ui.visible.' + direction + '.sidebar ~ .pusher {' 11150 + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);' 11151 + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);' 11152 + ' }' 11153 ; 11154 } 11155 11156 /* IE is only browser not to create context with transforms */ 11157 /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */ 11158 if( module.is.ie() ) { 11159 if(direction === 'left' || direction === 'right') { 11160 module.debug('Adding CSS rules for animation distance', width); 11161 style += '' 11162 + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {' 11163 + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);' 11164 + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);' 11165 + ' }' 11166 ; 11167 } 11168 else if(direction === 'top' || direction == 'bottom') { 11169 style += '' 11170 + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {' 11171 + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);' 11172 + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);' 11173 + ' }' 11174 ; 11175 } 11176 /* opposite sides visible forces content overlay */ 11177 style += '' 11178 + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,' 11179 + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {' 11180 + ' -webkit-transform: translate3d(0px, 0, 0);' 11181 + ' transform: translate3d(0px, 0, 0);' 11182 + ' }' 11183 ; 11184 } 11185 style += '</style>'; 11186 $head.append(style); 11187 $style = $('style[title=' + namespace + ']'); 11188 module.debug('Adding sizing css to head', $style); 11189 } 11190 }, 11191 11192 refresh: function() { 11193 module.verbose('Refreshing selector cache'); 11194 $context = $(settings.context); 11195 $sidebars = $context.children(selector.sidebar); 11196 $pusher = $context.children(selector.pusher); 11197 $fixed = $context.children(selector.fixed); 11198 }, 11199 11200 refreshSidebars: function() { 11201 module.verbose('Refreshing other sidebars'); 11202 $sidebars = $context.children(selector.sidebar); 11203 }, 11204 11205 repaint: function() { 11206 module.verbose('Forcing repaint event'); 11207 element.style.display='none'; 11208 element.offsetHeight; 11209 element.scrollTop = element.scrollTop; 11210 element.style.display=''; 11211 }, 11212 11213 setup: { 11214 layout: function() { 11215 if( $context.children(selector.pusher).length === 0 ) { 11216 module.debug('Adding wrapper element for sidebar'); 11217 module.error(error.pusher); 11218 $pusher = $('<div class="pusher" />'); 11219 $context 11220 .children() 11221 .not(selector.omitted) 11222 .not($sidebars) 11223 .wrapAll($pusher) 11224 ; 11225 module.refresh(); 11226 } 11227 if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) { 11228 module.debug('Moved sidebar to correct parent element'); 11229 module.error(error.movedSidebar, element); 11230 $module.detach().prependTo($context); 11231 module.refresh(); 11232 } 11233 module.set.pushable(); 11234 module.set.direction(); 11235 } 11236 }, 11237 11238 attachEvents: function(selector, event) { 11239 var 11240 $toggle = $(selector) 11241 ; 11242 event = $.isFunction(module[event]) 11243 ? module[event] 11244 : module.toggle 11245 ; 11246 if($toggle.length > 0) { 11247 module.debug('Attaching sidebar events to element', selector, event); 11248 $toggle 11249 .on('click' + eventNamespace, event) 11250 ; 11251 } 11252 else { 11253 module.error(error.notFound, selector); 11254 } 11255 }, 11256 11257 show: function(callback) { 11258 var 11259 animateMethod = (settings.useLegacy === true) 11260 ? module.legacyPushPage 11261 : module.pushPage 11262 ; 11263 callback = $.isFunction(callback) 11264 ? callback 11265 : function(){} 11266 ; 11267 if(module.is.hidden()) { 11268 module.refreshSidebars(); 11269 if(settings.overlay) { 11270 module.error(error.overlay); 11271 settings.transition = 'overlay'; 11272 } 11273 module.refresh(); 11274 if(module.othersActive()) { 11275 module.debug('Other sidebars currently visible'); 11276 if(settings.exclusive) { 11277 // if not overlay queue animation after hide 11278 if(settings.transition != 'overlay') { 11279 module.hideOthers(module.show); 11280 return; 11281 } 11282 else { 11283 module.hideOthers(); 11284 } 11285 } 11286 else { 11287 settings.transition = 'overlay'; 11288 } 11289 } 11290 animateMethod(function() { 11291 callback.call(element); 11292 settings.onShow.call(element); 11293 }); 11294 settings.onChange.call(element); 11295 settings.onVisible.call(element); 11296 } 11297 else { 11298 module.debug('Sidebar is already visible'); 11299 } 11300 }, 11301 11302 hide: function(callback) { 11303 var 11304 animateMethod = (settings.useLegacy === true) 11305 ? module.legacyPullPage 11306 : module.pullPage 11307 ; 11308 callback = $.isFunction(callback) 11309 ? callback 11310 : function(){} 11311 ; 11312 if(module.is.visible() || module.is.animating()) { 11313 module.debug('Hiding sidebar', callback); 11314 module.refreshSidebars(); 11315 animateMethod(function() { 11316 callback.call(element); 11317 settings.onHidden.call(element); 11318 }); 11319 settings.onChange.call(element); 11320 settings.onHide.call(element); 11321 } 11322 }, 11323 11324 othersAnimating: function() { 11325 return ($sidebars.not($module).filter('.' + className.animating).length > 0); 11326 }, 11327 othersVisible: function() { 11328 return ($sidebars.not($module).filter('.' + className.visible).length > 0); 11329 }, 11330 othersActive: function() { 11331 return(module.othersVisible() || module.othersAnimating()); 11332 }, 11333 11334 hideOthers: function(callback) { 11335 var 11336 $otherSidebars = $sidebars.not($module).filter('.' + className.visible), 11337 sidebarCount = $otherSidebars.length, 11338 callbackCount = 0 11339 ; 11340 callback = callback || function(){}; 11341 $otherSidebars 11342 .sidebar('hide', function() { 11343 callbackCount++; 11344 if(callbackCount == sidebarCount) { 11345 callback(); 11346 } 11347 }) 11348 ; 11349 }, 11350 11351 toggle: function() { 11352 module.verbose('Determining toggled direction'); 11353 if(module.is.hidden()) { 11354 module.show(); 11355 } 11356 else { 11357 module.hide(); 11358 } 11359 }, 11360 11361 pushPage: function(callback) { 11362 var 11363 transition = module.get.transition(), 11364 $transition = (transition == 'safe') 11365 ? $context 11366 : (transition === 'overlay' || module.othersActive()) 11367 ? $module 11368 : $pusher, 11369 animate, 11370 transitionEnd 11371 ; 11372 callback = $.isFunction(callback) 11373 ? callback 11374 : function(){} 11375 ; 11376 if(settings.transition == 'scale down') { 11377 module.scrollToTop(); 11378 } 11379 module.set.transition(transition); 11380 module.repaint(); 11381 animate = function() { 11382 module.bind.clickaway(); 11383 module.add.bodyCSS(); 11384 module.set.animating(); 11385 module.set.visible(); 11386 if(!module.othersVisible()) { 11387 if(settings.dimPage) { 11388 $pusher.addClass(className.dimmed); 11389 } 11390 } 11391 }; 11392 transitionEnd = function(event) { 11393 if( event.target == $transition[0] ) { 11394 $transition.off(transitionEvent + elementNamespace, transitionEnd); 11395 module.remove.animating(); 11396 module.bind.scrollLock(); 11397 callback.call(element); 11398 } 11399 }; 11400 $transition.off(transitionEvent + elementNamespace); 11401 $transition.on(transitionEvent + elementNamespace, transitionEnd); 11402 requestAnimationFrame(animate); 11403 }, 11404 11405 pullPage: function(callback) { 11406 var 11407 transition = module.get.transition(), 11408 $transition = (transition == 'safe') 11409 ? $context 11410 : (transition == 'overlay' || module.othersActive()) 11411 ? $module 11412 : $pusher, 11413 animate, 11414 transitionEnd 11415 ; 11416 callback = $.isFunction(callback) 11417 ? callback 11418 : function(){} 11419 ; 11420 module.verbose('Removing context push state', module.get.direction()); 11421 11422 module.set.transition(transition); 11423 module.unbind.clickaway(); 11424 module.unbind.scrollLock(); 11425 11426 animate = function() { 11427 module.set.animating(); 11428 module.remove.visible(); 11429 if(settings.dimPage && !module.othersVisible()) { 11430 $pusher.removeClass(className.dimmed); 11431 } 11432 }; 11433 transitionEnd = function(event) { 11434 if( event.target == $transition[0] ) { 11435 $transition.off(transitionEvent + elementNamespace, transitionEnd); 11436 module.remove.animating(); 11437 module.remove.transition(); 11438 module.remove.bodyCSS(); 11439 if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) { 11440 module.scrollBack(); 11441 } 11442 callback.call(element); 11443 } 11444 }; 11445 $transition.off(transitionEvent + elementNamespace); 11446 $transition.on(transitionEvent + elementNamespace, transitionEnd); 11447 requestAnimationFrame(animate); 11448 }, 11449 11450 legacyPushPage: function(callback) { 11451 var 11452 distance = $module.width(), 11453 direction = module.get.direction(), 11454 properties = {} 11455 ; 11456 distance = distance || $module.width(); 11457 callback = $.isFunction(callback) 11458 ? callback 11459 : function(){} 11460 ; 11461 properties[direction] = distance; 11462 module.debug('Using javascript to push context', properties); 11463 module.set.visible(); 11464 module.set.transition(); 11465 module.set.animating(); 11466 if(settings.dimPage) { 11467 $pusher.addClass(className.dimmed); 11468 } 11469 $context 11470 .css('position', 'relative') 11471 .animate(properties, settings.duration, settings.easing, function() { 11472 module.remove.animating(); 11473 module.bind.clickaway(); 11474 callback.call(element); 11475 }) 11476 ; 11477 }, 11478 legacyPullPage: function(callback) { 11479 var 11480 distance = 0, 11481 direction = module.get.direction(), 11482 properties = {} 11483 ; 11484 distance = distance || $module.width(); 11485 callback = $.isFunction(callback) 11486 ? callback 11487 : function(){} 11488 ; 11489 properties[direction] = '0px'; 11490 module.debug('Using javascript to pull context', properties); 11491 module.unbind.clickaway(); 11492 module.set.animating(); 11493 module.remove.visible(); 11494 if(settings.dimPage && !module.othersActive()) { 11495 $pusher.removeClass(className.dimmed); 11496 } 11497 $context 11498 .css('position', 'relative') 11499 .animate(properties, settings.duration, settings.easing, function() { 11500 module.remove.animating(); 11501 callback.call(element); 11502 }) 11503 ; 11504 }, 11505 11506 scrollToTop: function() { 11507 module.verbose('Scrolling to top of page to avoid animation issues'); 11508 currentScroll = $(window).scrollTop(); 11509 $module.scrollTop(0); 11510 window.scrollTo(0, 0); 11511 }, 11512 11513 scrollBack: function() { 11514 module.verbose('Scrolling back to original page position'); 11515 window.scrollTo(0, currentScroll); 11516 }, 11517 11518 set: { 11519 // html 11520 ios: function() { 11521 $html.addClass(className.ios); 11522 }, 11523 11524 // container 11525 pushed: function() { 11526 $context.addClass(className.pushed); 11527 }, 11528 pushable: function() { 11529 $context.addClass(className.pushable); 11530 }, 11531 11532 // sidebar 11533 active: function() { 11534 $module.addClass(className.active); 11535 }, 11536 animating: function() { 11537 $module.addClass(className.animating); 11538 }, 11539 transition: function(transition) { 11540 transition = transition || module.get.transition(); 11541 $module.addClass(transition); 11542 }, 11543 direction: function(direction) { 11544 direction = direction || module.get.direction(); 11545 $module.addClass(className[direction]); 11546 }, 11547 visible: function() { 11548 $module.addClass(className.visible); 11549 }, 11550 overlay: function() { 11551 $module.addClass(className.overlay); 11552 } 11553 }, 11554 remove: { 11555 11556 bodyCSS: function() { 11557 module.debug('Removing body css styles', $style); 11558 if($style && $style.length > 0) { 11559 $style.remove(); 11560 } 11561 }, 11562 11563 // context 11564 pushed: function() { 11565 $context.removeClass(className.pushed); 11566 }, 11567 pushable: function() { 11568 $context.removeClass(className.pushable); 11569 }, 11570 11571 // sidebar 11572 active: function() { 11573 $module.removeClass(className.active); 11574 }, 11575 animating: function() { 11576 $module.removeClass(className.animating); 11577 }, 11578 transition: function(transition) { 11579 transition = transition || module.get.transition(); 11580 $module.removeClass(transition); 11581 }, 11582 direction: function(direction) { 11583 direction = direction || module.get.direction(); 11584 $module.removeClass(className[direction]); 11585 }, 11586 visible: function() { 11587 $module.removeClass(className.visible); 11588 }, 11589 overlay: function() { 11590 $module.removeClass(className.overlay); 11591 } 11592 }, 11593 11594 get: { 11595 direction: function() { 11596 if($module.hasClass(className.top)) { 11597 return className.top; 11598 } 11599 else if($module.hasClass(className.right)) { 11600 return className.right; 11601 } 11602 else if($module.hasClass(className.bottom)) { 11603 return className.bottom; 11604 } 11605 return className.left; 11606 }, 11607 transition: function() { 11608 var 11609 direction = module.get.direction(), 11610 transition 11611 ; 11612 transition = ( module.is.mobile() ) 11613 ? (settings.mobileTransition == 'auto') 11614 ? settings.defaultTransition.mobile[direction] 11615 : settings.mobileTransition 11616 : (settings.transition == 'auto') 11617 ? settings.defaultTransition.computer[direction] 11618 : settings.transition 11619 ; 11620 module.verbose('Determined transition', transition); 11621 return transition; 11622 }, 11623 transitionEvent: function() { 11624 var 11625 element = document.createElement('element'), 11626 transitions = { 11627 'transition' :'transitionend', 11628 'OTransition' :'oTransitionEnd', 11629 'MozTransition' :'transitionend', 11630 'WebkitTransition' :'webkitTransitionEnd' 11631 }, 11632 transition 11633 ; 11634 for(transition in transitions){ 11635 if( element.style[transition] !== undefined ){ 11636 return transitions[transition]; 11637 } 11638 } 11639 } 11640 }, 11641 11642 is: { 11643 11644 ie: function() { 11645 var 11646 isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window), 11647 isIE = ('ActiveXObject' in window) 11648 ; 11649 return (isIE11 || isIE); 11650 }, 11651 11652 legacy: function() { 11653 var 11654 element = document.createElement('div'), 11655 transforms = { 11656 'webkitTransform' :'-webkit-transform', 11657 'OTransform' :'-o-transform', 11658 'msTransform' :'-ms-transform', 11659 'MozTransform' :'-moz-transform', 11660 'transform' :'transform' 11661 }, 11662 has3D 11663 ; 11664 11665 // Add it to the body to get the computed style. 11666 document.body.insertBefore(element, null); 11667 for (var transform in transforms) { 11668 if (element.style[transform] !== undefined) { 11669 element.style[transform] = "translate3d(1px,1px,1px)"; 11670 has3D = window.getComputedStyle(element).getPropertyValue(transforms[transform]); 11671 } 11672 } 11673 document.body.removeChild(element); 11674 return !(has3D !== undefined && has3D.length > 0 && has3D !== 'none'); 11675 }, 11676 ios: function() { 11677 var 11678 userAgent = navigator.userAgent, 11679 isIOS = userAgent.match(regExp.ios) 11680 ; 11681 if(isIOS) { 11682 module.verbose('Browser was found to be iOS', userAgent); 11683 return true; 11684 } 11685 else { 11686 return false; 11687 } 11688 }, 11689 mobile: function() { 11690 var 11691 userAgent = navigator.userAgent, 11692 isMobile = userAgent.match(regExp.mobile) 11693 ; 11694 if(isMobile) { 11695 module.verbose('Browser was found to be mobile', userAgent); 11696 return true; 11697 } 11698 else { 11699 module.verbose('Browser is not mobile, using regular transition', userAgent); 11700 return false; 11701 } 11702 }, 11703 hidden: function() { 11704 return !module.is.visible(); 11705 }, 11706 visible: function() { 11707 return $module.hasClass(className.visible); 11708 }, 11709 // alias 11710 open: function() { 11711 return module.is.visible(); 11712 }, 11713 closed: function() { 11714 return module.is.hidden(); 11715 }, 11716 vertical: function() { 11717 return $module.hasClass(className.top); 11718 }, 11719 animating: function() { 11720 return $context.hasClass(className.animating); 11721 }, 11722 rtl: function () { 11723 return $module.css('direction') == 'rtl'; 11724 } 11725 }, 11726 11727 setting: function(name, value) { 11728 module.debug('Changing setting', name, value); 11729 if( $.isPlainObject(name) ) { 11730 $.extend(true, settings, name); 11731 } 11732 else if(value !== undefined) { 11733 settings[name] = value; 11734 } 11735 else { 11736 return settings[name]; 11737 } 11738 }, 11739 internal: function(name, value) { 11740 if( $.isPlainObject(name) ) { 11741 $.extend(true, module, name); 11742 } 11743 else if(value !== undefined) { 11744 module[name] = value; 11745 } 11746 else { 11747 return module[name]; 11748 } 11749 }, 11750 debug: function() { 11751 if(settings.debug) { 11752 if(settings.performance) { 11753 module.performance.log(arguments); 11754 } 11755 else { 11756 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 11757 module.debug.apply(console, arguments); 11758 } 11759 } 11760 }, 11761 verbose: function() { 11762 if(settings.verbose && settings.debug) { 11763 if(settings.performance) { 11764 module.performance.log(arguments); 11765 } 11766 else { 11767 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 11768 module.verbose.apply(console, arguments); 11769 } 11770 } 11771 }, 11772 error: function() { 11773 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 11774 module.error.apply(console, arguments); 11775 }, 11776 performance: { 11777 log: function(message) { 11778 var 11779 currentTime, 11780 executionTime, 11781 previousTime 11782 ; 11783 if(settings.performance) { 11784 currentTime = new Date().getTime(); 11785 previousTime = time || currentTime; 11786 executionTime = currentTime - previousTime; 11787 time = currentTime; 11788 performance.push({ 11789 'Name' : message[0], 11790 'Arguments' : [].slice.call(message, 1) || '', 11791 'Element' : element, 11792 'Execution Time' : executionTime 11793 }); 11794 } 11795 clearTimeout(module.performance.timer); 11796 module.performance.timer = setTimeout(module.performance.display, 100); 11797 }, 11798 display: function() { 11799 var 11800 title = settings.name + ':', 11801 totalTime = 0 11802 ; 11803 time = false; 11804 clearTimeout(module.performance.timer); 11805 $.each(performance, function(index, data) { 11806 totalTime += data['Execution Time']; 11807 }); 11808 title += ' ' + totalTime + 'ms'; 11809 if(moduleSelector) { 11810 title += ' \'' + moduleSelector + '\''; 11811 } 11812 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 11813 console.groupCollapsed(title); 11814 if(console.table) { 11815 console.table(performance); 11816 } 11817 else { 11818 $.each(performance, function(index, data) { 11819 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 11820 }); 11821 } 11822 console.groupEnd(); 11823 } 11824 performance = []; 11825 } 11826 }, 11827 invoke: function(query, passedArguments, context) { 11828 var 11829 object = instance, 11830 maxDepth, 11831 found, 11832 response 11833 ; 11834 passedArguments = passedArguments || queryArguments; 11835 context = element || context; 11836 if(typeof query == 'string' && object !== undefined) { 11837 query = query.split(/[\. ]/); 11838 maxDepth = query.length - 1; 11839 $.each(query, function(depth, value) { 11840 var camelCaseValue = (depth != maxDepth) 11841 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 11842 : query 11843 ; 11844 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 11845 object = object[camelCaseValue]; 11846 } 11847 else if( object[camelCaseValue] !== undefined ) { 11848 found = object[camelCaseValue]; 11849 return false; 11850 } 11851 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 11852 object = object[value]; 11853 } 11854 else if( object[value] !== undefined ) { 11855 found = object[value]; 11856 return false; 11857 } 11858 else { 11859 module.error(error.method, query); 11860 return false; 11861 } 11862 }); 11863 } 11864 if ( $.isFunction( found ) ) { 11865 response = found.apply(context, passedArguments); 11866 } 11867 else if(found !== undefined) { 11868 response = found; 11869 } 11870 if($.isArray(returnedValue)) { 11871 returnedValue.push(response); 11872 } 11873 else if(returnedValue !== undefined) { 11874 returnedValue = [returnedValue, response]; 11875 } 11876 else if(response !== undefined) { 11877 returnedValue = response; 11878 } 11879 return found; 11880 } 11881 } 11882 ; 11883 11884 if(methodInvoked) { 11885 if(instance === undefined) { 11886 module.initialize(); 11887 } 11888 module.invoke(query); 11889 } 11890 else { 11891 if(instance !== undefined) { 11892 module.invoke('destroy'); 11893 } 11894 module.initialize(); 11895 } 11896 }); 11897 11898 return (returnedValue !== undefined) 11899 ? returnedValue 11900 : this 11901 ; 11902 }; 11903 11904 $.fn.sidebar.settings = { 11905 11906 name : 'Sidebar', 11907 namespace : 'sidebar', 11908 11909 debug : false, 11910 verbose : true, 11911 performance : true, 11912 11913 transition : 'auto', 11914 mobileTransition : 'auto', 11915 11916 defaultTransition : { 11917 computer: { 11918 left : 'uncover', 11919 right : 'uncover', 11920 top : 'overlay', 11921 bottom : 'overlay' 11922 }, 11923 mobile: { 11924 left : 'uncover', 11925 right : 'uncover', 11926 top : 'overlay', 11927 bottom : 'overlay' 11928 } 11929 }, 11930 11931 context : 'body', 11932 exclusive : false, 11933 closable : true, 11934 dimPage : true, 11935 scrollLock : false, 11936 returnScroll : false, 11937 delaySetup : false, 11938 11939 useLegacy : 'auto', 11940 duration : 500, 11941 easing : 'easeInOutQuint', 11942 11943 onChange : function(){}, 11944 onShow : function(){}, 11945 onHide : function(){}, 11946 11947 onHidden : function(){}, 11948 onVisible : function(){}, 11949 11950 className : { 11951 active : 'active', 11952 animating : 'animating', 11953 dimmed : 'dimmed', 11954 ios : 'ios', 11955 pushable : 'pushable', 11956 pushed : 'pushed', 11957 right : 'right', 11958 top : 'top', 11959 left : 'left', 11960 bottom : 'bottom', 11961 visible : 'visible' 11962 }, 11963 11964 selector: { 11965 fixed : '.fixed', 11966 omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed', 11967 pusher : '.pusher', 11968 sidebar : '.ui.sidebar' 11969 }, 11970 11971 regExp: { 11972 ios : /(iPad|iPhone|iPod)/g, 11973 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 11974 }, 11975 11976 error : { 11977 method : 'The method you called is not defined.', 11978 pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element', 11979 movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag', 11980 overlay : 'The overlay setting is no longer supported, use animation: overlay', 11981 notFound : 'There were no elements that matched the specified selector' 11982 } 11983 11984 }; 11985 11986 // Adds easing 11987 $.extend( $.easing, { 11988 easeInOutQuint: function (x, t, b, c, d) { 11989 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 11990 return c/2*((t-=2)*t*t*t*t + 2) + b; 11991 } 11992 }); 11993 11994 11995 })( jQuery, window , document ); 11996 11997 /*! 11998 * # Semantic UI x.x - Sticky 11999 * http://github.com/semantic-org/semantic-ui/ 12000 * 12001 * 12002 * Copyright 2014 Contributorss 12003 * Released under the MIT license 12004 * http://opensource.org/licenses/MIT 12005 * 12006 */ 12007 12008 ;(function ( $, window, document, undefined ) { 12009 12010 "use strict"; 12011 12012 $.fn.sticky = function(parameters) { 12013 var 12014 $allModules = $(this), 12015 moduleSelector = $allModules.selector || '', 12016 12017 time = new Date().getTime(), 12018 performance = [], 12019 12020 query = arguments[0], 12021 methodInvoked = (typeof query == 'string'), 12022 queryArguments = [].slice.call(arguments, 1), 12023 returnedValue 12024 ; 12025 12026 $allModules 12027 .each(function() { 12028 var 12029 settings = ( $.isPlainObject(parameters) ) 12030 ? $.extend(true, {}, $.fn.sticky.settings, parameters) 12031 : $.extend({}, $.fn.sticky.settings), 12032 12033 className = settings.className, 12034 namespace = settings.namespace, 12035 error = settings.error, 12036 12037 eventNamespace = '.' + namespace, 12038 moduleNamespace = 'module-' + namespace, 12039 12040 $module = $(this), 12041 $window = $(window), 12042 $container = $module.offsetParent(), 12043 $scroll = $(settings.scrollContext), 12044 $context, 12045 12046 selector = $module.selector || '', 12047 instance = $module.data(moduleNamespace), 12048 12049 requestAnimationFrame = window.requestAnimationFrame 12050 || window.mozRequestAnimationFrame 12051 || window.webkitRequestAnimationFrame 12052 || window.msRequestAnimationFrame 12053 || function(callback) { setTimeout(callback, 0); }, 12054 12055 element = this, 12056 observer, 12057 module 12058 ; 12059 12060 module = { 12061 12062 initialize: function() { 12063 12064 module.determineContext(); 12065 module.verbose('Initializing sticky', settings, $container); 12066 12067 module.save.positions(); 12068 module.checkErrors(); 12069 module.bind.events(); 12070 12071 if(settings.observeChanges) { 12072 module.observeChanges(); 12073 } 12074 module.instantiate(); 12075 }, 12076 12077 instantiate: function() { 12078 module.verbose('Storing instance of module', module); 12079 instance = module; 12080 $module 12081 .data(moduleNamespace, module) 12082 ; 12083 }, 12084 12085 destroy: function() { 12086 module.verbose('Destroying previous module'); 12087 module.reset(); 12088 if(observer) { 12089 observer.disconnect(); 12090 } 12091 $window.off('resize' + eventNamespace, module.event.resize); 12092 $scroll.off('scroll' + eventNamespace, module.event.scroll); 12093 $module.removeData(moduleNamespace); 12094 }, 12095 12096 observeChanges: function() { 12097 var 12098 context = $context[0] 12099 ; 12100 if('MutationObserver' in window) { 12101 observer = new MutationObserver(function(mutations) { 12102 clearTimeout(module.timer); 12103 module.timer = setTimeout(function() { 12104 module.verbose('DOM tree modified, updating sticky menu'); 12105 module.refresh(); 12106 }, 20); 12107 }); 12108 observer.observe(element, { 12109 childList : true, 12110 subtree : true 12111 }); 12112 observer.observe(context, { 12113 childList : true, 12114 subtree : true 12115 }); 12116 module.debug('Setting up mutation observer', observer); 12117 } 12118 }, 12119 12120 determineContext: function() { 12121 if(settings.context) { 12122 $context = $(settings.context); 12123 } 12124 else { 12125 $context = $container; 12126 } 12127 if($context.length === 0) { 12128 module.error(error.invalidContext, settings.context, $module); 12129 return; 12130 } 12131 }, 12132 12133 checkErrors: function() { 12134 if( module.is.hidden() ) { 12135 module.error(error.visible, $module); 12136 } 12137 if(module.cache.element.height > module.cache.context.height) { 12138 module.reset(); 12139 module.error(error.elementSize, $module); 12140 return; 12141 } 12142 }, 12143 12144 bind: { 12145 events: function() { 12146 $window.on('resize' + eventNamespace, module.event.resize); 12147 $scroll.on('scroll' + eventNamespace, module.event.scroll); 12148 } 12149 }, 12150 12151 event: { 12152 resize: function() { 12153 requestAnimationFrame(function() { 12154 module.refresh(); 12155 module.stick(); 12156 }); 12157 }, 12158 scroll: function() { 12159 requestAnimationFrame(function() { 12160 module.stick(); 12161 settings.onScroll.call(element); 12162 }); 12163 } 12164 }, 12165 12166 refresh: function(hardRefresh) { 12167 module.reset(); 12168 if(hardRefresh) { 12169 $container = $module.offsetParent(); 12170 } 12171 module.save.positions(); 12172 module.stick(); 12173 settings.onReposition.call(element); 12174 }, 12175 12176 supports: { 12177 sticky: function() { 12178 var 12179 $element = $('<div/>'), 12180 element = $element.get() 12181 ; 12182 $element.addClass(className.supported); 12183 return($element.css('position').match('sticky')); 12184 } 12185 }, 12186 12187 save: { 12188 scroll: function(scroll) { 12189 module.lastScroll = scroll; 12190 }, 12191 positions: function() { 12192 var 12193 window = { 12194 height: $window.height() 12195 }, 12196 element = { 12197 margin: { 12198 top : parseInt($module.css('margin-top'), 10), 12199 bottom : parseInt($module.css('margin-bottom'), 10), 12200 }, 12201 offset : $module.offset(), 12202 width : $module.outerWidth(), 12203 height : $module.outerHeight() 12204 }, 12205 context = { 12206 offset : $context.offset(), 12207 height : $context.outerHeight(), 12208 bottomPadding : parseInt($context.css('padding-bottom'), 10) 12209 } 12210 ; 12211 module.cache = { 12212 fits : ( element.height < window.height ), 12213 window: { 12214 height: window.height 12215 }, 12216 element: { 12217 margin : element.margin, 12218 top : element.offset.top - element.margin.top, 12219 left : element.offset.left, 12220 width : element.width, 12221 height : element.height, 12222 bottom : element.offset.top + element.height 12223 }, 12224 context: { 12225 top : context.offset.top, 12226 height : context.height, 12227 bottomPadding : context.bottomPadding, 12228 bottom : context.offset.top + context.height - context.bottomPadding 12229 } 12230 }; 12231 module.set.containerSize(); 12232 module.set.size(); 12233 module.stick(); 12234 module.debug('Caching element positions', module.cache); 12235 } 12236 }, 12237 12238 get: { 12239 direction: function(scroll) { 12240 var 12241 direction = 'down' 12242 ; 12243 scroll = scroll || $scroll.scrollTop(); 12244 if(module.lastScroll !== undefined) { 12245 if(module.lastScroll < scroll) { 12246 direction = 'down'; 12247 } 12248 else if(module.lastScroll > scroll) { 12249 direction = 'up'; 12250 } 12251 } 12252 return direction; 12253 }, 12254 scrollChange: function(scroll) { 12255 scroll = scroll || $scroll.scrollTop(); 12256 return (module.lastScroll) 12257 ? (scroll - module.lastScroll) 12258 : 0 12259 ; 12260 }, 12261 currentElementScroll: function() { 12262 return ( module.is.top() ) 12263 ? Math.abs(parseInt($module.css('top'), 10)) || 0 12264 : Math.abs(parseInt($module.css('bottom'), 10)) || 0 12265 ; 12266 }, 12267 elementScroll: function(scroll) { 12268 scroll = scroll || $scroll.scrollTop(); 12269 var 12270 element = module.cache.element, 12271 window = module.cache.window, 12272 delta = module.get.scrollChange(scroll), 12273 maxScroll = (element.height - window.height + settings.offset), 12274 currentScroll = module.get.currentElementScroll(), 12275 possibleScroll = (currentScroll + delta), 12276 elementScroll 12277 ; 12278 if(module.cache.fits || possibleScroll < 0) { 12279 elementScroll = 0; 12280 } 12281 else if (possibleScroll > maxScroll ) { 12282 elementScroll = maxScroll; 12283 } 12284 else { 12285 elementScroll = possibleScroll; 12286 } 12287 return elementScroll; 12288 } 12289 }, 12290 12291 remove: { 12292 offset: function() { 12293 $module.css('margin-top', ''); 12294 } 12295 }, 12296 12297 set: { 12298 offset: function() { 12299 module.verbose('Setting offset on element', settings.offset); 12300 $module.css('margin-top', settings.offset); 12301 }, 12302 containerSize: function() { 12303 var 12304 tagName = $container.get(0).tagName 12305 ; 12306 if(tagName === 'HTML' || tagName == 'body') { 12307 // this can trigger for too many reasons 12308 //module.error(error.container, tagName, $module); 12309 $container = $module.offsetParent(); 12310 } 12311 else { 12312 module.debug('Settings container size', module.cache.context.height); 12313 if( Math.abs($container.height() - module.cache.context.height) > 5) { 12314 $container.css({ 12315 height: module.cache.context.height 12316 }); 12317 } 12318 } 12319 }, 12320 scroll: function(scroll) { 12321 module.debug('Setting scroll on element', scroll); 12322 if( module.is.top() ) { 12323 $module 12324 .css('bottom', '') 12325 .css('top', -scroll) 12326 ; 12327 } 12328 if( module.is.bottom() ) { 12329 $module 12330 .css('top', '') 12331 .css('bottom', scroll) 12332 ; 12333 } 12334 }, 12335 size: function() { 12336 if(module.cache.element.height !== 0 && module.cache.element.width !== 0) { 12337 $module 12338 .css({ 12339 width : module.cache.element.width, 12340 height : module.cache.element.height 12341 }) 12342 ; 12343 } 12344 } 12345 }, 12346 12347 is: { 12348 top: function() { 12349 return $module.hasClass(className.top); 12350 }, 12351 bottom: function() { 12352 return $module.hasClass(className.bottom); 12353 }, 12354 initialPosition: function() { 12355 return (!module.is.fixed() && !module.is.bound()); 12356 }, 12357 hidden: function() { 12358 return (!$module.is(':visible')); 12359 }, 12360 bound: function() { 12361 return $module.hasClass(className.bound); 12362 }, 12363 fixed: function() { 12364 return $module.hasClass(className.fixed); 12365 } 12366 }, 12367 12368 stick: function() { 12369 var 12370 cache = module.cache, 12371 fits = cache.fits, 12372 element = cache.element, 12373 window = cache.window, 12374 context = cache.context, 12375 offset = (module.is.bottom() && settings.pushing) 12376 ? settings.bottomOffset 12377 : settings.offset, 12378 scroll = { 12379 top : $scroll.scrollTop() + offset, 12380 bottom : $scroll.scrollTop() + offset + window.height 12381 }, 12382 direction = module.get.direction(scroll.top), 12383 elementScroll = module.get.elementScroll(scroll.top), 12384 12385 // shorthand 12386 doesntFit = !fits, 12387 elementVisible = (element.height !== 0) 12388 ; 12389 12390 // save current scroll for next run 12391 module.save.scroll(scroll.top); 12392 12393 if(elementVisible) { 12394 12395 if( module.is.initialPosition() ) { 12396 if(scroll.top >= context.bottom) { 12397 console.log(scroll.top, context.bottom); 12398 module.debug('Element bottom of container'); 12399 module.bindBottom(); 12400 } 12401 else if(scroll.top >= element.top) { 12402 module.debug('Element passed, fixing element to page'); 12403 module.fixTop(); 12404 } 12405 } 12406 else if( module.is.fixed() ) { 12407 12408 // currently fixed top 12409 if( module.is.top() ) { 12410 if( scroll.top < element.top ) { 12411 module.debug('Fixed element reached top of container'); 12412 module.setInitialPosition(); 12413 } 12414 else if( (element.height + scroll.top - elementScroll) > context.bottom ) { 12415 module.debug('Fixed element reached bottom of container'); 12416 module.bindBottom(); 12417 } 12418 // scroll element if larger than screen 12419 else if(doesntFit) { 12420 module.set.scroll(elementScroll); 12421 } 12422 } 12423 12424 // currently fixed bottom 12425 else if(module.is.bottom() ) { 12426 12427 // top edge 12428 if( (scroll.bottom - element.height) < element.top) { 12429 module.debug('Bottom fixed rail has reached top of container'); 12430 module.setInitialPosition(); 12431 } 12432 // bottom edge 12433 else if(scroll.bottom > context.bottom) { 12434 module.debug('Bottom fixed rail has reached bottom of container'); 12435 module.bindBottom(); 12436 } 12437 // scroll element if larger than screen 12438 else if(doesntFit) { 12439 module.set.scroll(elementScroll); 12440 } 12441 12442 } 12443 } 12444 else if( module.is.bottom() ) { 12445 if(settings.pushing) { 12446 if(module.is.bound() && scroll.bottom < context.bottom ) { 12447 module.debug('Fixing bottom attached element to bottom of browser.'); 12448 module.fixBottom(); 12449 } 12450 } 12451 else { 12452 if(module.is.bound() && (scroll.top < context.bottom - element.height) ) { 12453 module.debug('Fixing bottom attached element to top of browser.'); 12454 module.fixTop(); 12455 } 12456 } 12457 } 12458 } 12459 }, 12460 12461 bindTop: function() { 12462 module.debug('Binding element to top of parent container'); 12463 module.remove.offset(); 12464 $module 12465 .css('left' , '') 12466 .css('top' , '') 12467 .css('margin-bottom' , '') 12468 .removeClass(className.fixed) 12469 .removeClass(className.bottom) 12470 .addClass(className.bound) 12471 .addClass(className.top) 12472 ; 12473 settings.onTop.call(element); 12474 settings.onUnstick.call(element); 12475 }, 12476 bindBottom: function() { 12477 module.debug('Binding element to bottom of parent container'); 12478 module.remove.offset(); 12479 $module 12480 .css('left' , '') 12481 .css('top' , '') 12482 .css('margin-bottom' , module.cache.context.bottomPadding) 12483 .removeClass(className.fixed) 12484 .removeClass(className.top) 12485 .addClass(className.bound) 12486 .addClass(className.bottom) 12487 ; 12488 settings.onBottom.call(element); 12489 settings.onUnstick.call(element); 12490 }, 12491 12492 setInitialPosition: function() { 12493 module.unfix(); 12494 module.unbind(); 12495 }, 12496 12497 12498 fixTop: function() { 12499 module.debug('Fixing element to top of page'); 12500 module.set.offset(); 12501 $module 12502 .css('left', module.cache.element.left) 12503 .css('bottom' , '') 12504 .removeClass(className.bound) 12505 .removeClass(className.bottom) 12506 .addClass(className.fixed) 12507 .addClass(className.top) 12508 ; 12509 settings.onStick.call(element); 12510 }, 12511 12512 fixBottom: function() { 12513 module.debug('Sticking element to bottom of page'); 12514 module.set.offset(); 12515 $module 12516 .css('left', module.cache.element.left) 12517 .css('bottom' , '') 12518 .removeClass(className.bound) 12519 .removeClass(className.top) 12520 .addClass(className.fixed) 12521 .addClass(className.bottom) 12522 ; 12523 settings.onStick.call(element); 12524 }, 12525 12526 unbind: function() { 12527 module.debug('Removing absolute position on element'); 12528 module.remove.offset(); 12529 $module 12530 .removeClass(className.bound) 12531 .removeClass(className.top) 12532 .removeClass(className.bottom) 12533 ; 12534 }, 12535 12536 unfix: function() { 12537 module.debug('Removing fixed position on element'); 12538 module.remove.offset(); 12539 $module 12540 .removeClass(className.fixed) 12541 .removeClass(className.top) 12542 .removeClass(className.bottom) 12543 ; 12544 settings.onUnstick.call(element); 12545 }, 12546 12547 reset: function() { 12548 module.debug('Reseting elements position'); 12549 module.unbind(); 12550 module.unfix(); 12551 module.resetCSS(); 12552 }, 12553 12554 resetCSS: function() { 12555 $module 12556 .css({ 12557 top : '', 12558 bottom : '', 12559 width : '', 12560 height : '' 12561 }) 12562 ; 12563 $container 12564 .css({ 12565 height: '' 12566 }) 12567 ; 12568 }, 12569 12570 setting: function(name, value) { 12571 if( $.isPlainObject(name) ) { 12572 $.extend(true, settings, name); 12573 } 12574 else if(value !== undefined) { 12575 settings[name] = value; 12576 } 12577 else { 12578 return settings[name]; 12579 } 12580 }, 12581 internal: function(name, value) { 12582 if( $.isPlainObject(name) ) { 12583 $.extend(true, module, name); 12584 } 12585 else if(value !== undefined) { 12586 module[name] = value; 12587 } 12588 else { 12589 return module[name]; 12590 } 12591 }, 12592 debug: function() { 12593 if(settings.debug) { 12594 if(settings.performance) { 12595 module.performance.log(arguments); 12596 } 12597 else { 12598 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 12599 module.debug.apply(console, arguments); 12600 } 12601 } 12602 }, 12603 verbose: function() { 12604 if(settings.verbose && settings.debug) { 12605 if(settings.performance) { 12606 module.performance.log(arguments); 12607 } 12608 else { 12609 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 12610 module.verbose.apply(console, arguments); 12611 } 12612 } 12613 }, 12614 error: function() { 12615 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 12616 module.error.apply(console, arguments); 12617 }, 12618 performance: { 12619 log: function(message) { 12620 var 12621 currentTime, 12622 executionTime, 12623 previousTime 12624 ; 12625 if(settings.performance) { 12626 currentTime = new Date().getTime(); 12627 previousTime = time || currentTime; 12628 executionTime = currentTime - previousTime; 12629 time = currentTime; 12630 performance.push({ 12631 'Name' : message[0], 12632 'Arguments' : [].slice.call(message, 1) || '', 12633 'Element' : element, 12634 'Execution Time' : executionTime 12635 }); 12636 } 12637 clearTimeout(module.performance.timer); 12638 module.performance.timer = setTimeout(module.performance.display, 0); 12639 }, 12640 display: function() { 12641 var 12642 title = settings.name + ':', 12643 totalTime = 0 12644 ; 12645 time = false; 12646 clearTimeout(module.performance.timer); 12647 $.each(performance, function(index, data) { 12648 totalTime += data['Execution Time']; 12649 }); 12650 title += ' ' + totalTime + 'ms'; 12651 if(moduleSelector) { 12652 title += ' \'' + moduleSelector + '\''; 12653 } 12654 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 12655 console.groupCollapsed(title); 12656 if(console.table) { 12657 console.table(performance); 12658 } 12659 else { 12660 $.each(performance, function(index, data) { 12661 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 12662 }); 12663 } 12664 console.groupEnd(); 12665 } 12666 performance = []; 12667 } 12668 }, 12669 invoke: function(query, passedArguments, context) { 12670 var 12671 object = instance, 12672 maxDepth, 12673 found, 12674 response 12675 ; 12676 passedArguments = passedArguments || queryArguments; 12677 context = element || context; 12678 if(typeof query == 'string' && object !== undefined) { 12679 query = query.split(/[\. ]/); 12680 maxDepth = query.length - 1; 12681 $.each(query, function(depth, value) { 12682 var camelCaseValue = (depth != maxDepth) 12683 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 12684 : query 12685 ; 12686 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 12687 object = object[camelCaseValue]; 12688 } 12689 else if( object[camelCaseValue] !== undefined ) { 12690 found = object[camelCaseValue]; 12691 return false; 12692 } 12693 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 12694 object = object[value]; 12695 } 12696 else if( object[value] !== undefined ) { 12697 found = object[value]; 12698 return false; 12699 } 12700 else { 12701 return false; 12702 } 12703 }); 12704 } 12705 if ( $.isFunction( found ) ) { 12706 response = found.apply(context, passedArguments); 12707 } 12708 else if(found !== undefined) { 12709 response = found; 12710 } 12711 if($.isArray(returnedValue)) { 12712 returnedValue.push(response); 12713 } 12714 else if(returnedValue !== undefined) { 12715 returnedValue = [returnedValue, response]; 12716 } 12717 else if(response !== undefined) { 12718 returnedValue = response; 12719 } 12720 return found; 12721 } 12722 }; 12723 12724 if(methodInvoked) { 12725 if(instance === undefined) { 12726 module.initialize(); 12727 } 12728 module.invoke(query); 12729 } 12730 else { 12731 if(instance !== undefined) { 12732 instance.invoke('destroy'); 12733 } 12734 module.initialize(); 12735 } 12736 }) 12737 ; 12738 12739 return (returnedValue !== undefined) 12740 ? returnedValue 12741 : this 12742 ; 12743 }; 12744 12745 $.fn.sticky.settings = { 12746 12747 name : 'Sticky', 12748 namespace : 'sticky', 12749 12750 debug : false, 12751 verbose : false, 12752 performance : false, 12753 12754 pushing : false, 12755 context : false, 12756 scrollContext : window, 12757 12758 offset : 0, 12759 bottomOffset : 0, 12760 12761 observeChanges : true, 12762 12763 onReposition : function(){}, 12764 onScroll : function(){}, 12765 onStick : function(){}, 12766 onUnstick : function(){}, 12767 onTop : function(){}, 12768 onBottom : function(){}, 12769 12770 error : { 12771 container : 'Sticky element must be inside a relative container', 12772 visible : 'Element is hidden, you must call refresh after element becomes visible', 12773 method : 'The method you called is not defined.', 12774 invalidContext : 'Context specified does not exist', 12775 elementSize : 'Sticky element is larger than its container, cannot create sticky.' 12776 }, 12777 12778 className : { 12779 bound : 'bound', 12780 fixed : 'fixed', 12781 supported : 'native', 12782 top : 'top', 12783 bottom : 'bottom' 12784 } 12785 12786 }; 12787 12788 })( jQuery, window , document ); 12789 12790 /*! 12791 * # Semantic UI x.x - Tab 12792 * http://github.com/semantic-org/semantic-ui/ 12793 * 12794 * 12795 * Copyright 2014 Contributorss 12796 * Released under the MIT license 12797 * http://opensource.org/licenses/MIT 12798 * 12799 */ 12800 12801 ;(function ($, window, document, undefined) { 12802 12803 "use strict"; 12804 12805 $.fn.tab = function(parameters) { 12806 12807 var 12808 // use window context if none specified 12809 $allModules = $.isFunction(this) 12810 ? $(window) 12811 : $(this), 12812 12813 settings = ( $.isPlainObject(parameters) ) 12814 ? $.extend(true, {}, $.fn.tab.settings, parameters) 12815 : $.extend({}, $.fn.tab.settings), 12816 12817 moduleSelector = $allModules.selector || '', 12818 time = new Date().getTime(), 12819 performance = [], 12820 12821 query = arguments[0], 12822 methodInvoked = (typeof query == 'string'), 12823 queryArguments = [].slice.call(arguments, 1), 12824 12825 module, 12826 returnedValue 12827 ; 12828 12829 $allModules 12830 .each(function() { 12831 var 12832 12833 className = settings.className, 12834 metadata = settings.metadata, 12835 selector = settings.selector, 12836 error = settings.error, 12837 12838 eventNamespace = '.' + settings.namespace, 12839 moduleNamespace = 'module-' + settings.namespace, 12840 12841 $module = $(this), 12842 12843 cache = {}, 12844 firstLoad = true, 12845 recursionDepth = 0, 12846 12847 $context, 12848 $tabs, 12849 activeTabPath, 12850 parameterArray, 12851 historyEvent, 12852 12853 element = this, 12854 instance = $module.data(moduleNamespace) 12855 ; 12856 12857 module = { 12858 12859 initialize: function() { 12860 module.debug('Initializing tab menu item', $module); 12861 12862 module.determineTabs(); 12863 module.debug('Determining tabs', settings.context, $tabs); 12864 12865 // set up automatic routing 12866 if(settings.auto) { 12867 module.set.auto(); 12868 } 12869 12870 // attach events if navigation wasn't set to window 12871 if( !$.isWindow( element ) ) { 12872 module.debug('Attaching tab activation events to element', $module); 12873 $module 12874 .on('click' + eventNamespace, module.event.click) 12875 ; 12876 } 12877 module.instantiate(); 12878 }, 12879 12880 determineTabs: function() { 12881 var 12882 $reference 12883 ; 12884 12885 // determine tab context 12886 if(settings.context === 'parent') { 12887 if($module.closest(selector.ui).length > 0) { 12888 $reference = $module.closest(selector.ui); 12889 module.verbose('Using closest UI element for determining parent', $reference); 12890 } 12891 else { 12892 $reference = $module; 12893 } 12894 $context = $reference.parent(); 12895 module.verbose('Determined parent element for creating context', $context); 12896 } 12897 else if(settings.context) { 12898 $context = $(settings.context); 12899 module.verbose('Using selector for tab context', settings.context, $context); 12900 } 12901 else { 12902 $context = $('body'); 12903 } 12904 12905 // find tabs 12906 if(settings.childrenOnly) { 12907 $tabs = $context.children(selector.tabs); 12908 module.debug('Searching tab context children for tabs', $context, $tabs); 12909 } 12910 else { 12911 $tabs = $context.find(selector.tabs); 12912 module.debug('Searching tab context for tabs', $context, $tabs); 12913 } 12914 }, 12915 12916 initializeHistory: function() { 12917 if(settings.history) { 12918 module.debug('Initializing page state'); 12919 if( $.address === undefined ) { 12920 module.error(error.state); 12921 return false; 12922 } 12923 else { 12924 if(settings.historyType == 'state') { 12925 module.debug('Using HTML5 to manage state'); 12926 if(settings.path !== false) { 12927 $.address 12928 .history(true) 12929 .state(settings.path) 12930 ; 12931 } 12932 else { 12933 module.error(error.path); 12934 return false; 12935 } 12936 } 12937 $.address 12938 .bind('change', module.event.history.change) 12939 ; 12940 } 12941 } 12942 }, 12943 12944 instantiate: function () { 12945 module.verbose('Storing instance of module', module); 12946 instance = module; 12947 $module 12948 .data(moduleNamespace, module) 12949 ; 12950 }, 12951 12952 destroy: function() { 12953 module.debug('Destroying tabs', $module); 12954 $module 12955 .removeData(moduleNamespace) 12956 .off(eventNamespace) 12957 ; 12958 }, 12959 12960 event: { 12961 click: function(event) { 12962 var 12963 tabPath = $(this).data(metadata.tab) 12964 ; 12965 if(tabPath !== undefined) { 12966 if(settings.history) { 12967 module.verbose('Updating page state', event); 12968 $.address.value(tabPath); 12969 } 12970 else { 12971 module.verbose('Changing tab', event); 12972 module.changeTab(tabPath); 12973 } 12974 event.preventDefault(); 12975 } 12976 else { 12977 module.debug('No tab specified'); 12978 } 12979 }, 12980 history: { 12981 change: function(event) { 12982 var 12983 tabPath = event.pathNames.join('/') || module.get.initialPath(), 12984 pageTitle = settings.templates.determineTitle(tabPath) || false 12985 ; 12986 module.performance.display(); 12987 module.debug('History change event', tabPath, event); 12988 historyEvent = event; 12989 if(tabPath !== undefined) { 12990 module.changeTab(tabPath); 12991 } 12992 if(pageTitle) { 12993 $.address.title(pageTitle); 12994 } 12995 } 12996 } 12997 }, 12998 12999 refresh: function() { 13000 if(activeTabPath) { 13001 module.debug('Refreshing tab', activeTabPath); 13002 module.changeTab(activeTabPath); 13003 } 13004 }, 13005 13006 cache: { 13007 13008 read: function(cacheKey) { 13009 return (cacheKey !== undefined) 13010 ? cache[cacheKey] 13011 : false 13012 ; 13013 }, 13014 add: function(cacheKey, content) { 13015 cacheKey = cacheKey || activeTabPath; 13016 module.debug('Adding cached content for', cacheKey); 13017 cache[cacheKey] = content; 13018 }, 13019 remove: function(cacheKey) { 13020 cacheKey = cacheKey || activeTabPath; 13021 module.debug('Removing cached content for', cacheKey); 13022 delete cache[cacheKey]; 13023 } 13024 }, 13025 13026 set: { 13027 auto: function() { 13028 var 13029 url = (typeof settings.path == 'string') 13030 ? settings.path.replace(/\/$/, '') + '/{$tab}' 13031 : '/{$tab}' 13032 ; 13033 module.verbose('Setting up automatic tab retrieval from server', url); 13034 if($.isPlainObject(settings.apiSettings)) { 13035 settings.apiSettings.url = url; 13036 } 13037 else { 13038 settings.apiSettings = { 13039 url: url 13040 }; 13041 } 13042 }, 13043 state: function(state) { 13044 $.address.value(state); 13045 } 13046 }, 13047 13048 changeTab: function(tabPath) { 13049 var 13050 pushStateAvailable = (window.history && window.history.pushState), 13051 shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad), 13052 remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ), 13053 // only get default path if not remote content 13054 pathArray = (remoteContent && !shouldIgnoreLoad) 13055 ? module.utilities.pathToArray(tabPath) 13056 : module.get.defaultPathArray(tabPath) 13057 ; 13058 tabPath = module.utilities.arrayToPath(pathArray); 13059 $.each(pathArray, function(index, tab) { 13060 var 13061 currentPathArray = pathArray.slice(0, index + 1), 13062 currentPath = module.utilities.arrayToPath(currentPathArray), 13063 13064 isTab = module.is.tab(currentPath), 13065 isLastIndex = (index + 1 == pathArray.length), 13066 13067 $tab = module.get.tabElement(currentPath), 13068 $anchor, 13069 nextPathArray, 13070 nextPath, 13071 isLastTab 13072 ; 13073 module.verbose('Looking for tab', tab); 13074 if(isTab) { 13075 13076 module.verbose('Tab was found', tab); 13077 // scope up 13078 activeTabPath = currentPath; 13079 parameterArray = module.utilities.filterArray(pathArray, currentPathArray); 13080 13081 if(isLastIndex) { 13082 isLastTab = true; 13083 } 13084 else { 13085 nextPathArray = pathArray.slice(0, index + 2); 13086 nextPath = module.utilities.arrayToPath(nextPathArray); 13087 isLastTab = ( !module.is.tab(nextPath) ); 13088 if(isLastTab) { 13089 module.verbose('Tab parameters found', nextPathArray); 13090 } 13091 } 13092 if(isLastTab && remoteContent) { 13093 if(!shouldIgnoreLoad) { 13094 module.activate.navigation(currentPath); 13095 module.content.fetch(currentPath, tabPath); 13096 } 13097 else { 13098 module.debug('Ignoring remote content on first tab load', currentPath); 13099 firstLoad = false; 13100 module.cache.add(tabPath, $tab.html()); 13101 module.activate.all(currentPath); 13102 settings.onTabInit.call($tab, currentPath, parameterArray, historyEvent); 13103 settings.onTabLoad.call($tab, currentPath, parameterArray, historyEvent); 13104 } 13105 return false; 13106 } 13107 else { 13108 module.debug('Opened local tab', currentPath); 13109 module.activate.all(currentPath); 13110 if( !module.cache.read(currentPath) ) { 13111 module.cache.add(currentPath, true); 13112 module.debug('First time tab loaded calling tab init'); 13113 settings.onTabInit.call($tab, currentPath, parameterArray, historyEvent); 13114 } 13115 settings.onTabLoad.call($tab, currentPath, parameterArray, historyEvent); 13116 } 13117 } 13118 else if(tabPath.search('/') == -1 && tabPath !== '') { 13119 // look for in page anchor 13120 $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]'), 13121 currentPath = $anchor.closest('[data-tab]').data('tab'); 13122 $tab = module.get.tabElement(currentPath); 13123 // if anchor exists use parent tab 13124 if($anchor && $anchor.length > 0 && currentPath) { 13125 module.debug('No tab found, but deep anchor link present, opening parent tab'); 13126 module.activate.all(currentPath); 13127 if( !module.cache.read(currentPath) ) { 13128 module.cache.add(currentPath, true); 13129 module.debug('First time tab loaded calling tab init'); 13130 settings.onTabInit.call($tab, currentPath, parameterArray, historyEvent); 13131 } 13132 return false; 13133 } 13134 } 13135 else { 13136 module.error(error.missingTab, $module, $context, currentPath); 13137 return false; 13138 } 13139 }); 13140 }, 13141 13142 content: { 13143 13144 fetch: function(tabPath, fullTabPath) { 13145 var 13146 $tab = module.get.tabElement(tabPath), 13147 apiSettings = { 13148 dataType : 'html', 13149 on : 'now', 13150 onSuccess : function(response) { 13151 module.cache.add(fullTabPath, response); 13152 module.content.update(tabPath, response); 13153 if(tabPath == activeTabPath) { 13154 module.debug('Content loaded', tabPath); 13155 module.activate.tab(tabPath); 13156 } 13157 else { 13158 module.debug('Content loaded in background', tabPath); 13159 } 13160 settings.onTabInit.call($tab, tabPath, parameterArray, historyEvent); 13161 settings.onTabLoad.call($tab, tabPath, parameterArray, historyEvent); 13162 }, 13163 urlData: { tab: fullTabPath } 13164 }, 13165 request = $tab.api('get request') || false, 13166 existingRequest = ( request && request.state() === 'pending' ), 13167 requestSettings, 13168 cachedContent 13169 ; 13170 13171 fullTabPath = fullTabPath || tabPath; 13172 cachedContent = module.cache.read(fullTabPath); 13173 13174 13175 module.activate.tab(tabPath); 13176 13177 if(settings.cache && cachedContent) { 13178 module.debug('Showing existing content', fullTabPath); 13179 module.content.update(tabPath, cachedContent); 13180 settings.onTabLoad.call($tab, tabPath, parameterArray, historyEvent); 13181 } 13182 else if(existingRequest) { 13183 module.debug('Content is already loading', fullTabPath); 13184 $tab.addClass(className.loading); 13185 } 13186 else if($.api !== undefined) { 13187 requestSettings = $.extend(true, { 13188 headers: { 'X-Remote': true } 13189 }, settings.apiSettings, apiSettings); 13190 module.debug('Retrieving remote content', fullTabPath, requestSettings); 13191 $tab.api( requestSettings ); 13192 } 13193 else { 13194 module.error(error.api); 13195 } 13196 }, 13197 13198 update: function(tabPath, html) { 13199 module.debug('Updating html for', tabPath); 13200 var 13201 $tab = module.get.tabElement(tabPath) 13202 ; 13203 $tab 13204 .html(html) 13205 ; 13206 } 13207 }, 13208 13209 activate: { 13210 all: function(tabPath) { 13211 module.activate.tab(tabPath); 13212 module.activate.navigation(tabPath); 13213 }, 13214 tab: function(tabPath) { 13215 var 13216 $tab = module.get.tabElement(tabPath) 13217 ; 13218 module.verbose('Showing tab content for', $tab); 13219 $tab 13220 .addClass(className.active) 13221 .siblings($tabs) 13222 .removeClass(className.active + ' ' + className.loading) 13223 ; 13224 }, 13225 navigation: function(tabPath) { 13226 var 13227 $navigation = module.get.navElement(tabPath) 13228 ; 13229 module.verbose('Activating tab navigation for', $navigation, tabPath); 13230 $navigation 13231 .addClass(className.active) 13232 .siblings($allModules) 13233 .removeClass(className.active + ' ' + className.loading) 13234 ; 13235 } 13236 }, 13237 13238 deactivate: { 13239 all: function() { 13240 module.deactivate.navigation(); 13241 module.deactivate.tabs(); 13242 }, 13243 navigation: function() { 13244 $allModules 13245 .removeClass(className.active) 13246 ; 13247 }, 13248 tabs: function() { 13249 $tabs 13250 .removeClass(className.active + ' ' + className.loading) 13251 ; 13252 } 13253 }, 13254 13255 is: { 13256 tab: function(tabName) { 13257 return (tabName !== undefined) 13258 ? ( module.get.tabElement(tabName).length > 0 ) 13259 : false 13260 ; 13261 } 13262 }, 13263 13264 get: { 13265 initialPath: function() { 13266 return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab); 13267 }, 13268 path: function() { 13269 return $.address.value(); 13270 }, 13271 // adds default tabs to tab path 13272 defaultPathArray: function(tabPath) { 13273 return module.utilities.pathToArray( module.get.defaultPath(tabPath) ); 13274 }, 13275 defaultPath: function(tabPath) { 13276 var 13277 $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0), 13278 defaultTab = $defaultNav.data(metadata.tab) || false 13279 ; 13280 if( defaultTab ) { 13281 module.debug('Found default tab', defaultTab); 13282 if(recursionDepth < settings.maxDepth) { 13283 recursionDepth++; 13284 return module.get.defaultPath(defaultTab); 13285 } 13286 module.error(error.recursion); 13287 } 13288 else { 13289 module.debug('No default tabs found for', tabPath, $tabs); 13290 } 13291 recursionDepth = 0; 13292 return tabPath; 13293 }, 13294 navElement: function(tabPath) { 13295 tabPath = tabPath || activeTabPath; 13296 return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); 13297 }, 13298 tabElement: function(tabPath) { 13299 var 13300 $fullPathTab, 13301 $simplePathTab, 13302 tabPathArray, 13303 lastTab 13304 ; 13305 tabPath = tabPath || activeTabPath; 13306 tabPathArray = module.utilities.pathToArray(tabPath); 13307 lastTab = module.utilities.last(tabPathArray); 13308 $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]'); 13309 $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); 13310 return ($fullPathTab.length > 0) 13311 ? $fullPathTab 13312 : $simplePathTab 13313 ; 13314 }, 13315 tab: function() { 13316 return activeTabPath; 13317 } 13318 }, 13319 13320 utilities: { 13321 filterArray: function(keepArray, removeArray) { 13322 return $.grep(keepArray, function(keepValue) { 13323 return ( $.inArray(keepValue, removeArray) == -1); 13324 }); 13325 }, 13326 last: function(array) { 13327 return $.isArray(array) 13328 ? array[ array.length - 1] 13329 : false 13330 ; 13331 }, 13332 pathToArray: function(pathName) { 13333 if(pathName === undefined) { 13334 pathName = activeTabPath; 13335 } 13336 return typeof pathName == 'string' 13337 ? pathName.split('/') 13338 : [pathName] 13339 ; 13340 }, 13341 arrayToPath: function(pathArray) { 13342 return $.isArray(pathArray) 13343 ? pathArray.join('/') 13344 : false 13345 ; 13346 } 13347 }, 13348 13349 setting: function(name, value) { 13350 module.debug('Changing setting', name, value); 13351 if( $.isPlainObject(name) ) { 13352 $.extend(true, settings, name); 13353 } 13354 else if(value !== undefined) { 13355 settings[name] = value; 13356 } 13357 else { 13358 return settings[name]; 13359 } 13360 }, 13361 internal: function(name, value) { 13362 if( $.isPlainObject(name) ) { 13363 $.extend(true, module, name); 13364 } 13365 else if(value !== undefined) { 13366 module[name] = value; 13367 } 13368 else { 13369 return module[name]; 13370 } 13371 }, 13372 debug: function() { 13373 if(settings.debug) { 13374 if(settings.performance) { 13375 module.performance.log(arguments); 13376 } 13377 else { 13378 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 13379 module.debug.apply(console, arguments); 13380 } 13381 } 13382 }, 13383 verbose: function() { 13384 if(settings.verbose && settings.debug) { 13385 if(settings.performance) { 13386 module.performance.log(arguments); 13387 } 13388 else { 13389 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 13390 module.verbose.apply(console, arguments); 13391 } 13392 } 13393 }, 13394 error: function() { 13395 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 13396 module.error.apply(console, arguments); 13397 }, 13398 performance: { 13399 log: function(message) { 13400 var 13401 currentTime, 13402 executionTime, 13403 previousTime 13404 ; 13405 if(settings.performance) { 13406 currentTime = new Date().getTime(); 13407 previousTime = time || currentTime; 13408 executionTime = currentTime - previousTime; 13409 time = currentTime; 13410 performance.push({ 13411 'Name' : message[0], 13412 'Arguments' : [].slice.call(message, 1) || '', 13413 'Element' : element, 13414 'Execution Time' : executionTime 13415 }); 13416 } 13417 clearTimeout(module.performance.timer); 13418 module.performance.timer = setTimeout(module.performance.display, 100); 13419 }, 13420 display: function() { 13421 var 13422 title = settings.name + ':', 13423 totalTime = 0 13424 ; 13425 time = false; 13426 clearTimeout(module.performance.timer); 13427 $.each(performance, function(index, data) { 13428 totalTime += data['Execution Time']; 13429 }); 13430 title += ' ' + totalTime + 'ms'; 13431 if(moduleSelector) { 13432 title += ' \'' + moduleSelector + '\''; 13433 } 13434 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 13435 console.groupCollapsed(title); 13436 if(console.table) { 13437 console.table(performance); 13438 } 13439 else { 13440 $.each(performance, function(index, data) { 13441 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 13442 }); 13443 } 13444 console.groupEnd(); 13445 } 13446 performance = []; 13447 } 13448 }, 13449 invoke: function(query, passedArguments, context) { 13450 var 13451 object = instance, 13452 maxDepth, 13453 found, 13454 response 13455 ; 13456 passedArguments = passedArguments || queryArguments; 13457 context = element || context; 13458 if(typeof query == 'string' && object !== undefined) { 13459 query = query.split(/[\. ]/); 13460 maxDepth = query.length - 1; 13461 $.each(query, function(depth, value) { 13462 var camelCaseValue = (depth != maxDepth) 13463 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 13464 : query 13465 ; 13466 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 13467 object = object[camelCaseValue]; 13468 } 13469 else if( object[camelCaseValue] !== undefined ) { 13470 found = object[camelCaseValue]; 13471 return false; 13472 } 13473 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 13474 object = object[value]; 13475 } 13476 else if( object[value] !== undefined ) { 13477 found = object[value]; 13478 return false; 13479 } 13480 else { 13481 module.error(error.method, query); 13482 return false; 13483 } 13484 }); 13485 } 13486 if ( $.isFunction( found ) ) { 13487 response = found.apply(context, passedArguments); 13488 } 13489 else if(found !== undefined) { 13490 response = found; 13491 } 13492 if($.isArray(returnedValue)) { 13493 returnedValue.push(response); 13494 } 13495 else if(returnedValue !== undefined) { 13496 returnedValue = [returnedValue, response]; 13497 } 13498 else if(response !== undefined) { 13499 returnedValue = response; 13500 } 13501 return found; 13502 } 13503 }; 13504 if(methodInvoked) { 13505 if(instance === undefined) { 13506 module.initialize(); 13507 } 13508 module.invoke(query); 13509 } 13510 else { 13511 if(instance !== undefined) { 13512 instance.invoke('destroy'); 13513 } 13514 module.initialize(); 13515 } 13516 }) 13517 ; 13518 if(module && !methodInvoked) { 13519 module.initializeHistory(); 13520 } 13521 return (returnedValue !== undefined) 13522 ? returnedValue 13523 : this 13524 ; 13525 13526 }; 13527 13528 // shortcut for tabbed content with no defined navigation 13529 $.tab = function() { 13530 $(window).tab.apply(this, arguments); 13531 }; 13532 13533 $.fn.tab.settings = { 13534 13535 name : 'Tab', 13536 namespace : 'tab', 13537 13538 debug : false, 13539 verbose : true, 13540 performance : true, 13541 13542 auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers 13543 history : false, // use browser history 13544 historyType : 'hash', // #/ or html5 state 13545 path : false, // base path of url 13546 13547 context : false, // specify a context that tabs must appear inside 13548 childrenOnly : false, // use only tabs that are children of context 13549 maxDepth : 25, // max depth a tab can be nested 13550 13551 alwaysRefresh : false, // load tab content new every tab click 13552 cache : true, // cache the content requests to pull locally 13553 ignoreFirstLoad : false, // don't load remote content on first load 13554 apiSettings : false, // settings for api call 13555 13556 onTabInit : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded 13557 onTabLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load 13558 13559 templates : { 13560 determineTitle: function(tabArray) {} // returns page title for path 13561 }, 13562 13563 error: { 13564 api : 'You attempted to load content without API module', 13565 method : 'The method you called is not defined', 13566 missingTab : 'Activated tab cannot be found for this context.', 13567 noContent : 'The tab you specified is missing a content url.', 13568 path : 'History enabled, but no path was specified', 13569 recursion : 'Max recursive depth reached', 13570 state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>' 13571 }, 13572 13573 metadata : { 13574 tab : 'tab', 13575 loaded : 'loaded', 13576 promise: 'promise' 13577 }, 13578 13579 className : { 13580 loading : 'loading', 13581 active : 'active' 13582 }, 13583 13584 selector : { 13585 tabs : '.ui.tab', 13586 ui : '.ui' 13587 } 13588 13589 }; 13590 13591 })( jQuery, window , document ); 13592 /*! 13593 * # Semantic UI x.x - Transition 13594 * http://github.com/semantic-org/semantic-ui/ 13595 * 13596 * 13597 * Copyright 2014 Contributors 13598 * Released under the MIT license 13599 * http://opensource.org/licenses/MIT 13600 * 13601 */ 13602 13603 ;(function ( $, window, document, undefined ) { 13604 13605 "use strict"; 13606 13607 $.fn.transition = function() { 13608 var 13609 $allModules = $(this), 13610 moduleSelector = $allModules.selector || '', 13611 13612 time = new Date().getTime(), 13613 performance = [], 13614 13615 moduleArguments = arguments, 13616 query = moduleArguments[0], 13617 queryArguments = [].slice.call(arguments, 1), 13618 methodInvoked = (typeof query === 'string'), 13619 13620 requestAnimationFrame = window.requestAnimationFrame 13621 || window.mozRequestAnimationFrame 13622 || window.webkitRequestAnimationFrame 13623 || window.msRequestAnimationFrame 13624 || function(callback) { setTimeout(callback, 0); }, 13625 13626 returnedValue 13627 ; 13628 $allModules 13629 .each(function(index) { 13630 var 13631 $module = $(this), 13632 element = this, 13633 13634 // set at run time 13635 settings, 13636 instance, 13637 13638 error, 13639 className, 13640 metadata, 13641 animationStart, 13642 animationEnd, 13643 animationName, 13644 13645 namespace, 13646 moduleNamespace, 13647 eventNamespace, 13648 module 13649 ; 13650 13651 module = { 13652 13653 initialize: function() { 13654 13655 // get full settings 13656 settings = module.get.settings.apply(element, moduleArguments); 13657 13658 // shorthand 13659 className = settings.className; 13660 error = settings.error; 13661 metadata = settings.metadata; 13662 13663 // define namespace 13664 eventNamespace = '.' + settings.namespace; 13665 moduleNamespace = 'module-' + settings.namespace; 13666 instance = $module.data(moduleNamespace) || module; 13667 13668 // get vendor specific events 13669 animationEnd = module.get.animationEndEvent(); 13670 animationName = module.get.animationName(); 13671 animationStart = module.get.animationStartEvent(); 13672 13673 if(methodInvoked) { 13674 methodInvoked = module.invoke(query); 13675 } 13676 13677 // method not invoked, lets run an animation 13678 if(methodInvoked === false) { 13679 module.verbose('Converted arguments into settings object', settings); 13680 if(settings.interval) { 13681 module.delay(settings.animate); 13682 } 13683 else { 13684 module.animate(); 13685 } 13686 module.instantiate(); 13687 } 13688 }, 13689 13690 instantiate: function() { 13691 module.verbose('Storing instance of module', module); 13692 instance = module; 13693 $module 13694 .data(moduleNamespace, instance) 13695 ; 13696 }, 13697 13698 destroy: function() { 13699 module.verbose('Destroying previous module for', element); 13700 $module 13701 .removeData(moduleNamespace) 13702 ; 13703 }, 13704 13705 refresh: function() { 13706 module.verbose('Refreshing display type on next animation'); 13707 delete module.displayType; 13708 }, 13709 13710 forceRepaint: function() { 13711 module.verbose('Forcing element repaint'); 13712 var 13713 $parentElement = $module.parent(), 13714 $nextElement = $module.next() 13715 ; 13716 if($nextElement.length === 0) { 13717 $module.detach().appendTo($parentElement); 13718 } 13719 else { 13720 $module.detach().insertBefore($nextElement); 13721 } 13722 }, 13723 13724 repaint: function() { 13725 module.verbose('Repainting element'); 13726 var 13727 fakeAssignment = element.offsetWidth 13728 ; 13729 }, 13730 13731 delay: function(interval) { 13732 var 13733 isReverse = (settings.reverse === true), 13734 shouldReverse = (settings.reverse == 'auto' && module.get.direction() == className.outward), 13735 delay 13736 ; 13737 interval = (typeof interval !== undefined) 13738 ? interval 13739 : settings.interval 13740 ; 13741 delay = (isReverse || shouldReverse) 13742 ? ($allModules.length - index) * settings.interval 13743 : index * settings.interval 13744 ; 13745 module.debug('Delaying animation by', delay); 13746 setTimeout(module.animate, delay); 13747 }, 13748 13749 animate: function(overrideSettings) { 13750 settings = overrideSettings || settings; 13751 if(!module.is.supported()) { 13752 module.error(error.support); 13753 return false; 13754 } 13755 module.debug('Preparing animation', settings.animation); 13756 if(module.is.animating()) { 13757 if(settings.queue) { 13758 if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) { 13759 module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation); 13760 } 13761 else { 13762 module.queue(settings.animation); 13763 } 13764 return false; 13765 } 13766 else if(!settings.allowRepeats && module.is.occurring()) { 13767 module.debug('Animation is already occurring, will not execute repeated animation', settings.animation); 13768 return false; 13769 } 13770 else { 13771 module.debug('New animation started, completing previous early', settings.animation); 13772 module.complete(); 13773 } 13774 } 13775 if( module.can.animate() ) { 13776 module.set.animating(settings.animation); 13777 } 13778 else { 13779 module.error(error.noAnimation, settings.animation, element); 13780 } 13781 }, 13782 13783 reset: function() { 13784 module.debug('Resetting animation to beginning conditions'); 13785 module.remove.animationCallbacks(); 13786 module.restore.conditions(); 13787 module.remove.animating(); 13788 }, 13789 13790 queue: function(animation) { 13791 module.debug('Queueing animation of', animation); 13792 module.queuing = true; 13793 $module 13794 .one(animationEnd + '.queue' + eventNamespace, function() { 13795 module.queuing = false; 13796 module.repaint(); 13797 module.animate.apply(this, settings); 13798 }) 13799 ; 13800 }, 13801 13802 complete: function (event) { 13803 module.debug('Animation complete', settings.animation); 13804 module.remove.completeCallback(); 13805 module.remove.failSafe(); 13806 if(!module.is.looping()) { 13807 if( module.is.outward() ) { 13808 module.verbose('Animation is outward, hiding element'); 13809 module.restore.conditions(); 13810 module.hide(); 13811 settings.onHide.call(this); 13812 } 13813 else if( module.is.inward() ) { 13814 module.verbose('Animation is outward, showing element'); 13815 module.restore.conditions(); 13816 module.show(); 13817 settings.onShow.call(this); 13818 } 13819 else { 13820 module.restore.conditions(); 13821 } 13822 module.remove.animation(); 13823 module.remove.animating(); 13824 } 13825 settings.onComplete.call(this); 13826 }, 13827 13828 has: { 13829 direction: function(animation) { 13830 var 13831 hasDirection = false 13832 ; 13833 animation = animation || settings.animation; 13834 if(typeof animation === 'string') { 13835 animation = animation.split(' '); 13836 $.each(animation, function(index, word){ 13837 if(word === className.inward || word === className.outward) { 13838 hasDirection = true; 13839 } 13840 }); 13841 } 13842 return hasDirection; 13843 }, 13844 inlineDisplay: function() { 13845 var 13846 style = $module.attr('style') || '' 13847 ; 13848 return $.isArray(style.match(/display.*?;/, '')); 13849 } 13850 }, 13851 13852 set: { 13853 animating: function(animation) { 13854 animation = animation || settings.animation; 13855 if(!module.is.animating()) { 13856 module.save.conditions(); 13857 } 13858 module.remove.direction(); 13859 module.remove.completeCallback(); 13860 if(module.can.transition() && !module.has.direction()) { 13861 module.set.direction(); 13862 } 13863 module.remove.hidden(); 13864 module.set.display(); 13865 $module 13866 .addClass(className.animating + ' ' + className.transition + ' ' + animation) 13867 .addClass(animation) 13868 .one(animationEnd + '.complete' + eventNamespace, module.complete) 13869 ; 13870 if(settings.useFailSafe) { 13871 module.add.failSafe(); 13872 } 13873 module.set.duration(settings.duration); 13874 settings.onStart.call(this); 13875 module.debug('Starting tween', animation, $module.attr('class')); 13876 }, 13877 duration: function(animationName, duration) { 13878 duration = duration || settings.duration; 13879 duration = (typeof duration == 'number') 13880 ? duration + 'ms' 13881 : duration 13882 ; 13883 if(duration || duration === 0) { 13884 module.verbose('Setting animation duration', duration); 13885 $module 13886 .css({ 13887 '-webkit-animation-duration': duration, 13888 '-moz-animation-duration': duration, 13889 '-ms-animation-duration': duration, 13890 '-o-animation-duration': duration, 13891 'animation-duration': duration 13892 }) 13893 ; 13894 } 13895 }, 13896 display: function() { 13897 var 13898 style = module.get.style(), 13899 displayType = module.get.displayType(), 13900 overrideStyle = style + 'display: ' + displayType + ' !important;' 13901 ; 13902 $module.css('display', ''); 13903 module.refresh(); 13904 if( $module.css('display') !== displayType ) { 13905 module.verbose('Setting inline visibility to', displayType); 13906 $module 13907 .attr('style', overrideStyle) 13908 ; 13909 } 13910 }, 13911 direction: function() { 13912 if($module.is(':visible') && !module.is.hidden()) { 13913 module.debug('Automatically determining the direction of animation', 'Outward'); 13914 $module 13915 .removeClass(className.inward) 13916 .addClass(className.outward) 13917 ; 13918 } 13919 else { 13920 module.debug('Automatically determining the direction of animation', 'Inward'); 13921 $module 13922 .removeClass(className.outward) 13923 .addClass(className.inward) 13924 ; 13925 } 13926 }, 13927 looping: function() { 13928 module.debug('Transition set to loop'); 13929 $module 13930 .addClass(className.looping) 13931 ; 13932 }, 13933 hidden: function() { 13934 if(!module.is.hidden()) { 13935 $module 13936 .addClass(className.transition) 13937 .addClass(className.hidden) 13938 ; 13939 } 13940 if($module.css('display') !== 'none') { 13941 module.verbose('Overriding default display to hide element'); 13942 $module 13943 .css('display', 'none') 13944 ; 13945 } 13946 }, 13947 visible: function() { 13948 $module 13949 .addClass(className.transition) 13950 .addClass(className.visible) 13951 ; 13952 } 13953 }, 13954 13955 save: { 13956 displayType: function(displayType) { 13957 $module.data(metadata.displayType, displayType); 13958 }, 13959 transitionExists: function(animation, exists) { 13960 $.fn.transition.exists[animation] = exists; 13961 module.verbose('Saving existence of transition', animation, exists); 13962 }, 13963 conditions: function() { 13964 var 13965 clasName = $module.attr('class') || false, 13966 style = $module.attr('style') || '' 13967 ; 13968 $module.removeClass(settings.animation); 13969 module.remove.direction(); 13970 module.cache = { 13971 className : $module.attr('class'), 13972 style : module.get.style() 13973 }; 13974 module.verbose('Saving original attributes', module.cache); 13975 } 13976 }, 13977 13978 restore: { 13979 conditions: function() { 13980 if(module.cache === undefined) { 13981 return false; 13982 } 13983 if(module.cache.className) { 13984 $module.attr('class', module.cache.className); 13985 } 13986 else { 13987 $module.removeAttr('class'); 13988 } 13989 if(module.cache.style) { 13990 module.verbose('Restoring original style attribute', module.cache.style); 13991 $module.attr('style', module.cache.style); 13992 } 13993 else { 13994 module.verbose('Clearing style attribute'); 13995 $module.removeAttr('style'); 13996 } 13997 module.verbose('Restoring original attributes', module.cache); 13998 } 13999 }, 14000 14001 add: { 14002 failSafe: function() { 14003 var 14004 duration = module.get.duration() 14005 ; 14006 module.timer = setTimeout(function() { 14007 $module.trigger(animationEnd); 14008 }, duration + settings.failSafeDelay); 14009 module.verbose('Adding fail safe timer', module.timer); 14010 } 14011 }, 14012 14013 remove: { 14014 animating: function() { 14015 $module.removeClass(className.animating); 14016 }, 14017 animation: function() { 14018 $module 14019 .css({ 14020 '-webkit-animation' : '', 14021 '-moz-animation' : '', 14022 '-ms-animation' : '', 14023 '-o-animation' : '', 14024 'animation' : '' 14025 }) 14026 ; 14027 }, 14028 animationCallbacks: function() { 14029 module.remove.queueCallback(); 14030 module.remove.completeCallback(); 14031 }, 14032 queueCallback: function() { 14033 $module.off('.queue' + eventNamespace) 14034 }, 14035 completeCallback: function() { 14036 $module.off('.complete' + eventNamespace); 14037 }, 14038 display: function() { 14039 $module.css('display', ''); 14040 }, 14041 direction: function() { 14042 $module 14043 .removeClass(className.inward) 14044 .removeClass(className.outward) 14045 ; 14046 }, 14047 failSafe: function() { 14048 module.verbose('Removing fail safe timer', module.timer); 14049 if(module.timer) { 14050 clearTimeout(module.timer); 14051 } 14052 }, 14053 hidden: function() { 14054 $module.removeClass(className.hidden); 14055 }, 14056 visible: function() { 14057 $module.removeClass(className.visible); 14058 }, 14059 looping: function() { 14060 module.debug('Transitions are no longer looping'); 14061 if( module.is.looping() ) { 14062 module.reset(); 14063 $module 14064 .removeClass(className.looping) 14065 ; 14066 } 14067 }, 14068 transition: function() { 14069 $module 14070 .removeClass(className.visible) 14071 .removeClass(className.hidden) 14072 ; 14073 } 14074 }, 14075 get: { 14076 settings: function(animation, duration, onComplete) { 14077 // single settings object 14078 if(typeof animation == 'object') { 14079 return $.extend(true, {}, $.fn.transition.settings, animation); 14080 } 14081 // all arguments provided 14082 else if(typeof onComplete == 'function') { 14083 return $.extend({}, $.fn.transition.settings, { 14084 animation : animation, 14085 onComplete : onComplete, 14086 duration : duration 14087 }); 14088 } 14089 // only duration provided 14090 else if(typeof duration == 'string' || typeof duration == 'number') { 14091 return $.extend({}, $.fn.transition.settings, { 14092 animation : animation, 14093 duration : duration 14094 }); 14095 } 14096 // duration is actually settings object 14097 else if(typeof duration == 'object') { 14098 return $.extend({}, $.fn.transition.settings, duration, { 14099 animation : animation 14100 }); 14101 } 14102 // duration is actually callback 14103 else if(typeof duration == 'function') { 14104 return $.extend({}, $.fn.transition.settings, { 14105 animation : animation, 14106 onComplete : duration 14107 }); 14108 } 14109 // only animation provided 14110 else { 14111 return $.extend({}, $.fn.transition.settings, { 14112 animation : animation 14113 }); 14114 } 14115 return $.fn.transition.settings; 14116 }, 14117 direction: function(animation) { 14118 // quickest manually specified direction 14119 animation = animation || settings.animation; 14120 if(typeof animation === 'string') { 14121 animation = animation.split(' '); 14122 $.each(animation, function(index, word){ 14123 if(word === className.inward) { 14124 return className.inward; 14125 } 14126 else if(word === className.outward) { 14127 return className.outward; 14128 } 14129 }); 14130 } 14131 // slower backup 14132 if( !module.can.transition() ) { 14133 return 'static'; 14134 } 14135 if($module.is(':visible') && !module.is.hidden()) { 14136 return className.outward; 14137 } 14138 else { 14139 return className.inward; 14140 } 14141 }, 14142 duration: function(duration) { 14143 duration = duration || settings.duration; 14144 if(duration === false) { 14145 duration = $module.css('animation-duration') || 0; 14146 } 14147 return (typeof duration === 'string') 14148 ? (duration.indexOf('ms') > -1) 14149 ? parseFloat(duration) 14150 : parseFloat(duration) * 1000 14151 : duration 14152 ; 14153 }, 14154 displayType: function() { 14155 if(settings.displayType) { 14156 return settings.displayType; 14157 } 14158 if($module.data(metadata.displayType) === undefined) { 14159 // create fake element to determine display state 14160 module.can.transition(true); 14161 } 14162 return $module.data(metadata.displayType); 14163 }, 14164 style: function() { 14165 var 14166 style = $module.attr('style') || '' 14167 ; 14168 return style.replace(/display.*?;/, ''); 14169 }, 14170 transitionExists: function(animation) { 14171 return $.fn.transition.exists[animation]; 14172 }, 14173 animationName: function() { 14174 var 14175 element = document.createElement('div'), 14176 animations = { 14177 'animation' :'animationName', 14178 'OAnimation' :'oAnimationName', 14179 'MozAnimation' :'mozAnimationName', 14180 'WebkitAnimation' :'webkitAnimationName' 14181 }, 14182 animation 14183 ; 14184 for(animation in animations){ 14185 if( element.style[animation] !== undefined ){ 14186 return animations[animation]; 14187 } 14188 } 14189 return false; 14190 }, 14191 animationStartEvent: function() { 14192 var 14193 element = document.createElement('div'), 14194 animations = { 14195 'animation' :'animationstart', 14196 'OAnimation' :'oAnimationStart', 14197 'MozAnimation' :'mozAnimationStart', 14198 'WebkitAnimation' :'webkitAnimationStart' 14199 }, 14200 animation 14201 ; 14202 for(animation in animations){ 14203 if( element.style[animation] !== undefined ){ 14204 return animations[animation]; 14205 } 14206 } 14207 return false; 14208 }, 14209 animationEndEvent: function() { 14210 var 14211 element = document.createElement('div'), 14212 animations = { 14213 'animation' :'animationend', 14214 'OAnimation' :'oAnimationEnd', 14215 'MozAnimation' :'mozAnimationEnd', 14216 'WebkitAnimation' :'webkitAnimationEnd' 14217 }, 14218 animation 14219 ; 14220 for(animation in animations){ 14221 if( element.style[animation] !== undefined ){ 14222 return animations[animation]; 14223 } 14224 } 14225 return false; 14226 } 14227 14228 }, 14229 14230 can: { 14231 transition: function(forced) { 14232 var 14233 elementClass = $module.attr('class'), 14234 tagName = $module.prop('tagName'), 14235 animation = settings.animation, 14236 transitionExists = module.get.transitionExists(animation), 14237 $clone, 14238 currentAnimation, 14239 inAnimation, 14240 directionExists, 14241 displayType 14242 ; 14243 if( transitionExists === undefined || forced) { 14244 module.verbose('Determining whether animation exists'); 14245 $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module); 14246 currentAnimation = $clone 14247 .addClass(animation) 14248 .removeClass(className.inward) 14249 .removeClass(className.outward) 14250 .addClass(className.animating) 14251 .addClass(className.transition) 14252 .css(animationName) 14253 ; 14254 inAnimation = $clone 14255 .addClass(className.inward) 14256 .css(animationName) 14257 ; 14258 displayType = $clone 14259 .attr('class', elementClass) 14260 .removeAttr('style') 14261 .removeClass(className.hidden) 14262 .removeClass(className.visible) 14263 .show() 14264 .css('display') 14265 ; 14266 module.verbose('Determining final display state', displayType); 14267 module.save.displayType(displayType); 14268 14269 $clone.remove(); 14270 if(currentAnimation != inAnimation) { 14271 module.debug('Direction exists for animation', animation); 14272 directionExists = true; 14273 } 14274 else if(currentAnimation == 'none' || !currentAnimation) { 14275 module.debug('No animation defined in css', animation); 14276 return; 14277 } 14278 else { 14279 module.debug('Static animation found', animation, displayType); 14280 directionExists = false; 14281 } 14282 module.save.transitionExists(animation, directionExists); 14283 } 14284 return (transitionExists !== undefined) 14285 ? transitionExists 14286 : directionExists 14287 ; 14288 }, 14289 animate: function() { 14290 // can transition does not return a value if animation does not exist 14291 return (module.can.transition() !== undefined); 14292 } 14293 }, 14294 14295 is: { 14296 animating: function() { 14297 return $module.hasClass(className.animating); 14298 }, 14299 inward: function() { 14300 return $module.hasClass(className.inward); 14301 }, 14302 outward: function() { 14303 return $module.hasClass(className.outward); 14304 }, 14305 looping: function() { 14306 return $module.hasClass(className.looping); 14307 }, 14308 occurring: function(animation) { 14309 animation = animation || settings.animation; 14310 animation = '.' + animation.replace(' ', '.'); 14311 return ( $module.filter(animation).length > 0 ); 14312 }, 14313 visible: function() { 14314 return $module.is(':visible'); 14315 }, 14316 hidden: function() { 14317 return $module.css('visibility') === 'hidden'; 14318 }, 14319 supported: function() { 14320 return(animationName !== false && animationEnd !== false); 14321 } 14322 }, 14323 14324 hide: function() { 14325 module.verbose('Hiding element'); 14326 if( module.is.animating() ) { 14327 module.reset(); 14328 } 14329 module.remove.display(); 14330 module.remove.visible(); 14331 module.set.hidden(); 14332 module.repaint(); 14333 }, 14334 14335 show: function(display) { 14336 module.verbose('Showing element', display); 14337 module.remove.hidden(); 14338 module.set.visible(); 14339 module.set.display(); 14340 module.repaint(); 14341 }, 14342 14343 toggle: function() { 14344 if( module.is.visible() ) { 14345 module.hide(); 14346 } 14347 else { 14348 module.show(); 14349 } 14350 }, 14351 14352 stop: function() { 14353 module.debug('Stopping current animation'); 14354 $module.trigger(animationEnd); 14355 }, 14356 14357 stopAll: function() { 14358 module.debug('Stopping all animation'); 14359 module.remove.queueCallback(); 14360 $module.trigger(animationEnd); 14361 }, 14362 14363 clear: { 14364 queue: function() { 14365 module.debug('Clearing animation queue') 14366 module.remove.queueCallback(); 14367 } 14368 }, 14369 14370 enable: function() { 14371 module.verbose('Starting animation'); 14372 $module.removeClass(className.disabled); 14373 }, 14374 14375 disable: function() { 14376 module.debug('Stopping animation'); 14377 $module.addClass(className.disabled); 14378 }, 14379 14380 setting: function(name, value) { 14381 module.debug('Changing setting', name, value); 14382 if( $.isPlainObject(name) ) { 14383 $.extend(true, settings, name); 14384 } 14385 else if(value !== undefined) { 14386 settings[name] = value; 14387 } 14388 else { 14389 return settings[name]; 14390 } 14391 }, 14392 internal: function(name, value) { 14393 if( $.isPlainObject(name) ) { 14394 $.extend(true, module, name); 14395 } 14396 else if(value !== undefined) { 14397 module[name] = value; 14398 } 14399 else { 14400 return module[name]; 14401 } 14402 }, 14403 debug: function() { 14404 if(settings.debug) { 14405 if(settings.performance) { 14406 module.performance.log(arguments); 14407 } 14408 else { 14409 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 14410 module.debug.apply(console, arguments); 14411 } 14412 } 14413 }, 14414 verbose: function() { 14415 if(settings.verbose && settings.debug) { 14416 if(settings.performance) { 14417 module.performance.log(arguments); 14418 } 14419 else { 14420 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 14421 module.verbose.apply(console, arguments); 14422 } 14423 } 14424 }, 14425 error: function() { 14426 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 14427 module.error.apply(console, arguments); 14428 }, 14429 performance: { 14430 log: function(message) { 14431 var 14432 currentTime, 14433 executionTime, 14434 previousTime 14435 ; 14436 if(settings.performance) { 14437 currentTime = new Date().getTime(); 14438 previousTime = time || currentTime; 14439 executionTime = currentTime - previousTime; 14440 time = currentTime; 14441 performance.push({ 14442 'Name' : message[0], 14443 'Arguments' : [].slice.call(message, 1) || '', 14444 'Element' : element, 14445 'Execution Time' : executionTime 14446 }); 14447 } 14448 clearTimeout(module.performance.timer); 14449 module.performance.timer = setTimeout(module.performance.display, 100); 14450 }, 14451 display: function() { 14452 var 14453 title = settings.name + ':', 14454 totalTime = 0 14455 ; 14456 time = false; 14457 clearTimeout(module.performance.timer); 14458 $.each(performance, function(index, data) { 14459 totalTime += data['Execution Time']; 14460 }); 14461 title += ' ' + totalTime + 'ms'; 14462 if(moduleSelector) { 14463 title += ' \'' + moduleSelector + '\''; 14464 } 14465 if($allModules.length > 1) { 14466 title += ' ' + '(' + $allModules.length + ')'; 14467 } 14468 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 14469 console.groupCollapsed(title); 14470 if(console.table) { 14471 console.table(performance); 14472 } 14473 else { 14474 $.each(performance, function(index, data) { 14475 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 14476 }); 14477 } 14478 console.groupEnd(); 14479 } 14480 performance = []; 14481 } 14482 }, 14483 // modified for transition to return invoke success 14484 invoke: function(query, passedArguments, context) { 14485 var 14486 object = instance, 14487 maxDepth, 14488 found, 14489 response 14490 ; 14491 passedArguments = passedArguments || queryArguments; 14492 context = element || context; 14493 if(typeof query == 'string' && object !== undefined) { 14494 query = query.split(/[\. ]/); 14495 maxDepth = query.length - 1; 14496 $.each(query, function(depth, value) { 14497 var camelCaseValue = (depth != maxDepth) 14498 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 14499 : query 14500 ; 14501 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 14502 object = object[camelCaseValue]; 14503 } 14504 else if( object[camelCaseValue] !== undefined ) { 14505 found = object[camelCaseValue]; 14506 return false; 14507 } 14508 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 14509 object = object[value]; 14510 } 14511 else if( object[value] !== undefined ) { 14512 found = object[value]; 14513 return false; 14514 } 14515 else { 14516 return false; 14517 } 14518 }); 14519 } 14520 if ( $.isFunction( found ) ) { 14521 response = found.apply(context, passedArguments); 14522 } 14523 else if(found !== undefined) { 14524 response = found; 14525 } 14526 14527 if($.isArray(returnedValue)) { 14528 returnedValue.push(response); 14529 } 14530 else if(returnedValue !== undefined) { 14531 returnedValue = [returnedValue, response]; 14532 } 14533 else if(response !== undefined) { 14534 returnedValue = response; 14535 } 14536 return (found !== undefined) 14537 ? found 14538 : false 14539 ; 14540 } 14541 }; 14542 module.initialize(); 14543 }) 14544 ; 14545 return (returnedValue !== undefined) 14546 ? returnedValue 14547 : this 14548 ; 14549 }; 14550 14551 // Records if CSS transition is available 14552 $.fn.transition.exists = {}; 14553 14554 $.fn.transition.settings = { 14555 14556 // module info 14557 name : 'Transition', 14558 14559 // debug content outputted to console 14560 debug : false, 14561 14562 // verbose debug output 14563 verbose : true, 14564 14565 // performance data output 14566 performance : true, 14567 14568 // event namespace 14569 namespace : 'transition', 14570 14571 // delay between animations in group 14572 interval : 0, 14573 14574 // whether group animations should be reversed 14575 reverse : 'auto', 14576 14577 // animation callback event 14578 onStart : function() {}, 14579 onComplete : function() {}, 14580 onShow : function() {}, 14581 onHide : function() {}, 14582 14583 // whether timeout should be used to ensure callback fires in cases animationend does not 14584 useFailSafe : true, 14585 14586 // delay in ms for fail safe 14587 failSafeDelay : 100, 14588 14589 // whether EXACT animation can occur twice in a row 14590 allowRepeats : false, 14591 14592 // Override final display type on visible 14593 displayType : false, 14594 14595 // animation duration 14596 animation : 'fade', 14597 duration : false, 14598 14599 // new animations will occur after previous ones 14600 queue : true, 14601 14602 metadata : { 14603 displayType: 'display' 14604 }, 14605 14606 className : { 14607 animating : 'animating', 14608 disabled : 'disabled', 14609 hidden : 'hidden', 14610 inward : 'in', 14611 loading : 'loading', 14612 looping : 'looping', 14613 outward : 'out', 14614 transition : 'transition', 14615 visible : 'visible' 14616 }, 14617 14618 // possible errors 14619 error: { 14620 noAnimation : 'There is no css animation matching the one you specified.', 14621 repeated : 'That animation is already occurring, cancelling repeated animation', 14622 method : 'The method you called is not defined', 14623 support : 'This browser does not support CSS animations' 14624 } 14625 14626 }; 14627 14628 14629 })( jQuery, window , document ); 14630 14631 /*! 14632 * # Semantic UI x.x - Video 14633 * http://github.com/semantic-org/semantic-ui/ 14634 * 14635 * 14636 * Copyright 2014 Contributorss 14637 * Released under the MIT license 14638 * http://opensource.org/licenses/MIT 14639 * 14640 */ 14641 14642 ;(function ($, window, document, undefined) { 14643 14644 "use strict"; 14645 14646 $.fn.video = function(parameters) { 14647 14648 var 14649 $allModules = $(this), 14650 14651 moduleSelector = $allModules.selector || '', 14652 14653 time = new Date().getTime(), 14654 performance = [], 14655 14656 query = arguments[0], 14657 methodInvoked = (typeof query == 'string'), 14658 queryArguments = [].slice.call(arguments, 1), 14659 14660 requestAnimationFrame = window.requestAnimationFrame 14661 || window.mozRequestAnimationFrame 14662 || window.webkitRequestAnimationFrame 14663 || window.msRequestAnimationFrame 14664 || function(callback) { setTimeout(callback, 0); }, 14665 14666 returnedValue 14667 ; 14668 14669 $allModules 14670 .each(function() { 14671 var 14672 settings = ( $.isPlainObject(parameters) ) 14673 ? $.extend(true, {}, $.fn.video.settings, parameters) 14674 : $.extend({}, $.fn.video.settings), 14675 14676 selector = settings.selector, 14677 className = settings.className, 14678 error = settings.error, 14679 metadata = settings.metadata, 14680 namespace = settings.namespace, 14681 templates = settings.templates, 14682 14683 eventNamespace = '.' + namespace, 14684 moduleNamespace = 'module-' + namespace, 14685 14686 $window = $(window), 14687 $module = $(this), 14688 $placeholder = $module.find(selector.placeholder), 14689 $playButton = $module.find(selector.playButton), 14690 $embed = $module.find(selector.embed), 14691 14692 element = this, 14693 instance = $module.data(moduleNamespace), 14694 module 14695 ; 14696 14697 module = { 14698 14699 initialize: function() { 14700 module.debug('Initializing video'); 14701 module.create(); 14702 $placeholder 14703 .on('click' + eventNamespace, module.play) 14704 ; 14705 $playButton 14706 .on('click' + eventNamespace, module.play) 14707 ; 14708 module.instantiate(); 14709 }, 14710 14711 instantiate: function() { 14712 module.verbose('Storing instance of module', module); 14713 instance = module; 14714 $module 14715 .data(moduleNamespace, module) 14716 ; 14717 }, 14718 14719 create: function() { 14720 var 14721 image = $module.data(metadata.image), 14722 html = templates.video(image) 14723 ; 14724 $module.html(html); 14725 module.refresh(); 14726 if(!image) { 14727 module.play(); 14728 } 14729 module.debug('Creating html for video element', html); 14730 }, 14731 14732 destroy: function() { 14733 module.verbose('Destroying previous instance of video'); 14734 module.reset(); 14735 $module 14736 .removeData(moduleNamespace) 14737 .off(eventNamespace) 14738 ; 14739 $placeholder 14740 .off(eventNamespace) 14741 ; 14742 $playButton 14743 .off(eventNamespace) 14744 ; 14745 }, 14746 14747 refresh: function() { 14748 module.verbose('Refreshing selector cache'); 14749 $placeholder = $module.find(selector.placeholder); 14750 $playButton = $module.find(selector.playButton); 14751 $embed = $module.find(selector.embed); 14752 }, 14753 14754 // sets new video 14755 change: function(source, id, url) { 14756 module.debug('Changing video to ', source, id, url); 14757 $module 14758 .data(metadata.source, source) 14759 .data(metadata.id, id) 14760 .data(metadata.url, url) 14761 ; 14762 settings.onChange(); 14763 }, 14764 14765 // clears video embed 14766 reset: function() { 14767 module.debug('Clearing video embed and showing placeholder'); 14768 $module 14769 .removeClass(className.active) 14770 ; 14771 $embed 14772 .html(' ') 14773 ; 14774 $placeholder 14775 .show() 14776 ; 14777 settings.onReset(); 14778 }, 14779 14780 // plays current video 14781 play: function() { 14782 module.debug('Playing video'); 14783 var 14784 source = $module.data(metadata.source) || false, 14785 url = $module.data(metadata.url) || false, 14786 id = $module.data(metadata.id) || false 14787 ; 14788 $embed 14789 .html( module.generate.html(source, id, url) ) 14790 ; 14791 $module 14792 .addClass(className.active) 14793 ; 14794 settings.onPlay(); 14795 }, 14796 14797 get: { 14798 source: function(url) { 14799 if(typeof url !== 'string') { 14800 return false; 14801 } 14802 if(url.search('youtube.com') !== -1) { 14803 return 'youtube'; 14804 } 14805 else if(url.search('vimeo.com') !== -1) { 14806 return 'vimeo'; 14807 } 14808 return false; 14809 }, 14810 id: function(url) { 14811 if(url.match(settings.regExp.youtube)) { 14812 return url.match(settings.regExp.youtube)[1]; 14813 } 14814 else if(url.match(settings.regExp.vimeo)) { 14815 return url.match(settings.regExp.vimeo)[2]; 14816 } 14817 return false; 14818 } 14819 }, 14820 14821 generate: { 14822 // generates iframe html 14823 html: function(source, id, url) { 14824 module.debug('Generating embed html'); 14825 var 14826 html 14827 ; 14828 // allow override of settings 14829 source = source || settings.source; 14830 id = id || settings.id; 14831 if((source && id) || url) { 14832 if(!source || !id) { 14833 source = module.get.source(url); 14834 id = module.get.id(url); 14835 } 14836 if(source == 'vimeo') { 14837 html = '' 14838 + '<iframe src="//player.vimeo.com/video/' + id + '?=' + module.generate.url(source) + '"' 14839 + ' width="100%" height="100%"' 14840 + ' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>' 14841 ; 14842 } 14843 else if(source == 'youtube') { 14844 html = '' 14845 + '<iframe src="//www.youtube.com/embed/' + id + '?=' + module.generate.url(source) + '"' 14846 + ' width="100%" height="100%"' 14847 + ' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>' 14848 ; 14849 } 14850 } 14851 else { 14852 module.error(error.noVideo); 14853 } 14854 return html; 14855 }, 14856 14857 // generate url parameters 14858 url: function(source) { 14859 var 14860 api = (settings.api) 14861 ? 1 14862 : 0, 14863 autoplay = (settings.autoplay === 'auto') 14864 ? ($module.data('image') !== undefined) 14865 : settings.autoplay, 14866 hd = (settings.hd) 14867 ? 1 14868 : 0, 14869 showUI = (settings.showUI) 14870 ? 1 14871 : 0, 14872 // opposite used for some params 14873 hideUI = !(settings.showUI) 14874 ? 1 14875 : 0, 14876 url = '' 14877 ; 14878 if(source == 'vimeo') { 14879 url = '' 14880 + 'api=' + api 14881 + '&title=' + showUI 14882 + '&byline=' + showUI 14883 + '&portrait=' + showUI 14884 + '&autoplay=' + autoplay 14885 ; 14886 if(settings.color) { 14887 url += '&color=' + settings.color; 14888 } 14889 } 14890 if(source == 'ustream') { 14891 url = '' 14892 + 'autoplay=' + autoplay 14893 ; 14894 if(settings.color) { 14895 url += '&color=' + settings.color; 14896 } 14897 } 14898 else if(source == 'youtube') { 14899 url = '' 14900 + 'enablejsapi=' + api 14901 + '&autoplay=' + autoplay 14902 + '&autohide=' + hideUI 14903 + '&hq=' + hd 14904 + '&modestbranding=1' 14905 ; 14906 if(settings.color) { 14907 url += '&color=' + settings.color; 14908 } 14909 } 14910 return url; 14911 } 14912 }, 14913 14914 setting: function(name, value) { 14915 module.debug('Changing setting', name, value); 14916 if( $.isPlainObject(name) ) { 14917 $.extend(true, settings, name); 14918 } 14919 else if(value !== undefined) { 14920 settings[name] = value; 14921 } 14922 else { 14923 return settings[name]; 14924 } 14925 }, 14926 internal: function(name, value) { 14927 if( $.isPlainObject(name) ) { 14928 $.extend(true, module, name); 14929 } 14930 else if(value !== undefined) { 14931 module[name] = value; 14932 } 14933 else { 14934 return module[name]; 14935 } 14936 }, 14937 debug: function() { 14938 if(settings.debug) { 14939 if(settings.performance) { 14940 module.performance.log(arguments); 14941 } 14942 else { 14943 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 14944 module.debug.apply(console, arguments); 14945 } 14946 } 14947 }, 14948 verbose: function() { 14949 if(settings.verbose && settings.debug) { 14950 if(settings.performance) { 14951 module.performance.log(arguments); 14952 } 14953 else { 14954 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 14955 module.verbose.apply(console, arguments); 14956 } 14957 } 14958 }, 14959 error: function() { 14960 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 14961 module.error.apply(console, arguments); 14962 }, 14963 performance: { 14964 log: function(message) { 14965 var 14966 currentTime, 14967 executionTime, 14968 previousTime 14969 ; 14970 if(settings.performance) { 14971 currentTime = new Date().getTime(); 14972 previousTime = time || currentTime; 14973 executionTime = currentTime - previousTime; 14974 time = currentTime; 14975 performance.push({ 14976 'Name' : message[0], 14977 'Arguments' : [].slice.call(message, 1) || '', 14978 'Element' : element, 14979 'Execution Time' : executionTime 14980 }); 14981 } 14982 clearTimeout(module.performance.timer); 14983 module.performance.timer = setTimeout(module.performance.display, 100); 14984 }, 14985 display: function() { 14986 var 14987 title = settings.name + ':', 14988 totalTime = 0 14989 ; 14990 time = false; 14991 clearTimeout(module.performance.timer); 14992 $.each(performance, function(index, data) { 14993 totalTime += data['Execution Time']; 14994 }); 14995 title += ' ' + totalTime + 'ms'; 14996 if(moduleSelector) { 14997 title += ' \'' + moduleSelector + '\''; 14998 } 14999 if($allModules.length > 1) { 15000 title += ' ' + '(' + $allModules.length + ')'; 15001 } 15002 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 15003 console.groupCollapsed(title); 15004 if(console.table) { 15005 console.table(performance); 15006 } 15007 else { 15008 $.each(performance, function(index, data) { 15009 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 15010 }); 15011 } 15012 console.groupEnd(); 15013 } 15014 performance = []; 15015 } 15016 }, 15017 invoke: function(query, passedArguments, context) { 15018 var 15019 object = instance, 15020 maxDepth, 15021 found, 15022 response 15023 ; 15024 passedArguments = passedArguments || queryArguments; 15025 context = element || context; 15026 if(typeof query == 'string' && object !== undefined) { 15027 query = query.split(/[\. ]/); 15028 maxDepth = query.length - 1; 15029 $.each(query, function(depth, value) { 15030 var camelCaseValue = (depth != maxDepth) 15031 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 15032 : query 15033 ; 15034 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 15035 object = object[camelCaseValue]; 15036 } 15037 else if( object[camelCaseValue] !== undefined ) { 15038 found = object[camelCaseValue]; 15039 return false; 15040 } 15041 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 15042 object = object[value]; 15043 } 15044 else if( object[value] !== undefined ) { 15045 found = object[value]; 15046 return false; 15047 } 15048 else { 15049 module.error(error.method, query); 15050 return false; 15051 } 15052 }); 15053 } 15054 if ( $.isFunction( found ) ) { 15055 response = found.apply(context, passedArguments); 15056 } 15057 else if(found !== undefined) { 15058 response = found; 15059 } 15060 if($.isArray(returnedValue)) { 15061 returnedValue.push(response); 15062 } 15063 else if(returnedValue !== undefined) { 15064 returnedValue = [returnedValue, response]; 15065 } 15066 else if(response !== undefined) { 15067 returnedValue = response; 15068 } 15069 return found; 15070 } 15071 }; 15072 15073 if(methodInvoked) { 15074 if(instance === undefined) { 15075 module.initialize(); 15076 } 15077 module.invoke(query); 15078 } 15079 else { 15080 if(instance !== undefined) { 15081 instance.invoke('destroy'); 15082 } 15083 module.initialize(); 15084 } 15085 }) 15086 ; 15087 return (returnedValue !== undefined) 15088 ? returnedValue 15089 : this 15090 ; 15091 }; 15092 15093 $.fn.video.settings = { 15094 15095 name : 'Video', 15096 namespace : 'video', 15097 15098 debug : false, 15099 verbose : true, 15100 performance : true, 15101 15102 metadata : { 15103 id : 'id', 15104 image : 'image', 15105 source : 'source', 15106 url : 'url' 15107 }, 15108 15109 source : false, 15110 url : false, 15111 id : false, 15112 15113 aspectRatio : (16/9), 15114 15115 onPlay : function(){}, 15116 onReset : function(){}, 15117 onChange : function(){}, 15118 15119 // callbacks not coded yet (needs to use jsapi) 15120 onPause : function() {}, 15121 onStop : function() {}, 15122 15123 width : 'auto', 15124 height : 'auto', 15125 15126 autoplay : 'auto', 15127 color : '#442359', 15128 hd : true, 15129 showUI : false, 15130 api : true, 15131 15132 regExp : { 15133 youtube : /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/, 15134 vimeo : /http:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/ 15135 }, 15136 15137 error : { 15138 noVideo : 'No video specified', 15139 method : 'The method you called is not defined' 15140 }, 15141 15142 className : { 15143 active : 'active' 15144 }, 15145 15146 selector : { 15147 embed : '.embed', 15148 placeholder : '.placeholder', 15149 playButton : '.play' 15150 } 15151 }; 15152 15153 $.fn.video.settings.templates = { 15154 video: function(image) { 15155 var 15156 html = '' 15157 ; 15158 if(image) { 15159 html += '' 15160 + '<i class="video play icon"></i>' 15161 + '<img class="placeholder" src="' + image + '">' 15162 ; 15163 } 15164 html += '<div class="embed"></div>'; 15165 return html; 15166 } 15167 }; 15168 15169 15170 })( jQuery, window , document ); 15171 15172 /*! 15173 * # Semantic UI x.x - API 15174 * http://github.com/semantic-org/semantic-ui/ 15175 * 15176 * 15177 * Copyright 2014 Contributors 15178 * Released under the MIT license 15179 * http://opensource.org/licenses/MIT 15180 * 15181 */ 15182 15183 ;(function ( $, window, document, undefined ) { 15184 15185 "use strict"; 15186 15187 $.api = $.fn.api = function(parameters) { 15188 15189 var 15190 // use window context if none specified 15191 $allModules = $.isFunction(this) 15192 ? $(window) 15193 : $(this), 15194 moduleSelector = $allModules.selector || '', 15195 time = new Date().getTime(), 15196 performance = [], 15197 15198 query = arguments[0], 15199 methodInvoked = (typeof query == 'string'), 15200 queryArguments = [].slice.call(arguments, 1), 15201 15202 returnedValue 15203 ; 15204 15205 $allModules 15206 .each(function() { 15207 var 15208 settings = ( $.isPlainObject(parameters) ) 15209 ? $.extend(true, {}, $.fn.api.settings, parameters) 15210 : $.extend({}, $.fn.api.settings), 15211 15212 // internal aliases 15213 namespace = settings.namespace, 15214 metadata = settings.metadata, 15215 selector = settings.selector, 15216 error = settings.error, 15217 className = settings.className, 15218 15219 // define namespaces for modules 15220 eventNamespace = '.' + namespace, 15221 moduleNamespace = 'module-' + namespace, 15222 15223 // element that creates request 15224 $module = $(this), 15225 $form = $module.closest(selector.form), 15226 15227 // context used for state 15228 $context = (settings.stateContext) 15229 ? $(settings.stateContext) 15230 : $module, 15231 15232 // request details 15233 ajaxSettings, 15234 requestSettings, 15235 url, 15236 data, 15237 15238 // standard module 15239 element = this, 15240 context = $context.get(), 15241 instance = $module.data(moduleNamespace), 15242 module 15243 ; 15244 15245 module = { 15246 15247 initialize: function() { 15248 var 15249 triggerEvent = module.get.event() 15250 ; 15251 // bind events 15252 if(!methodInvoked) { 15253 if( triggerEvent ) { 15254 module.debug('Attaching API events to element', triggerEvent); 15255 $module 15256 .on(triggerEvent + eventNamespace, module.event.trigger) 15257 ; 15258 } 15259 else if(settings.on == 'now') { 15260 module.debug('Querying API now', triggerEvent); 15261 module.query(); 15262 } 15263 } 15264 module.instantiate(); 15265 }, 15266 15267 instantiate: function() { 15268 module.verbose('Storing instance of module', module); 15269 instance = module; 15270 $module 15271 .data(moduleNamespace, instance) 15272 ; 15273 }, 15274 15275 destroy: function() { 15276 module.verbose('Destroying previous module for', element); 15277 $module 15278 .removeData(moduleNamespace) 15279 .off(eventNamespace) 15280 ; 15281 }, 15282 15283 query: function() { 15284 15285 if(module.is.disabled()) { 15286 module.debug('Element is disabled API request aborted'); 15287 return; 15288 } 15289 // determine if an api event already occurred 15290 if(module.is.loading() && settings.throttle === 0 ) { 15291 module.debug('Cancelling request, previous request is still pending'); 15292 return; 15293 } 15294 15295 // pass element metadata to url (value, text) 15296 if(settings.defaultData) { 15297 $.extend(true, settings.urlData, module.get.defaultData()); 15298 } 15299 15300 // Add form content 15301 if(settings.serializeForm !== false || $context.is('form')) { 15302 if(settings.serializeForm == 'json') { 15303 $.extend(true, settings.data, module.get.formData()); 15304 } 15305 else { 15306 settings.data = module.get.formData(); 15307 } 15308 } 15309 15310 // call beforesend and get any settings changes 15311 requestSettings = module.get.settings(); 15312 15313 // check if before send cancelled request 15314 if(requestSettings === false) { 15315 module.cancelled = true; 15316 module.error(error.beforeSend); 15317 return; 15318 } 15319 else { 15320 module.cancelled = false; 15321 } 15322 15323 if(settings.url) { 15324 // override with url if specified 15325 module.debug('Using specified url', url); 15326 url = module.add.urlData( settings.url ); 15327 } 15328 else { 15329 // otherwise find url from api endpoints 15330 url = module.add.urlData( module.get.templateURL() ); 15331 module.debug('Added URL Data to url', url); 15332 } 15333 15334 // exit conditions reached, missing url parameters 15335 if( !url ) { 15336 if( module.is.form() ) { 15337 url = $module.attr('action') || ''; 15338 module.debug('No url or action specified, defaulting to form action', url); 15339 } 15340 else { 15341 module.error(error.missingURL, settings.action); 15342 return; 15343 } 15344 } 15345 15346 // add loading state 15347 module.set.loading(); 15348 15349 // look for jQuery ajax parameters in settings 15350 ajaxSettings = $.extend(true, {}, settings, { 15351 type : settings.method || settings.type, 15352 data : data, 15353 url : settings.base + url, 15354 beforeSend : settings.beforeXHR, 15355 success : function() {}, 15356 failure : function() {}, 15357 complete : function() {} 15358 }); 15359 15360 module.debug('Querying URL', ajaxSettings.url); 15361 module.debug('Sending data', data, ajaxSettings.method); 15362 module.verbose('Using AJAX settings', ajaxSettings); 15363 15364 if( module.is.loading() ) { 15365 // throttle additional requests 15366 module.timer = setTimeout(function() { 15367 module.request = module.create.request(); 15368 module.xhr = module.create.xhr(); 15369 settings.onRequest.call(context, module.request, module.xhr); 15370 }, settings.throttle); 15371 } 15372 else { 15373 // immediately on first request 15374 module.request = module.create.request(); 15375 module.xhr = module.create.xhr(); 15376 settings.onRequest.call(context, module.request, module.xhr); 15377 } 15378 15379 }, 15380 15381 15382 is: { 15383 disabled: function() { 15384 return ($module.filter(settings.filter).length > 0); 15385 }, 15386 form: function() { 15387 return $module.is('form'); 15388 }, 15389 input: function() { 15390 return $module.is('input'); 15391 }, 15392 loading: function() { 15393 return (module.request && module.request.state() == 'pending'); 15394 } 15395 }, 15396 15397 was: { 15398 cancelled: function() { 15399 return (module.cancelled || false); 15400 }, 15401 succesful: function() { 15402 return (module.request && module.request.state() == 'resolved'); 15403 }, 15404 failure: function() { 15405 return (module.request && module.request.state() == 'rejected'); 15406 }, 15407 complete: function() { 15408 return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') ); 15409 } 15410 }, 15411 15412 add: { 15413 urlData: function(url, urlData) { 15414 var 15415 requiredVariables, 15416 optionalVariables 15417 ; 15418 if(url) { 15419 requiredVariables = url.match(settings.regExp.required); 15420 optionalVariables = url.match(settings.regExp.optional); 15421 urlData = urlData || settings.urlData; 15422 if(requiredVariables) { 15423 module.debug('Looking for required URL variables', requiredVariables); 15424 $.each(requiredVariables, function(index, templatedString) { 15425 var 15426 // allow legacy {$var} style 15427 variable = (templatedString.indexOf('$') !== -1) 15428 ? templatedString.substr(2, templatedString.length - 3) 15429 : templatedString.substr(1, templatedString.length - 2), 15430 value = ($.isPlainObject(urlData) && urlData[variable] !== undefined) 15431 ? urlData[variable] 15432 : ($module.data(variable) !== undefined) 15433 ? $module.data(variable) 15434 : ($context.data(variable) !== undefined) 15435 ? $context.data(variable) 15436 : urlData[variable] 15437 ; 15438 // remove value 15439 if(value === undefined) { 15440 module.error(error.requiredParameter, variable, url); 15441 url = false; 15442 return false; 15443 } 15444 else { 15445 module.verbose('Found required variable', variable, value); 15446 url = url.replace(templatedString, value); 15447 } 15448 }); 15449 } 15450 if(optionalVariables) { 15451 module.debug('Looking for optional URL variables', requiredVariables); 15452 $.each(optionalVariables, function(index, templatedString) { 15453 var 15454 // allow legacy {/$var} style 15455 variable = (templatedString.indexOf('$') !== -1) 15456 ? templatedString.substr(3, templatedString.length - 4) 15457 : templatedString.substr(2, templatedString.length - 3), 15458 value = ($.isPlainObject(urlData) && urlData[variable] !== undefined) 15459 ? urlData[variable] 15460 : ($module.data(variable) !== undefined) 15461 ? $module.data(variable) 15462 : ($context.data(variable) !== undefined) 15463 ? $context.data(variable) 15464 : urlData[variable] 15465 ; 15466 // optional replacement 15467 if(value !== undefined) { 15468 module.verbose('Optional variable Found', variable, value); 15469 url = url.replace(templatedString, value); 15470 } 15471 else { 15472 module.verbose('Optional variable not found', variable); 15473 // remove preceding slash if set 15474 if(url.indexOf('/' + templatedString) !== -1) { 15475 url = url.replace('/' + templatedString, ''); 15476 } 15477 else { 15478 url = url.replace(templatedString, ''); 15479 } 15480 } 15481 }); 15482 } 15483 } 15484 return url; 15485 } 15486 }, 15487 15488 event: { 15489 trigger: function(event) { 15490 module.query(); 15491 if(event.type == 'submit' || event.type == 'click') { 15492 event.preventDefault(); 15493 } 15494 }, 15495 xhr: { 15496 always: function() { 15497 // calculate if loading time was below minimum threshold 15498 }, 15499 done: function(response) { 15500 var 15501 context = this, 15502 elapsedTime = (new Date().getTime() - time), 15503 timeLeft = (settings.loadingDuration - elapsedTime) 15504 ; 15505 timeLeft = (timeLeft > 0) 15506 ? timeLeft 15507 : 0 15508 ; 15509 setTimeout(function() { 15510 module.request.resolveWith(context, [response]); 15511 }, timeLeft); 15512 }, 15513 fail: function(xhr, status, httpMessage) { 15514 var 15515 context = this, 15516 elapsedTime = (new Date().getTime() - time), 15517 timeLeft = (settings.loadingDuration - elapsedTime) 15518 ; 15519 timeLeft = (timeLeft > 0) 15520 ? timeLeft 15521 : 0 15522 ; 15523 // page triggers abort on navigation, dont show error 15524 setTimeout(function() { 15525 if(status !== 'abort') { 15526 module.request.rejectWith(context, [xhr, status, httpMessage]); 15527 } 15528 else { 15529 module.reset(); 15530 } 15531 }, timeLeft); 15532 } 15533 }, 15534 request: { 15535 complete: function(response) { 15536 module.remove.loading(); 15537 settings.onComplete.call(context, response, $module); 15538 }, 15539 done: function(response) { 15540 module.debug('API Response Received', response); 15541 if(settings.dataType == 'json') { 15542 if( $.isFunction(settings.successTest) ) { 15543 module.debug('Checking JSON returned success', settings.successTest, response); 15544 if( settings.successTest(response) ) { 15545 settings.onSuccess.call(context, response, $module); 15546 } 15547 else { 15548 module.debug('JSON test specified by user and response failed', response); 15549 settings.onFailure.call(context, response, $module); 15550 } 15551 } 15552 else { 15553 settings.onSuccess.call(context, response, $module); 15554 } 15555 } 15556 else { 15557 settings.onSuccess.call(context, response, $module); 15558 } 15559 }, 15560 error: function(xhr, status, httpMessage) { 15561 var 15562 errorMessage = (settings.error[status] !== undefined) 15563 ? settings.error[status] 15564 : httpMessage, 15565 response 15566 ; 15567 // let em know unless request aborted 15568 if(xhr !== undefined) { 15569 // readyState 4 = done, anything less is not really sent 15570 if(xhr.readyState !== undefined && xhr.readyState == 4) { 15571 15572 // if http status code returned and json returned error, look for it 15573 if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') { 15574 module.error(error.statusMessage + httpMessage, ajaxSettings.url); 15575 } 15576 else { 15577 if(status == 'error' && settings.dataType == 'json') { 15578 try { 15579 response = $.parseJSON(xhr.responseText); 15580 if(response && response.error !== undefined) { 15581 errorMessage = response.error; 15582 } 15583 } 15584 catch(e) { 15585 module.error(error.JSONParse); 15586 } 15587 } 15588 } 15589 module.remove.loading(); 15590 module.set.error(); 15591 // show error state only for duration specified in settings 15592 if(settings.errorDuration) { 15593 setTimeout(module.remove.error, settings.errorDuration); 15594 } 15595 module.debug('API Request error:', errorMessage); 15596 settings.onError.call(context, errorMessage, $module); 15597 } 15598 else { 15599 settings.onAbort.call(context, errorMessage, $module); 15600 module.debug('Request Aborted (Most likely caused by page change or CORS Policy)', status, httpMessage); 15601 } 15602 } 15603 } 15604 } 15605 }, 15606 15607 create: { 15608 request: function() { 15609 return $.Deferred() 15610 .always(module.event.request.complete) 15611 .done(module.event.request.done) 15612 .fail(module.event.request.error) 15613 ; 15614 }, 15615 xhr: function() { 15616 return $.ajax(ajaxSettings) 15617 .always(module.event.xhr.always) 15618 .done(module.event.xhr.done) 15619 .fail(module.event.xhr.fail) 15620 ; 15621 } 15622 }, 15623 15624 set: { 15625 error: function() { 15626 module.verbose('Adding error state to element', $context); 15627 $context.addClass(className.error); 15628 }, 15629 loading: function() { 15630 module.verbose('Adding loading state to element', $context); 15631 $context.addClass(className.loading); 15632 } 15633 }, 15634 15635 remove: { 15636 error: function() { 15637 module.verbose('Removing error state from element', $context); 15638 $context.removeClass(className.error); 15639 }, 15640 loading: function() { 15641 module.verbose('Removing loading state from element', $context); 15642 $context.removeClass(className.loading); 15643 } 15644 }, 15645 15646 get: { 15647 request: function() { 15648 return module.request || false; 15649 }, 15650 xhr: function() { 15651 return module.xhr || false; 15652 }, 15653 settings: function() { 15654 var 15655 runSettings 15656 ; 15657 runSettings = settings.beforeSend.call($module, settings); 15658 if(runSettings) { 15659 if(runSettings.success !== undefined) { 15660 module.debug('Legacy success callback detected', runSettings); 15661 module.error(error.legacyParameters, runSettings.success); 15662 runSettings.onSuccess = runSettings.success; 15663 } 15664 if(runSettings.failure !== undefined) { 15665 module.debug('Legacy failure callback detected', runSettings); 15666 module.error(error.legacyParameters, runSettings.failure); 15667 runSettings.onFailure = runSettings.failure; 15668 } 15669 if(runSettings.complete !== undefined) { 15670 module.debug('Legacy complete callback detected', runSettings); 15671 module.error(error.legacyParameters, runSettings.complete); 15672 runSettings.onComplete = runSettings.complete; 15673 } 15674 } 15675 if(runSettings === undefined) { 15676 module.error(error.noReturnedValue); 15677 } 15678 return (runSettings !== undefined) 15679 ? runSettings 15680 : settings 15681 ; 15682 }, 15683 defaultData: function() { 15684 var 15685 data = {} 15686 ; 15687 if( !$.isWindow(element) ) { 15688 if( module.is.input() ) { 15689 data.value = $module.val(); 15690 } 15691 else if( !module.is.form() ) { 15692 15693 } 15694 else { 15695 data.text = $module.text(); 15696 } 15697 } 15698 return data; 15699 }, 15700 event: function() { 15701 if( $.isWindow(element) || settings.on == 'now' ) { 15702 module.debug('API called without element, no events attached'); 15703 return false; 15704 } 15705 else if(settings.on == 'auto') { 15706 if( $module.is('input') ) { 15707 return (element.oninput !== undefined) 15708 ? 'input' 15709 : (element.onpropertychange !== undefined) 15710 ? 'propertychange' 15711 : 'keyup' 15712 ; 15713 } 15714 else if( $module.is('form') ) { 15715 return 'submit'; 15716 } 15717 else { 15718 return 'click'; 15719 } 15720 } 15721 else { 15722 return settings.on; 15723 } 15724 }, 15725 formData: function() { 15726 var 15727 formData 15728 ; 15729 if($module.serializeObject !== undefined) { 15730 formData = $form.serializeObject(); 15731 } 15732 else { 15733 module.error(error.missingSerialize); 15734 formData = $form.serialize(); 15735 } 15736 module.debug('Retrieved form data', formData); 15737 return formData; 15738 }, 15739 templateURL: function(action) { 15740 var 15741 url 15742 ; 15743 action = action || $module.data(metadata.action) || settings.action || false; 15744 if(action) { 15745 module.debug('Looking up url for action', action, settings.api); 15746 if(settings.api[action] !== undefined) { 15747 url = settings.api[action]; 15748 module.debug('Found template url', url); 15749 } 15750 else if( !module.is.form() ) { 15751 module.error(error.missingAction, settings.action, settings.api); 15752 } 15753 } 15754 return url; 15755 } 15756 }, 15757 15758 abort: function() { 15759 var 15760 xhr = module.get.xhr() 15761 ; 15762 if( xhr && xhr.state() !== 'resolved') { 15763 module.debug('Cancelling API request'); 15764 xhr.abort(); 15765 module.request.rejectWith(settings.apiSettings); 15766 } 15767 }, 15768 15769 // reset state 15770 reset: function() { 15771 module.remove.error(); 15772 module.remove.loading(); 15773 }, 15774 15775 setting: function(name, value) { 15776 module.debug('Changing setting', name, value); 15777 if( $.isPlainObject(name) ) { 15778 $.extend(true, settings, name); 15779 } 15780 else if(value !== undefined) { 15781 settings[name] = value; 15782 } 15783 else { 15784 return settings[name]; 15785 } 15786 }, 15787 internal: function(name, value) { 15788 if( $.isPlainObject(name) ) { 15789 $.extend(true, module, name); 15790 } 15791 else if(value !== undefined) { 15792 module[name] = value; 15793 } 15794 else { 15795 return module[name]; 15796 } 15797 }, 15798 debug: function() { 15799 if(settings.debug) { 15800 if(settings.performance) { 15801 module.performance.log(arguments); 15802 } 15803 else { 15804 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 15805 module.debug.apply(console, arguments); 15806 } 15807 } 15808 }, 15809 verbose: function() { 15810 if(settings.verbose && settings.debug) { 15811 if(settings.performance) { 15812 module.performance.log(arguments); 15813 } 15814 else { 15815 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 15816 module.verbose.apply(console, arguments); 15817 } 15818 } 15819 }, 15820 error: function() { 15821 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 15822 module.error.apply(console, arguments); 15823 }, 15824 performance: { 15825 log: function(message) { 15826 var 15827 currentTime, 15828 executionTime, 15829 previousTime 15830 ; 15831 if(settings.performance) { 15832 currentTime = new Date().getTime(); 15833 previousTime = time || currentTime; 15834 executionTime = currentTime - previousTime; 15835 time = currentTime; 15836 performance.push({ 15837 'Name' : message[0], 15838 'Arguments' : [].slice.call(message, 1) || '', 15839 //'Element' : element, 15840 'Execution Time' : executionTime 15841 }); 15842 } 15843 clearTimeout(module.performance.timer); 15844 module.performance.timer = setTimeout(module.performance.display, 100); 15845 }, 15846 display: function() { 15847 var 15848 title = settings.name + ':', 15849 totalTime = 0 15850 ; 15851 time = false; 15852 clearTimeout(module.performance.timer); 15853 $.each(performance, function(index, data) { 15854 totalTime += data['Execution Time']; 15855 }); 15856 title += ' ' + totalTime + 'ms'; 15857 if(moduleSelector) { 15858 title += ' \'' + moduleSelector + '\''; 15859 } 15860 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 15861 console.groupCollapsed(title); 15862 if(console.table) { 15863 console.table(performance); 15864 } 15865 else { 15866 $.each(performance, function(index, data) { 15867 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 15868 }); 15869 } 15870 console.groupEnd(); 15871 } 15872 performance = []; 15873 } 15874 }, 15875 invoke: function(query, passedArguments, context) { 15876 var 15877 object = instance, 15878 maxDepth, 15879 found, 15880 response 15881 ; 15882 passedArguments = passedArguments || queryArguments; 15883 context = element || context; 15884 if(typeof query == 'string' && object !== undefined) { 15885 query = query.split(/[\. ]/); 15886 maxDepth = query.length - 1; 15887 $.each(query, function(depth, value) { 15888 var camelCaseValue = (depth != maxDepth) 15889 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 15890 : query 15891 ; 15892 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 15893 object = object[camelCaseValue]; 15894 } 15895 else if( object[camelCaseValue] !== undefined ) { 15896 found = object[camelCaseValue]; 15897 return false; 15898 } 15899 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 15900 object = object[value]; 15901 } 15902 else if( object[value] !== undefined ) { 15903 found = object[value]; 15904 return false; 15905 } 15906 else { 15907 module.error(error.method, query); 15908 return false; 15909 } 15910 }); 15911 } 15912 if ( $.isFunction( found ) ) { 15913 response = found.apply(context, passedArguments); 15914 } 15915 else if(found !== undefined) { 15916 response = found; 15917 } 15918 if($.isArray(returnedValue)) { 15919 returnedValue.push(response); 15920 } 15921 else if(returnedValue !== undefined) { 15922 returnedValue = [returnedValue, response]; 15923 } 15924 else if(response !== undefined) { 15925 returnedValue = response; 15926 } 15927 return found; 15928 } 15929 }; 15930 15931 if(methodInvoked) { 15932 if(instance === undefined) { 15933 module.initialize(); 15934 } 15935 module.invoke(query); 15936 } 15937 else { 15938 if(instance !== undefined) { 15939 instance.invoke('destroy'); 15940 } 15941 module.initialize(); 15942 } 15943 }) 15944 ; 15945 15946 return (returnedValue !== undefined) 15947 ? returnedValue 15948 : this 15949 ; 15950 }; 15951 15952 $.api.settings = { 15953 15954 name : 'API', 15955 namespace : 'api', 15956 15957 debug : true, 15958 verbose : false, 15959 performance : true, 15960 15961 // event binding 15962 on : 'auto', 15963 filter : '.disabled', 15964 stateContext : false, 15965 15966 // state 15967 loadingDuration : 0, 15968 errorDuration : 2000, 15969 15970 // templating 15971 action : false, 15972 url : false, 15973 base : '', 15974 15975 // data 15976 urlData : {}, 15977 15978 // ui 15979 defaultData : true, 15980 serializeForm : false, 15981 throttle : 0, 15982 15983 // jQ ajax 15984 method : 'get', 15985 data : {}, 15986 dataType : 'json', 15987 15988 // callbacks 15989 beforeSend : function(settings) { return settings; }, 15990 beforeXHR : function(xhr) {}, 15991 15992 onRequest : function(promise, xhr) {}, 15993 onSuccess : function(response, $module) {}, 15994 onComplete : function(response, $module) {}, 15995 onFailure : function(errorMessage, $module) {}, 15996 onError : function(errorMessage, $module) {}, 15997 onAbort : function(errorMessage, $module) {}, 15998 15999 successTest : false, 16000 16001 // errors 16002 error : { 16003 beforeSend : 'The before send function has aborted the request', 16004 error : 'There was an error with your request', 16005 exitConditions : 'API Request Aborted. Exit conditions met', 16006 JSONParse : 'JSON could not be parsed during error handling', 16007 legacyParameters : 'You are using legacy API success callback names', 16008 method : 'The method you called is not defined', 16009 missingAction : 'API action used but no url was defined', 16010 missingSerialize : 'Required dependency jquery-serialize-object missing, using basic serialize', 16011 missingURL : 'No URL specified for api event', 16012 noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.', 16013 parseError : 'There was an error parsing your request', 16014 requiredParameter : 'Missing a required URL parameter: ', 16015 statusMessage : 'Server gave an error: ', 16016 timeout : 'Your request timed out' 16017 }, 16018 16019 regExp : { 16020 required: /\{\$*[A-z0-9]+\}/g, 16021 optional: /\{\/\$*[A-z0-9]+\}/g, 16022 }, 16023 16024 className: { 16025 loading : 'loading', 16026 error : 'error' 16027 }, 16028 16029 selector: { 16030 form: 'form' 16031 }, 16032 16033 metadata: { 16034 action : 'action' 16035 } 16036 }; 16037 16038 16039 $.api.settings.api = {}; 16040 16041 16042 })( jQuery, window , document ); 16043 /*! 16044 * # Semantic UI x.x - Form Validation 16045 * http://github.com/semantic-org/semantic-ui/ 16046 * 16047 * 16048 * Copyright 2014 Contributors 16049 * Released under the MIT license 16050 * http://opensource.org/licenses/MIT 16051 * 16052 */ 16053 16054 ;(function ( $, window, document, undefined ) { 16055 16056 "use strict"; 16057 16058 $.fn.form = function(fields, parameters) { 16059 var 16060 $allModules = $(this), 16061 16062 settings = $.extend(true, {}, $.fn.form.settings, parameters), 16063 validation = $.extend({}, $.fn.form.settings.defaults, fields), 16064 16065 namespace = settings.namespace, 16066 metadata = settings.metadata, 16067 selector = settings.selector, 16068 className = settings.className, 16069 error = settings.error, 16070 16071 eventNamespace = '.' + namespace, 16072 moduleNamespace = 'module-' + namespace, 16073 16074 moduleSelector = $allModules.selector || '', 16075 16076 time = new Date().getTime(), 16077 performance = [], 16078 16079 query = arguments[0], 16080 methodInvoked = (typeof query == 'string'), 16081 queryArguments = [].slice.call(arguments, 1), 16082 returnedValue 16083 ; 16084 $allModules 16085 .each(function() { 16086 var 16087 $module = $(this), 16088 $field = $(this).find(selector.field), 16089 $group = $(this).find(selector.group), 16090 $message = $(this).find(selector.message), 16091 $prompt = $(this).find(selector.prompt), 16092 16093 $submit = $(this).find(selector.submit), 16094 $clear = $(this).find(selector.clear), 16095 $reset = $(this).find(selector.reset), 16096 16097 formErrors = [], 16098 keyHeldDown = false, 16099 16100 element = this, 16101 instance = $module.data(moduleNamespace), 16102 module 16103 ; 16104 16105 module = { 16106 16107 initialize: function() { 16108 module.verbose('Initializing form validation', $module, validation, settings); 16109 module.bindEvents(); 16110 module.set.defaults(); 16111 module.instantiate(); 16112 }, 16113 16114 instantiate: function() { 16115 module.verbose('Storing instance of module', module); 16116 instance = module; 16117 $module 16118 .data(moduleNamespace, module) 16119 ; 16120 }, 16121 16122 destroy: function() { 16123 module.verbose('Destroying previous module', instance); 16124 module.removeEvents(); 16125 $module 16126 .removeData(moduleNamespace) 16127 ; 16128 }, 16129 16130 refresh: function() { 16131 module.verbose('Refreshing selector cache'); 16132 $field = $module.find(selector.field); 16133 }, 16134 16135 submit: function() { 16136 module.verbose('Submitting form', $module); 16137 $module 16138 .submit() 16139 ; 16140 }, 16141 16142 attachEvents: function(selector, action) { 16143 action = action || 'submit'; 16144 $(selector) 16145 .on('click', function(event) { 16146 module[action](); 16147 event.preventDefault(); 16148 }) 16149 ; 16150 }, 16151 16152 bindEvents: function() { 16153 if(settings.keyboardShortcuts) { 16154 $field 16155 .on('keydown' + eventNamespace, module.event.field.keydown) 16156 ; 16157 } 16158 $module 16159 .on('submit' + eventNamespace, module.validate.form) 16160 ; 16161 $field 16162 .on('blur' + eventNamespace, module.event.field.blur) 16163 ; 16164 16165 // attach events to common elements 16166 module.attachEvents($submit, 'submit'); 16167 module.attachEvents($reset, 'reset'); 16168 module.attachEvents($clear, 'clear'); 16169 16170 $field 16171 .each(function() { 16172 var 16173 type = $(this).prop('type'), 16174 inputEvent = module.get.changeEvent(type) 16175 ; 16176 $(this) 16177 .on(inputEvent + eventNamespace, module.event.field.change) 16178 ; 16179 }) 16180 ; 16181 }, 16182 16183 clear: function() { 16184 $field 16185 .each(function () { 16186 var 16187 $field = $(this), 16188 $element = $field.parent(), 16189 $fieldGroup = $field.closest($group), 16190 $prompt = $fieldGroup.find(selector.prompt), 16191 defaultValue = $field.data(metadata.defaultValue) || '', 16192 isCheckbox = $element.is(selector.uiCheckbox), 16193 isDropdown = $element.is(selector.uiDropdown), 16194 isErrored = $fieldGroup.hasClass(className.error) 16195 ; 16196 if(isErrored) { 16197 module.verbose('Resetting error on field', $fieldGroup); 16198 $fieldGroup.removeClass(className.error); 16199 $prompt.remove(); 16200 } 16201 if(isDropdown) { 16202 module.verbose('Resetting dropdown value', $element, defaultValue); 16203 $element.dropdown('clear'); 16204 } 16205 else if(isCheckbox) { 16206 $element.checkbox('uncheck'); 16207 } 16208 else { 16209 module.verbose('Resetting field value', $field, defaultValue); 16210 $field.val(''); 16211 } 16212 }) 16213 ; 16214 }, 16215 16216 reset: function() { 16217 $field 16218 .each(function () { 16219 var 16220 $field = $(this), 16221 $element = $field.parent(), 16222 $fieldGroup = $field.closest($group), 16223 $prompt = $fieldGroup.find(selector.prompt), 16224 defaultValue = $field.data(metadata.defaultValue) || '', 16225 isCheckbox = $element.is(selector.uiCheckbox), 16226 isDropdown = $element.is(selector.uiDropdown), 16227 isErrored = $fieldGroup.hasClass(className.error) 16228 ; 16229 if(isErrored) { 16230 module.verbose('Resetting error on field', $fieldGroup); 16231 $fieldGroup.removeClass(className.error); 16232 $prompt.remove(); 16233 } 16234 if(isDropdown) { 16235 module.verbose('Resetting dropdown value', $element, defaultValue); 16236 $element.dropdown('restore defaults'); 16237 } 16238 else if(isCheckbox) { 16239 module.verbose('Resetting checkbox value', $element, defaultValue); 16240 if(defaultValue === true) { 16241 $element.checkbox('check'); 16242 } 16243 else { 16244 $element.checkbox('uncheck'); 16245 } 16246 } 16247 else { 16248 module.verbose('Resetting field value', $field, defaultValue); 16249 $field.val(defaultValue); 16250 } 16251 }) 16252 ; 16253 }, 16254 16255 removeEvents: function() { 16256 $module 16257 .off(eventNamespace) 16258 ; 16259 $field 16260 .off(eventNamespace) 16261 ; 16262 $submit 16263 .off(eventNamespace) 16264 ; 16265 $field 16266 .off(eventNamespace) 16267 ; 16268 }, 16269 16270 event: { 16271 field: { 16272 keydown: function(event) { 16273 var 16274 $field = $(this), 16275 key = event.which, 16276 keyCode = { 16277 enter : 13, 16278 escape : 27 16279 } 16280 ; 16281 if( key == keyCode.escape) { 16282 module.verbose('Escape key pressed blurring field'); 16283 $field 16284 .blur() 16285 ; 16286 } 16287 if(!event.ctrlKey && key == keyCode.enter && $field.is(selector.input) && $field.not(selector.checkbox).length > 0 ) { 16288 $submit 16289 .addClass(className.pressed) 16290 ; 16291 if(!keyHeldDown) { 16292 $field 16293 .one('keyup' + eventNamespace, module.event.field.keyup) 16294 ; 16295 module.submit(); 16296 module.debug('Enter pressed on input submitting form'); 16297 } 16298 keyHeldDown = true; 16299 } 16300 }, 16301 keyup: function() { 16302 keyHeldDown = false; 16303 $submit.removeClass(className.pressed); 16304 }, 16305 blur: function() { 16306 var 16307 $field = $(this), 16308 $fieldGroup = $field.closest($group) 16309 ; 16310 if( $fieldGroup.hasClass(className.error) ) { 16311 module.debug('Revalidating field', $field, module.get.validation($field)); 16312 module.validate.field( module.get.validation($field) ); 16313 } 16314 else if(settings.on == 'blur' || settings.on == 'change') { 16315 module.validate.field( module.get.validation($field) ); 16316 } 16317 }, 16318 change: function() { 16319 var 16320 $field = $(this), 16321 $fieldGroup = $field.closest($group) 16322 ; 16323 if(settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) ) { 16324 clearTimeout(module.timer); 16325 module.timer = setTimeout(function() { 16326 module.debug('Revalidating field', $field, module.get.validation($field)); 16327 module.validate.field( module.get.validation($field) ); 16328 }, settings.delay); 16329 } 16330 } 16331 } 16332 16333 }, 16334 16335 get: { 16336 changeEvent: function(type) { 16337 if(type == 'checkbox' || type == 'radio' || type == 'hidden') { 16338 return 'change'; 16339 } 16340 else { 16341 return module.get.inputEvent(); 16342 } 16343 }, 16344 inputEvent: function() { 16345 return (document.createElement('input').oninput !== undefined) 16346 ? 'input' 16347 : (document.createElement('input').onpropertychange !== undefined) 16348 ? 'propertychange' 16349 : 'keyup' 16350 ; 16351 }, 16352 field: function(identifier) { 16353 module.verbose('Finding field with identifier', identifier); 16354 if( $field.filter('#' + identifier).length > 0 ) { 16355 return $field.filter('#' + identifier); 16356 } 16357 else if( $field.filter('[name="' + identifier +'"]').length > 0 ) { 16358 return $field.filter('[name="' + identifier +'"]'); 16359 } 16360 else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) { 16361 return $field.filter('[name="' + identifier +'[]"]'); 16362 } 16363 else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) { 16364 return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]'); 16365 } 16366 return $('<input/>'); 16367 }, 16368 fields: function(fields) { 16369 var 16370 $fields = $() 16371 ; 16372 $.each(fields, function(index, name) { 16373 $fields = $fields.add( module.get.field(name) ); 16374 }); 16375 return $fields; 16376 }, 16377 validation: function($field) { 16378 var 16379 rules 16380 ; 16381 $.each(validation, function(fieldName, field) { 16382 if( module.get.field(field.identifier).get(0) == $field.get(0) ) { 16383 rules = field; 16384 } 16385 }); 16386 return rules || false; 16387 }, 16388 value: function (field) { 16389 var 16390 fields = [], 16391 results 16392 ; 16393 fields.push(field); 16394 results = module.get.values.call(element, fields); 16395 return results[field]; 16396 }, 16397 values: function (fields) { 16398 var 16399 $fields = $.isArray(fields) 16400 ? module.get.fields(fields) 16401 : $field, 16402 values = {} 16403 ; 16404 $fields.each(function(index, field) { 16405 var 16406 $field = $(field), 16407 type = $field.prop('type'), 16408 name = $field.prop('name'), 16409 value = $field.val(), 16410 isCheckbox = $field.is(selector.checkbox), 16411 isRadio = $field.is(selector.radio), 16412 isMultiple = (name.indexOf('[]') !== -1), 16413 isChecked = (isCheckbox) 16414 ? $field.is(':checked') 16415 : false 16416 ; 16417 if(name) { 16418 if(isMultiple) { 16419 name = name.replace('[]', ''); 16420 if(!values[name]) { 16421 values[name] = []; 16422 } 16423 if(isCheckbox) { 16424 if(isChecked) { 16425 values[name].push(value) 16426 } 16427 else { 16428 module.debug('Omitted unchecked checkbox', $field); 16429 return true; 16430 } 16431 } 16432 else { 16433 values[name].push(value); 16434 } 16435 } 16436 else { 16437 if(isRadio) { 16438 if(isChecked) { 16439 values[name] = value; 16440 } 16441 } 16442 else if(isCheckbox) { 16443 if(isChecked) { 16444 values[name] = true; 16445 } 16446 else { 16447 module.debug('Omitted unchecked checkbox', $field); 16448 return true; 16449 } 16450 } 16451 else { 16452 values[name] = value; 16453 } 16454 } 16455 } 16456 }); 16457 return values; 16458 } 16459 }, 16460 16461 has: { 16462 16463 field: function(identifier) { 16464 module.verbose('Checking for existence of a field with identifier', identifier); 16465 if( $field.filter('#' + identifier).length > 0 ) { 16466 return true; 16467 } 16468 else if( $field.filter('[name="' + identifier +'"]').length > 0 ) { 16469 return true; 16470 } 16471 else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) { 16472 return true; 16473 } 16474 return false; 16475 } 16476 16477 }, 16478 16479 add: { 16480 prompt: function(identifier, errors) { 16481 var 16482 $field = module.get.field(identifier), 16483 $fieldGroup = $field.closest($group), 16484 $prompt = $fieldGroup.children(selector.prompt), 16485 promptExists = ($prompt.length !== 0) 16486 ; 16487 errors = (typeof errors == 'string') 16488 ? [errors] 16489 : errors 16490 ; 16491 module.verbose('Adding field error state', identifier); 16492 $fieldGroup 16493 .addClass(className.error) 16494 ; 16495 if(settings.inline) { 16496 if(!promptExists) { 16497 $prompt = settings.templates.prompt(errors); 16498 $prompt 16499 .appendTo($fieldGroup) 16500 ; 16501 } 16502 $prompt 16503 .html(errors[0]) 16504 ; 16505 if(!promptExists) { 16506 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 16507 module.verbose('Displaying error with css transition', settings.transition); 16508 $prompt.transition(settings.transition + ' in', settings.duration); 16509 } 16510 else { 16511 module.verbose('Displaying error with fallback javascript animation'); 16512 $prompt 16513 .fadeIn(settings.duration) 16514 ; 16515 } 16516 } 16517 else { 16518 module.verbose('Inline errors are disabled, no inline error added', identifier); 16519 } 16520 } 16521 }, 16522 errors: function(errors) { 16523 module.debug('Adding form error messages', errors); 16524 $message 16525 .html( settings.templates.error(errors) ) 16526 ; 16527 } 16528 }, 16529 16530 remove: { 16531 prompt: function(field) { 16532 var 16533 $field = module.get.field(field.identifier), 16534 $fieldGroup = $field.closest($group), 16535 $prompt = $fieldGroup.children(selector.prompt) 16536 ; 16537 $fieldGroup 16538 .removeClass(className.error) 16539 ; 16540 if(settings.inline && $prompt.is(':visible')) { 16541 module.verbose('Removing prompt for field', field); 16542 if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { 16543 $prompt.transition(settings.transition + ' out', settings.duration, function() { 16544 $prompt.remove(); 16545 }); 16546 } 16547 else { 16548 $prompt 16549 .fadeOut(settings.duration, function(){ 16550 $prompt.remove(); 16551 }) 16552 ; 16553 } 16554 } 16555 } 16556 }, 16557 16558 set: { 16559 success: function() { 16560 $module 16561 .removeClass(className.error) 16562 .addClass(className.success) 16563 ; 16564 }, 16565 defaults: function () { 16566 $field 16567 .each(function () { 16568 var 16569 $field = $(this), 16570 isCheckbox = ($field.filter(selector.checkbox).length > 0), 16571 value = (isCheckbox) 16572 ? $field.is(':checked') 16573 : $field.val() 16574 ; 16575 $field.data(metadata.defaultValue, value); 16576 }) 16577 ; 16578 }, 16579 error: function() { 16580 $module 16581 .removeClass(className.success) 16582 .addClass(className.error) 16583 ; 16584 }, 16585 value: function (field, value) { 16586 var 16587 fields = {} 16588 ; 16589 fields[field] = value; 16590 return module.set.values.call(element, fields); 16591 }, 16592 values: function (fields) { 16593 if($.isEmptyObject(fields)) { 16594 return; 16595 } 16596 $.each(fields, function(key, value) { 16597 var 16598 $field = module.get.field(key), 16599 $element = $field.parent(), 16600 isMultiple = $.isArray(value), 16601 isCheckbox = $element.is(selector.uiCheckbox), 16602 isDropdown = $element.is(selector.uiDropdown), 16603 isRadio = ($field.is(selector.radio) && isCheckbox), 16604 fieldExists = ($field.length > 0), 16605 $multipleField 16606 ; 16607 if(fieldExists) { 16608 if(isMultiple && isCheckbox) { 16609 module.verbose('Selecting multiple', value, $field); 16610 $element.checkbox('uncheck'); 16611 $.each(value, function(index, value) { 16612 $multipleField = $field.filter('[value="' + value + '"]'); 16613 $element = $multipleField.parent(); 16614 if($multipleField.length > 0) { 16615 $element.checkbox('check'); 16616 } 16617 }); 16618 } 16619 else if(isRadio) { 16620 module.verbose('Selecting radio value', value, $field); 16621 $field.filter('[value="' + value + '"]') 16622 .parent(selector.uiCheckbox) 16623 .checkbox('check') 16624 ; 16625 } 16626 else if(isCheckbox) { 16627 module.verbose('Setting checkbox value', value, $element); 16628 if(value === true) { 16629 $element.checkbox('check'); 16630 } 16631 else { 16632 $element.checkbox('uncheck'); 16633 } 16634 } 16635 else if(isDropdown) { 16636 module.verbose('Setting dropdown value', value, $element); 16637 $element.dropdown('set selected', value); 16638 } 16639 else { 16640 module.verbose('Setting field value', value, $field); 16641 $field.val(value); 16642 } 16643 } 16644 }); 16645 module.validate.form(); 16646 } 16647 }, 16648 16649 validate: { 16650 16651 form: function(event) { 16652 var 16653 allValid = true, 16654 apiRequest 16655 ; 16656 16657 // input keydown event will fire submit repeatedly by browser default 16658 if(keyHeldDown) { 16659 return false; 16660 } 16661 16662 // reset errors 16663 formErrors = []; 16664 $.each(validation, function(fieldName, field) { 16665 if( !( module.validate.field(field) ) ) { 16666 allValid = false; 16667 } 16668 }); 16669 if(allValid) { 16670 module.debug('Form has no validation errors, submitting'); 16671 module.set.success(); 16672 return settings.onSuccess.call(element, event); 16673 } 16674 else { 16675 module.debug('Form has errors'); 16676 module.set.error(); 16677 if(!settings.inline) { 16678 module.add.errors(formErrors); 16679 } 16680 // prevent ajax submit 16681 if($module.data('moduleApi') !== undefined) { 16682 event.stopImmediatePropagation(); 16683 } 16684 return settings.onFailure.call(element, formErrors); 16685 } 16686 }, 16687 16688 // takes a validation object and returns whether field passes validation 16689 field: function(field) { 16690 var 16691 $field = module.get.field(field.identifier), 16692 fieldValid = true, 16693 fieldErrors = [] 16694 ; 16695 if($field.prop('disabled')) { 16696 module.debug('Field is disabled. Skipping', field.identifier); 16697 fieldValid = true; 16698 } 16699 else if(field.optional && $.trim($field.val()) === ''){ 16700 module.debug('Field is optional and empty. Skipping', field.identifier); 16701 fieldValid = true; 16702 } 16703 else if(field.rules !== undefined) { 16704 $.each(field.rules, function(index, rule) { 16705 if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) { 16706 module.debug('Field is invalid', field.identifier, rule.type); 16707 fieldErrors.push(rule.prompt); 16708 fieldValid = false; 16709 } 16710 }); 16711 } 16712 if(fieldValid) { 16713 module.remove.prompt(field, fieldErrors); 16714 settings.onValid.call($field); 16715 } 16716 else { 16717 formErrors = formErrors.concat(fieldErrors); 16718 module.add.prompt(field.identifier, fieldErrors); 16719 settings.onInvalid.call($field, fieldErrors); 16720 return false; 16721 } 16722 return true; 16723 }, 16724 16725 // takes validation rule and returns whether field passes rule 16726 rule: function(field, validation) { 16727 var 16728 $field = module.get.field(field.identifier), 16729 type = validation.type, 16730 value = $.trim($field.val() + ''), 16731 16732 bracketRegExp = /\[(.*)\]/i, 16733 bracket = bracketRegExp.exec(type), 16734 isValid = true, 16735 ancillary, 16736 functionType 16737 ; 16738 // if bracket notation is used, pass in extra parameters 16739 if(bracket !== undefined && bracket !== null) { 16740 ancillary = '' + bracket[1]; 16741 functionType = type.replace(bracket[0], ''); 16742 isValid = settings.rules[functionType].call(element, value, ancillary); 16743 } 16744 // normal notation 16745 else { 16746 isValid = settings.rules[type].call($field, value); 16747 } 16748 return isValid; 16749 } 16750 }, 16751 16752 setting: function(name, value) { 16753 if( $.isPlainObject(name) ) { 16754 $.extend(true, settings, name); 16755 } 16756 else if(value !== undefined) { 16757 settings[name] = value; 16758 } 16759 else { 16760 return settings[name]; 16761 } 16762 }, 16763 internal: function(name, value) { 16764 if( $.isPlainObject(name) ) { 16765 $.extend(true, module, name); 16766 } 16767 else if(value !== undefined) { 16768 module[name] = value; 16769 } 16770 else { 16771 return module[name]; 16772 } 16773 }, 16774 debug: function() { 16775 if(settings.debug) { 16776 if(settings.performance) { 16777 module.performance.log(arguments); 16778 } 16779 else { 16780 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 16781 module.debug.apply(console, arguments); 16782 } 16783 } 16784 }, 16785 verbose: function() { 16786 if(settings.verbose && settings.debug) { 16787 if(settings.performance) { 16788 module.performance.log(arguments); 16789 } 16790 else { 16791 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 16792 module.verbose.apply(console, arguments); 16793 } 16794 } 16795 }, 16796 error: function() { 16797 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 16798 module.error.apply(console, arguments); 16799 }, 16800 performance: { 16801 log: function(message) { 16802 var 16803 currentTime, 16804 executionTime, 16805 previousTime 16806 ; 16807 if(settings.performance) { 16808 currentTime = new Date().getTime(); 16809 previousTime = time || currentTime; 16810 executionTime = currentTime - previousTime; 16811 time = currentTime; 16812 performance.push({ 16813 'Name' : message[0], 16814 'Arguments' : [].slice.call(message, 1) || '', 16815 'Element' : element, 16816 'Execution Time' : executionTime 16817 }); 16818 } 16819 clearTimeout(module.performance.timer); 16820 module.performance.timer = setTimeout(module.performance.display, 100); 16821 }, 16822 display: function() { 16823 var 16824 title = settings.name + ':', 16825 totalTime = 0 16826 ; 16827 time = false; 16828 clearTimeout(module.performance.timer); 16829 $.each(performance, function(index, data) { 16830 totalTime += data['Execution Time']; 16831 }); 16832 title += ' ' + totalTime + 'ms'; 16833 if(moduleSelector) { 16834 title += ' \'' + moduleSelector + '\''; 16835 } 16836 if($allModules.length > 1) { 16837 title += ' ' + '(' + $allModules.length + ')'; 16838 } 16839 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 16840 console.groupCollapsed(title); 16841 if(console.table) { 16842 console.table(performance); 16843 } 16844 else { 16845 $.each(performance, function(index, data) { 16846 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 16847 }); 16848 } 16849 console.groupEnd(); 16850 } 16851 performance = []; 16852 } 16853 }, 16854 invoke: function(query, passedArguments, context) { 16855 var 16856 object = instance, 16857 maxDepth, 16858 found, 16859 response 16860 ; 16861 passedArguments = passedArguments || queryArguments; 16862 context = element || context; 16863 if(typeof query == 'string' && object !== undefined) { 16864 query = query.split(/[\. ]/); 16865 maxDepth = query.length - 1; 16866 $.each(query, function(depth, value) { 16867 var camelCaseValue = (depth != maxDepth) 16868 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 16869 : query 16870 ; 16871 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 16872 object = object[camelCaseValue]; 16873 } 16874 else if( object[camelCaseValue] !== undefined ) { 16875 found = object[camelCaseValue]; 16876 return false; 16877 } 16878 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 16879 object = object[value]; 16880 } 16881 else if( object[value] !== undefined ) { 16882 found = object[value]; 16883 return false; 16884 } 16885 else { 16886 return false; 16887 } 16888 }); 16889 } 16890 if( $.isFunction( found ) ) { 16891 response = found.apply(context, passedArguments); 16892 } 16893 else if(found !== undefined) { 16894 response = found; 16895 } 16896 if($.isArray(returnedValue)) { 16897 returnedValue.push(response); 16898 } 16899 else if(returnedValue !== undefined) { 16900 returnedValue = [returnedValue, response]; 16901 } 16902 else if(response !== undefined) { 16903 returnedValue = response; 16904 } 16905 return found; 16906 } 16907 }; 16908 if(methodInvoked) { 16909 if(instance === undefined) { 16910 module.initialize(); 16911 } 16912 module.invoke(query); 16913 } 16914 else { 16915 if(instance !== undefined) { 16916 instance.invoke('destroy'); 16917 } 16918 module.initialize(); 16919 } 16920 16921 }) 16922 ; 16923 16924 return (returnedValue !== undefined) 16925 ? returnedValue 16926 : this 16927 ; 16928 }; 16929 16930 $.fn.form.settings = { 16931 16932 name : 'Form', 16933 namespace : 'form', 16934 16935 debug : false, 16936 verbose : true, 16937 performance : true, 16938 16939 16940 keyboardShortcuts : true, 16941 on : 'submit', 16942 inline : false, 16943 16944 delay : 200, 16945 revalidate : true, 16946 16947 transition : 'scale', 16948 duration : 200, 16949 16950 onValid : function() {}, 16951 onInvalid : function() {}, 16952 onSuccess : function() { return true; }, 16953 onFailure : function() { return false; }, 16954 16955 metadata : { 16956 defaultValue : 'default', 16957 validate : 'validate' 16958 }, 16959 16960 selector : { 16961 checkbox : 'input[type="checkbox"], input[type="radio"]', 16962 clear : '.clear', 16963 field : 'input, textarea, select', 16964 group : '.field', 16965 input : 'input', 16966 message : '.error.message', 16967 prompt : '.prompt.label', 16968 radio : 'input[type="radio"]', 16969 reset : '.reset', 16970 submit : '.submit', 16971 uiCheckbox : '.ui.checkbox', 16972 uiDropdown : '.ui.dropdown' 16973 }, 16974 16975 className : { 16976 error : 'error', 16977 label : 'ui prompt label', 16978 pressed : 'down', 16979 success : 'success' 16980 }, 16981 16982 error: { 16983 method : 'The method you called is not defined.' 16984 }, 16985 16986 templates: { 16987 16988 // template that produces error message 16989 error: function(errors) { 16990 var 16991 html = '<ul class="list">' 16992 ; 16993 $.each(errors, function(index, value) { 16994 html += '<li>' + value + '</li>'; 16995 }); 16996 html += '</ul>'; 16997 return $(html); 16998 }, 16999 17000 // template that produces label 17001 prompt: function(errors) { 17002 return $('<div/>') 17003 .addClass('ui red pointing prompt label') 17004 .html(errors[0]) 17005 ; 17006 } 17007 }, 17008 17009 rules: { 17010 17011 // checkbox checked 17012 checked: function() { 17013 return ($(this).filter(':checked').length > 0); 17014 }, 17015 17016 // value contains text (insensitive) 17017 contains: function(value, text) { 17018 // escape regex characters 17019 text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 17020 return (value.search( new RegExp(text, 'i') ) !== -1); 17021 }, 17022 17023 // value contains text (case sensitive) 17024 containsExactly: function(value, text) { 17025 // escape regex characters 17026 text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 17027 return (value.search( new RegExp(text) ) !== -1); 17028 }, 17029 17030 // is most likely an email 17031 email: function(value){ 17032 var 17033 emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", "i") 17034 ; 17035 return emailRegExp.test(value); 17036 }, 17037 17038 // is not empty or blank string 17039 empty: function(value) { 17040 return !(value === undefined || '' === value); 17041 }, 17042 17043 // is valid integer 17044 integer: function(value, range) { 17045 var 17046 intRegExp = /^\-?\d+$/, 17047 min, 17048 max, 17049 parts 17050 ; 17051 if(range === undefined || range === '' || range === '..') { 17052 // do nothing 17053 } 17054 else if(range.indexOf('..') == -1) { 17055 if(intRegExp.test(range)) { 17056 min = max = range - 0; 17057 } 17058 } 17059 else { 17060 parts = range.split('..', 2); 17061 if(intRegExp.test(parts[0])) { 17062 min = parts[0] - 0; 17063 } 17064 if(intRegExp.test(parts[1])) { 17065 max = parts[1] - 0; 17066 } 17067 } 17068 return ( 17069 intRegExp.test(value) && 17070 (min === undefined || value >= min) && 17071 (max === undefined || value <= max) 17072 ); 17073 }, 17074 17075 // is value (case insensitive) 17076 is: function(value, text) { 17077 text = (typeof text == 'string') 17078 ? text.toLowerCase() 17079 : text 17080 ; 17081 value = (typeof value == 'string') 17082 ? value.toLowerCase() 17083 : value 17084 ; 17085 return (value == text); 17086 }, 17087 17088 // is value 17089 isExactly: function(value, text) { 17090 return (value == text); 17091 }, 17092 17093 // is at least string length 17094 length: function(value, requiredLength) { 17095 return (value !== undefined) 17096 ? (value.length >= requiredLength) 17097 : false 17098 ; 17099 }, 17100 17101 // matches another field 17102 match: function(value, fieldIdentifier) { 17103 // use either id or name of field 17104 var 17105 $form = $(this), 17106 matchingValue 17107 ; 17108 if($form.find('#' + fieldIdentifier).length > 0) { 17109 matchingValue = $form.find('#' + fieldIdentifier).val(); 17110 } 17111 else if($form.find('[name="' + fieldIdentifier +'"]').length > 0) { 17112 matchingValue = $form.find('[name="' + fieldIdentifier + '"]').val(); 17113 } 17114 else if( $form.find('[data-validate="'+ fieldIdentifier +'"]').length > 0 ) { 17115 matchingValue = $form.find('[data-validate="'+ fieldIdentifier +'"]').val(); 17116 } 17117 return (matchingValue !== undefined) 17118 ? ( value.toString() == matchingValue.toString() ) 17119 : false 17120 ; 17121 }, 17122 17123 // string length is less than max length 17124 maxLength: function(value, maxLength) { 17125 return (value !== undefined) 17126 ? (value.length <= maxLength) 17127 : false 17128 ; 17129 }, 17130 17131 // value is not value (case insensitive) 17132 not: function(value, notValue) { 17133 value = (typeof value == 'string') 17134 ? value.toLowerCase() 17135 : value 17136 ; 17137 notValue = (typeof notValue == 'string') 17138 ? notValue.toLowerCase() 17139 : notValue 17140 ; 17141 return (value != notValue); 17142 }, 17143 17144 // value is not value (case sensitive) 17145 notExactly: function(value, notValue) { 17146 return (value != notValue); 17147 }, 17148 17149 // value is most likely url 17150 url: function(value) { 17151 var 17152 urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ 17153 ; 17154 return urlRegExp.test(value); 17155 } 17156 } 17157 17158 }; 17159 17160 })( jQuery, window , document ); 17161 17162 /*! 17163 * # Semantic UI x.x - State 17164 * http://github.com/semantic-org/semantic-ui/ 17165 * 17166 * 17167 * Copyright 2014 Contributors 17168 * Released under the MIT license 17169 * http://opensource.org/licenses/MIT 17170 * 17171 */ 17172 17173 ;(function ( $, window, document, undefined ) { 17174 17175 "use strict"; 17176 17177 $.fn.state = function(parameters) { 17178 var 17179 $allModules = $(this), 17180 17181 moduleSelector = $allModules.selector || '', 17182 17183 hasTouch = ('ontouchstart' in document.documentElement), 17184 time = new Date().getTime(), 17185 performance = [], 17186 17187 query = arguments[0], 17188 methodInvoked = (typeof query == 'string'), 17189 queryArguments = [].slice.call(arguments, 1), 17190 17191 returnedValue 17192 ; 17193 $allModules 17194 .each(function() { 17195 var 17196 settings = ( $.isPlainObject(parameters) ) 17197 ? $.extend(true, {}, $.fn.state.settings, parameters) 17198 : $.extend({}, $.fn.state.settings), 17199 17200 error = settings.error, 17201 metadata = settings.metadata, 17202 className = settings.className, 17203 namespace = settings.namespace, 17204 states = settings.states, 17205 text = settings.text, 17206 17207 eventNamespace = '.' + namespace, 17208 moduleNamespace = namespace + '-module', 17209 17210 $module = $(this), 17211 17212 element = this, 17213 instance = $module.data(moduleNamespace), 17214 17215 module 17216 ; 17217 module = { 17218 17219 initialize: function() { 17220 module.verbose('Initializing module'); 17221 17222 // allow module to guess desired state based on element 17223 if(settings.automatic) { 17224 module.add.defaults(); 17225 } 17226 17227 // bind events with delegated events 17228 if(settings.context && moduleSelector !== '') { 17229 $(settings.context) 17230 .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text) 17231 .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text) 17232 .on(moduleSelector, 'click' + eventNamespace, module.toggle.state) 17233 ; 17234 } 17235 else { 17236 $module 17237 .on('mouseenter' + eventNamespace, module.change.text) 17238 .on('mouseleave' + eventNamespace, module.reset.text) 17239 .on('click' + eventNamespace, module.toggle.state) 17240 ; 17241 } 17242 module.instantiate(); 17243 }, 17244 17245 instantiate: function() { 17246 module.verbose('Storing instance of module', module); 17247 instance = module; 17248 $module 17249 .data(moduleNamespace, module) 17250 ; 17251 }, 17252 17253 destroy: function() { 17254 module.verbose('Destroying previous module', instance); 17255 $module 17256 .off(eventNamespace) 17257 .removeData(moduleNamespace) 17258 ; 17259 }, 17260 17261 refresh: function() { 17262 module.verbose('Refreshing selector cache'); 17263 $module = $(element); 17264 }, 17265 17266 add: { 17267 defaults: function() { 17268 var 17269 userStates = parameters && $.isPlainObject(parameters.states) 17270 ? parameters.states 17271 : {} 17272 ; 17273 $.each(settings.defaults, function(type, typeStates) { 17274 if( module.is[type] !== undefined && module.is[type]() ) { 17275 module.verbose('Adding default states', type, element); 17276 $.extend(settings.states, typeStates, userStates); 17277 } 17278 }); 17279 } 17280 }, 17281 17282 is: { 17283 17284 active: function() { 17285 return $module.hasClass(className.active); 17286 }, 17287 loading: function() { 17288 return $module.hasClass(className.loading); 17289 }, 17290 inactive: function() { 17291 return !( $module.hasClass(className.active) ); 17292 }, 17293 state: function(state) { 17294 if(className[state] === undefined) { 17295 return false; 17296 } 17297 return $module.hasClass( className[state] ); 17298 }, 17299 17300 enabled: function() { 17301 return !( $module.is(settings.filter.active) ); 17302 }, 17303 disabled: function() { 17304 return ( $module.is(settings.filter.active) ); 17305 }, 17306 textEnabled: function() { 17307 return !( $module.is(settings.filter.text) ); 17308 }, 17309 17310 // definitions for automatic type detection 17311 button: function() { 17312 return $module.is('.button:not(a, .submit)'); 17313 }, 17314 input: function() { 17315 return $module.is('input'); 17316 }, 17317 progress: function() { 17318 return $module.is('.ui.progress'); 17319 } 17320 }, 17321 17322 allow: function(state) { 17323 module.debug('Now allowing state', state); 17324 states[state] = true; 17325 }, 17326 disallow: function(state) { 17327 module.debug('No longer allowing', state); 17328 states[state] = false; 17329 }, 17330 17331 allows: function(state) { 17332 return states[state] || false; 17333 }, 17334 17335 enable: function() { 17336 $module.removeClass(className.disabled); 17337 }, 17338 17339 disable: function() { 17340 $module.addClass(className.disabled); 17341 }, 17342 17343 setState: function(state) { 17344 if(module.allows(state)) { 17345 $module.addClass( className[state] ); 17346 } 17347 }, 17348 17349 removeState: function(state) { 17350 if(module.allows(state)) { 17351 $module.removeClass( className[state] ); 17352 } 17353 }, 17354 17355 toggle: { 17356 state: function() { 17357 var 17358 apiRequest, 17359 requestCancelled 17360 ; 17361 if( module.allows('active') && module.is.enabled() ) { 17362 module.refresh(); 17363 if($.fn.api !== undefined) { 17364 apiRequest = $module.api('get request'); 17365 requestCancelled = $module.api('was cancelled'); 17366 if( requestCancelled ) { 17367 module.debug('API Request cancelled by beforesend'); 17368 settings.activateTest = function(){ return false; }; 17369 settings.deactivateTest = function(){ return false; }; 17370 } 17371 else if(apiRequest) { 17372 module.listenTo(apiRequest); 17373 return; 17374 } 17375 } 17376 module.change.state(); 17377 } 17378 } 17379 }, 17380 17381 listenTo: function(apiRequest) { 17382 module.debug('API request detected, waiting for state signal', apiRequest); 17383 if(apiRequest) { 17384 if(text.loading) { 17385 module.update.text(text.loading); 17386 } 17387 $.when(apiRequest) 17388 .then(function() { 17389 if(apiRequest.state() == 'resolved') { 17390 module.debug('API request succeeded'); 17391 settings.activateTest = function(){ return true; }; 17392 settings.deactivateTest = function(){ return true; }; 17393 } 17394 else { 17395 module.debug('API request failed'); 17396 settings.activateTest = function(){ return false; }; 17397 settings.deactivateTest = function(){ return false; }; 17398 } 17399 module.change.state(); 17400 }) 17401 ; 17402 } 17403 }, 17404 17405 // checks whether active/inactive state can be given 17406 change: { 17407 17408 state: function() { 17409 module.debug('Determining state change direction'); 17410 // inactive to active change 17411 if( module.is.inactive() ) { 17412 module.activate(); 17413 } 17414 else { 17415 module.deactivate(); 17416 } 17417 if(settings.sync) { 17418 module.sync(); 17419 } 17420 settings.onChange.call(element); 17421 }, 17422 17423 text: function() { 17424 if( module.is.textEnabled() ) { 17425 if(module.is.disabled() ) { 17426 module.verbose('Changing text to disabled text', text.hover); 17427 module.update.text(text.disabled); 17428 } 17429 else if( module.is.active() ) { 17430 if(text.hover) { 17431 module.verbose('Changing text to hover text', text.hover); 17432 module.update.text(text.hover); 17433 } 17434 else if(text.deactivate) { 17435 module.verbose('Changing text to deactivating text', text.deactivate); 17436 module.update.text(text.deactivate); 17437 } 17438 } 17439 else { 17440 if(text.hover) { 17441 module.verbose('Changing text to hover text', text.hover); 17442 module.update.text(text.hover); 17443 } 17444 else if(text.activate){ 17445 module.verbose('Changing text to activating text', text.activate); 17446 module.update.text(text.activate); 17447 } 17448 } 17449 } 17450 } 17451 17452 }, 17453 17454 activate: function() { 17455 if( settings.activateTest.call(element) ) { 17456 module.debug('Setting state to active'); 17457 $module 17458 .addClass(className.active) 17459 ; 17460 module.update.text(text.active); 17461 settings.onActivate.call(element); 17462 } 17463 }, 17464 17465 deactivate: function() { 17466 if( settings.deactivateTest.call(element) ) { 17467 module.debug('Setting state to inactive'); 17468 $module 17469 .removeClass(className.active) 17470 ; 17471 module.update.text(text.inactive); 17472 settings.onDeactivate.call(element); 17473 } 17474 }, 17475 17476 sync: function() { 17477 module.verbose('Syncing other buttons to current state'); 17478 if( module.is.active() ) { 17479 $allModules 17480 .not($module) 17481 .state('activate'); 17482 } 17483 else { 17484 $allModules 17485 .not($module) 17486 .state('deactivate') 17487 ; 17488 } 17489 }, 17490 17491 get: { 17492 text: function() { 17493 return (settings.selector.text) 17494 ? $module.find(settings.selector.text).text() 17495 : $module.html() 17496 ; 17497 }, 17498 textFor: function(state) { 17499 return text[state] || false; 17500 } 17501 }, 17502 17503 flash: { 17504 text: function(text, duration, callback) { 17505 var 17506 previousText = module.get.text() 17507 ; 17508 module.debug('Flashing text message', text, duration); 17509 text = text || settings.text.flash; 17510 duration = duration || settings.flashDuration; 17511 callback = callback || function() {}; 17512 module.update.text(text); 17513 setTimeout(function(){ 17514 module.update.text(previousText); 17515 callback.call(element); 17516 }, duration); 17517 } 17518 }, 17519 17520 reset: { 17521 // on mouseout sets text to previous value 17522 text: function() { 17523 var 17524 activeText = text.active || $module.data(metadata.storedText), 17525 inactiveText = text.inactive || $module.data(metadata.storedText) 17526 ; 17527 if( module.is.textEnabled() ) { 17528 if( module.is.active() && activeText) { 17529 module.verbose('Resetting active text', activeText); 17530 module.update.text(activeText); 17531 } 17532 else if(inactiveText) { 17533 module.verbose('Resetting inactive text', activeText); 17534 module.update.text(inactiveText); 17535 } 17536 } 17537 } 17538 }, 17539 17540 update: { 17541 text: function(text) { 17542 var 17543 currentText = module.get.text() 17544 ; 17545 if(text && text !== currentText) { 17546 module.debug('Updating text', text); 17547 if(settings.selector.text) { 17548 $module 17549 .data(metadata.storedText, text) 17550 .find(settings.selector.text) 17551 .text(text) 17552 ; 17553 } 17554 else { 17555 $module 17556 .data(metadata.storedText, text) 17557 .html(text) 17558 ; 17559 } 17560 } 17561 else { 17562 module.debug('Text is already set, ignoring update', text); 17563 } 17564 } 17565 }, 17566 17567 setting: function(name, value) { 17568 module.debug('Changing setting', name, value); 17569 if( $.isPlainObject(name) ) { 17570 $.extend(true, settings, name); 17571 } 17572 else if(value !== undefined) { 17573 settings[name] = value; 17574 } 17575 else { 17576 return settings[name]; 17577 } 17578 }, 17579 internal: function(name, value) { 17580 if( $.isPlainObject(name) ) { 17581 $.extend(true, module, name); 17582 } 17583 else if(value !== undefined) { 17584 module[name] = value; 17585 } 17586 else { 17587 return module[name]; 17588 } 17589 }, 17590 debug: function() { 17591 if(settings.debug) { 17592 if(settings.performance) { 17593 module.performance.log(arguments); 17594 } 17595 else { 17596 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 17597 module.debug.apply(console, arguments); 17598 } 17599 } 17600 }, 17601 verbose: function() { 17602 if(settings.verbose && settings.debug) { 17603 if(settings.performance) { 17604 module.performance.log(arguments); 17605 } 17606 else { 17607 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 17608 module.verbose.apply(console, arguments); 17609 } 17610 } 17611 }, 17612 error: function() { 17613 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 17614 module.error.apply(console, arguments); 17615 }, 17616 performance: { 17617 log: function(message) { 17618 var 17619 currentTime, 17620 executionTime, 17621 previousTime 17622 ; 17623 if(settings.performance) { 17624 currentTime = new Date().getTime(); 17625 previousTime = time || currentTime; 17626 executionTime = currentTime - previousTime; 17627 time = currentTime; 17628 performance.push({ 17629 'Name' : message[0], 17630 'Arguments' : [].slice.call(message, 1) || '', 17631 'Element' : element, 17632 'Execution Time' : executionTime 17633 }); 17634 } 17635 clearTimeout(module.performance.timer); 17636 module.performance.timer = setTimeout(module.performance.display, 100); 17637 }, 17638 display: function() { 17639 var 17640 title = settings.name + ':', 17641 totalTime = 0 17642 ; 17643 time = false; 17644 clearTimeout(module.performance.timer); 17645 $.each(performance, function(index, data) { 17646 totalTime += data['Execution Time']; 17647 }); 17648 title += ' ' + totalTime + 'ms'; 17649 if(moduleSelector) { 17650 title += ' \'' + moduleSelector + '\''; 17651 } 17652 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 17653 console.groupCollapsed(title); 17654 if(console.table) { 17655 console.table(performance); 17656 } 17657 else { 17658 $.each(performance, function(index, data) { 17659 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 17660 }); 17661 } 17662 console.groupEnd(); 17663 } 17664 performance = []; 17665 } 17666 }, 17667 invoke: function(query, passedArguments, context) { 17668 var 17669 object = instance, 17670 maxDepth, 17671 found, 17672 response 17673 ; 17674 passedArguments = passedArguments || queryArguments; 17675 context = element || context; 17676 if(typeof query == 'string' && object !== undefined) { 17677 query = query.split(/[\. ]/); 17678 maxDepth = query.length - 1; 17679 $.each(query, function(depth, value) { 17680 var camelCaseValue = (depth != maxDepth) 17681 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 17682 : query 17683 ; 17684 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 17685 object = object[camelCaseValue]; 17686 } 17687 else if( object[camelCaseValue] !== undefined ) { 17688 found = object[camelCaseValue]; 17689 return false; 17690 } 17691 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 17692 object = object[value]; 17693 } 17694 else if( object[value] !== undefined ) { 17695 found = object[value]; 17696 return false; 17697 } 17698 else { 17699 module.error(error.method, query); 17700 return false; 17701 } 17702 }); 17703 } 17704 if ( $.isFunction( found ) ) { 17705 response = found.apply(context, passedArguments); 17706 } 17707 else if(found !== undefined) { 17708 response = found; 17709 } 17710 if($.isArray(returnedValue)) { 17711 returnedValue.push(response); 17712 } 17713 else if(returnedValue !== undefined) { 17714 returnedValue = [returnedValue, response]; 17715 } 17716 else if(response !== undefined) { 17717 returnedValue = response; 17718 } 17719 return found; 17720 } 17721 }; 17722 17723 if(methodInvoked) { 17724 if(instance === undefined) { 17725 module.initialize(); 17726 } 17727 module.invoke(query); 17728 } 17729 else { 17730 if(instance !== undefined) { 17731 instance.invoke('destroy'); 17732 } 17733 module.initialize(); 17734 } 17735 }) 17736 ; 17737 17738 return (returnedValue !== undefined) 17739 ? returnedValue 17740 : this 17741 ; 17742 }; 17743 17744 $.fn.state.settings = { 17745 17746 // module info 17747 name : 'State', 17748 17749 // debug output 17750 debug : false, 17751 17752 // verbose debug output 17753 verbose : true, 17754 17755 // namespace for events 17756 namespace : 'state', 17757 17758 // debug data includes performance 17759 performance : true, 17760 17761 // callback occurs on state change 17762 onActivate : function() {}, 17763 onDeactivate : function() {}, 17764 onChange : function() {}, 17765 17766 // state test functions 17767 activateTest : function() { return true; }, 17768 deactivateTest : function() { return true; }, 17769 17770 // whether to automatically map default states 17771 automatic : true, 17772 17773 // activate / deactivate changes all elements instantiated at same time 17774 sync : false, 17775 17776 // default flash text duration, used for temporarily changing text of an element 17777 flashDuration : 1000, 17778 17779 // selector filter 17780 filter : { 17781 text : '.loading, .disabled', 17782 active : '.disabled' 17783 }, 17784 17785 context : false, 17786 17787 // error 17788 error: { 17789 beforeSend : 'The before send function has cancelled state change', 17790 method : 'The method you called is not defined.' 17791 }, 17792 17793 // metadata 17794 metadata: { 17795 promise : 'promise', 17796 storedText : 'stored-text' 17797 }, 17798 17799 // change class on state 17800 className: { 17801 active : 'active', 17802 disabled : 'disabled', 17803 error : 'error', 17804 loading : 'loading', 17805 success : 'success', 17806 warning : 'warning' 17807 }, 17808 17809 selector: { 17810 // selector for text node 17811 text: false 17812 }, 17813 17814 defaults : { 17815 input: { 17816 disabled : true, 17817 loading : true, 17818 active : true 17819 }, 17820 button: { 17821 disabled : true, 17822 loading : true, 17823 active : true, 17824 }, 17825 progress: { 17826 active : true, 17827 success : true, 17828 warning : true, 17829 error : true 17830 } 17831 }, 17832 17833 states : { 17834 active : true, 17835 disabled : true, 17836 error : true, 17837 loading : true, 17838 success : true, 17839 warning : true 17840 }, 17841 17842 text : { 17843 disabled : false, 17844 flash : false, 17845 hover : false, 17846 active : false, 17847 inactive : false, 17848 activate : false, 17849 deactivate : false 17850 } 17851 17852 }; 17853 17854 17855 17856 })( jQuery, window , document ); 17857 17858 /*! 17859 * # Semantic UI x.x - Visibility 17860 * http://github.com/semantic-org/semantic-ui/ 17861 * 17862 * 17863 * Copyright 2014 Contributors 17864 * Released under the MIT license 17865 * http://opensource.org/licenses/MIT 17866 * 17867 */ 17868 17869 ;(function ( $, window, document, undefined ) { 17870 17871 "use strict"; 17872 17873 $.fn.visibility = function(parameters) { 17874 var 17875 $allModules = $(this), 17876 moduleSelector = $allModules.selector || '', 17877 17878 time = new Date().getTime(), 17879 performance = [], 17880 17881 query = arguments[0], 17882 methodInvoked = (typeof query == 'string'), 17883 queryArguments = [].slice.call(arguments, 1), 17884 returnedValue 17885 ; 17886 17887 $allModules 17888 .each(function() { 17889 var 17890 settings = ( $.isPlainObject(parameters) ) 17891 ? $.extend(true, {}, $.fn.visibility.settings, parameters) 17892 : $.extend({}, $.fn.visibility.settings), 17893 17894 className = settings.className, 17895 namespace = settings.namespace, 17896 error = settings.error, 17897 17898 eventNamespace = '.' + namespace, 17899 moduleNamespace = 'module-' + namespace, 17900 17901 $window = $(window), 17902 $module = $(this), 17903 $context = $(settings.context), 17904 $images = $module.find('img'), 17905 17906 selector = $module.selector || '', 17907 instance = $module.data(moduleNamespace), 17908 17909 requestAnimationFrame = window.requestAnimationFrame 17910 || window.mozRequestAnimationFrame 17911 || window.webkitRequestAnimationFrame 17912 || window.msRequestAnimationFrame 17913 || function(callback) { setTimeout(callback, 0); }, 17914 17915 element = this, 17916 observer, 17917 module 17918 ; 17919 17920 module = { 17921 17922 initialize: function() { 17923 module.debug('Initializing', settings); 17924 17925 module.setup.cache(); 17926 module.save.position(); 17927 17928 if( module.should.trackChanges() ) { 17929 module.bind.events(); 17930 if(settings.type == 'image') { 17931 module.setup.image(); 17932 } 17933 if(settings.type == 'fixed') { 17934 module.setup.fixed(); 17935 } 17936 } 17937 if(settings.initialCheck) { 17938 module.checkVisibility(); 17939 } 17940 if(settings.observeChanges) { 17941 module.observeChanges(); 17942 } 17943 module.instantiate(); 17944 }, 17945 17946 instantiate: function() { 17947 module.debug('Storing instance', module); 17948 $module 17949 .data(moduleNamespace, module) 17950 ; 17951 instance = module; 17952 }, 17953 17954 destroy: function() { 17955 module.verbose('Destroying previous module'); 17956 $module 17957 .off(eventNamespace) 17958 .removeData(moduleNamespace) 17959 ; 17960 $window.off('resize' + eventNamespace, module.event.refresh); 17961 $context.off('scroll' + eventNamespace, module.event.scroll); 17962 }, 17963 17964 observeChanges: function() { 17965 var 17966 context = $context[0] 17967 ; 17968 if('MutationObserver' in window) { 17969 observer = new MutationObserver(function(mutations) { 17970 module.verbose('DOM tree modified, updating visibility calculations'); 17971 module.refresh(); 17972 }); 17973 observer.observe(element, { 17974 childList : true, 17975 subtree : true 17976 }); 17977 module.debug('Setting up mutation observer', observer); 17978 } 17979 }, 17980 17981 bind: { 17982 events: function() { 17983 module.verbose('Binding visibility events to scroll and resize'); 17984 $window 17985 .on('resize' + eventNamespace, module.event.refresh) 17986 ; 17987 $context 17988 .on('scroll' + eventNamespace, module.event.scroll) 17989 ; 17990 if($images.length > 0) { 17991 module.bind.imageLoad(); 17992 } 17993 }, 17994 imageLoad: function() { 17995 var 17996 imageCount = $images.length, 17997 index = imageCount, 17998 loadedCount = 0, 17999 images = [], 18000 cache = [], 18001 cacheImage = document.createElement('img'), 18002 handleLoad = function() { 18003 loadedCount++; 18004 if(loadedCount >= imageCount) { 18005 module.debug('Images finished loading inside element, refreshing position'); 18006 module.refresh(); 18007 } 18008 } 18009 ; 18010 $images 18011 .each(function() { 18012 images.push( $(this).attr('src') ); 18013 }) 18014 ; 18015 while(index--) { 18016 cacheImage = document.createElement('img'); 18017 cacheImage.onload = handleLoad; 18018 cacheImage.onerror = handleLoad; 18019 cacheImage.src = images[index]; 18020 cache.push(cacheImage); 18021 } 18022 } 18023 }, 18024 18025 event: { 18026 refresh: function() { 18027 requestAnimationFrame(module.refresh); 18028 }, 18029 scroll: function() { 18030 module.verbose('Scroll position changed'); 18031 if(settings.throttle) { 18032 clearTimeout(module.timer); 18033 module.timer = setTimeout(function() { 18034 module.checkVisibility(); 18035 }, settings.throttle); 18036 } 18037 else { 18038 requestAnimationFrame(function() { 18039 module.checkVisibility(); 18040 }); 18041 } 18042 } 18043 }, 18044 18045 should: { 18046 trackChanges: function() { 18047 if(methodInvoked && queryArguments.length > 0) { 18048 module.debug('One time query, no need to bind events'); 18049 return false; 18050 } 18051 module.debug('Callbacks being attached'); 18052 return true; 18053 } 18054 }, 18055 18056 setup: { 18057 cache: function() { 18058 module.cache = { 18059 occurred : {}, 18060 screen : {}, 18061 element : {}, 18062 }; 18063 }, 18064 image: function() { 18065 var 18066 src = $module.data('src') 18067 ; 18068 if(src) { 18069 module.verbose('Lazy loading image', src); 18070 settings.observeChanges = false; 18071 // show when top visible 18072 module.topVisible(function() { 18073 module.debug('Image top visible', element); 18074 module.precache(src, function() { 18075 module.set.image(src); 18076 settings.onTopVisible = false; 18077 }); 18078 }); 18079 } 18080 }, 18081 fixed: function() { 18082 module.verbose('Setting up fixed on element pass'); 18083 settings.once = false; 18084 settings.onTopPassed = function() { 18085 $module 18086 .addClass(className.fixed) 18087 .css({ 18088 top: settings.offset + 'px' 18089 }) 18090 ; 18091 if(settings.transition) { 18092 if($.fn.transition !== undefined) { 18093 $module.transition(settings.transition, settings.duration); 18094 } 18095 } 18096 }; 18097 settings.onTopPassedReverse = function() { 18098 $module 18099 .removeClass(className.fixed) 18100 .css({ 18101 position: '', 18102 top: '' 18103 }) 18104 ; 18105 }; 18106 } 18107 }, 18108 18109 set: { 18110 image: function(src) { 18111 var 18112 offScreen = (module.cache.screen.bottom < module.cache.element.top) 18113 ; 18114 $module 18115 .attr('src', src) 18116 ; 18117 if(offScreen) { 18118 module.verbose('Image outside browser, no show animation'); 18119 $module.show(); 18120 } 18121 else { 18122 if(settings.transition) { 18123 if( $.fn.transition !== undefined ) { 18124 $module.transition(settings.transition, settings.duration); 18125 } 18126 else { 18127 $module.fadeIn(settings.duration); 18128 } 18129 } 18130 else { 18131 $module.show(); 18132 } 18133 } 18134 } 18135 }, 18136 18137 is: { 18138 visible: function() { 18139 if(module.cache && module.cache.element) { 18140 return (module.cache.element.width > 0); 18141 } 18142 return false; 18143 } 18144 }, 18145 18146 refresh: function() { 18147 module.debug('Refreshing constants (element width/height)'); 18148 module.reset(); 18149 module.save.position(); 18150 module.checkVisibility(); 18151 settings.onRefresh.call(element); 18152 }, 18153 18154 reset: function() { 18155 module.verbose('Reseting all cached values'); 18156 if( $.isPlainObject(module.cache) ) { 18157 module.cache.screen = {}; 18158 module.cache.element = {}; 18159 } 18160 }, 18161 18162 checkVisibility: function() { 18163 module.verbose('Checking visibility of element', module.cache.element); 18164 18165 if( module.is.visible() ) { 18166 18167 // update calculations derived from scroll 18168 module.save.calculations(); 18169 18170 // percentage 18171 module.passed(); 18172 18173 // reverse (must be first) 18174 module.passingReverse(); 18175 module.topVisibleReverse(); 18176 module.bottomVisibleReverse(); 18177 module.topPassedReverse(); 18178 module.bottomPassedReverse(); 18179 18180 // one time 18181 module.passing(); 18182 module.topVisible(); 18183 module.bottomVisible(); 18184 module.topPassed(); 18185 module.bottomPassed(); 18186 18187 // on update callback 18188 if(settings.onUpdate) { 18189 settings.onUpdate.call(element, module.get.elementCalculations()); 18190 } 18191 } 18192 }, 18193 18194 passed: function(amount, newCallback) { 18195 var 18196 calculations = module.get.elementCalculations(), 18197 amountInPixels 18198 ; 18199 // assign callback 18200 if(amount !== undefined && newCallback !== undefined) { 18201 settings.onPassed[amount] = newCallback; 18202 } 18203 else if(amount !== undefined) { 18204 return (module.get.pixelsPassed(amount) > calculations.pixelsPassed); 18205 } 18206 else if(calculations.passing) { 18207 $.each(settings.onPassed, function(amount, callback) { 18208 if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) { 18209 module.execute(callback, amount); 18210 } 18211 else if(!settings.once) { 18212 module.remove.occurred(callback); 18213 } 18214 }); 18215 } 18216 }, 18217 18218 passing: function(newCallback) { 18219 var 18220 calculations = module.get.elementCalculations(), 18221 callback = newCallback || settings.onPassing, 18222 callbackName = 'passing' 18223 ; 18224 if(newCallback) { 18225 module.debug('Adding callback for passing', newCallback); 18226 settings.onPassing = newCallback; 18227 } 18228 if(calculations.passing) { 18229 module.execute(callback, callbackName); 18230 } 18231 else if(!settings.once) { 18232 module.remove.occurred(callbackName); 18233 } 18234 if(newCallback !== undefined) { 18235 return calculations.passing; 18236 } 18237 }, 18238 18239 18240 topVisible: function(newCallback) { 18241 var 18242 calculations = module.get.elementCalculations(), 18243 callback = newCallback || settings.onTopVisible, 18244 callbackName = 'topVisible' 18245 ; 18246 if(newCallback) { 18247 module.debug('Adding callback for top visible', newCallback); 18248 settings.onTopVisible = newCallback; 18249 } 18250 if(calculations.topVisible) { 18251 module.execute(callback, callbackName); 18252 } 18253 else if(!settings.once) { 18254 module.remove.occurred(callbackName); 18255 } 18256 if(newCallback === undefined) { 18257 return calculations.topVisible; 18258 } 18259 }, 18260 18261 bottomVisible: function(newCallback) { 18262 var 18263 calculations = module.get.elementCalculations(), 18264 callback = newCallback || settings.onBottomVisible, 18265 callbackName = 'bottomVisible' 18266 ; 18267 if(newCallback) { 18268 module.debug('Adding callback for bottom visible', newCallback); 18269 settings.onBottomVisible = newCallback; 18270 } 18271 if(calculations.bottomVisible) { 18272 module.execute(callback, callbackName); 18273 } 18274 else if(!settings.once) { 18275 module.remove.occurred(callbackName); 18276 } 18277 if(newCallback === undefined) { 18278 return calculations.bottomVisible; 18279 } 18280 }, 18281 18282 topPassed: function(newCallback) { 18283 var 18284 calculations = module.get.elementCalculations(), 18285 callback = newCallback || settings.onTopPassed, 18286 callbackName = 'topPassed' 18287 ; 18288 if(newCallback) { 18289 module.debug('Adding callback for top passed', newCallback); 18290 settings.onTopPassed = newCallback; 18291 } 18292 if(calculations.topPassed) { 18293 module.execute(callback, callbackName); 18294 } 18295 else if(!settings.once) { 18296 module.remove.occurred(callbackName); 18297 } 18298 if(newCallback === undefined) { 18299 return calculations.topPassed; 18300 } 18301 }, 18302 18303 bottomPassed: function(newCallback) { 18304 var 18305 calculations = module.get.elementCalculations(), 18306 callback = newCallback || settings.onBottomPassed, 18307 callbackName = 'bottomPassed' 18308 ; 18309 if(newCallback) { 18310 module.debug('Adding callback for bottom passed', newCallback); 18311 settings.onBottomPassed = newCallback; 18312 } 18313 if(calculations.bottomPassed) { 18314 module.execute(callback, callbackName); 18315 } 18316 else if(!settings.once) { 18317 module.remove.occurred(callbackName); 18318 } 18319 if(newCallback === undefined) { 18320 return calculations.bottomPassed; 18321 } 18322 }, 18323 18324 passingReverse: function(newCallback) { 18325 var 18326 calculations = module.get.elementCalculations(), 18327 callback = newCallback || settings.onPassingReverse, 18328 callbackName = 'passingReverse' 18329 ; 18330 if(newCallback) { 18331 module.debug('Adding callback for passing reverse', newCallback); 18332 settings.onPassingReverse = newCallback; 18333 } 18334 if(!calculations.passing) { 18335 if(module.get.occurred('passing')) { 18336 module.execute(callback, callbackName); 18337 } 18338 } 18339 else if(!settings.once) { 18340 module.remove.occurred(callbackName); 18341 } 18342 if(newCallback !== undefined) { 18343 return !calculations.passing; 18344 } 18345 }, 18346 18347 18348 topVisibleReverse: function(newCallback) { 18349 var 18350 calculations = module.get.elementCalculations(), 18351 callback = newCallback || settings.onTopVisibleReverse, 18352 callbackName = 'topVisibleReverse' 18353 ; 18354 if(newCallback) { 18355 module.debug('Adding callback for top visible reverse', newCallback); 18356 settings.onTopVisibleReverse = newCallback; 18357 } 18358 if(!calculations.topVisible) { 18359 if(module.get.occurred('topVisible')) { 18360 module.execute(callback, callbackName); 18361 } 18362 } 18363 else if(!settings.once) { 18364 module.remove.occurred(callbackName); 18365 } 18366 if(newCallback === undefined) { 18367 return !calculations.topVisible; 18368 } 18369 }, 18370 18371 bottomVisibleReverse: function(newCallback) { 18372 var 18373 calculations = module.get.elementCalculations(), 18374 callback = newCallback || settings.onBottomVisibleReverse, 18375 callbackName = 'bottomVisibleReverse' 18376 ; 18377 if(newCallback) { 18378 module.debug('Adding callback for bottom visible reverse', newCallback); 18379 settings.onBottomVisibleReverse = newCallback; 18380 } 18381 if(!calculations.bottomVisible) { 18382 if(module.get.occurred('bottomVisible')) { 18383 module.execute(callback, callbackName); 18384 } 18385 } 18386 else if(!settings.once) { 18387 module.remove.occurred(callbackName); 18388 } 18389 if(newCallback === undefined) { 18390 return !calculations.bottomVisible; 18391 } 18392 }, 18393 18394 topPassedReverse: function(newCallback) { 18395 var 18396 calculations = module.get.elementCalculations(), 18397 callback = newCallback || settings.onTopPassedReverse, 18398 callbackName = 'topPassedReverse' 18399 ; 18400 if(newCallback) { 18401 module.debug('Adding callback for top passed reverse', newCallback); 18402 settings.onTopPassedReverse = newCallback; 18403 } 18404 if(!calculations.topPassed) { 18405 if(module.get.occurred('topPassed')) { 18406 module.execute(callback, callbackName); 18407 } 18408 } 18409 else if(!settings.once) { 18410 module.remove.occurred(callbackName); 18411 } 18412 if(newCallback === undefined) { 18413 return !calculations.onTopPassed; 18414 } 18415 }, 18416 18417 bottomPassedReverse: function(newCallback) { 18418 var 18419 calculations = module.get.elementCalculations(), 18420 callback = newCallback || settings.onBottomPassedReverse, 18421 callbackName = 'bottomPassedReverse' 18422 ; 18423 if(newCallback) { 18424 module.debug('Adding callback for bottom passed reverse', newCallback); 18425 settings.onBottomPassedReverse = newCallback; 18426 } 18427 if(!calculations.bottomPassed) { 18428 if(module.get.occurred('bottomPassed')) { 18429 module.execute(callback, callbackName); 18430 } 18431 } 18432 else if(!settings.once) { 18433 module.remove.occurred(callbackName); 18434 } 18435 if(newCallback === undefined) { 18436 return !calculations.bottomPassed; 18437 } 18438 }, 18439 18440 execute: function(callback, callbackName) { 18441 var 18442 calculations = module.get.elementCalculations(), 18443 screen = module.get.screenCalculations() 18444 ; 18445 callback = callback || false; 18446 if(callback) { 18447 if(settings.continuous) { 18448 module.debug('Callback being called continuously', callbackName, calculations); 18449 callback.call(element, calculations, screen); 18450 } 18451 else if(!module.get.occurred(callbackName)) { 18452 module.debug('Conditions met', callbackName, calculations); 18453 callback.call(element, calculations, screen); 18454 } 18455 } 18456 module.save.occurred(callbackName); 18457 }, 18458 18459 remove: { 18460 occurred: function(callback) { 18461 if(callback) { 18462 if(module.cache.occurred[callback] !== undefined && module.cache.occurred[callback] === true) { 18463 module.debug('Callback can now be called again', callback); 18464 module.cache.occurred[callback] = false; 18465 } 18466 } 18467 else { 18468 module.cache.occurred = {}; 18469 } 18470 } 18471 }, 18472 18473 save: { 18474 calculations: function() { 18475 module.verbose('Saving all calculations necessary to determine positioning'); 18476 module.save.scroll(); 18477 module.save.direction(); 18478 module.save.screenCalculations(); 18479 module.save.elementCalculations(); 18480 }, 18481 occurred: function(callback) { 18482 if(callback) { 18483 if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) { 18484 module.verbose('Saving callback occurred', callback); 18485 module.cache.occurred[callback] = true; 18486 } 18487 } 18488 }, 18489 scroll: function() { 18490 module.cache.scroll = $context.scrollTop() + settings.offset; 18491 }, 18492 direction: function() { 18493 var 18494 scroll = module.get.scroll(), 18495 lastScroll = module.get.lastScroll(), 18496 direction 18497 ; 18498 if(scroll > lastScroll && lastScroll) { 18499 direction = 'down'; 18500 } 18501 else if(scroll < lastScroll && lastScroll) { 18502 direction = 'up'; 18503 } 18504 else { 18505 direction = 'static'; 18506 } 18507 module.cache.direction = direction; 18508 return module.cache.direction; 18509 }, 18510 elementPosition: function() { 18511 var 18512 element = module.cache.element, 18513 screen = module.get.screenSize() 18514 ; 18515 module.verbose('Saving element position'); 18516 // (quicker than $.extend) 18517 element.fits = (element.height < screen.height); 18518 element.offset = $module.offset(); 18519 element.width = $module.outerWidth(); 18520 element.height = $module.outerHeight(); 18521 // store 18522 module.cache.element = element; 18523 return element; 18524 }, 18525 elementCalculations: function() { 18526 var 18527 screen = module.get.screenCalculations(), 18528 element = module.get.elementPosition() 18529 ; 18530 // offset 18531 if(settings.includeMargin) { 18532 element.margin = {}; 18533 element.margin.top = parseInt($module.css('margin-top'), 10); 18534 element.margin.bottom = parseInt($module.css('margin-bottom'), 10); 18535 element.top = element.offset.top - element.margin.top; 18536 element.bottom = element.offset.top + element.height + element.margin.bottom; 18537 } 18538 else { 18539 element.top = element.offset.top; 18540 element.bottom = element.offset.top + element.height; 18541 } 18542 18543 // visibility 18544 element.topVisible = (screen.bottom >= element.top); 18545 element.topPassed = (screen.top >= element.top); 18546 element.bottomVisible = (screen.bottom >= element.bottom); 18547 element.bottomPassed = (screen.top >= element.bottom); 18548 element.pixelsPassed = 0; 18549 element.percentagePassed = 0; 18550 18551 // meta calculations 18552 element.visible = (element.topVisible || element.bottomVisible); 18553 element.passing = (element.topPassed && !element.bottomPassed); 18554 element.hidden = (!element.topVisible && !element.bottomVisible); 18555 18556 // passing calculations 18557 if(element.passing) { 18558 element.pixelsPassed = (screen.top - element.top); 18559 element.percentagePassed = (screen.top - element.top) / element.height; 18560 } 18561 module.cache.element = element; 18562 module.verbose('Updated element calculations', element); 18563 return element; 18564 }, 18565 screenCalculations: function() { 18566 var 18567 scroll = module.get.scroll() 18568 ; 18569 module.save.direction(); 18570 module.cache.screen.top = scroll; 18571 module.cache.screen.bottom = scroll + module.cache.screen.height; 18572 return module.cache.screen; 18573 }, 18574 screenSize: function() { 18575 module.verbose('Saving window position'); 18576 module.cache.screen = { 18577 height: $context.height() 18578 }; 18579 }, 18580 position: function() { 18581 module.save.screenSize(); 18582 module.save.elementPosition(); 18583 } 18584 }, 18585 18586 get: { 18587 pixelsPassed: function(amount) { 18588 var 18589 element = module.get.elementCalculations() 18590 ; 18591 if(amount.search('%') > -1) { 18592 return ( element.height * (parseInt(amount, 10) / 100) ); 18593 } 18594 return parseInt(amount, 10); 18595 }, 18596 occurred: function(callback) { 18597 return (module.cache.occurred !== undefined) 18598 ? module.cache.occurred[callback] || false 18599 : false 18600 ; 18601 }, 18602 direction: function() { 18603 if(module.cache.direction === undefined) { 18604 module.save.direction(); 18605 } 18606 return module.cache.direction; 18607 }, 18608 elementPosition: function() { 18609 if(module.cache.element === undefined) { 18610 module.save.elementPosition(); 18611 } 18612 return module.cache.element; 18613 }, 18614 elementCalculations: function() { 18615 if(module.cache.element === undefined) { 18616 module.save.elementCalculations(); 18617 } 18618 return module.cache.element; 18619 }, 18620 screenCalculations: function() { 18621 if(module.cache.screen === undefined) { 18622 module.save.screenCalculations(); 18623 } 18624 return module.cache.screen; 18625 }, 18626 screenSize: function() { 18627 if(module.cache.screen === undefined) { 18628 module.save.screenSize(); 18629 } 18630 return module.cache.screen; 18631 }, 18632 scroll: function() { 18633 if(module.cache.scroll === undefined) { 18634 module.save.scroll(); 18635 } 18636 return module.cache.scroll; 18637 }, 18638 lastScroll: function() { 18639 if(module.cache.screen === undefined) { 18640 module.debug('First scroll event, no last scroll could be found'); 18641 return false; 18642 } 18643 return module.cache.screen.top; 18644 } 18645 }, 18646 18647 setting: function(name, value) { 18648 if( $.isPlainObject(name) ) { 18649 $.extend(true, settings, name); 18650 } 18651 else if(value !== undefined) { 18652 settings[name] = value; 18653 } 18654 else { 18655 return settings[name]; 18656 } 18657 }, 18658 internal: function(name, value) { 18659 if( $.isPlainObject(name) ) { 18660 $.extend(true, module, name); 18661 } 18662 else if(value !== undefined) { 18663 module[name] = value; 18664 } 18665 else { 18666 return module[name]; 18667 } 18668 }, 18669 debug: function() { 18670 if(settings.debug) { 18671 if(settings.performance) { 18672 module.performance.log(arguments); 18673 } 18674 else { 18675 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 18676 module.debug.apply(console, arguments); 18677 } 18678 } 18679 }, 18680 verbose: function() { 18681 if(settings.verbose && settings.debug) { 18682 if(settings.performance) { 18683 module.performance.log(arguments); 18684 } 18685 else { 18686 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 18687 module.verbose.apply(console, arguments); 18688 } 18689 } 18690 }, 18691 error: function() { 18692 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 18693 module.error.apply(console, arguments); 18694 }, 18695 performance: { 18696 log: function(message) { 18697 var 18698 currentTime, 18699 executionTime, 18700 previousTime 18701 ; 18702 if(settings.performance) { 18703 currentTime = new Date().getTime(); 18704 previousTime = time || currentTime; 18705 executionTime = currentTime - previousTime; 18706 time = currentTime; 18707 performance.push({ 18708 'Name' : message[0], 18709 'Arguments' : [].slice.call(message, 1) || '', 18710 'Element' : element, 18711 'Execution Time' : executionTime 18712 }); 18713 } 18714 clearTimeout(module.performance.timer); 18715 module.performance.timer = setTimeout(module.performance.display, 100); 18716 }, 18717 display: function() { 18718 var 18719 title = settings.name + ':', 18720 totalTime = 0 18721 ; 18722 time = false; 18723 clearTimeout(module.performance.timer); 18724 $.each(performance, function(index, data) { 18725 totalTime += data['Execution Time']; 18726 }); 18727 title += ' ' + totalTime + 'ms'; 18728 if(moduleSelector) { 18729 title += ' \'' + moduleSelector + '\''; 18730 } 18731 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 18732 console.groupCollapsed(title); 18733 if(console.table) { 18734 console.table(performance); 18735 } 18736 else { 18737 $.each(performance, function(index, data) { 18738 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 18739 }); 18740 } 18741 console.groupEnd(); 18742 } 18743 performance = []; 18744 } 18745 }, 18746 invoke: function(query, passedArguments, context) { 18747 var 18748 object = instance, 18749 maxDepth, 18750 found, 18751 response 18752 ; 18753 passedArguments = passedArguments || queryArguments; 18754 context = element || context; 18755 if(typeof query == 'string' && object !== undefined) { 18756 query = query.split(/[\. ]/); 18757 maxDepth = query.length - 1; 18758 $.each(query, function(depth, value) { 18759 var camelCaseValue = (depth != maxDepth) 18760 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 18761 : query 18762 ; 18763 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 18764 object = object[camelCaseValue]; 18765 } 18766 else if( object[camelCaseValue] !== undefined ) { 18767 found = object[camelCaseValue]; 18768 return false; 18769 } 18770 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 18771 object = object[value]; 18772 } 18773 else if( object[value] !== undefined ) { 18774 found = object[value]; 18775 return false; 18776 } 18777 else { 18778 module.error(error.method, query); 18779 return false; 18780 } 18781 }); 18782 } 18783 if ( $.isFunction( found ) ) { 18784 response = found.apply(context, passedArguments); 18785 } 18786 else if(found !== undefined) { 18787 response = found; 18788 } 18789 if($.isArray(returnedValue)) { 18790 returnedValue.push(response); 18791 } 18792 else if(returnedValue !== undefined) { 18793 returnedValue = [returnedValue, response]; 18794 } 18795 else if(response !== undefined) { 18796 returnedValue = response; 18797 } 18798 return found; 18799 } 18800 }; 18801 18802 if(methodInvoked) { 18803 if(instance === undefined) { 18804 module.initialize(); 18805 } 18806 module.invoke(query); 18807 } 18808 else { 18809 if(instance !== undefined) { 18810 instance.invoke('destroy'); 18811 } 18812 module.initialize(); 18813 } 18814 }) 18815 ; 18816 18817 return (returnedValue !== undefined) 18818 ? returnedValue 18819 : this 18820 ; 18821 }; 18822 18823 $.fn.visibility.settings = { 18824 18825 name : 'Visibility', 18826 namespace : 'visibility', 18827 18828 debug : false, 18829 verbose : false, 18830 performance : true, 18831 18832 // whether to use mutation observers to follow changes 18833 observeChanges : true, 18834 18835 // callback should only occur one time 18836 once : true, 18837 18838 // callback should fire continuously whe evaluates to true 18839 continuous : false, 18840 18841 // offset to use with scroll top 18842 offset : 0, 18843 18844 // whether to include margin in elements position 18845 includeMargin : false, 18846 18847 // scroll context for visibility checks 18848 context : window, 18849 18850 // check position immediately on init 18851 initialCheck : true, 18852 18853 // visibility check delay in ms (defaults to animationFrame) 18854 throttle : false, 18855 18856 // special visibility type (image, fixed) 18857 type : false, 18858 18859 // image only animation settings 18860 transition : false, 18861 duration : 1000, 18862 18863 // array of callbacks for percentage 18864 onPassed : {}, 18865 18866 // standard callbacks 18867 onPassing : false, 18868 onTopVisible : false, 18869 onBottomVisible : false, 18870 onTopPassed : false, 18871 onBottomPassed : false, 18872 18873 // reverse callbacks 18874 onPassingReverse : false, 18875 onTopVisibleReverse : false, 18876 onBottomVisibleReverse : false, 18877 onTopPassedReverse : false, 18878 onBottomPassedReverse : false, 18879 18880 // utility callbacks 18881 onUpdate : false, // disabled by default for performance 18882 onRefresh : function(){}, 18883 18884 className: { 18885 fixed: 'fixed' 18886 }, 18887 18888 error : { 18889 method : 'The method you called is not defined.' 18890 } 18891 18892 }; 18893 18894 })( jQuery, window , document );