You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

20610 lines
645 KiB

  1. /*
  2. * # Semantic UI - 2.0.0
  3. * https://github.com/Semantic-Org/Semantic-UI
  4. * http://www.semantic-ui.com/
  5. *
  6. * Copyright 2014 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. /*!
  12. * # Semantic UI 2.0.0 - Site
  13. * http://github.com/semantic-org/semantic-ui/
  14. *
  15. *
  16. * Copyright 2015 Contributors
  17. * Released under the MIT license
  18. * http://opensource.org/licenses/MIT
  19. *
  20. */
  21. ;(function ( $, window, document, undefined ) {
  22. $.site = $.fn.site = function(parameters) {
  23. var
  24. time = new Date().getTime(),
  25. performance = [],
  26. query = arguments[0],
  27. methodInvoked = (typeof query == 'string'),
  28. queryArguments = [].slice.call(arguments, 1),
  29. settings = ( $.isPlainObject(parameters) )
  30. ? $.extend(true, {}, $.site.settings, parameters)
  31. : $.extend({}, $.site.settings),
  32. namespace = settings.namespace,
  33. error = settings.error,
  34. eventNamespace = '.' + namespace,
  35. moduleNamespace = 'module-' + namespace,
  36. $document = $(document),
  37. $module = $document,
  38. element = this,
  39. instance = $module.data(moduleNamespace),
  40. module,
  41. returnedValue
  42. ;
  43. module = {
  44. initialize: function() {
  45. module.instantiate();
  46. },
  47. instantiate: function() {
  48. module.verbose('Storing instance of site', module);
  49. instance = module;
  50. $module
  51. .data(moduleNamespace, module)
  52. ;
  53. },
  54. normalize: function() {
  55. module.fix.console();
  56. module.fix.requestAnimationFrame();
  57. },
  58. fix: {
  59. console: function() {
  60. module.debug('Normalizing window.console');
  61. if (console === undefined || console.log === undefined) {
  62. module.verbose('Console not available, normalizing events');
  63. module.disable.console();
  64. }
  65. if (typeof console.group == 'undefined' || typeof console.groupEnd == 'undefined' || typeof console.groupCollapsed == 'undefined') {
  66. module.verbose('Console group not available, normalizing events');
  67. window.console.group = function() {};
  68. window.console.groupEnd = function() {};
  69. window.console.groupCollapsed = function() {};
  70. }
  71. if (typeof console.markTimeline == 'undefined') {
  72. module.verbose('Mark timeline not available, normalizing events');
  73. window.console.markTimeline = function() {};
  74. }
  75. },
  76. consoleClear: function() {
  77. module.debug('Disabling programmatic console clearing');
  78. window.console.clear = function() {};
  79. },
  80. requestAnimationFrame: function() {
  81. module.debug('Normalizing requestAnimationFrame');
  82. if(window.requestAnimationFrame === undefined) {
  83. module.debug('RequestAnimationFrame not available, normailizing event');
  84. window.requestAnimationFrame = window.requestAnimationFrame
  85. || window.mozRequestAnimationFrame
  86. || window.webkitRequestAnimationFrame
  87. || window.msRequestAnimationFrame
  88. || function(callback) { setTimeout(callback, 0); }
  89. ;
  90. }
  91. }
  92. },
  93. moduleExists: function(name) {
  94. return ($.fn[name] !== undefined && $.fn[name].settings !== undefined);
  95. },
  96. enabled: {
  97. modules: function(modules) {
  98. var
  99. enabledModules = []
  100. ;
  101. modules = modules || settings.modules;
  102. $.each(modules, function(index, name) {
  103. if(module.moduleExists(name)) {
  104. enabledModules.push(name);
  105. }
  106. });
  107. return enabledModules;
  108. }
  109. },
  110. disabled: {
  111. modules: function(modules) {
  112. var
  113. disabledModules = []
  114. ;
  115. modules = modules || settings.modules;
  116. $.each(modules, function(index, name) {
  117. if(!module.moduleExists(name)) {
  118. disabledModules.push(name);
  119. }
  120. });
  121. return disabledModules;
  122. }
  123. },
  124. change: {
  125. setting: function(setting, value, modules, modifyExisting) {
  126. modules = (typeof modules === 'string')
  127. ? (modules === 'all')
  128. ? settings.modules
  129. : [modules]
  130. : modules || settings.modules
  131. ;
  132. modifyExisting = (modifyExisting !== undefined)
  133. ? modifyExisting
  134. : true
  135. ;
  136. $.each(modules, function(index, name) {
  137. var
  138. namespace = (module.moduleExists(name))
  139. ? $.fn[name].settings.namespace || false
  140. : true,
  141. $existingModules
  142. ;
  143. if(module.moduleExists(name)) {
  144. module.verbose('Changing default setting', setting, value, name);
  145. $.fn[name].settings[setting] = value;
  146. if(modifyExisting && namespace) {
  147. $existingModules = $(':data(module-' + namespace + ')');
  148. if($existingModules.length > 0) {
  149. module.verbose('Modifying existing settings', $existingModules);
  150. $existingModules[name]('setting', setting, value);
  151. }
  152. }
  153. }
  154. });
  155. },
  156. settings: function(newSettings, modules, modifyExisting) {
  157. modules = (typeof modules === 'string')
  158. ? [modules]
  159. : modules || settings.modules
  160. ;
  161. modifyExisting = (modifyExisting !== undefined)
  162. ? modifyExisting
  163. : true
  164. ;
  165. $.each(modules, function(index, name) {
  166. var
  167. $existingModules
  168. ;
  169. if(module.moduleExists(name)) {
  170. module.verbose('Changing default setting', newSettings, name);
  171. $.extend(true, $.fn[name].settings, newSettings);
  172. if(modifyExisting && namespace) {
  173. $existingModules = $(':data(module-' + namespace + ')');
  174. if($existingModules.length > 0) {
  175. module.verbose('Modifying existing settings', $existingModules);
  176. $existingModules[name]('setting', newSettings);
  177. }
  178. }
  179. }
  180. });
  181. }
  182. },
  183. enable: {
  184. console: function() {
  185. module.console(true);
  186. },
  187. debug: function(modules, modifyExisting) {
  188. modules = modules || settings.modules;
  189. module.debug('Enabling debug for modules', modules);
  190. module.change.setting('debug', true, modules, modifyExisting);
  191. },
  192. verbose: function(modules, modifyExisting) {
  193. modules = modules || settings.modules;
  194. module.debug('Enabling verbose debug for modules', modules);
  195. module.change.setting('verbose', true, modules, modifyExisting);
  196. }
  197. },
  198. disable: {
  199. console: function() {
  200. module.console(false);
  201. },
  202. debug: function(modules, modifyExisting) {
  203. modules = modules || settings.modules;
  204. module.debug('Disabling debug for modules', modules);
  205. module.change.setting('debug', false, modules, modifyExisting);
  206. },
  207. verbose: function(modules, modifyExisting) {
  208. modules = modules || settings.modules;
  209. module.debug('Disabling verbose debug for modules', modules);
  210. module.change.setting('verbose', false, modules, modifyExisting);
  211. }
  212. },
  213. console: function(enable) {
  214. if(enable) {
  215. if(instance.cache.console === undefined) {
  216. module.error(error.console);
  217. return;
  218. }
  219. module.debug('Restoring console function');
  220. window.console = instance.cache.console;
  221. }
  222. else {
  223. module.debug('Disabling console function');
  224. instance.cache.console = window.console;
  225. window.console = {
  226. clear : function(){},
  227. error : function(){},
  228. group : function(){},
  229. groupCollapsed : function(){},
  230. groupEnd : function(){},
  231. info : function(){},
  232. log : function(){},
  233. markTimeline : function(){},
  234. warn : function(){}
  235. };
  236. }
  237. },
  238. destroy: function() {
  239. module.verbose('Destroying previous site for', $module);
  240. $module
  241. .removeData(moduleNamespace)
  242. ;
  243. },
  244. cache: {},
  245. setting: function(name, value) {
  246. if( $.isPlainObject(name) ) {
  247. $.extend(true, settings, name);
  248. }
  249. else if(value !== undefined) {
  250. settings[name] = value;
  251. }
  252. else {
  253. return settings[name];
  254. }
  255. },
  256. internal: function(name, value) {
  257. if( $.isPlainObject(name) ) {
  258. $.extend(true, module, name);
  259. }
  260. else if(value !== undefined) {
  261. module[name] = value;
  262. }
  263. else {
  264. return module[name];
  265. }
  266. },
  267. debug: function() {
  268. if(settings.debug) {
  269. if(settings.performance) {
  270. module.performance.log(arguments);
  271. }
  272. else {
  273. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  274. module.debug.apply(console, arguments);
  275. }
  276. }
  277. },
  278. verbose: function() {
  279. if(settings.verbose && settings.debug) {
  280. if(settings.performance) {
  281. module.performance.log(arguments);
  282. }
  283. else {
  284. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  285. module.verbose.apply(console, arguments);
  286. }
  287. }
  288. },
  289. error: function() {
  290. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  291. module.error.apply(console, arguments);
  292. },
  293. performance: {
  294. log: function(message) {
  295. var
  296. currentTime,
  297. executionTime,
  298. previousTime
  299. ;
  300. if(settings.performance) {
  301. currentTime = new Date().getTime();
  302. previousTime = time || currentTime;
  303. executionTime = currentTime - previousTime;
  304. time = currentTime;
  305. performance.push({
  306. 'Element' : element,
  307. 'Name' : message[0],
  308. 'Arguments' : [].slice.call(message, 1) || '',
  309. 'Execution Time' : executionTime
  310. });
  311. }
  312. clearTimeout(module.performance.timer);
  313. module.performance.timer = setTimeout(module.performance.display, 500);
  314. },
  315. display: function() {
  316. var
  317. title = settings.name + ':',
  318. totalTime = 0
  319. ;
  320. time = false;
  321. clearTimeout(module.performance.timer);
  322. $.each(performance, function(index, data) {
  323. totalTime += data['Execution Time'];
  324. });
  325. title += ' ' + totalTime + 'ms';
  326. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  327. console.groupCollapsed(title);
  328. if(console.table) {
  329. console.table(performance);
  330. }
  331. else {
  332. $.each(performance, function(index, data) {
  333. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  334. });
  335. }
  336. console.groupEnd();
  337. }
  338. performance = [];
  339. }
  340. },
  341. invoke: function(query, passedArguments, context) {
  342. var
  343. object = instance,
  344. maxDepth,
  345. found,
  346. response
  347. ;
  348. passedArguments = passedArguments || queryArguments;
  349. context = element || context;
  350. if(typeof query == 'string' && object !== undefined) {
  351. query = query.split(/[\. ]/);
  352. maxDepth = query.length - 1;
  353. $.each(query, function(depth, value) {
  354. var camelCaseValue = (depth != maxDepth)
  355. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  356. : query
  357. ;
  358. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  359. object = object[camelCaseValue];
  360. }
  361. else if( object[camelCaseValue] !== undefined ) {
  362. found = object[camelCaseValue];
  363. return false;
  364. }
  365. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  366. object = object[value];
  367. }
  368. else if( object[value] !== undefined ) {
  369. found = object[value];
  370. return false;
  371. }
  372. else {
  373. module.error(error.method, query);
  374. return false;
  375. }
  376. });
  377. }
  378. if ( $.isFunction( found ) ) {
  379. response = found.apply(context, passedArguments);
  380. }
  381. else if(found !== undefined) {
  382. response = found;
  383. }
  384. if($.isArray(returnedValue)) {
  385. returnedValue.push(response);
  386. }
  387. else if(returnedValue !== undefined) {
  388. returnedValue = [returnedValue, response];
  389. }
  390. else if(response !== undefined) {
  391. returnedValue = response;
  392. }
  393. return found;
  394. }
  395. };
  396. if(methodInvoked) {
  397. if(instance === undefined) {
  398. module.initialize();
  399. }
  400. module.invoke(query);
  401. }
  402. else {
  403. if(instance !== undefined) {
  404. module.destroy();
  405. }
  406. module.initialize();
  407. }
  408. return (returnedValue !== undefined)
  409. ? returnedValue
  410. : this
  411. ;
  412. };
  413. $.site.settings = {
  414. name : 'Site',
  415. namespace : 'site',
  416. error : {
  417. console : 'Console cannot be restored, most likely it was overwritten outside of module',
  418. method : 'The method you called is not defined.'
  419. },
  420. debug : false,
  421. verbose : false,
  422. performance : true,
  423. modules: [
  424. 'accordion',
  425. 'api',
  426. 'checkbox',
  427. 'dimmer',
  428. 'dropdown',
  429. 'embed',
  430. 'form',
  431. 'modal',
  432. 'nag',
  433. 'popup',
  434. 'rating',
  435. 'shape',
  436. 'sidebar',
  437. 'state',
  438. 'sticky',
  439. 'tab',
  440. 'transition',
  441. 'visit',
  442. 'visibility'
  443. ],
  444. siteNamespace : 'site',
  445. namespaceStub : {
  446. cache : {},
  447. config : {},
  448. sections : {},
  449. section : {},
  450. utilities : {}
  451. }
  452. };
  453. // allows for selection of elements with data attributes
  454. $.extend($.expr[ ":" ], {
  455. data: ($.expr.createPseudo)
  456. ? $.expr.createPseudo(function(dataName) {
  457. return function(elem) {
  458. return !!$.data(elem, dataName);
  459. };
  460. })
  461. : function(elem, i, match) {
  462. // support: jQuery < 1.8
  463. return !!$.data(elem, match[ 3 ]);
  464. }
  465. });
  466. })( jQuery, window , document );
  467. /*!
  468. * # Semantic UI 2.0.0 - Form Validation
  469. * http://github.com/semantic-org/semantic-ui/
  470. *
  471. *
  472. * Copyright 2015 Contributors
  473. * Released under the MIT license
  474. * http://opensource.org/licenses/MIT
  475. *
  476. */
  477. ;(function ( $, window, document, undefined ) {
  478. "use strict";
  479. $.fn.form = function(parameters) {
  480. var
  481. $allModules = $(this),
  482. moduleSelector = $allModules.selector || '',
  483. time = new Date().getTime(),
  484. performance = [],
  485. query = arguments[0],
  486. legacyParameters = arguments[1],
  487. methodInvoked = (typeof query == 'string'),
  488. queryArguments = [].slice.call(arguments, 1),
  489. returnedValue
  490. ;
  491. $allModules
  492. .each(function() {
  493. var
  494. $module = $(this),
  495. element = this,
  496. formErrors = [],
  497. keyHeldDown = false,
  498. // set at run-time
  499. $field,
  500. $group,
  501. $message,
  502. $prompt,
  503. $submit,
  504. $clear,
  505. $reset,
  506. settings,
  507. validation,
  508. metadata,
  509. selector,
  510. className,
  511. error,
  512. namespace,
  513. moduleNamespace,
  514. eventNamespace,
  515. instance,
  516. module
  517. ;
  518. module = {
  519. initialize: function() {
  520. // settings grabbed at run time
  521. module.get.settings();
  522. if(methodInvoked) {
  523. if(instance === undefined) {
  524. module.instantiate();
  525. }
  526. module.invoke(query);
  527. }
  528. else {
  529. module.verbose('Initializing form validation', $module, settings);
  530. module.bindEvents();
  531. module.set.defaults();
  532. module.instantiate();
  533. }
  534. },
  535. instantiate: function() {
  536. module.verbose('Storing instance of module', module);
  537. instance = module;
  538. $module
  539. .data(moduleNamespace, module)
  540. ;
  541. },
  542. destroy: function() {
  543. module.verbose('Destroying previous module', instance);
  544. module.removeEvents();
  545. $module
  546. .removeData(moduleNamespace)
  547. ;
  548. },
  549. refresh: function() {
  550. module.verbose('Refreshing selector cache');
  551. $field = $module.find(selector.field);
  552. $group = $module.find(selector.group);
  553. $message = $module.find(selector.message);
  554. $prompt = $module.find(selector.prompt);
  555. $submit = $module.find(selector.submit);
  556. $clear = $module.find(selector.clear);
  557. $reset = $module.find(selector.reset);
  558. },
  559. submit: function() {
  560. module.verbose('Submitting form', $module);
  561. $module
  562. .submit()
  563. ;
  564. },
  565. attachEvents: function(selector, action) {
  566. action = action || 'submit';
  567. $(selector)
  568. .on('click' + eventNamespace, function(event) {
  569. module[action]();
  570. event.preventDefault();
  571. })
  572. ;
  573. },
  574. bindEvents: function() {
  575. module.verbose('Attaching form events');
  576. $module
  577. .on('submit' + eventNamespace, module.validate.form)
  578. .on('blur' + eventNamespace, selector.field, module.event.field.blur)
  579. .on('click' + eventNamespace, selector.submit, module.submit)
  580. .on('click' + eventNamespace, selector.reset, module.reset)
  581. .on('click' + eventNamespace, selector.clear, module.clear)
  582. ;
  583. if(settings.keyboardShortcuts) {
  584. $module
  585. .on('keydown' + eventNamespace, selector.field, module.event.field.keydown)
  586. ;
  587. }
  588. $field
  589. .each(function() {
  590. var
  591. $input = $(this),
  592. type = $input.prop('type'),
  593. inputEvent = module.get.changeEvent(type, $input)
  594. ;
  595. $(this)
  596. .on(inputEvent + eventNamespace, module.event.field.change)
  597. ;
  598. })
  599. ;
  600. },
  601. clear: function() {
  602. $field
  603. .each(function () {
  604. var
  605. $field = $(this),
  606. $element = $field.parent(),
  607. $fieldGroup = $field.closest($group),
  608. $prompt = $fieldGroup.find(selector.prompt),
  609. defaultValue = $field.data(metadata.defaultValue) || '',
  610. isCheckbox = $element.is(selector.uiCheckbox),
  611. isDropdown = $element.is(selector.uiDropdown),
  612. isErrored = $fieldGroup.hasClass(className.error)
  613. ;
  614. if(isErrored) {
  615. module.verbose('Resetting error on field', $fieldGroup);
  616. $fieldGroup.removeClass(className.error);
  617. $prompt.remove();
  618. }
  619. if(isDropdown) {
  620. module.verbose('Resetting dropdown value', $element, defaultValue);
  621. $element.dropdown('clear');
  622. }
  623. else if(isCheckbox) {
  624. $field.prop('checked', false);
  625. }
  626. else {
  627. module.verbose('Resetting field value', $field, defaultValue);
  628. $field.val('');
  629. }
  630. })
  631. ;
  632. },
  633. reset: function() {
  634. $field
  635. .each(function () {
  636. var
  637. $field = $(this),
  638. $element = $field.parent(),
  639. $fieldGroup = $field.closest($group),
  640. $prompt = $fieldGroup.find(selector.prompt),
  641. defaultValue = $field.data(metadata.defaultValue),
  642. isCheckbox = $element.is(selector.uiCheckbox),
  643. isDropdown = $element.is(selector.uiDropdown),
  644. isErrored = $fieldGroup.hasClass(className.error)
  645. ;
  646. if(defaultValue === undefined) {
  647. defaultValue = '';
  648. }
  649. if(isErrored) {
  650. module.verbose('Resetting error on field', $fieldGroup);
  651. $fieldGroup.removeClass(className.error);
  652. $prompt.remove();
  653. }
  654. if(isDropdown) {
  655. module.verbose('Resetting dropdown value', $element, defaultValue);
  656. $element.dropdown('restore defaults');
  657. }
  658. else if(isCheckbox) {
  659. module.verbose('Resetting checkbox value', $element, defaultValue);
  660. $field.prop('checked', defaultValue);
  661. }
  662. else {
  663. module.verbose('Resetting field value', $field, defaultValue);
  664. $field.val(defaultValue);
  665. }
  666. })
  667. ;
  668. },
  669. is: {
  670. valid: function() {
  671. var
  672. allValid = true
  673. ;
  674. module.verbose('Checking if form is valid');
  675. $.each(validation, function(fieldName, field) {
  676. if( !( module.validate.field(field) ) ) {
  677. allValid = false;
  678. }
  679. });
  680. return allValid;
  681. }
  682. },
  683. removeEvents: function() {
  684. $module
  685. .off(eventNamespace)
  686. ;
  687. $field
  688. .off(eventNamespace)
  689. ;
  690. $submit
  691. .off(eventNamespace)
  692. ;
  693. $field
  694. .off(eventNamespace)
  695. ;
  696. },
  697. event: {
  698. field: {
  699. keydown: function(event) {
  700. var
  701. $field = $(this),
  702. key = event.which,
  703. keyCode = {
  704. enter : 13,
  705. escape : 27
  706. }
  707. ;
  708. if( key == keyCode.escape) {
  709. module.verbose('Escape key pressed blurring field');
  710. $field
  711. .blur()
  712. ;
  713. }
  714. if(!event.ctrlKey && key == keyCode.enter && $field.is(selector.input) && $field.not(selector.checkbox).length > 0 ) {
  715. if(!keyHeldDown) {
  716. $field
  717. .one('keyup' + eventNamespace, module.event.field.keyup)
  718. ;
  719. module.submit();
  720. module.debug('Enter pressed on input submitting form');
  721. }
  722. keyHeldDown = true;
  723. }
  724. },
  725. keyup: function() {
  726. keyHeldDown = false;
  727. },
  728. blur: function() {
  729. var
  730. $field = $(this),
  731. $fieldGroup = $field.closest($group),
  732. validationRules = module.get.validation($field)
  733. ;
  734. if( $fieldGroup.hasClass(className.error) ) {
  735. module.debug('Revalidating field', $field, validationRules);
  736. module.validate.field( validationRules );
  737. }
  738. else if(settings.on == 'blur' || settings.on == 'change') {
  739. module.validate.field( validationRules );
  740. }
  741. },
  742. change: function() {
  743. var
  744. $field = $(this),
  745. $fieldGroup = $field.closest($group)
  746. ;
  747. if(settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) ) {
  748. clearTimeout(module.timer);
  749. module.timer = setTimeout(function() {
  750. module.debug('Revalidating field', $field, module.get.validation($field));
  751. module.validate.field( module.get.validation($field) );
  752. }, settings.delay);
  753. }
  754. }
  755. }
  756. },
  757. get: {
  758. changeEvent: function(type, $input) {
  759. if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
  760. return 'change';
  761. }
  762. else {
  763. return module.get.inputEvent();
  764. }
  765. },
  766. inputEvent: function() {
  767. return (document.createElement('input').oninput !== undefined)
  768. ? 'input'
  769. : (document.createElement('input').onpropertychange !== undefined)
  770. ? 'propertychange'
  771. : 'keyup'
  772. ;
  773. },
  774. settings: function() {
  775. var
  776. firstProperty
  777. ;
  778. if($.isPlainObject(parameters)) {
  779. var
  780. keys = Object.keys(parameters),
  781. isLegacySettings = (keys.length > 0)
  782. ? (parameters[keys[0]].identifier !== undefined)
  783. : false
  784. ;
  785. if(isLegacySettings) {
  786. // 1.x (ducktyped)
  787. settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
  788. validation = $.extend({}, $.fn.form.settings.defaults, parameters);
  789. module.error(settings.error.oldSyntax, element);
  790. module.verbose('Extending settings from legacy parameters', validation, settings);
  791. }
  792. else {
  793. // 2.x
  794. settings = $.extend(true, {}, $.fn.form.settings, parameters);
  795. validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
  796. module.verbose('Extending settings', validation, settings);
  797. }
  798. }
  799. else {
  800. settings = $.fn.form.settings;
  801. validation = $.fn.form.settings.defaults;
  802. module.verbose('Using default form validation', validation, settings);
  803. }
  804. // shorthand
  805. namespace = settings.namespace;
  806. metadata = settings.metadata;
  807. selector = settings.selector;
  808. className = settings.className;
  809. error = settings.error;
  810. moduleNamespace = 'module-' + namespace;
  811. eventNamespace = '.' + namespace;
  812. // grab instance
  813. instance = $module.data(moduleNamespace);
  814. // refresh selector cache
  815. module.refresh();
  816. },
  817. field: function(identifier) {
  818. module.verbose('Finding field with identifier', identifier);
  819. if( $field.filter('#' + identifier).length > 0 ) {
  820. return $field.filter('#' + identifier);
  821. }
  822. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  823. return $field.filter('[name="' + identifier +'"]');
  824. }
  825. else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) {
  826. return $field.filter('[name="' + identifier +'[]"]');
  827. }
  828. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  829. return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]');
  830. }
  831. return $('<input/>');
  832. },
  833. fields: function(fields) {
  834. var
  835. $fields = $()
  836. ;
  837. $.each(fields, function(index, name) {
  838. $fields = $fields.add( module.get.field(name) );
  839. });
  840. return $fields;
  841. },
  842. validation: function($field) {
  843. var
  844. rules
  845. ;
  846. if(!validation) {
  847. return false;
  848. }
  849. $.each(validation, function(fieldName, field) {
  850. if( module.get.field(field.identifier)[0] == $field[0] ) {
  851. rules = field;
  852. }
  853. });
  854. return rules || false;
  855. },
  856. value: function (field) {
  857. var
  858. fields = [],
  859. results
  860. ;
  861. fields.push(field);
  862. results = module.get.values.call(element, fields);
  863. return results[field];
  864. },
  865. values: function (fields) {
  866. var
  867. $fields = $.isArray(fields)
  868. ? module.get.fields(fields)
  869. : $field,
  870. values = {}
  871. ;
  872. $fields.each(function(index, field) {
  873. var
  874. $field = $(field),
  875. type = $field.prop('type'),
  876. name = $field.prop('name'),
  877. value = $field.val(),
  878. isCheckbox = $field.is(selector.checkbox),
  879. isRadio = $field.is(selector.radio),
  880. isMultiple = (name.indexOf('[]') !== -1),
  881. isChecked = (isCheckbox)
  882. ? $field.is(':checked')
  883. : false
  884. ;
  885. if(name) {
  886. if(isMultiple) {
  887. name = name.replace('[]', '');
  888. if(!values[name]) {
  889. values[name] = [];
  890. }
  891. if(isCheckbox) {
  892. if(isChecked) {
  893. values[name].push(value);
  894. }
  895. else {
  896. module.debug('Omitted unchecked checkbox', $field);
  897. return true;
  898. }
  899. }
  900. else {
  901. values[name].push(value);
  902. }
  903. }
  904. else {
  905. if(isRadio) {
  906. if(isChecked) {
  907. values[name] = value;
  908. }
  909. }
  910. else if(isCheckbox) {
  911. if(isChecked) {
  912. values[name] = true;
  913. }
  914. else {
  915. module.debug('Omitted unchecked checkbox', $field);
  916. return true;
  917. }
  918. }
  919. else {
  920. values[name] = value;
  921. }
  922. }
  923. }
  924. });
  925. return values;
  926. }
  927. },
  928. has: {
  929. field: function(identifier) {
  930. module.verbose('Checking for existence of a field with identifier', identifier);
  931. if( $field.filter('#' + identifier).length > 0 ) {
  932. return true;
  933. }
  934. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  935. return true;
  936. }
  937. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  938. return true;
  939. }
  940. return false;
  941. }
  942. },
  943. add: {
  944. prompt: function(identifier, errors) {
  945. var
  946. $field = module.get.field(identifier),
  947. $fieldGroup = $field.closest($group),
  948. $prompt = $fieldGroup.children(selector.prompt),
  949. promptExists = ($prompt.length !== 0)
  950. ;
  951. errors = (typeof errors == 'string')
  952. ? [errors]
  953. : errors
  954. ;
  955. module.verbose('Adding field error state', identifier);
  956. $fieldGroup
  957. .addClass(className.error)
  958. ;
  959. if(settings.inline) {
  960. if(!promptExists) {
  961. $prompt = settings.templates.prompt(errors);
  962. $prompt
  963. .appendTo($fieldGroup)
  964. ;
  965. }
  966. $prompt
  967. .html(errors[0])
  968. ;
  969. if(!promptExists) {
  970. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  971. module.verbose('Displaying error with css transition', settings.transition);
  972. $prompt.transition(settings.transition + ' in', settings.duration);
  973. }
  974. else {
  975. module.verbose('Displaying error with fallback javascript animation');
  976. $prompt
  977. .fadeIn(settings.duration)
  978. ;
  979. }
  980. }
  981. else {
  982. module.verbose('Inline errors are disabled, no inline error added', identifier);
  983. }
  984. }
  985. },
  986. errors: function(errors) {
  987. module.debug('Adding form error messages', errors);
  988. $message
  989. .html( settings.templates.error(errors) )
  990. ;
  991. }
  992. },
  993. remove: {
  994. prompt: function(field) {
  995. var
  996. $field = module.get.field(field.identifier),
  997. $fieldGroup = $field.closest($group),
  998. $prompt = $fieldGroup.children(selector.prompt)
  999. ;
  1000. $fieldGroup
  1001. .removeClass(className.error)
  1002. ;
  1003. if(settings.inline && $prompt.is(':visible')) {
  1004. module.verbose('Removing prompt for field', field);
  1005. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  1006. $prompt.transition(settings.transition + ' out', settings.duration, function() {
  1007. $prompt.remove();
  1008. });
  1009. }
  1010. else {
  1011. $prompt
  1012. .fadeOut(settings.duration, function(){
  1013. $prompt.remove();
  1014. })
  1015. ;
  1016. }
  1017. }
  1018. }
  1019. },
  1020. set: {
  1021. success: function() {
  1022. $module
  1023. .removeClass(className.error)
  1024. .addClass(className.success)
  1025. ;
  1026. },
  1027. defaults: function () {
  1028. $field
  1029. .each(function () {
  1030. var
  1031. $field = $(this),
  1032. isCheckbox = ($field.filter(selector.checkbox).length > 0),
  1033. value = (isCheckbox)
  1034. ? $field.is(':checked')
  1035. : $field.val()
  1036. ;
  1037. $field.data(metadata.defaultValue, value);
  1038. })
  1039. ;
  1040. },
  1041. error: function() {
  1042. $module
  1043. .removeClass(className.success)
  1044. .addClass(className.error)
  1045. ;
  1046. },
  1047. value: function (field, value) {
  1048. var
  1049. fields = {}
  1050. ;
  1051. fields[field] = value;
  1052. return module.set.values.call(element, fields);
  1053. },
  1054. values: function (fields) {
  1055. if($.isEmptyObject(fields)) {
  1056. return;
  1057. }
  1058. $.each(fields, function(key, value) {
  1059. var
  1060. $field = module.get.field(key),
  1061. $element = $field.parent(),
  1062. isMultiple = $.isArray(value),
  1063. isCheckbox = $element.is(selector.uiCheckbox),
  1064. isDropdown = $element.is(selector.uiDropdown),
  1065. isRadio = ($field.is(selector.radio) && isCheckbox),
  1066. fieldExists = ($field.length > 0),
  1067. $multipleField
  1068. ;
  1069. if(fieldExists) {
  1070. if(isMultiple && isCheckbox) {
  1071. module.verbose('Selecting multiple', value, $field);
  1072. $element.checkbox('uncheck');
  1073. $.each(value, function(index, value) {
  1074. $multipleField = $field.filter('[value="' + value + '"]');
  1075. $element = $multipleField.parent();
  1076. if($multipleField.length > 0) {
  1077. $element.checkbox('check');
  1078. }
  1079. });
  1080. }
  1081. else if(isRadio) {
  1082. module.verbose('Selecting radio value', value, $field);
  1083. $field.filter('[value="' + value + '"]')
  1084. .parent(selector.uiCheckbox)
  1085. .checkbox('check')
  1086. ;
  1087. }
  1088. else if(isCheckbox) {
  1089. module.verbose('Setting checkbox value', value, $element);
  1090. if(value === true) {
  1091. $element.checkbox('check');
  1092. }
  1093. else {
  1094. $element.checkbox('uncheck');
  1095. }
  1096. }
  1097. else if(isDropdown) {
  1098. module.verbose('Setting dropdown value', value, $element);
  1099. $element.dropdown('set selected', value);
  1100. }
  1101. else {
  1102. module.verbose('Setting field value', value, $field);
  1103. $field.val(value);
  1104. }
  1105. }
  1106. });
  1107. }
  1108. },
  1109. validate: {
  1110. form: function(event) {
  1111. var
  1112. apiRequest
  1113. ;
  1114. // input keydown event will fire submit repeatedly by browser default
  1115. if(keyHeldDown) {
  1116. return false;
  1117. }
  1118. // reset errors
  1119. formErrors = [];
  1120. if( module.is.valid() ) {
  1121. module.debug('Form has no validation errors, submitting');
  1122. module.set.success();
  1123. return settings.onSuccess.call(element, event);
  1124. }
  1125. else {
  1126. module.debug('Form has errors');
  1127. module.set.error();
  1128. if(!settings.inline) {
  1129. module.add.errors(formErrors);
  1130. }
  1131. // prevent ajax submit
  1132. if($module.data('moduleApi') !== undefined) {
  1133. event.stopImmediatePropagation();
  1134. }
  1135. return settings.onFailure.call(element, formErrors);
  1136. }
  1137. },
  1138. // takes a validation object and returns whether field passes validation
  1139. field: function(field) {
  1140. var
  1141. $field = module.get.field(field.identifier),
  1142. fieldValid = true,
  1143. fieldErrors = []
  1144. ;
  1145. if($field.prop('disabled')) {
  1146. module.debug('Field is disabled. Skipping', field.identifier);
  1147. fieldValid = true;
  1148. }
  1149. else if(field.optional && $.trim($field.val()) === ''){
  1150. module.debug('Field is optional and empty. Skipping', field.identifier);
  1151. fieldValid = true;
  1152. }
  1153. else if(field.rules !== undefined) {
  1154. $.each(field.rules, function(index, rule) {
  1155. if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) {
  1156. module.debug('Field is invalid', field.identifier, rule.type);
  1157. fieldErrors.push(rule.prompt);
  1158. fieldValid = false;
  1159. }
  1160. });
  1161. }
  1162. if(fieldValid) {
  1163. module.remove.prompt(field, fieldErrors);
  1164. settings.onValid.call($field);
  1165. }
  1166. else {
  1167. formErrors = formErrors.concat(fieldErrors);
  1168. module.add.prompt(field.identifier, fieldErrors);
  1169. settings.onInvalid.call($field, fieldErrors);
  1170. return false;
  1171. }
  1172. return true;
  1173. },
  1174. // takes validation rule and returns whether field passes rule
  1175. rule: function(field, validation) {
  1176. var
  1177. $field = module.get.field(field.identifier),
  1178. type = validation.type,
  1179. value = $field.val(),
  1180. bracket = type.match(settings.regExp.bracket),
  1181. isValid = true,
  1182. rule,
  1183. ancillary,
  1184. functionType
  1185. ;
  1186. // cast to string
  1187. value = $.trim($field.val() + '');
  1188. // if bracket notation is used, pass in extra parameters
  1189. if(bracket) {
  1190. ancillary = '' + bracket[1];
  1191. functionType = type.replace(bracket[0], '');
  1192. rule = settings.rules[functionType];
  1193. if( !$.isFunction(rule) ) {
  1194. module.error(error.noRule, functionType);
  1195. return;
  1196. }
  1197. isValid = rule.call($field, value, ancillary);
  1198. }
  1199. else {
  1200. rule = settings.rules[type];
  1201. if( !$.isFunction(rule) ) {
  1202. module.error(error.noRule, type);
  1203. return;
  1204. }
  1205. isValid = rule.call($field, value);
  1206. }
  1207. return isValid;
  1208. }
  1209. },
  1210. setting: function(name, value) {
  1211. if( $.isPlainObject(name) ) {
  1212. $.extend(true, settings, name);
  1213. }
  1214. else if(value !== undefined) {
  1215. settings[name] = value;
  1216. }
  1217. else {
  1218. return settings[name];
  1219. }
  1220. },
  1221. internal: function(name, value) {
  1222. if( $.isPlainObject(name) ) {
  1223. $.extend(true, module, name);
  1224. }
  1225. else if(value !== undefined) {
  1226. module[name] = value;
  1227. }
  1228. else {
  1229. return module[name];
  1230. }
  1231. },
  1232. debug: function() {
  1233. if(settings.debug) {
  1234. if(settings.performance) {
  1235. module.performance.log(arguments);
  1236. }
  1237. else {
  1238. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1239. module.debug.apply(console, arguments);
  1240. }
  1241. }
  1242. },
  1243. verbose: function() {
  1244. if(settings.verbose && settings.debug) {
  1245. if(settings.performance) {
  1246. module.performance.log(arguments);
  1247. }
  1248. else {
  1249. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1250. module.verbose.apply(console, arguments);
  1251. }
  1252. }
  1253. },
  1254. error: function() {
  1255. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  1256. module.error.apply(console, arguments);
  1257. },
  1258. performance: {
  1259. log: function(message) {
  1260. var
  1261. currentTime,
  1262. executionTime,
  1263. previousTime
  1264. ;
  1265. if(settings.performance) {
  1266. currentTime = new Date().getTime();
  1267. previousTime = time || currentTime;
  1268. executionTime = currentTime - previousTime;
  1269. time = currentTime;
  1270. performance.push({
  1271. 'Name' : message[0],
  1272. 'Arguments' : [].slice.call(message, 1) || '',
  1273. 'Element' : element,
  1274. 'Execution Time' : executionTime
  1275. });
  1276. }
  1277. clearTimeout(module.performance.timer);
  1278. module.performance.timer = setTimeout(module.performance.display, 500);
  1279. },
  1280. display: function() {
  1281. var
  1282. title = settings.name + ':',
  1283. totalTime = 0
  1284. ;
  1285. time = false;
  1286. clearTimeout(module.performance.timer);
  1287. $.each(performance, function(index, data) {
  1288. totalTime += data['Execution Time'];
  1289. });
  1290. title += ' ' + totalTime + 'ms';
  1291. if(moduleSelector) {
  1292. title += ' \'' + moduleSelector + '\'';
  1293. }
  1294. if($allModules.length > 1) {
  1295. title += ' ' + '(' + $allModules.length + ')';
  1296. }
  1297. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  1298. console.groupCollapsed(title);
  1299. if(console.table) {
  1300. console.table(performance);
  1301. }
  1302. else {
  1303. $.each(performance, function(index, data) {
  1304. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  1305. });
  1306. }
  1307. console.groupEnd();
  1308. }
  1309. performance = [];
  1310. }
  1311. },
  1312. invoke: function(query, passedArguments, context) {
  1313. var
  1314. object = instance,
  1315. maxDepth,
  1316. found,
  1317. response
  1318. ;
  1319. passedArguments = passedArguments || queryArguments;
  1320. context = element || context;
  1321. if(typeof query == 'string' && object !== undefined) {
  1322. query = query.split(/[\. ]/);
  1323. maxDepth = query.length - 1;
  1324. $.each(query, function(depth, value) {
  1325. var camelCaseValue = (depth != maxDepth)
  1326. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  1327. : query
  1328. ;
  1329. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  1330. object = object[camelCaseValue];
  1331. }
  1332. else if( object[camelCaseValue] !== undefined ) {
  1333. found = object[camelCaseValue];
  1334. return false;
  1335. }
  1336. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  1337. object = object[value];
  1338. }
  1339. else if( object[value] !== undefined ) {
  1340. found = object[value];
  1341. return false;
  1342. }
  1343. else {
  1344. return false;
  1345. }
  1346. });
  1347. }
  1348. if( $.isFunction( found ) ) {
  1349. response = found.apply(context, passedArguments);
  1350. }
  1351. else if(found !== undefined) {
  1352. response = found;
  1353. }
  1354. if($.isArray(returnedValue)) {
  1355. returnedValue.push(response);
  1356. }
  1357. else if(returnedValue !== undefined) {
  1358. returnedValue = [returnedValue, response];
  1359. }
  1360. else if(response !== undefined) {
  1361. returnedValue = response;
  1362. }
  1363. return found;
  1364. }
  1365. };
  1366. module.initialize();
  1367. })
  1368. ;
  1369. return (returnedValue !== undefined)
  1370. ? returnedValue
  1371. : this
  1372. ;
  1373. };
  1374. $.fn.form.settings = {
  1375. name : 'Form',
  1376. namespace : 'form',
  1377. debug : false,
  1378. verbose : false,
  1379. performance : true,
  1380. fields : false,
  1381. keyboardShortcuts : true,
  1382. on : 'submit',
  1383. inline : false,
  1384. delay : 200,
  1385. revalidate : true,
  1386. transition : 'scale',
  1387. duration : 200,
  1388. onValid : function() {},
  1389. onInvalid : function() {},
  1390. onSuccess : function() { return true; },
  1391. onFailure : function() { return false; },
  1392. metadata : {
  1393. defaultValue : 'default',
  1394. validate : 'validate'
  1395. },
  1396. regExp: {
  1397. bracket : /\[(.*)\]/i,
  1398. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  1399. email : "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
  1400. integer : /^\-?\d+$/,
  1401. flags : /^\/(.*)\/(.*)?/,
  1402. url : /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i
  1403. },
  1404. selector : {
  1405. checkbox : 'input[type="checkbox"], input[type="radio"]',
  1406. clear : '.clear',
  1407. field : 'input, textarea, select',
  1408. group : '.field',
  1409. input : 'input',
  1410. message : '.error.message',
  1411. prompt : '.prompt.label',
  1412. radio : 'input[type="radio"]',
  1413. reset : '.reset:not([type="reset"])',
  1414. submit : '.submit:not([type="submit"])',
  1415. uiCheckbox : '.ui.checkbox',
  1416. uiDropdown : '.ui.dropdown'
  1417. },
  1418. className : {
  1419. error : 'error',
  1420. label : 'ui prompt label',
  1421. pressed : 'down',
  1422. success : 'success'
  1423. },
  1424. error: {
  1425. oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.',
  1426. noRule : 'There is no rule matching the one you specified',
  1427. method : 'The method you called is not defined.'
  1428. },
  1429. templates: {
  1430. // template that produces error message
  1431. error: function(errors) {
  1432. var
  1433. html = '<ul class="list">'
  1434. ;
  1435. $.each(errors, function(index, value) {
  1436. html += '<li>' + value + '</li>';
  1437. });
  1438. html += '</ul>';
  1439. return $(html);
  1440. },
  1441. // template that produces label
  1442. prompt: function(errors) {
  1443. return $('<div/>')
  1444. .addClass('ui red pointing prompt label')
  1445. .html(errors[0])
  1446. ;
  1447. }
  1448. },
  1449. rules: {
  1450. // checkbox checked
  1451. checked: function() {
  1452. return ($(this).filter(':checked').length > 0);
  1453. },
  1454. // value contains text (insensitive)
  1455. contains: function(value, text) {
  1456. // escape regex characters
  1457. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1458. return (value.search( new RegExp(text, 'i') ) !== -1);
  1459. },
  1460. // value contains text (case sensitive)
  1461. containsExactly: function(value, text) {
  1462. // escape regex characters
  1463. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1464. return (value.search( new RegExp(text) ) !== -1);
  1465. },
  1466. // is most likely an email
  1467. email: function(value){
  1468. var
  1469. emailRegExp = new RegExp($.fn.form.settings.regExp.email, 'i')
  1470. ;
  1471. return emailRegExp.test(value);
  1472. },
  1473. // is not empty or blank string
  1474. empty: function(value) {
  1475. return !(value === undefined || '' === value || $.isArray(value) && value.length === 0);
  1476. },
  1477. // is valid integer
  1478. integer: function(value, range) {
  1479. var
  1480. intRegExp = $.fn.form.settings.regExp.integer,
  1481. min,
  1482. max,
  1483. parts
  1484. ;
  1485. if(range === undefined || range === '' || range === '..') {
  1486. // do nothing
  1487. }
  1488. else if(range.indexOf('..') == -1) {
  1489. if(intRegExp.test(range)) {
  1490. min = max = range - 0;
  1491. }
  1492. }
  1493. else {
  1494. parts = range.split('..', 2);
  1495. if(intRegExp.test(parts[0])) {
  1496. min = parts[0] - 0;
  1497. }
  1498. if(intRegExp.test(parts[1])) {
  1499. max = parts[1] - 0;
  1500. }
  1501. }
  1502. return (
  1503. intRegExp.test(value) &&
  1504. (min === undefined || value >= min) &&
  1505. (max === undefined || value <= max)
  1506. );
  1507. },
  1508. // is value (case insensitive)
  1509. is: function(value, text) {
  1510. text = (typeof text == 'string')
  1511. ? text.toLowerCase()
  1512. : text
  1513. ;
  1514. value = (typeof value == 'string')
  1515. ? value.toLowerCase()
  1516. : value
  1517. ;
  1518. return (value == text);
  1519. },
  1520. // is value
  1521. isExactly: function(value, text) {
  1522. return (value == text);
  1523. },
  1524. // is at least string length
  1525. length: function(value, requiredLength) {
  1526. return (value !== undefined)
  1527. ? (value.length >= requiredLength)
  1528. : false
  1529. ;
  1530. },
  1531. // matches another field
  1532. different: function(value, identifier) {
  1533. // use either id or name of field
  1534. var
  1535. $form = $(this),
  1536. matchingValue
  1537. ;
  1538. if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
  1539. matchingValue = $('[data-validate="'+ identifier +'"]').val();
  1540. }
  1541. else if($('#' + identifier).length > 0) {
  1542. matchingValue = $('#' + identifier).val();
  1543. }
  1544. else if($('[name="' + identifier +'"]').length > 0) {
  1545. matchingValue = $('[name="' + identifier + '"]').val();
  1546. }
  1547. else if( $('[name="' + identifier +'[]"]').length > 0 ) {
  1548. matchingValue = $('[name="' + identifier +'[]"]');
  1549. }
  1550. return (matchingValue !== undefined)
  1551. ? ( value.toString() !== matchingValue.toString() )
  1552. : false
  1553. ;
  1554. },
  1555. // matches another field
  1556. match: function(value, identifier) {
  1557. // use either id or name of field
  1558. var
  1559. $form = $(this),
  1560. matchingValue
  1561. ;
  1562. if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
  1563. matchingValue = $('[data-validate="'+ identifier +'"]').val();
  1564. }
  1565. else if($('#' + identifier).length > 0) {
  1566. matchingValue = $('#' + identifier).val();
  1567. }
  1568. else if($('[name="' + identifier +'"]').length > 0) {
  1569. matchingValue = $('[name="' + identifier + '"]').val();
  1570. }
  1571. else if( $('[name="' + identifier +'[]"]').length > 0 ) {
  1572. matchingValue = $('[name="' + identifier +'[]"]');
  1573. }
  1574. return (matchingValue !== undefined)
  1575. ? ( value.toString() == matchingValue.toString() )
  1576. : false
  1577. ;
  1578. },
  1579. maxCount: function(value, count) {
  1580. value = value.split(',');
  1581. return ($.isArray(value) && value.length <= count);
  1582. },
  1583. exactCount: function(value, count) {
  1584. value = value.split(',');
  1585. return ($.isArray(value) && value.length == count);
  1586. },
  1587. minCount: function(value, count) {
  1588. value = value.split(',');
  1589. return ($.isArray(value) && value.length >= count);
  1590. },
  1591. regExp: function(value, regExp) {
  1592. var
  1593. regExpParts = regExp.match($.fn.form.settings.regExp.flags),
  1594. flags
  1595. ;
  1596. // regular expression specified as /baz/gi (flags)
  1597. if(regExpParts) {
  1598. regExp = (regExpParts.length >= 2)
  1599. ? regExpParts[1]
  1600. : regExp
  1601. ;
  1602. flags = (regExpParts.length >= 3)
  1603. ? regExpParts[2]
  1604. : ''
  1605. ;
  1606. }
  1607. return value.match( new RegExp(regExp, flags) );
  1608. },
  1609. // string length is less than max length
  1610. maxLength: function(value, maxLength) {
  1611. return (value !== undefined)
  1612. ? (value.length <= maxLength)
  1613. : false
  1614. ;
  1615. },
  1616. // value is not value (case insensitive)
  1617. not: function(value, notValue) {
  1618. value = (typeof value == 'string')
  1619. ? value.toLowerCase()
  1620. : value
  1621. ;
  1622. notValue = (typeof notValue == 'string')
  1623. ? notValue.toLowerCase()
  1624. : notValue
  1625. ;
  1626. return (value != notValue);
  1627. },
  1628. // value is not value (case sensitive)
  1629. notExactly: function(value, notValue) {
  1630. return (value != notValue);
  1631. },
  1632. // value is most likely url
  1633. url: function(value) {
  1634. return $.fn.form.settings.regExp.url.match(value);
  1635. }
  1636. }
  1637. };
  1638. })( jQuery, window , document );
  1639. /*!
  1640. * # Semantic UI 2.0.0 - Accordion
  1641. * http://github.com/semantic-org/semantic-ui/
  1642. *
  1643. *
  1644. * Copyright 2015 Contributors
  1645. * Released under the MIT license
  1646. * http://opensource.org/licenses/MIT
  1647. *
  1648. */
  1649. ;(function ($, window, document, undefined) {
  1650. "use strict";
  1651. $.fn.accordion = function(parameters) {
  1652. var
  1653. $allModules = $(this),
  1654. time = new Date().getTime(),
  1655. performance = [],
  1656. query = arguments[0],
  1657. methodInvoked = (typeof query == 'string'),
  1658. queryArguments = [].slice.call(arguments, 1),
  1659. requestAnimationFrame = window.requestAnimationFrame
  1660. || window.mozRequestAnimationFrame
  1661. || window.webkitRequestAnimationFrame
  1662. || window.msRequestAnimationFrame
  1663. || function(callback) { setTimeout(callback, 0); },
  1664. returnedValue
  1665. ;
  1666. $allModules
  1667. .each(function() {
  1668. var
  1669. settings = ( $.isPlainObject(parameters) )
  1670. ? $.extend(true, {}, $.fn.accordion.settings, parameters)
  1671. : $.extend({}, $.fn.accordion.settings),
  1672. className = settings.className,
  1673. namespace = settings.namespace,
  1674. selector = settings.selector,
  1675. error = settings.error,
  1676. eventNamespace = '.' + namespace,
  1677. moduleNamespace = 'module-' + namespace,
  1678. moduleSelector = $allModules.selector || '',
  1679. $module = $(this),
  1680. $title = $module.find(selector.title),
  1681. $content = $module.find(selector.content),
  1682. element = this,
  1683. instance = $module.data(moduleNamespace),
  1684. observer,
  1685. module
  1686. ;
  1687. module = {
  1688. initialize: function() {
  1689. module.debug('Initializing', $module);
  1690. module.bind.events();
  1691. module.observeChanges();
  1692. module.instantiate();
  1693. },
  1694. instantiate: function() {
  1695. instance = module;
  1696. $module
  1697. .data(moduleNamespace, module)
  1698. ;
  1699. },
  1700. destroy: function() {
  1701. module.debug('Destroying previous instance', $module);
  1702. $module
  1703. .off(eventNamespace)
  1704. .removeData(moduleNamespace)
  1705. ;
  1706. },
  1707. refresh: function() {
  1708. $title = $module.find(selector.title);
  1709. $content = $module.find(selector.content);
  1710. },
  1711. observeChanges: function() {
  1712. if('MutationObserver' in window) {
  1713. observer = new MutationObserver(function(mutations) {
  1714. module.debug('DOM tree modified, updating selector cache');
  1715. module.refresh();
  1716. });
  1717. observer.observe(element, {
  1718. childList : true,
  1719. subtree : true
  1720. });
  1721. module.debug('Setting up mutation observer', observer);
  1722. }
  1723. },
  1724. bind: {
  1725. events: function() {
  1726. module.debug('Binding delegated events');
  1727. $module
  1728. .on(settings.on + eventNamespace, selector.trigger, module.event.click)
  1729. ;
  1730. }
  1731. },
  1732. event: {
  1733. click: function() {
  1734. module.toggle.call(this);
  1735. }
  1736. },
  1737. toggle: function(query) {
  1738. var
  1739. $activeTitle = (query !== undefined)
  1740. ? (typeof query === 'number')
  1741. ? $title.eq(query)
  1742. : $(query).closest(selector.title)
  1743. : $(this).closest(selector.title),
  1744. $activeContent = $activeTitle.next($content),
  1745. isAnimating = $activeContent.hasClass(className.animating),
  1746. isActive = $activeContent.hasClass(className.active),
  1747. isOpen = (isActive && !isAnimating),
  1748. isOpening = (!isActive && isAnimating)
  1749. ;
  1750. module.debug('Toggling visibility of content', $activeTitle);
  1751. if(isOpen || isOpening) {
  1752. if(settings.collapsible) {
  1753. module.close.call($activeTitle);
  1754. }
  1755. else {
  1756. module.debug('Cannot close accordion content collapsing is disabled');
  1757. }
  1758. }
  1759. else {
  1760. module.open.call($activeTitle);
  1761. }
  1762. },
  1763. open: function(query) {
  1764. var
  1765. $activeTitle = (query !== undefined)
  1766. ? (typeof query === 'number')
  1767. ? $title.eq(query)
  1768. : $(query).closest(selector.title)
  1769. : $(this).closest(selector.title),
  1770. $activeContent = $activeTitle.next($content),
  1771. isAnimating = $activeContent.hasClass(className.animating),
  1772. isActive = $activeContent.hasClass(className.active),
  1773. isOpen = (isActive || isAnimating)
  1774. ;
  1775. if(isOpen) {
  1776. module.debug('Accordion already open, skipping', $activeContent);
  1777. return;
  1778. }
  1779. module.debug('Opening accordion content', $activeTitle);
  1780. settings.onOpening.call($activeContent);
  1781. if(settings.exclusive) {
  1782. module.closeOthers.call($activeTitle);
  1783. }
  1784. $activeTitle
  1785. .addClass(className.active)
  1786. ;
  1787. $activeContent
  1788. .stop(true, true)
  1789. .addClass(className.animating)
  1790. ;
  1791. if(settings.animateChildren) {
  1792. if($.fn.transition !== undefined && $module.transition('is supported')) {
  1793. $activeContent
  1794. .children()
  1795. .transition({
  1796. animation : 'fade in',
  1797. queue : false,
  1798. useFailSafe : true,
  1799. debug : settings.debug,
  1800. verbose : settings.verbose,
  1801. duration : settings.duration
  1802. })
  1803. ;
  1804. }
  1805. else {
  1806. $activeContent
  1807. .children()
  1808. .stop(true, true)
  1809. .animate({
  1810. opacity: 1
  1811. }, settings.duration, module.resetOpacity)
  1812. ;
  1813. }
  1814. }
  1815. $activeContent
  1816. .slideDown(settings.duration, settings.easing, function() {
  1817. $activeContent
  1818. .removeClass(className.animating)
  1819. .addClass(className.active)
  1820. ;
  1821. module.reset.display.call(this);
  1822. settings.onOpen.call(this);
  1823. settings.onChange.call(this);
  1824. })
  1825. ;
  1826. },
  1827. close: function(query) {
  1828. var
  1829. $activeTitle = (query !== undefined)
  1830. ? (typeof query === 'number')
  1831. ? $title.eq(query)
  1832. : $(query).closest(selector.title)
  1833. : $(this).closest(selector.title),
  1834. $activeContent = $activeTitle.next($content),
  1835. isAnimating = $activeContent.hasClass(className.animating),
  1836. isActive = $activeContent.hasClass(className.active),
  1837. isOpening = (!isActive && isAnimating),
  1838. isClosing = (isActive && isAnimating)
  1839. ;
  1840. if((isActive || isOpening) && !isClosing) {
  1841. module.debug('Closing accordion content', $activeContent);
  1842. settings.onClosing.call($activeContent);
  1843. $activeTitle
  1844. .removeClass(className.active)
  1845. ;
  1846. $activeContent
  1847. .stop(true, true)
  1848. .addClass(className.animating)
  1849. ;
  1850. if(settings.animateChildren) {
  1851. if($.fn.transition !== undefined && $module.transition('is supported')) {
  1852. $activeContent
  1853. .children()
  1854. .transition({
  1855. animation : 'fade out',
  1856. queue : false,
  1857. useFailSafe : true,
  1858. debug : settings.debug,
  1859. verbose : settings.verbose,
  1860. duration : settings.duration
  1861. })
  1862. ;
  1863. }
  1864. else {
  1865. $activeContent
  1866. .children()
  1867. .stop(true, true)
  1868. .animate({
  1869. opacity: 0
  1870. }, settings.duration, module.resetOpacity)
  1871. ;
  1872. }
  1873. }
  1874. $activeContent
  1875. .slideUp(settings.duration, settings.easing, function() {
  1876. $activeContent
  1877. .removeClass(className.animating)
  1878. .removeClass(className.active)
  1879. ;
  1880. module.reset.display.call(this);
  1881. settings.onClose.call(this);
  1882. settings.onChange.call(this);
  1883. })
  1884. ;
  1885. }
  1886. },
  1887. closeOthers: function(index) {
  1888. var
  1889. $activeTitle = (index !== undefined)
  1890. ? $title.eq(index)
  1891. : $(this).closest(selector.title),
  1892. $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
  1893. $activeAccordion = $activeTitle.closest(selector.accordion),
  1894. activeSelector = selector.title + '.' + className.active + ':visible',
  1895. activeContent = selector.content + '.' + className.active + ':visible',
  1896. $openTitles,
  1897. $nestedTitles,
  1898. $openContents
  1899. ;
  1900. if(settings.closeNested) {
  1901. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  1902. $openContents = $openTitles.next($content);
  1903. }
  1904. else {
  1905. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  1906. $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
  1907. $openTitles = $openTitles.not($nestedTitles);
  1908. $openContents = $openTitles.next($content);
  1909. }
  1910. if( ($openTitles.length > 0) ) {
  1911. module.debug('Exclusive enabled, closing other content', $openTitles);
  1912. $openTitles
  1913. .removeClass(className.active)
  1914. ;
  1915. $openContents
  1916. .removeClass(className.animating)
  1917. .stop(true, true)
  1918. ;
  1919. if(settings.animateChildren) {
  1920. if($.fn.transition !== undefined && $module.transition('is supported')) {
  1921. $openContents
  1922. .children()
  1923. .transition({
  1924. animation : 'fade out',
  1925. useFailSafe : true,
  1926. debug : settings.debug,
  1927. verbose : settings.verbose,
  1928. duration : settings.duration
  1929. })
  1930. ;
  1931. }
  1932. else {
  1933. $openContents
  1934. .children()
  1935. .stop(true, true)
  1936. .animate({
  1937. opacity: 0
  1938. }, settings.duration, module.resetOpacity)
  1939. ;
  1940. }
  1941. }
  1942. $openContents
  1943. .slideUp(settings.duration , settings.easing, function() {
  1944. $(this).removeClass(className.active);
  1945. module.reset.display.call(this);
  1946. })
  1947. ;
  1948. }
  1949. },
  1950. reset: {
  1951. display: function() {
  1952. module.verbose('Removing inline display from element', this);
  1953. $(this).css('display', '');
  1954. if( $(this).attr('style') === '') {
  1955. $(this)
  1956. .attr('style', '')
  1957. .removeAttr('style')
  1958. ;
  1959. }
  1960. },
  1961. opacity: function() {
  1962. module.verbose('Removing inline opacity from element', this);
  1963. $(this).css('opacity', '');
  1964. if( $(this).attr('style') === '') {
  1965. $(this)
  1966. .attr('style', '')
  1967. .removeAttr('style')
  1968. ;
  1969. }
  1970. },
  1971. },
  1972. setting: function(name, value) {
  1973. module.debug('Changing setting', name, value);
  1974. if( $.isPlainObject(name) ) {
  1975. $.extend(true, settings, name);
  1976. }
  1977. else if(value !== undefined) {
  1978. settings[name] = value;
  1979. }
  1980. else {
  1981. return settings[name];
  1982. }
  1983. },
  1984. internal: function(name, value) {
  1985. module.debug('Changing internal', name, value);
  1986. if(value !== undefined) {
  1987. if( $.isPlainObject(name) ) {
  1988. $.extend(true, module, name);
  1989. }
  1990. else {
  1991. module[name] = value;
  1992. }
  1993. }
  1994. else {
  1995. return module[name];
  1996. }
  1997. },
  1998. debug: function() {
  1999. if(settings.debug) {
  2000. if(settings.performance) {
  2001. module.performance.log(arguments);
  2002. }
  2003. else {
  2004. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2005. module.debug.apply(console, arguments);
  2006. }
  2007. }
  2008. },
  2009. verbose: function() {
  2010. if(settings.verbose && settings.debug) {
  2011. if(settings.performance) {
  2012. module.performance.log(arguments);
  2013. }
  2014. else {
  2015. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2016. module.verbose.apply(console, arguments);
  2017. }
  2018. }
  2019. },
  2020. error: function() {
  2021. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  2022. module.error.apply(console, arguments);
  2023. },
  2024. performance: {
  2025. log: function(message) {
  2026. var
  2027. currentTime,
  2028. executionTime,
  2029. previousTime
  2030. ;
  2031. if(settings.performance) {
  2032. currentTime = new Date().getTime();
  2033. previousTime = time || currentTime;
  2034. executionTime = currentTime - previousTime;
  2035. time = currentTime;
  2036. performance.push({
  2037. 'Name' : message[0],
  2038. 'Arguments' : [].slice.call(message, 1) || '',
  2039. 'Element' : element,
  2040. 'Execution Time' : executionTime
  2041. });
  2042. }
  2043. clearTimeout(module.performance.timer);
  2044. module.performance.timer = setTimeout(module.performance.display, 500);
  2045. },
  2046. display: function() {
  2047. var
  2048. title = settings.name + ':',
  2049. totalTime = 0
  2050. ;
  2051. time = false;
  2052. clearTimeout(module.performance.timer);
  2053. $.each(performance, function(index, data) {
  2054. totalTime += data['Execution Time'];
  2055. });
  2056. title += ' ' + totalTime + 'ms';
  2057. if(moduleSelector) {
  2058. title += ' \'' + moduleSelector + '\'';
  2059. }
  2060. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  2061. console.groupCollapsed(title);
  2062. if(console.table) {
  2063. console.table(performance);
  2064. }
  2065. else {
  2066. $.each(performance, function(index, data) {
  2067. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  2068. });
  2069. }
  2070. console.groupEnd();
  2071. }
  2072. performance = [];
  2073. }
  2074. },
  2075. invoke: function(query, passedArguments, context) {
  2076. var
  2077. object = instance,
  2078. maxDepth,
  2079. found,
  2080. response
  2081. ;
  2082. passedArguments = passedArguments || queryArguments;
  2083. context = element || context;
  2084. if(typeof query == 'string' && object !== undefined) {
  2085. query = query.split(/[\. ]/);
  2086. maxDepth = query.length - 1;
  2087. $.each(query, function(depth, value) {
  2088. var camelCaseValue = (depth != maxDepth)
  2089. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  2090. : query
  2091. ;
  2092. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  2093. object = object[camelCaseValue];
  2094. }
  2095. else if( object[camelCaseValue] !== undefined ) {
  2096. found = object[camelCaseValue];
  2097. return false;
  2098. }
  2099. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  2100. object = object[value];
  2101. }
  2102. else if( object[value] !== undefined ) {
  2103. found = object[value];
  2104. return false;
  2105. }
  2106. else {
  2107. module.error(error.method, query);
  2108. return false;
  2109. }
  2110. });
  2111. }
  2112. if ( $.isFunction( found ) ) {
  2113. response = found.apply(context, passedArguments);
  2114. }
  2115. else if(found !== undefined) {
  2116. response = found;
  2117. }
  2118. if($.isArray(returnedValue)) {
  2119. returnedValue.push(response);
  2120. }
  2121. else if(returnedValue !== undefined) {
  2122. returnedValue = [returnedValue, response];
  2123. }
  2124. else if(response !== undefined) {
  2125. returnedValue = response;
  2126. }
  2127. return found;
  2128. }
  2129. };
  2130. if(methodInvoked) {
  2131. if(instance === undefined) {
  2132. module.initialize();
  2133. }
  2134. module.invoke(query);
  2135. }
  2136. else {
  2137. if(instance !== undefined) {
  2138. instance.invoke('destroy');
  2139. }
  2140. module.initialize();
  2141. }
  2142. })
  2143. ;
  2144. return (returnedValue !== undefined)
  2145. ? returnedValue
  2146. : this
  2147. ;
  2148. };
  2149. $.fn.accordion.settings = {
  2150. name : 'Accordion',
  2151. namespace : 'accordion',
  2152. debug : false,
  2153. verbose : false,
  2154. performance : true,
  2155. on : 'click',
  2156. exclusive : true,
  2157. collapsible : true,
  2158. closeNested : false,
  2159. animateChildren : true,
  2160. duration : 350,
  2161. easing : 'easeOutQuad',
  2162. onOpening : function(){},
  2163. onOpen : function(){},
  2164. onClosing : function(){},
  2165. onClose : function(){},
  2166. onChange : function(){},
  2167. error: {
  2168. method : 'The method you called is not defined'
  2169. },
  2170. className : {
  2171. active : 'active',
  2172. animating : 'animating'
  2173. },
  2174. selector : {
  2175. accordion : '.accordion',
  2176. title : '.title',
  2177. trigger : '.title',
  2178. content : '.content'
  2179. }
  2180. };
  2181. // Adds easing
  2182. $.extend( $.easing, {
  2183. easeOutQuad: function (x, t, b, c, d) {
  2184. return -c *(t/=d)*(t-2) + b;
  2185. }
  2186. });
  2187. })( jQuery, window , document );
  2188. /*!
  2189. * # Semantic UI 2.0.0 - Checkbox
  2190. * http://github.com/semantic-org/semantic-ui/
  2191. *
  2192. *
  2193. * Copyright 2015 Contributors
  2194. * Released under the MIT license
  2195. * http://opensource.org/licenses/MIT
  2196. *
  2197. */
  2198. ;(function ( $, window, document, undefined ) {
  2199. "use strict";
  2200. $.fn.checkbox = function(parameters) {
  2201. var
  2202. $allModules = $(this),
  2203. moduleSelector = $allModules.selector || '',
  2204. time = new Date().getTime(),
  2205. performance = [],
  2206. query = arguments[0],
  2207. methodInvoked = (typeof query == 'string'),
  2208. queryArguments = [].slice.call(arguments, 1),
  2209. returnedValue
  2210. ;
  2211. $allModules
  2212. .each(function() {
  2213. var
  2214. settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
  2215. className = settings.className,
  2216. namespace = settings.namespace,
  2217. selector = settings.selector,
  2218. error = settings.error,
  2219. eventNamespace = '.' + namespace,
  2220. moduleNamespace = 'module-' + namespace,
  2221. $module = $(this),
  2222. $label = $(this).children(selector.label),
  2223. $input = $(this).children(selector.input),
  2224. instance = $module.data(moduleNamespace),
  2225. observer,
  2226. element = this,
  2227. module
  2228. ;
  2229. module = {
  2230. initialize: function() {
  2231. module.verbose('Initializing checkbox', settings);
  2232. module.create.label();
  2233. module.bind.events();
  2234. module.set.tabbable();
  2235. module.hide.input();
  2236. module.observeChanges();
  2237. module.instantiate();
  2238. module.setup();
  2239. },
  2240. instantiate: function() {
  2241. module.verbose('Storing instance of module', module);
  2242. instance = module;
  2243. $module
  2244. .data(moduleNamespace, module)
  2245. ;
  2246. },
  2247. destroy: function() {
  2248. module.verbose('Destroying module');
  2249. module.unbind.events();
  2250. module.show.input();
  2251. $module.removeData(moduleNamespace);
  2252. },
  2253. fix: {
  2254. reference: function() {
  2255. if( $module.is(selector.input) ) {
  2256. module.debug('Behavior called on <input> adjusting invoked element');
  2257. $module = $module.closest(selector.checkbox);
  2258. module.refresh();
  2259. }
  2260. }
  2261. },
  2262. setup: function() {
  2263. if( module.is.indeterminate() ) {
  2264. module.debug('Initial value is indeterminate');
  2265. module.set.indeterminate();
  2266. if(settings.fireOnInit) {
  2267. settings.onIndeterminate.call($input[0]);
  2268. settings.onChange.call($input[0]);
  2269. }
  2270. }
  2271. else if( module.is.checked() ) {
  2272. module.debug('Initial value is checked');
  2273. module.set.checked();
  2274. if(settings.fireOnInit) {
  2275. settings.onChecked.call($input[0]);
  2276. settings.onChange.call($input[0]);
  2277. }
  2278. }
  2279. else {
  2280. module.debug('Initial value is unchecked');
  2281. module.set.unchecked();
  2282. if(settings.fireOnInit) {
  2283. settings.onUnchecked.call($input[0]);
  2284. settings.onChange.call($input[0]);
  2285. }
  2286. }
  2287. },
  2288. refresh: function() {
  2289. $label = $module.children(selector.label);
  2290. $input = $module.children(selector.input);
  2291. },
  2292. hide: {
  2293. input: function() {
  2294. module.verbose('Modfying <input> z-index to be unselectable');
  2295. $input.addClass(className.hidden);
  2296. }
  2297. },
  2298. show: {
  2299. input: function() {
  2300. module.verbose('Modfying <input> z-index to be selectable');
  2301. $input.removeClass(className.hidden);
  2302. }
  2303. },
  2304. observeChanges: function() {
  2305. if('MutationObserver' in window) {
  2306. observer = new MutationObserver(function(mutations) {
  2307. module.debug('DOM tree modified, updating selector cache');
  2308. module.refresh();
  2309. });
  2310. observer.observe(element, {
  2311. childList : true,
  2312. subtree : true
  2313. });
  2314. module.debug('Setting up mutation observer', observer);
  2315. }
  2316. },
  2317. attachEvents: function(selector, event) {
  2318. var
  2319. $element = $(selector)
  2320. ;
  2321. event = $.isFunction(module[event])
  2322. ? module[event]
  2323. : module.toggle
  2324. ;
  2325. if($element.length > 0) {
  2326. module.debug('Attaching checkbox events to element', selector, event);
  2327. $element
  2328. .on('click' + eventNamespace, event)
  2329. ;
  2330. }
  2331. else {
  2332. module.error(error.notFound);
  2333. }
  2334. },
  2335. event: {
  2336. click: function(event) {
  2337. if( $(event.target).is(selector.input) ) {
  2338. module.verbose('Using default check action on initialized checkbox');
  2339. return;
  2340. }
  2341. module.toggle();
  2342. },
  2343. keydown: function(event) {
  2344. var
  2345. key = event.which,
  2346. keyCode = {
  2347. enter : 13,
  2348. space : 32,
  2349. escape : 27
  2350. }
  2351. ;
  2352. if(key == keyCode.escape) {
  2353. module.verbose('Escape key pressed blurring field');
  2354. $input.blur();
  2355. event.preventDefault();
  2356. }
  2357. if(!event.ctrlKey && (key == keyCode.enter || key == keyCode.space)) {
  2358. module.verbose('Enter key pressed, toggling checkbox');
  2359. module.toggle();
  2360. event.preventDefault();
  2361. }
  2362. }
  2363. },
  2364. check: function() {
  2365. if( !module.is.indeterminate() && module.is.checked() ) {
  2366. module.debug('Checkbox is already checked');
  2367. return;
  2368. }
  2369. module.debug('Checking checkbox', $input);
  2370. module.set.checked();
  2371. settings.onChecked.call($input[0]);
  2372. settings.onChange.call($input[0]);
  2373. },
  2374. uncheck: function() {
  2375. if( !module.is.indeterminate() && module.is.unchecked() ) {
  2376. module.debug('Checkbox is already unchecked');
  2377. return;
  2378. }
  2379. module.debug('Unchecking checkbox');
  2380. module.set.unchecked();
  2381. settings.onUnchecked.call($input[0]);
  2382. settings.onChange.call($input[0]);
  2383. },
  2384. indeterminate: function() {
  2385. if( module.is.indeterminate() ) {
  2386. module.debug('Checkbox is already indeterminate');
  2387. return;
  2388. }
  2389. module.debug('Making checkbox indeterminate');
  2390. module.set.indeterminate();
  2391. settings.onIndeterminate.call($input[0]);
  2392. settings.onChange.call($input[0]);
  2393. },
  2394. determinate: function() {
  2395. if( module.is.determinate() ) {
  2396. module.debug('Checkbox is already determinate');
  2397. return;
  2398. }
  2399. module.debug('Making checkbox determinate');
  2400. module.set.determinate();
  2401. settings.onDeterminate.call($input[0]);
  2402. settings.onChange.call($input[0]);
  2403. },
  2404. enable: function() {
  2405. if( module.is.enabled() ) {
  2406. module.debug('Checkbox is already enabled');
  2407. return;
  2408. }
  2409. module.debug('Enabling checkbox');
  2410. module.set.enabled();
  2411. settings.onEnable.call($input[0]);
  2412. },
  2413. disable: function() {
  2414. if( module.is.disabled() ) {
  2415. module.debug('Checkbox is already disabled');
  2416. return;
  2417. }
  2418. module.debug('Disabling checkbox');
  2419. module.set.disabled();
  2420. settings.onDisable.call($input[0]);
  2421. },
  2422. get: {
  2423. radios: function() {
  2424. var
  2425. name = module.get.name()
  2426. ;
  2427. return $('input[name="' + name + '"]').closest(selector.checkbox);
  2428. },
  2429. name: function() {
  2430. return $input.attr('name');
  2431. }
  2432. },
  2433. is: {
  2434. radio: function() {
  2435. return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
  2436. },
  2437. indeterminate: function() {
  2438. return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
  2439. },
  2440. checked: function() {
  2441. return $input.prop('checked') !== undefined && $input.prop('checked');
  2442. },
  2443. disabled: function() {
  2444. return $input.prop('disabled') !== undefined && $input.prop('disabled');
  2445. },
  2446. enabled: function() {
  2447. return !module.is.disabled();
  2448. },
  2449. determinate: function() {
  2450. return !module.is.indeterminate();
  2451. },
  2452. unchecked: function() {
  2453. return !module.is.checked();
  2454. }
  2455. },
  2456. can: {
  2457. change: function() {
  2458. return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
  2459. },
  2460. uncheck: function() {
  2461. return (typeof settings.uncheckable === 'boolean')
  2462. ? settings.uncheckable
  2463. : !module.is.radio()
  2464. ;
  2465. }
  2466. },
  2467. set: {
  2468. checked: function() {
  2469. if(!module.is.indeterminate() && module.is.checked()) {
  2470. module.debug('Input is already checked');
  2471. return;
  2472. }
  2473. module.verbose('Setting state to checked', $input[0]);
  2474. if( module.is.radio() ) {
  2475. module.uncheckOthers();
  2476. }
  2477. $input
  2478. .prop('indeterminate', false)
  2479. .prop('checked', true)
  2480. ;
  2481. $module
  2482. .removeClass(className.indeterminate)
  2483. .addClass(className.checked)
  2484. ;
  2485. module.trigger.change();
  2486. },
  2487. unchecked: function() {
  2488. if(!module.is.indeterminate() && module.is.unchecked() ) {
  2489. module.debug('Input is already unchecked');
  2490. return;
  2491. }
  2492. module.debug('Setting state to unchecked');
  2493. $input
  2494. .prop('indeterminate', false)
  2495. .prop('checked', false)
  2496. ;
  2497. $module
  2498. .removeClass(className.indeterminate)
  2499. .removeClass(className.checked)
  2500. ;
  2501. module.trigger.change();
  2502. },
  2503. indeterminate: function() {
  2504. if( module.is.indeterminate() ) {
  2505. module.debug('Input is already indeterminate');
  2506. return;
  2507. }
  2508. module.debug('Setting state to indeterminate');
  2509. $input
  2510. .prop('indeterminate', true)
  2511. ;
  2512. $module
  2513. .addClass(className.indeterminate)
  2514. ;
  2515. module.trigger.change();
  2516. },
  2517. determinate: function() {
  2518. if( module.is.determinate() ) {
  2519. module.debug('Input is already determinate');
  2520. return;
  2521. }
  2522. module.debug('Setting state to determinate');
  2523. $input
  2524. .prop('indeterminate', false)
  2525. ;
  2526. $module
  2527. .removeClass(className.indeterminate)
  2528. ;
  2529. },
  2530. disabled: function() {
  2531. if( module.is.disabled() ) {
  2532. module.debug('Input is already disabled');
  2533. return;
  2534. }
  2535. module.debug('Setting state to disabled');
  2536. $input
  2537. .prop('disabled', 'disabled')
  2538. ;
  2539. $module
  2540. .addClass(className.disabled)
  2541. ;
  2542. module.trigger.change();
  2543. },
  2544. enabled: function() {
  2545. if( module.is.enabled() ) {
  2546. module.debug('Input is already enabled');
  2547. return;
  2548. }
  2549. module.debug('Setting state to enabled');
  2550. $input
  2551. .prop('disabled', false)
  2552. ;
  2553. $module.removeClass(className.disabled);
  2554. module.trigger.change();
  2555. },
  2556. tabbable: function() {
  2557. module.verbose('Adding tabindex to checkbox');
  2558. if( $input.attr('tabindex') === undefined) {
  2559. $input.attr('tabindex', 0);
  2560. }
  2561. }
  2562. },
  2563. trigger: {
  2564. change: function() {
  2565. module.verbose('Triggering change event from programmatic change');
  2566. $input
  2567. .trigger('change')
  2568. ;
  2569. }
  2570. },
  2571. create: {
  2572. label: function() {
  2573. if($input.prevAll(selector.label).length > 0) {
  2574. $input.prev(selector.label).detach().insertAfter($input);
  2575. module.debug('Moving existing label', $label);
  2576. }
  2577. else if( !module.has.label() ) {
  2578. $label = $('<label>').insertAfter($input);
  2579. module.debug('Creating label', $label);
  2580. }
  2581. }
  2582. },
  2583. has: {
  2584. label: function() {
  2585. return ($label.length > 0);
  2586. }
  2587. },
  2588. bind: {
  2589. events: function() {
  2590. module.verbose('Attaching checkbox events');
  2591. $module
  2592. .on('click' + eventNamespace, module.event.click)
  2593. .on('keydown' + eventNamespace, selector.input, module.event.keydown)
  2594. ;
  2595. }
  2596. },
  2597. unbind: {
  2598. events: function() {
  2599. module.debug('Removing events');
  2600. $module
  2601. .off(eventNamespace)
  2602. ;
  2603. }
  2604. },
  2605. uncheckOthers: function() {
  2606. var
  2607. $radios = module.get.radios()
  2608. ;
  2609. module.debug('Unchecking other radios', $radios);
  2610. $radios.removeClass(className.checked);
  2611. },
  2612. toggle: function() {
  2613. if( !module.can.change() ) {
  2614. if(!module.is.radio()) {
  2615. module.debug('Checkbox is read-only or disabled, ignoring toggle');
  2616. }
  2617. return;
  2618. }
  2619. if( module.is.indeterminate() || module.is.unchecked() ) {
  2620. module.debug('Currently unchecked');
  2621. module.check();
  2622. }
  2623. else if( module.is.checked() && module.can.uncheck() ) {
  2624. module.debug('Currently checked');
  2625. module.uncheck();
  2626. }
  2627. },
  2628. setting: function(name, value) {
  2629. module.debug('Changing setting', name, value);
  2630. if( $.isPlainObject(name) ) {
  2631. $.extend(true, settings, name);
  2632. }
  2633. else if(value !== undefined) {
  2634. settings[name] = value;
  2635. }
  2636. else {
  2637. return settings[name];
  2638. }
  2639. },
  2640. internal: function(name, value) {
  2641. if( $.isPlainObject(name) ) {
  2642. $.extend(true, module, name);
  2643. }
  2644. else if(value !== undefined) {
  2645. module[name] = value;
  2646. }
  2647. else {
  2648. return module[name];
  2649. }
  2650. },
  2651. debug: function() {
  2652. if(settings.debug) {
  2653. if(settings.performance) {
  2654. module.performance.log(arguments);
  2655. }
  2656. else {
  2657. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2658. module.debug.apply(console, arguments);
  2659. }
  2660. }
  2661. },
  2662. verbose: function() {
  2663. if(settings.verbose && settings.debug) {
  2664. if(settings.performance) {
  2665. module.performance.log(arguments);
  2666. }
  2667. else {
  2668. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2669. module.verbose.apply(console, arguments);
  2670. }
  2671. }
  2672. },
  2673. error: function() {
  2674. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  2675. module.error.apply(console, arguments);
  2676. },
  2677. performance: {
  2678. log: function(message) {
  2679. var
  2680. currentTime,
  2681. executionTime,
  2682. previousTime
  2683. ;
  2684. if(settings.performance) {
  2685. currentTime = new Date().getTime();
  2686. previousTime = time || currentTime;
  2687. executionTime = currentTime - previousTime;
  2688. time = currentTime;
  2689. performance.push({
  2690. 'Name' : message[0],
  2691. 'Arguments' : [].slice.call(message, 1) || '',
  2692. 'Element' : element,
  2693. 'Execution Time' : executionTime
  2694. });
  2695. }
  2696. clearTimeout(module.performance.timer);
  2697. module.performance.timer = setTimeout(module.performance.display, 500);
  2698. },
  2699. display: function() {
  2700. var
  2701. title = settings.name + ':',
  2702. totalTime = 0
  2703. ;
  2704. time = false;
  2705. clearTimeout(module.performance.timer);
  2706. $.each(performance, function(index, data) {
  2707. totalTime += data['Execution Time'];
  2708. });
  2709. title += ' ' + totalTime + 'ms';
  2710. if(moduleSelector) {
  2711. title += ' \'' + moduleSelector + '\'';
  2712. }
  2713. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  2714. console.groupCollapsed(title);
  2715. if(console.table) {
  2716. console.table(performance);
  2717. }
  2718. else {
  2719. $.each(performance, function(index, data) {
  2720. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  2721. });
  2722. }
  2723. console.groupEnd();
  2724. }
  2725. performance = [];
  2726. }
  2727. },
  2728. invoke: function(query, passedArguments, context) {
  2729. var
  2730. object = instance,
  2731. maxDepth,
  2732. found,
  2733. response
  2734. ;
  2735. passedArguments = passedArguments || queryArguments;
  2736. context = element || context;
  2737. if(typeof query == 'string' && object !== undefined) {
  2738. query = query.split(/[\. ]/);
  2739. maxDepth = query.length - 1;
  2740. $.each(query, function(depth, value) {
  2741. var camelCaseValue = (depth != maxDepth)
  2742. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  2743. : query
  2744. ;
  2745. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  2746. object = object[camelCaseValue];
  2747. }
  2748. else if( object[camelCaseValue] !== undefined ) {
  2749. found = object[camelCaseValue];
  2750. return false;
  2751. }
  2752. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  2753. object = object[value];
  2754. }
  2755. else if( object[value] !== undefined ) {
  2756. found = object[value];
  2757. return false;
  2758. }
  2759. else {
  2760. module.error(error.method, query);
  2761. return false;
  2762. }
  2763. });
  2764. }
  2765. if ( $.isFunction( found ) ) {
  2766. response = found.apply(context, passedArguments);
  2767. }
  2768. else if(found !== undefined) {
  2769. response = found;
  2770. }
  2771. if($.isArray(returnedValue)) {
  2772. returnedValue.push(response);
  2773. }
  2774. else if(returnedValue !== undefined) {
  2775. returnedValue = [returnedValue, response];
  2776. }
  2777. else if(response !== undefined) {
  2778. returnedValue = response;
  2779. }
  2780. return found;
  2781. }
  2782. };
  2783. if(methodInvoked) {
  2784. if(instance === undefined) {
  2785. module.initialize();
  2786. }
  2787. module.invoke(query);
  2788. }
  2789. else {
  2790. if(instance !== undefined) {
  2791. instance.invoke('destroy');
  2792. }
  2793. module.initialize();
  2794. }
  2795. })
  2796. ;
  2797. return (returnedValue !== undefined)
  2798. ? returnedValue
  2799. : this
  2800. ;
  2801. };
  2802. $.fn.checkbox.settings = {
  2803. name : 'Checkbox',
  2804. namespace : 'checkbox',
  2805. debug : false,
  2806. verbose : true,
  2807. performance : true,
  2808. // delegated event context
  2809. uncheckable : 'auto',
  2810. fireOnInit : false,
  2811. onChange : function(){},
  2812. onChecked : function(){},
  2813. onUnchecked : function(){},
  2814. onDeterminate : function() {},
  2815. onIndeterminate : function() {},
  2816. onEnabled : function(){},
  2817. onDisabled : function(){},
  2818. className : {
  2819. checked : 'checked',
  2820. indeterminate : 'indeterminate',
  2821. disabled : 'disabled',
  2822. hidden : 'hidden',
  2823. radio : 'radio',
  2824. readOnly : 'read-only'
  2825. },
  2826. error : {
  2827. method : 'The method you called is not defined'
  2828. },
  2829. selector : {
  2830. checkbox : '.ui.checkbox',
  2831. label : 'label, .box',
  2832. input : 'input[type="checkbox"], input[type="radio"]',
  2833. }
  2834. };
  2835. })( jQuery, window , document );
  2836. /*!
  2837. * # Semantic UI 2.0.0 - Dimmer
  2838. * http://github.com/semantic-org/semantic-ui/
  2839. *
  2840. *
  2841. * Copyright 2015 Contributors
  2842. * Released under the MIT license
  2843. * http://opensource.org/licenses/MIT
  2844. *
  2845. */
  2846. ;(function ( $, window, document, undefined ) {
  2847. "use strict";
  2848. $.fn.dimmer = function(parameters) {
  2849. var
  2850. $allModules = $(this),
  2851. time = new Date().getTime(),
  2852. performance = [],
  2853. query = arguments[0],
  2854. methodInvoked = (typeof query == 'string'),
  2855. queryArguments = [].slice.call(arguments, 1),
  2856. returnedValue
  2857. ;
  2858. $allModules
  2859. .each(function() {
  2860. var
  2861. settings = ( $.isPlainObject(parameters) )
  2862. ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
  2863. : $.extend({}, $.fn.dimmer.settings),
  2864. selector = settings.selector,
  2865. namespace = settings.namespace,
  2866. className = settings.className,
  2867. error = settings.error,
  2868. eventNamespace = '.' + namespace,
  2869. moduleNamespace = 'module-' + namespace,
  2870. moduleSelector = $allModules.selector || '',
  2871. clickEvent = ('ontouchstart' in document.documentElement)
  2872. ? 'touchstart'
  2873. : 'click',
  2874. $module = $(this),
  2875. $dimmer,
  2876. $dimmable,
  2877. element = this,
  2878. instance = $module.data(moduleNamespace),
  2879. module
  2880. ;
  2881. module = {
  2882. preinitialize: function() {
  2883. if( module.is.dimmer() ) {
  2884. $dimmable = $module.parent();
  2885. $dimmer = $module;
  2886. }
  2887. else {
  2888. $dimmable = $module;
  2889. if( module.has.dimmer() ) {
  2890. if(settings.dimmerName) {
  2891. $dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
  2892. }
  2893. else {
  2894. $dimmer = $dimmable.find(selector.dimmer);
  2895. }
  2896. }
  2897. else {
  2898. $dimmer = module.create();
  2899. }
  2900. }
  2901. },
  2902. initialize: function() {
  2903. module.debug('Initializing dimmer', settings);
  2904. if(settings.on == 'hover') {
  2905. $dimmable
  2906. .on('mouseenter' + eventNamespace, module.show)
  2907. .on('mouseleave' + eventNamespace, module.hide)
  2908. ;
  2909. }
  2910. else if(settings.on == 'click') {
  2911. $dimmable
  2912. .on(clickEvent + eventNamespace, module.toggle)
  2913. ;
  2914. }
  2915. if( module.is.page() ) {
  2916. module.debug('Setting as a page dimmer', $dimmable);
  2917. module.set.pageDimmer();
  2918. }
  2919. if( module.is.closable() ) {
  2920. module.verbose('Adding dimmer close event', $dimmer);
  2921. $dimmable
  2922. .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
  2923. ;
  2924. }
  2925. module.set.dimmable();
  2926. module.instantiate();
  2927. },
  2928. instantiate: function() {
  2929. module.verbose('Storing instance of module', module);
  2930. instance = module;
  2931. $module
  2932. .data(moduleNamespace, instance)
  2933. ;
  2934. },
  2935. destroy: function() {
  2936. module.verbose('Destroying previous module', $dimmer);
  2937. $module
  2938. .removeData(moduleNamespace)
  2939. ;
  2940. $dimmable
  2941. .off(eventNamespace)
  2942. ;
  2943. },
  2944. event: {
  2945. click: function(event) {
  2946. module.verbose('Determining if event occured on dimmer', event);
  2947. if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
  2948. module.hide();
  2949. event.stopImmediatePropagation();
  2950. }
  2951. }
  2952. },
  2953. addContent: function(element) {
  2954. var
  2955. $content = $(element)
  2956. ;
  2957. module.debug('Add content to dimmer', $content);
  2958. if($content.parent()[0] !== $dimmer[0]) {
  2959. $content.detach().appendTo($dimmer);
  2960. }
  2961. },
  2962. create: function() {
  2963. var
  2964. $element = $( settings.template.dimmer() )
  2965. ;
  2966. if(settings.variation) {
  2967. module.debug('Creating dimmer with variation', settings.variation);
  2968. $element.addClass(settings.variation);
  2969. }
  2970. if(settings.dimmerName) {
  2971. module.debug('Creating named dimmer', settings.dimmerName);
  2972. $element.addClass(settings.dimmerName);
  2973. }
  2974. $element
  2975. .appendTo($dimmable)
  2976. ;
  2977. return $element;
  2978. },
  2979. show: function(callback) {
  2980. callback = $.isFunction(callback)
  2981. ? callback
  2982. : function(){}
  2983. ;
  2984. module.debug('Showing dimmer', $dimmer, settings);
  2985. if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
  2986. module.animate.show(callback);
  2987. settings.onShow.call(element);
  2988. settings.onChange.call(element);
  2989. }
  2990. else {
  2991. module.debug('Dimmer is already shown or disabled');
  2992. }
  2993. },
  2994. hide: function(callback) {
  2995. callback = $.isFunction(callback)
  2996. ? callback
  2997. : function(){}
  2998. ;
  2999. if( module.is.dimmed() || module.is.animating() ) {
  3000. module.debug('Hiding dimmer', $dimmer);
  3001. module.animate.hide(callback);
  3002. settings.onHide.call(element);
  3003. settings.onChange.call(element);
  3004. }
  3005. else {
  3006. module.debug('Dimmer is not visible');
  3007. }
  3008. },
  3009. toggle: function() {
  3010. module.verbose('Toggling dimmer visibility', $dimmer);
  3011. if( !module.is.dimmed() ) {
  3012. module.show();
  3013. }
  3014. else {
  3015. module.hide();
  3016. }
  3017. },
  3018. animate: {
  3019. show: function(callback) {
  3020. callback = $.isFunction(callback)
  3021. ? callback
  3022. : function(){}
  3023. ;
  3024. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3025. if(settings.opacity !== 'auto') {
  3026. module.set.opacity();
  3027. }
  3028. $dimmer
  3029. .transition({
  3030. animation : settings.transition + ' in',
  3031. queue : false,
  3032. duration : module.get.duration(),
  3033. useFailSafe : true,
  3034. onStart : function() {
  3035. module.set.dimmed();
  3036. },
  3037. onComplete : function() {
  3038. module.set.active();
  3039. callback();
  3040. }
  3041. })
  3042. ;
  3043. }
  3044. else {
  3045. module.verbose('Showing dimmer animation with javascript');
  3046. module.set.dimmed();
  3047. if(settings.opacity == 'auto') {
  3048. settings.opacity = 0.8;
  3049. }
  3050. $dimmer
  3051. .stop()
  3052. .css({
  3053. opacity : 0,
  3054. width : '100%',
  3055. height : '100%'
  3056. })
  3057. .fadeTo(module.get.duration(), settings.opacity, function() {
  3058. $dimmer.removeAttr('style');
  3059. module.set.active();
  3060. callback();
  3061. })
  3062. ;
  3063. }
  3064. },
  3065. hide: function(callback) {
  3066. callback = $.isFunction(callback)
  3067. ? callback
  3068. : function(){}
  3069. ;
  3070. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3071. module.verbose('Hiding dimmer with css');
  3072. $dimmer
  3073. .transition({
  3074. animation : settings.transition + ' out',
  3075. queue : false,
  3076. duration : module.get.duration(),
  3077. useFailSafe : true,
  3078. onStart : function() {
  3079. module.remove.dimmed();
  3080. },
  3081. onComplete : function() {
  3082. module.remove.active();
  3083. callback();
  3084. }
  3085. })
  3086. ;
  3087. }
  3088. else {
  3089. module.verbose('Hiding dimmer with javascript');
  3090. module.remove.dimmed();
  3091. $dimmer
  3092. .stop()
  3093. .fadeOut(module.get.duration(), function() {
  3094. module.remove.active();
  3095. $dimmer.removeAttr('style');
  3096. callback();
  3097. })
  3098. ;
  3099. }
  3100. }
  3101. },
  3102. get: {
  3103. dimmer: function() {
  3104. return $dimmer;
  3105. },
  3106. duration: function() {
  3107. if(typeof settings.duration == 'object') {
  3108. if( module.is.active() ) {
  3109. return settings.duration.hide;
  3110. }
  3111. else {
  3112. return settings.duration.show;
  3113. }
  3114. }
  3115. return settings.duration;
  3116. }
  3117. },
  3118. has: {
  3119. dimmer: function() {
  3120. if(settings.dimmerName) {
  3121. return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
  3122. }
  3123. else {
  3124. return ( $module.find(selector.dimmer).length > 0 );
  3125. }
  3126. }
  3127. },
  3128. is: {
  3129. active: function() {
  3130. return $dimmer.hasClass(className.active);
  3131. },
  3132. animating: function() {
  3133. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
  3134. },
  3135. closable: function() {
  3136. if(settings.closable == 'auto') {
  3137. if(settings.on == 'hover') {
  3138. return false;
  3139. }
  3140. return true;
  3141. }
  3142. return settings.closable;
  3143. },
  3144. dimmer: function() {
  3145. return $module.hasClass(className.dimmer);
  3146. },
  3147. dimmable: function() {
  3148. return $module.hasClass(className.dimmable);
  3149. },
  3150. dimmed: function() {
  3151. return $dimmable.hasClass(className.dimmed);
  3152. },
  3153. disabled: function() {
  3154. return $dimmable.hasClass(className.disabled);
  3155. },
  3156. enabled: function() {
  3157. return !module.is.disabled();
  3158. },
  3159. page: function () {
  3160. return $dimmable.is('body');
  3161. },
  3162. pageDimmer: function() {
  3163. return $dimmer.hasClass(className.pageDimmer);
  3164. }
  3165. },
  3166. can: {
  3167. show: function() {
  3168. return !$dimmer.hasClass(className.disabled);
  3169. }
  3170. },
  3171. set: {
  3172. opacity: function(opacity) {
  3173. var
  3174. opacity = settings.opacity || opacity,
  3175. color = $dimmer.css('background-color'),
  3176. colorArray = color.split(','),
  3177. isRGBA = (colorArray && colorArray.length == 4)
  3178. ;
  3179. if(isRGBA) {
  3180. colorArray[3] = opacity + ')';
  3181. color = colorArray.join(',');
  3182. }
  3183. else {
  3184. color = 'rgba(0, 0, 0, ' + opacity + ')';
  3185. }
  3186. module.debug('Setting opacity to', opacity);
  3187. $dimmer.css('background-color', color);
  3188. },
  3189. active: function() {
  3190. $dimmer.addClass(className.active);
  3191. },
  3192. dimmable: function() {
  3193. $dimmable.addClass(className.dimmable);
  3194. },
  3195. dimmed: function() {
  3196. $dimmable.addClass(className.dimmed);
  3197. },
  3198. pageDimmer: function() {
  3199. $dimmer.addClass(className.pageDimmer);
  3200. },
  3201. disabled: function() {
  3202. $dimmer.addClass(className.disabled);
  3203. }
  3204. },
  3205. remove: {
  3206. active: function() {
  3207. $dimmer
  3208. .removeClass(className.active)
  3209. ;
  3210. },
  3211. dimmed: function() {
  3212. $dimmable.removeClass(className.dimmed);
  3213. },
  3214. disabled: function() {
  3215. $dimmer.removeClass(className.disabled);
  3216. }
  3217. },
  3218. setting: function(name, value) {
  3219. module.debug('Changing setting', name, value);
  3220. if( $.isPlainObject(name) ) {
  3221. $.extend(true, settings, name);
  3222. }
  3223. else if(value !== undefined) {
  3224. settings[name] = value;
  3225. }
  3226. else {
  3227. return settings[name];
  3228. }
  3229. },
  3230. internal: function(name, value) {
  3231. if( $.isPlainObject(name) ) {
  3232. $.extend(true, module, name);
  3233. }
  3234. else if(value !== undefined) {
  3235. module[name] = value;
  3236. }
  3237. else {
  3238. return module[name];
  3239. }
  3240. },
  3241. debug: function() {
  3242. if(settings.debug) {
  3243. if(settings.performance) {
  3244. module.performance.log(arguments);
  3245. }
  3246. else {
  3247. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3248. module.debug.apply(console, arguments);
  3249. }
  3250. }
  3251. },
  3252. verbose: function() {
  3253. if(settings.verbose && settings.debug) {
  3254. if(settings.performance) {
  3255. module.performance.log(arguments);
  3256. }
  3257. else {
  3258. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3259. module.verbose.apply(console, arguments);
  3260. }
  3261. }
  3262. },
  3263. error: function() {
  3264. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3265. module.error.apply(console, arguments);
  3266. },
  3267. performance: {
  3268. log: function(message) {
  3269. var
  3270. currentTime,
  3271. executionTime,
  3272. previousTime
  3273. ;
  3274. if(settings.performance) {
  3275. currentTime = new Date().getTime();
  3276. previousTime = time || currentTime;
  3277. executionTime = currentTime - previousTime;
  3278. time = currentTime;
  3279. performance.push({
  3280. 'Name' : message[0],
  3281. 'Arguments' : [].slice.call(message, 1) || '',
  3282. 'Element' : element,
  3283. 'Execution Time' : executionTime
  3284. });
  3285. }
  3286. clearTimeout(module.performance.timer);
  3287. module.performance.timer = setTimeout(module.performance.display, 500);
  3288. },
  3289. display: function() {
  3290. var
  3291. title = settings.name + ':',
  3292. totalTime = 0
  3293. ;
  3294. time = false;
  3295. clearTimeout(module.performance.timer);
  3296. $.each(performance, function(index, data) {
  3297. totalTime += data['Execution Time'];
  3298. });
  3299. title += ' ' + totalTime + 'ms';
  3300. if(moduleSelector) {
  3301. title += ' \'' + moduleSelector + '\'';
  3302. }
  3303. if($allModules.length > 1) {
  3304. title += ' ' + '(' + $allModules.length + ')';
  3305. }
  3306. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3307. console.groupCollapsed(title);
  3308. if(console.table) {
  3309. console.table(performance);
  3310. }
  3311. else {
  3312. $.each(performance, function(index, data) {
  3313. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  3314. });
  3315. }
  3316. console.groupEnd();
  3317. }
  3318. performance = [];
  3319. }
  3320. },
  3321. invoke: function(query, passedArguments, context) {
  3322. var
  3323. object = instance,
  3324. maxDepth,
  3325. found,
  3326. response
  3327. ;
  3328. passedArguments = passedArguments || queryArguments;
  3329. context = element || context;
  3330. if(typeof query == 'string' && object !== undefined) {
  3331. query = query.split(/[\. ]/);
  3332. maxDepth = query.length - 1;
  3333. $.each(query, function(depth, value) {
  3334. var camelCaseValue = (depth != maxDepth)
  3335. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3336. : query
  3337. ;
  3338. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  3339. object = object[camelCaseValue];
  3340. }
  3341. else if( object[camelCaseValue] !== undefined ) {
  3342. found = object[camelCaseValue];
  3343. return false;
  3344. }
  3345. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  3346. object = object[value];
  3347. }
  3348. else if( object[value] !== undefined ) {
  3349. found = object[value];
  3350. return false;
  3351. }
  3352. else {
  3353. module.error(error.method, query);
  3354. return false;
  3355. }
  3356. });
  3357. }
  3358. if ( $.isFunction( found ) ) {
  3359. response = found.apply(context, passedArguments);
  3360. }
  3361. else if(found !== undefined) {
  3362. response = found;
  3363. }
  3364. if($.isArray(returnedValue)) {
  3365. returnedValue.push(response);
  3366. }
  3367. else if(returnedValue !== undefined) {
  3368. returnedValue = [returnedValue, response];
  3369. }
  3370. else if(response !== undefined) {
  3371. returnedValue = response;
  3372. }
  3373. return found;
  3374. }
  3375. };
  3376. module.preinitialize();
  3377. if(methodInvoked) {
  3378. if(instance === undefined) {
  3379. module.initialize();
  3380. }
  3381. module.invoke(query);
  3382. }
  3383. else {
  3384. if(instance !== undefined) {
  3385. instance.invoke('destroy');
  3386. }
  3387. module.initialize();
  3388. }
  3389. })
  3390. ;
  3391. return (returnedValue !== undefined)
  3392. ? returnedValue
  3393. : this
  3394. ;
  3395. };
  3396. $.fn.dimmer.settings = {
  3397. name : 'Dimmer',
  3398. namespace : 'dimmer',
  3399. debug : false,
  3400. verbose : false,
  3401. performance : true,
  3402. // name to distinguish between multiple dimmers in context
  3403. dimmerName : false,
  3404. // whether to add a variation type
  3405. variation : false,
  3406. // whether to bind close events
  3407. closable : 'auto',
  3408. // whether to use css animations
  3409. useCSS : true,
  3410. // css animation to use
  3411. transition : 'fade',
  3412. // event to bind to
  3413. on : false,
  3414. // overriding opacity value
  3415. opacity : 'auto',
  3416. // transition durations
  3417. duration : {
  3418. show : 500,
  3419. hide : 500
  3420. },
  3421. onChange : function(){},
  3422. onShow : function(){},
  3423. onHide : function(){},
  3424. error : {
  3425. method : 'The method you called is not defined.'
  3426. },
  3427. className : {
  3428. active : 'active',
  3429. animating : 'animating',
  3430. dimmable : 'dimmable',
  3431. dimmed : 'dimmed',
  3432. dimmer : 'dimmer',
  3433. disabled : 'disabled',
  3434. hide : 'hide',
  3435. pageDimmer : 'page',
  3436. show : 'show'
  3437. },
  3438. selector: {
  3439. dimmer : '> .ui.dimmer',
  3440. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  3441. },
  3442. template: {
  3443. dimmer: function() {
  3444. return $('<div />').attr('class', 'ui dimmer');
  3445. }
  3446. }
  3447. };
  3448. })( jQuery, window , document );
  3449. /*!
  3450. * # Semantic UI 2.0.0 - Dropdown
  3451. * http://github.com/semantic-org/semantic-ui/
  3452. *
  3453. *
  3454. * Copyright 2015 Contributors
  3455. * Released under the MIT license
  3456. * http://opensource.org/licenses/MIT
  3457. *
  3458. */
  3459. ;(function ( $, window, document, undefined ) {
  3460. "use strict";
  3461. $.fn.dropdown = function(parameters) {
  3462. var
  3463. $allModules = $(this),
  3464. $document = $(document),
  3465. moduleSelector = $allModules.selector || '',
  3466. hasTouch = ('ontouchstart' in document.documentElement),
  3467. time = new Date().getTime(),
  3468. performance = [],
  3469. query = arguments[0],
  3470. methodInvoked = (typeof query == 'string'),
  3471. queryArguments = [].slice.call(arguments, 1),
  3472. returnedValue
  3473. ;
  3474. $allModules
  3475. .each(function(elementIndex) {
  3476. var
  3477. settings = ( $.isPlainObject(parameters) )
  3478. ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
  3479. : $.extend({}, $.fn.dropdown.settings),
  3480. className = settings.className,
  3481. message = settings.message,
  3482. metadata = settings.metadata,
  3483. namespace = settings.namespace,
  3484. regExp = settings.regExp,
  3485. selector = settings.selector,
  3486. error = settings.error,
  3487. templates = settings.templates,
  3488. eventNamespace = '.' + namespace,
  3489. moduleNamespace = 'module-' + namespace,
  3490. $module = $(this),
  3491. $context = $(settings.context),
  3492. $text = $module.find(selector.text),
  3493. $search = $module.find(selector.search),
  3494. $input = $module.find(selector.input),
  3495. $icon = $module.find(selector.icon),
  3496. $combo = ($module.prev().find(selector.text).length > 0)
  3497. ? $module.prev().find(selector.text)
  3498. : $module.prev(),
  3499. $menu = $module.children(selector.menu),
  3500. $item = $menu.find(selector.item),
  3501. activated = false,
  3502. itemActivated = false,
  3503. element = this,
  3504. instance = $module.data(moduleNamespace),
  3505. initialLoad,
  3506. pageLostFocus,
  3507. elementNamespace,
  3508. id,
  3509. selectObserver,
  3510. menuObserver,
  3511. module
  3512. ;
  3513. module = {
  3514. initialize: function() {
  3515. module.debug('Initializing dropdown', settings);
  3516. if( module.is.alreadySetup() ) {
  3517. module.setup.reference();
  3518. }
  3519. else {
  3520. module.setup.layout();
  3521. module.refreshData();
  3522. module.save.defaults();
  3523. module.restore.selected();
  3524. module.create.id();
  3525. if(hasTouch) {
  3526. module.bind.touchEvents();
  3527. }
  3528. module.bind.mouseEvents();
  3529. module.bind.keyboardEvents();
  3530. module.observeChanges();
  3531. module.instantiate();
  3532. }
  3533. },
  3534. instantiate: function() {
  3535. module.verbose('Storing instance of dropdown', module);
  3536. instance = module;
  3537. $module
  3538. .data(moduleNamespace, module)
  3539. ;
  3540. },
  3541. destroy: function() {
  3542. module.verbose('Destroying previous dropdown', $module);
  3543. module.remove.tabbable();
  3544. $module
  3545. .off(eventNamespace)
  3546. .removeData(moduleNamespace)
  3547. ;
  3548. $menu
  3549. .off(eventNamespace)
  3550. ;
  3551. $document
  3552. .off(elementNamespace)
  3553. ;
  3554. if(selectObserver) {
  3555. selectObserver.disconnect();
  3556. }
  3557. if(menuObserver) {
  3558. menuObserver.disconnect();
  3559. }
  3560. },
  3561. observeChanges: function() {
  3562. if('MutationObserver' in window) {
  3563. selectObserver = new MutationObserver(function(mutations) {
  3564. module.debug('<select> modified, recreating menu');
  3565. module.setup.select();
  3566. });
  3567. menuObserver = new MutationObserver(function(mutations) {
  3568. module.debug('Menu modified, updating selector cache');
  3569. module.refresh();
  3570. });
  3571. if(module.has.input()) {
  3572. selectObserver.observe($input[0], {
  3573. childList : true,
  3574. subtree : true
  3575. });
  3576. }
  3577. if(module.has.menu()) {
  3578. menuObserver.observe($menu[0], {
  3579. childList : true,
  3580. subtree : true
  3581. });
  3582. }
  3583. module.debug('Setting up mutation observer', selectObserver, menuObserver);
  3584. }
  3585. },
  3586. create: {
  3587. id: function() {
  3588. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  3589. elementNamespace = '.' + id;
  3590. module.verbose('Creating unique id for element', id);
  3591. },
  3592. userChoice: function(values) {
  3593. var
  3594. $userChoices,
  3595. $userChoice,
  3596. isUserValue,
  3597. html
  3598. ;
  3599. values = values || module.get.userValues();
  3600. if(!values) {
  3601. return false;
  3602. }
  3603. values = $.isArray(values)
  3604. ? values
  3605. : [values]
  3606. ;
  3607. $.each(values, function(index, value) {
  3608. if(module.get.item(value) === false) {
  3609. html = settings.templates.addition(value);
  3610. $userChoice = $('<div />')
  3611. .html(html)
  3612. .data(metadata.value, value)
  3613. .addClass(className.addition)
  3614. .addClass(className.item)
  3615. ;
  3616. $userChoices = ($userChoices === undefined)
  3617. ? $userChoice
  3618. : $userChoices.add($userChoice)
  3619. ;
  3620. module.verbose('Creating user choices for value', value, $userChoice);
  3621. }
  3622. });
  3623. return $userChoices;
  3624. },
  3625. userLabels: function(value) {
  3626. var
  3627. userValues = module.get.userValues()
  3628. ;
  3629. if(userValues) {
  3630. module.debug('Adding user labels', userValues);
  3631. $.each(userValues, function(index, value) {
  3632. module.verbose('Adding custom user value');
  3633. module.add.label(value, value);
  3634. });
  3635. }
  3636. },
  3637. },
  3638. search: function(query) {
  3639. query = (query !== undefined)
  3640. ? query
  3641. : module.get.query()
  3642. ;
  3643. module.verbose('Searching for query', query);
  3644. module.filter(query);
  3645. },
  3646. select: {
  3647. firstUnfiltered: function() {
  3648. module.verbose('Selecting first non-filtered element');
  3649. module.remove.selectedItem();
  3650. $item
  3651. .not(selector.unselectable)
  3652. .eq(0)
  3653. .addClass(className.selected)
  3654. ;
  3655. },
  3656. nextAvailable: function($selected) {
  3657. $selected = $selected.eq(0);
  3658. var
  3659. $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
  3660. $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
  3661. hasNext = ($nextAvailable.length > 0)
  3662. ;
  3663. if(hasNext) {
  3664. module.verbose('Moving selection to', $nextAvailable);
  3665. $nextAvailable.addClass(className.selected);
  3666. }
  3667. else {
  3668. module.verbose('Moving selection to', $prevAvailable);
  3669. $prevAvailable.addClass(className.selected);
  3670. }
  3671. }
  3672. },
  3673. setup: {
  3674. api: function() {
  3675. var
  3676. apiSettings = {
  3677. debug : settings.debug,
  3678. on : false
  3679. }
  3680. ;
  3681. module.verbose('First request, initializing API');
  3682. $module
  3683. .api(apiSettings)
  3684. ;
  3685. },
  3686. layout: function() {
  3687. if( $module.is('select') ) {
  3688. module.setup.select();
  3689. module.setup.returnedObject();
  3690. console.log($module);
  3691. }
  3692. if( module.is.search() && !module.has.search() ) {
  3693. module.verbose('Adding search input');
  3694. $search = $('<input />')
  3695. .addClass(className.search)
  3696. .insertBefore($text)
  3697. ;
  3698. }
  3699. if(settings.allowTab) {
  3700. module.set.tabbable();
  3701. }
  3702. if($menu.length === 0) {
  3703. $menu = $('<div />')
  3704. .addClass(className.menu)
  3705. .appendTo($module)
  3706. ;
  3707. }
  3708. },
  3709. select: function() {
  3710. var
  3711. selectValues = module.get.selectValues()
  3712. ;
  3713. module.debug('Dropdown initialized on a select', selectValues);
  3714. if( $module.is('select') ) {
  3715. $input = $module;
  3716. }
  3717. // see if select is placed correctly already
  3718. if($input.parent(selector.dropdown).length > 0) {
  3719. module.debug('UI dropdown already exists. Creating dropdown menu only');
  3720. $module = $input.closest(selector.dropdown);
  3721. $menu = $module.children(selector.menu);
  3722. module.setup.menu(selectValues);
  3723. }
  3724. else {
  3725. module.debug('Creating entire dropdown from select');
  3726. $module = $('<div />')
  3727. .attr('class', $input.attr('class') )
  3728. .addClass(className.selection)
  3729. .addClass(className.dropdown)
  3730. .html( templates.dropdown(selectValues) )
  3731. .insertBefore($input)
  3732. ;
  3733. $input
  3734. .removeAttr('class')
  3735. .detach()
  3736. .prependTo($module)
  3737. ;
  3738. console.log($module);
  3739. }
  3740. if($input.is('[multiple]')) {
  3741. module.set.multiple();
  3742. }
  3743. module.refresh();
  3744. },
  3745. menu: function(values) {
  3746. $menu.html( templates.menu( values ));
  3747. $item = $menu.find(selector.item);
  3748. },
  3749. reference: function() {
  3750. module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
  3751. // replace module reference
  3752. $module = $module.parent(selector.dropdown);
  3753. module.refresh();
  3754. module.setup.returnedObject();
  3755. // invoke method in context of current instance
  3756. if(methodInvoked) {
  3757. instance = module;
  3758. module.invoke(query);
  3759. }
  3760. },
  3761. returnedObject: function() {
  3762. var
  3763. $firstModules = $allModules.slice(0, elementIndex),
  3764. $lastModules = $allModules.slice(elementIndex + 1)
  3765. ;
  3766. // adjust all modules to use correct reference
  3767. $allModules = $firstModules.add($module).add($lastModules);
  3768. }
  3769. },
  3770. refresh: function() {
  3771. module.refreshSelectors();
  3772. module.refreshData();
  3773. },
  3774. refreshSelectors: function() {
  3775. module.verbose('Refreshing selector cache');
  3776. $text = $module.find(selector.text);
  3777. $search = $module.find(selector.search);
  3778. $input = $module.find(selector.input);
  3779. $icon = $module.find(selector.icon);
  3780. $combo = ($module.prev().find(selector.text).length > 0)
  3781. ? $module.prev().find(selector.text)
  3782. : $module.prev()
  3783. ;
  3784. $menu = $module.children(selector.menu);
  3785. $item = $menu.find(selector.item);
  3786. },
  3787. refreshData: function() {
  3788. module.verbose('Refreshing cached metadata');
  3789. $item
  3790. .removeData(metadata.text)
  3791. .removeData(metadata.value)
  3792. ;
  3793. $module
  3794. .removeData(metadata.defaultText)
  3795. .removeData(metadata.defaultValue)
  3796. .removeData(metadata.placeholderText)
  3797. ;
  3798. },
  3799. toggle: function() {
  3800. module.verbose('Toggling menu visibility');
  3801. if( !module.is.active() ) {
  3802. module.show();
  3803. }
  3804. else {
  3805. module.hide();
  3806. }
  3807. },
  3808. show: function(callback) {
  3809. callback = $.isFunction(callback)
  3810. ? callback
  3811. : function(){}
  3812. ;
  3813. if( module.can.show() && !module.is.active() ) {
  3814. module.debug('Showing dropdown');
  3815. if(module.is.multiple()) {
  3816. if(!module.has.search() && module.is.allFiltered()) {
  3817. return true;
  3818. }
  3819. }
  3820. module.animate.show(function() {
  3821. if( module.can.click() ) {
  3822. module.bind.intent();
  3823. }
  3824. module.set.visible();
  3825. callback.call(element);
  3826. });
  3827. settings.onShow.call(element);
  3828. }
  3829. },
  3830. hide: function(callback) {
  3831. callback = $.isFunction(callback)
  3832. ? callback
  3833. : function(){}
  3834. ;
  3835. if( module.is.active() ) {
  3836. module.debug('Hiding dropdown');
  3837. module.animate.hide(function() {
  3838. module.remove.visible();
  3839. callback.call(element);
  3840. });
  3841. settings.onHide.call(element);
  3842. }
  3843. },
  3844. hideOthers: function() {
  3845. module.verbose('Finding other dropdowns to hide');
  3846. $allModules
  3847. .not($module)
  3848. .has(selector.menu + '.' + className.visible)
  3849. .dropdown('hide')
  3850. ;
  3851. },
  3852. hideMenu: function() {
  3853. module.verbose('Hiding menu instantaneously');
  3854. module.remove.active();
  3855. module.remove.visible();
  3856. $menu.transition('hide');
  3857. },
  3858. hideSubMenus: function() {
  3859. var
  3860. $subMenus = $menu.children(selector.item).find(selector.menu)
  3861. ;
  3862. module.verbose('Hiding sub menus', $subMenus);
  3863. $subMenus.transition('hide');
  3864. },
  3865. bind: {
  3866. keyboardEvents: function() {
  3867. module.debug('Binding keyboard events');
  3868. $module
  3869. .on('keydown' + eventNamespace, module.event.keydown)
  3870. ;
  3871. if( module.has.search() ) {
  3872. $module
  3873. .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
  3874. ;
  3875. }
  3876. if( module.is.multiple() ) {
  3877. $document
  3878. .on('keydown' + elementNamespace, module.event.document.keydown)
  3879. ;
  3880. }
  3881. },
  3882. touchEvents: function() {
  3883. module.debug('Touch device detected binding additional touch events');
  3884. if( module.is.searchSelection() ) {
  3885. // do nothing special yet
  3886. }
  3887. else {
  3888. $module
  3889. .on('touchstart' + eventNamespace, module.event.test.toggle)
  3890. ;
  3891. }
  3892. $menu
  3893. .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
  3894. ;
  3895. },
  3896. mouseEvents: function() {
  3897. module.debug('Mouse detected binding mouse events');
  3898. if(module.is.multiple()) {
  3899. $module
  3900. .on('click' + eventNamespace, selector.label, module.event.label.click)
  3901. .on('click' + eventNamespace, selector.remove, module.event.remove.click)
  3902. ;
  3903. }
  3904. if( module.is.searchSelection() ) {
  3905. $module
  3906. .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
  3907. .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
  3908. .on('click' + eventNamespace, selector.search, module.show)
  3909. .on('focus' + eventNamespace, selector.search, module.event.search.focus)
  3910. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  3911. .on('click' + eventNamespace, selector.text, module.event.text.focus)
  3912. ;
  3913. if(module.is.multiple()) {
  3914. $module
  3915. .on('click' + eventNamespace, module.event.click)
  3916. ;
  3917. }
  3918. }
  3919. else {
  3920. if(settings.on == 'click') {
  3921. $module
  3922. .on('click' + eventNamespace, module.event.test.toggle)
  3923. ;
  3924. }
  3925. else if(settings.on == 'hover') {
  3926. $module
  3927. .on('mouseenter' + eventNamespace, module.delay.show)
  3928. .on('mouseleave' + eventNamespace, module.delay.hide)
  3929. ;
  3930. }
  3931. else {
  3932. $module
  3933. .on(settings.on + eventNamespace, module.toggle)
  3934. ;
  3935. }
  3936. $module
  3937. .on('mousedown' + eventNamespace, module.event.mousedown)
  3938. .on('mouseup' + eventNamespace, module.event.mouseup)
  3939. .on('focus' + eventNamespace, module.event.focus)
  3940. .on('blur' + eventNamespace, module.event.blur)
  3941. ;
  3942. }
  3943. $menu
  3944. .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
  3945. .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
  3946. .on('click' + eventNamespace, selector.item, module.event.item.click)
  3947. ;
  3948. },
  3949. intent: function() {
  3950. module.verbose('Binding hide intent event to document');
  3951. if(hasTouch) {
  3952. $document
  3953. .on('touchstart' + elementNamespace, module.event.test.touch)
  3954. .on('touchmove' + elementNamespace, module.event.test.touch)
  3955. ;
  3956. }
  3957. $document
  3958. .on('click' + elementNamespace, module.event.test.hide)
  3959. ;
  3960. }
  3961. },
  3962. unbind: {
  3963. intent: function() {
  3964. module.verbose('Removing hide intent event from document');
  3965. if(hasTouch) {
  3966. $document
  3967. .off('touchstart' + elementNamespace)
  3968. .off('touchmove' + elementNamespace)
  3969. ;
  3970. }
  3971. $document
  3972. .off('click' + elementNamespace)
  3973. ;
  3974. }
  3975. },
  3976. filter: function(query) {
  3977. var
  3978. searchTerm = (query !== undefined)
  3979. ? query
  3980. : module.get.query(),
  3981. afterFiltered = function() {
  3982. if(module.is.multiple()) {
  3983. module.filterActive();
  3984. }
  3985. module.select.firstUnfiltered();
  3986. if( module.has.allResultsFiltered() ) {
  3987. if( settings.onNoResults.call(element, searchTerm) ) {
  3988. if(!settings.allowAdditions) {
  3989. module.verbose('All items filtered, showing message', searchTerm);
  3990. module.add.message(message.noResults);
  3991. }
  3992. }
  3993. else {
  3994. module.verbose('All items filtered, hiding dropdown', searchTerm);
  3995. module.hideMenu();
  3996. }
  3997. }
  3998. else {
  3999. module.remove.message();
  4000. }
  4001. if(settings.allowAdditions) {
  4002. module.add.userSuggestion(query);
  4003. }
  4004. if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
  4005. module.show();
  4006. }
  4007. }
  4008. ;
  4009. if(module.has.maxSelections()) {
  4010. return;
  4011. }
  4012. if(settings.apiSettings) {
  4013. if( module.can.useAPI() ) {
  4014. module.queryRemote(searchTerm, function() {
  4015. afterFiltered();
  4016. });
  4017. }
  4018. else {
  4019. module.error(error.noAPI);
  4020. }
  4021. }
  4022. else {
  4023. module.filterItems(searchTerm);
  4024. afterFiltered();
  4025. }
  4026. },
  4027. queryRemote: function(query, callback) {
  4028. var
  4029. apiSettings = {
  4030. errorDuration : false,
  4031. throttle : settings.throttle,
  4032. cache : 'local',
  4033. urlData : {
  4034. query: query
  4035. },
  4036. onError: function() {
  4037. module.add.message(message.serverError);
  4038. callback();
  4039. },
  4040. onFailure: function() {
  4041. module.add.message(message.serverError);
  4042. callback();
  4043. },
  4044. onSuccess : function(response) {
  4045. module.remove.message();
  4046. module.setup.menu({
  4047. values: response.results
  4048. });
  4049. callback();
  4050. }
  4051. }
  4052. ;
  4053. if( !$module.api('get request') ) {
  4054. module.setup.api();
  4055. }
  4056. apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
  4057. $module
  4058. .api('setting', apiSettings)
  4059. .api('query')
  4060. ;
  4061. },
  4062. filterItems: function(query) {
  4063. var
  4064. searchTerm = (query !== undefined)
  4065. ? query
  4066. : module.get.query(),
  4067. $results = $(),
  4068. escapedTerm = module.escape.regExp(searchTerm),
  4069. beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm')
  4070. ;
  4071. // avoid loop if we're matching nothing
  4072. if(searchTerm === '') {
  4073. $results = $item;
  4074. }
  4075. else {
  4076. module.verbose('Searching for matching values', searchTerm);
  4077. $item
  4078. .each(function(){
  4079. var
  4080. $choice = $(this),
  4081. text,
  4082. value
  4083. ;
  4084. if(settings.match == 'both' || settings.match == 'text') {
  4085. text = String(module.get.choiceText($choice, false));
  4086. if(text.search(beginsWithRegExp) !== -1) {
  4087. $results = $results.add($choice);
  4088. return true;
  4089. }
  4090. else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, text)) {
  4091. $results = $results.add($choice);
  4092. return true;
  4093. }
  4094. }
  4095. if(settings.match == 'both' || settings.match == 'value') {
  4096. value = String(module.get.choiceValue($choice, text));
  4097. if(value.search(beginsWithRegExp) !== -1) {
  4098. $results = $results.add($choice);
  4099. return true;
  4100. }
  4101. else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, value)) {
  4102. $results = $results.add($choice);
  4103. return true;
  4104. }
  4105. }
  4106. })
  4107. ;
  4108. }
  4109. module.debug('Showing only matched items', searchTerm);
  4110. module.remove.filteredItem();
  4111. $item
  4112. .not($results)
  4113. .addClass(className.filtered)
  4114. ;
  4115. },
  4116. fuzzySearch: function(query, term) {
  4117. var
  4118. termLength = term.length,
  4119. queryLength = query.length
  4120. ;
  4121. query = query.toLowerCase();
  4122. term = term.toLowerCase();
  4123. if(queryLength > termLength) {
  4124. return false;
  4125. }
  4126. if(queryLength === termLength) {
  4127. return (query === term);
  4128. }
  4129. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  4130. var
  4131. queryCharacter = query.charCodeAt(characterIndex)
  4132. ;
  4133. while(nextCharacterIndex < termLength) {
  4134. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  4135. continue search;
  4136. }
  4137. }
  4138. return false;
  4139. }
  4140. return true;
  4141. },
  4142. filterActive: function() {
  4143. if(settings.useLabels) {
  4144. $item.filter('.' + className.active)
  4145. .addClass(className.filtered)
  4146. ;
  4147. }
  4148. },
  4149. focusSearch: function() {
  4150. if( module.is.search() && !module.is.focusedOnSearch() ) {
  4151. $search[0].focus();
  4152. }
  4153. },
  4154. forceSelection: function() {
  4155. var
  4156. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  4157. $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
  4158. $selectedItem = ($currentlySelected.length > 0)
  4159. ? $currentlySelected
  4160. : $activeItem,
  4161. hasSelected = ($selectedItem.size() > 0)
  4162. ;
  4163. if(hasSelected) {
  4164. module.debug('Forcing partial selection to selected item', $selectedItem);
  4165. module.event.item.click.call($selectedItem);
  4166. }
  4167. else {
  4168. module.hide();
  4169. }
  4170. },
  4171. event: {
  4172. focus: function() {
  4173. if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
  4174. module.show();
  4175. }
  4176. },
  4177. click: function(event) {
  4178. var
  4179. $target = $(event.target)
  4180. ;
  4181. // focus search
  4182. if(($target.is($module) || $target.is($icon)) && !module.is.focusedOnSearch()) {
  4183. module.focusSearch();
  4184. }
  4185. },
  4186. blur: function(event) {
  4187. pageLostFocus = (document.activeElement === this);
  4188. if(!activated && !pageLostFocus) {
  4189. module.remove.activeLabel();
  4190. module.hide();
  4191. }
  4192. },
  4193. // prevents focus callback from occuring on mousedown
  4194. mousedown: function() {
  4195. activated = true;
  4196. },
  4197. mouseup: function() {
  4198. activated = false;
  4199. },
  4200. search: {
  4201. focus: function() {
  4202. activated = true;
  4203. if(module.is.multiple()) {
  4204. module.remove.activeLabel();
  4205. }
  4206. if(settings.showOnFocus) {
  4207. module.show();
  4208. }
  4209. },
  4210. blur: function(event) {
  4211. pageLostFocus = (document.activeElement === this);
  4212. if(!itemActivated && !pageLostFocus) {
  4213. if(module.is.multiple()) {
  4214. module.remove.activeLabel();
  4215. module.hide();
  4216. }
  4217. else if(settings.forceSelection) {
  4218. module.forceSelection();
  4219. }
  4220. else {
  4221. module.hide();
  4222. }
  4223. }
  4224. }
  4225. },
  4226. text: {
  4227. focus: function(event) {
  4228. activated = true;
  4229. module.focusSearch();
  4230. }
  4231. },
  4232. input: function(event) {
  4233. if(module.is.multiple() || module.is.searchSelection()) {
  4234. module.set.filtered();
  4235. }
  4236. clearTimeout(module.timer);
  4237. module.timer = setTimeout(module.search, settings.delay.search);
  4238. },
  4239. label: {
  4240. click: function(event) {
  4241. var
  4242. $label = $(this),
  4243. $labels = $module.find(selector.label),
  4244. $activeLabels = $labels.filter('.' + className.active),
  4245. $nextActive = $label.nextAll('.' + className.active),
  4246. $prevActive = $label.prevAll('.' + className.active),
  4247. $range = ($nextActive.length > 0)
  4248. ? $label.nextUntil($nextActive).add($activeLabels).add($label)
  4249. : $label.prevUntil($prevActive).add($activeLabels).add($label)
  4250. ;
  4251. if(event.shiftKey) {
  4252. $activeLabels.removeClass(className.active);
  4253. $range.addClass(className.active);
  4254. }
  4255. else if(event.ctrlKey) {
  4256. $label.toggleClass(className.active);
  4257. }
  4258. else {
  4259. $activeLabels.removeClass(className.active);
  4260. $label.addClass(className.active);
  4261. }
  4262. settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
  4263. }
  4264. },
  4265. remove: {
  4266. click: function() {
  4267. var
  4268. $label = $(this).parent()
  4269. ;
  4270. if( $label.hasClass(className.active) ) {
  4271. // remove all selected labels
  4272. module.remove.activeLabels();
  4273. }
  4274. else {
  4275. // remove this label only
  4276. module.remove.activeLabels( $label );
  4277. }
  4278. }
  4279. },
  4280. test: {
  4281. toggle: function(event) {
  4282. var
  4283. toggleBehavior = (module.is.multiple())
  4284. ? module.show
  4285. : module.toggle
  4286. ;
  4287. if( module.determine.eventOnElement(event, toggleBehavior) ) {
  4288. event.preventDefault();
  4289. }
  4290. },
  4291. touch: function(event) {
  4292. module.determine.eventOnElement(event, function() {
  4293. if(event.type == 'touchstart') {
  4294. module.timer = setTimeout(module.hide, settings.delay.touch);
  4295. }
  4296. else if(event.type == 'touchmove') {
  4297. clearTimeout(module.timer);
  4298. }
  4299. });
  4300. event.stopPropagation();
  4301. },
  4302. hide: function(event) {
  4303. module.determine.eventInModule(event, module.hide);
  4304. }
  4305. },
  4306. menu: {
  4307. mousedown: function() {
  4308. itemActivated = true;
  4309. },
  4310. mouseup: function() {
  4311. itemActivated = false;
  4312. }
  4313. },
  4314. item: {
  4315. mouseenter: function(event) {
  4316. var
  4317. $subMenu = $(this).children(selector.menu),
  4318. $otherMenus = $(this).siblings(selector.item).children(selector.menu)
  4319. ;
  4320. if( $subMenu.length > 0 ) {
  4321. clearTimeout(module.itemTimer);
  4322. module.itemTimer = setTimeout(function() {
  4323. module.verbose('Showing sub-menu', $subMenu);
  4324. $.each($otherMenus, function() {
  4325. module.animate.hide(false, $(this));
  4326. });
  4327. module.animate.show(false, $subMenu);
  4328. }, settings.delay.show);
  4329. event.preventDefault();
  4330. }
  4331. },
  4332. mouseleave: function(event) {
  4333. var
  4334. $subMenu = $(this).children(selector.menu)
  4335. ;
  4336. if($subMenu.length > 0) {
  4337. clearTimeout(module.itemTimer);
  4338. module.itemTimer = setTimeout(function() {
  4339. module.verbose('Hiding sub-menu', $subMenu);
  4340. module.animate.hide(false, $subMenu);
  4341. }, settings.delay.hide);
  4342. }
  4343. },
  4344. click: function (event) {
  4345. var
  4346. $choice = $(this),
  4347. $target = (event)
  4348. ? $(event.target)
  4349. : $(''),
  4350. $subMenu = $choice.find(selector.menu),
  4351. text = module.get.choiceText($choice),
  4352. value = module.get.choiceValue($choice, text),
  4353. hasSubMenu = ($subMenu.length > 0),
  4354. isBubbledEvent = ($subMenu.find($target).length > 0)
  4355. ;
  4356. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  4357. if(!settings.useLabels) {
  4358. module.remove.searchTerm();
  4359. }
  4360. module.determine.selectAction.call(this, text, value);
  4361. }
  4362. }
  4363. },
  4364. document: {
  4365. // label selection should occur even when element has no focus
  4366. keydown: function(event) {
  4367. var
  4368. pressedKey = event.which,
  4369. keys = module.get.shortcutKeys(),
  4370. isShortcutKey = module.is.inObject(pressedKey, keys)
  4371. ;
  4372. if(isShortcutKey) {
  4373. var
  4374. $label = $module.find(selector.label),
  4375. $activeLabel = $label.filter('.' + className.active),
  4376. activeValue = $activeLabel.data('value'),
  4377. labelIndex = $label.index($activeLabel),
  4378. labelCount = $label.length,
  4379. hasActiveLabel = ($activeLabel.length > 0),
  4380. hasMultipleActive = ($activeLabel.length > 1),
  4381. isFirstLabel = (labelIndex === 0),
  4382. isLastLabel = (labelIndex + 1 == labelCount),
  4383. isSearch = module.is.searchSelection(),
  4384. isFocusedOnSearch = module.is.focusedOnSearch(),
  4385. isFocused = module.is.focused(),
  4386. caretAtStart = (isFocusedOnSearch && module.get.caretPosition() === 0),
  4387. $nextLabel
  4388. ;
  4389. if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
  4390. return;
  4391. }
  4392. if(pressedKey == keys.leftArrow) {
  4393. // activate previous label
  4394. if((isFocused || caretAtStart) && !hasActiveLabel) {
  4395. module.verbose('Selecting previous label');
  4396. $label.last().addClass(className.active);
  4397. }
  4398. else if(hasActiveLabel) {
  4399. if(!event.shiftKey) {
  4400. module.verbose('Selecting previous label');
  4401. $label.removeClass(className.active);
  4402. }
  4403. else {
  4404. module.verbose('Adding previous label to selection');
  4405. }
  4406. if(isFirstLabel && !hasMultipleActive) {
  4407. $activeLabel.addClass(className.active);
  4408. }
  4409. else {
  4410. $activeLabel.prev(selector.siblingLabel)
  4411. .addClass(className.active)
  4412. .end()
  4413. ;
  4414. }
  4415. event.preventDefault();
  4416. }
  4417. }
  4418. else if(pressedKey == keys.rightArrow) {
  4419. // activate first label
  4420. if(isFocused && !hasActiveLabel) {
  4421. $label.first().addClass(className.active);
  4422. }
  4423. // activate next label
  4424. if(hasActiveLabel) {
  4425. if(!event.shiftKey) {
  4426. module.verbose('Selecting next label');
  4427. $label.removeClass(className.active);
  4428. }
  4429. else {
  4430. module.verbose('Adding next label to selection');
  4431. }
  4432. if(isLastLabel) {
  4433. if(isSearch) {
  4434. if(!isFocusedOnSearch) {
  4435. module.focusSearch();
  4436. }
  4437. else {
  4438. $label.removeClass(className.active);
  4439. }
  4440. }
  4441. else if(hasMultipleActive) {
  4442. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  4443. }
  4444. else {
  4445. $activeLabel.addClass(className.active);
  4446. }
  4447. }
  4448. else {
  4449. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  4450. }
  4451. event.preventDefault();
  4452. }
  4453. }
  4454. else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
  4455. if(hasActiveLabel) {
  4456. module.verbose('Removing active labels');
  4457. if(isLastLabel) {
  4458. if(isSearch && !isFocusedOnSearch) {
  4459. module.focusSearch();
  4460. }
  4461. }
  4462. $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
  4463. module.remove.activeLabels($activeLabel);
  4464. event.preventDefault();
  4465. }
  4466. else if(caretAtStart && !hasActiveLabel && pressedKey == keys.backspace) {
  4467. module.verbose('Removing last label on input backspace');
  4468. $activeLabel = $label.last().addClass(className.active);
  4469. module.remove.activeLabels($activeLabel);
  4470. }
  4471. }
  4472. else {
  4473. $activeLabel.removeClass(className.active);
  4474. }
  4475. }
  4476. }
  4477. },
  4478. keydown: function(event) {
  4479. var
  4480. pressedKey = event.which,
  4481. keys = module.get.shortcutKeys(),
  4482. isShortcutKey = module.is.inObject(pressedKey, keys)
  4483. ;
  4484. if(isShortcutKey) {
  4485. var
  4486. $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
  4487. $activeItem = $menu.children('.' + className.active).eq(0),
  4488. $selectedItem = ($currentlySelected.length > 0)
  4489. ? $currentlySelected
  4490. : $activeItem,
  4491. $visibleItems = ($selectedItem.length > 0)
  4492. ? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf()
  4493. : $menu.children(':not(.' + className.filtered +')'),
  4494. $subMenu = $selectedItem.children(selector.menu),
  4495. $parentMenu = $selectedItem.closest(selector.menu),
  4496. inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
  4497. hasSubMenu = ($subMenu.length> 0),
  4498. hasSelectedItem = ($selectedItem.length > 0),
  4499. selectedIsVisible = ($selectedItem.not(selector.unselectable).length > 0),
  4500. $nextItem,
  4501. isSubMenuItem,
  4502. newIndex
  4503. ;
  4504. // visible menu keyboard shortcuts
  4505. if( module.is.visible() ) {
  4506. // enter (select or open sub-menu)
  4507. if(pressedKey == keys.enter || pressedKey == keys.delimiter) {
  4508. if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
  4509. module.verbose('Pressed enter on unselectable category, opening sub menu');
  4510. pressedKey = keys.rightArrow;
  4511. }
  4512. else if(selectedIsVisible) {
  4513. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  4514. module.event.item.click.call($selectedItem, event);
  4515. if(settings.useLabels && module.is.searchSelection()) {
  4516. module.hideAndClear();
  4517. }
  4518. else {
  4519. module.remove.searchTerm();
  4520. }
  4521. }
  4522. event.preventDefault();
  4523. }
  4524. // left arrow (hide sub-menu)
  4525. if(pressedKey == keys.leftArrow) {
  4526. isSubMenuItem = ($parentMenu[0] !== $menu[0]);
  4527. if(isSubMenuItem) {
  4528. module.verbose('Left key pressed, closing sub-menu');
  4529. module.animate.hide(false, $parentMenu);
  4530. $selectedItem
  4531. .removeClass(className.selected)
  4532. ;
  4533. $parentMenu
  4534. .closest(selector.item)
  4535. .addClass(className.selected)
  4536. ;
  4537. event.preventDefault();
  4538. }
  4539. }
  4540. // right arrow (show sub-menu)
  4541. if(pressedKey == keys.rightArrow) {
  4542. if(hasSubMenu) {
  4543. module.verbose('Right key pressed, opening sub-menu');
  4544. module.animate.show(false, $subMenu);
  4545. $selectedItem
  4546. .removeClass(className.selected)
  4547. ;
  4548. $subMenu
  4549. .find(selector.item).eq(0)
  4550. .addClass(className.selected)
  4551. ;
  4552. event.preventDefault();
  4553. }
  4554. }
  4555. // up arrow (traverse menu up)
  4556. if(pressedKey == keys.upArrow) {
  4557. $nextItem = (hasSelectedItem && inVisibleMenu)
  4558. ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  4559. : $item.eq(0)
  4560. ;
  4561. if($visibleItems.index( $nextItem ) < 0) {
  4562. module.verbose('Up key pressed but reached top of current menu');
  4563. event.preventDefault();
  4564. return;
  4565. }
  4566. else {
  4567. module.verbose('Up key pressed, changing active item');
  4568. $selectedItem
  4569. .removeClass(className.selected)
  4570. ;
  4571. $nextItem
  4572. .addClass(className.selected)
  4573. ;
  4574. module.set.scrollPosition($nextItem);
  4575. }
  4576. event.preventDefault();
  4577. }
  4578. // down arrow (traverse menu down)
  4579. if(pressedKey == keys.downArrow) {
  4580. $nextItem = (hasSelectedItem && inVisibleMenu)
  4581. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  4582. : $item.eq(0)
  4583. ;
  4584. if($nextItem.length === 0) {
  4585. module.verbose('Down key pressed but reached bottom of current menu');
  4586. event.preventDefault();
  4587. return;
  4588. }
  4589. else {
  4590. module.verbose('Down key pressed, changing active item');
  4591. $item
  4592. .removeClass(className.selected)
  4593. ;
  4594. $nextItem
  4595. .addClass(className.selected)
  4596. ;
  4597. module.set.scrollPosition($nextItem);
  4598. }
  4599. event.preventDefault();
  4600. }
  4601. // page down (show next page)
  4602. if(pressedKey == keys.pageUp) {
  4603. module.scrollPage('up');
  4604. event.preventDefault();
  4605. }
  4606. if(pressedKey == keys.pageDown) {
  4607. module.scrollPage('down');
  4608. event.preventDefault();
  4609. }
  4610. // escape (close menu)
  4611. if(pressedKey == keys.escape) {
  4612. module.verbose('Escape key pressed, closing dropdown');
  4613. module.hide();
  4614. }
  4615. }
  4616. else {
  4617. // delimiter key
  4618. if(pressedKey == keys.delimiter) {
  4619. event.preventDefault();
  4620. }
  4621. // down arrow (open menu)
  4622. if(pressedKey == keys.downArrow) {
  4623. module.verbose('Down key pressed, showing dropdown');
  4624. module.show();
  4625. event.preventDefault();
  4626. }
  4627. }
  4628. }
  4629. else {
  4630. if( module.is.selection() && !module.is.search() ) {
  4631. module.set.selectedLetter( String.fromCharCode(pressedKey) );
  4632. }
  4633. }
  4634. }
  4635. },
  4636. determine: {
  4637. selectAction: function(text, value) {
  4638. module.verbose('Determining action', settings.action);
  4639. if( $.isFunction( module.action[settings.action] ) ) {
  4640. module.verbose('Triggering preset action', settings.action, text, value);
  4641. module.action[ settings.action ].call(this, text, value);
  4642. }
  4643. else if( $.isFunction(settings.action) ) {
  4644. module.verbose('Triggering user action', settings.action, text, value);
  4645. settings.action.call(this, text, value);
  4646. }
  4647. else {
  4648. module.error(error.action, settings.action);
  4649. }
  4650. },
  4651. eventInModule: function(event, callback) {
  4652. callback = $.isFunction(callback)
  4653. ? callback
  4654. : function(){}
  4655. ;
  4656. if( $(event.target).closest($module).length === 0 ) {
  4657. module.verbose('Triggering event', callback);
  4658. callback();
  4659. return true;
  4660. }
  4661. else {
  4662. module.verbose('Event occurred in dropdown, canceling callback');
  4663. return false;
  4664. }
  4665. },
  4666. eventOnElement: function(event, callback) {
  4667. var
  4668. $target = $(event.target)
  4669. ;
  4670. callback = $.isFunction(callback)
  4671. ? callback
  4672. : function(){}
  4673. ;
  4674. if($target.closest($menu).length === 0) {
  4675. module.verbose('Triggering event', callback);
  4676. callback();
  4677. return true;
  4678. }
  4679. else {
  4680. module.verbose('Event occurred in dropdown menu, canceling callback');
  4681. return false;
  4682. }
  4683. }
  4684. },
  4685. action: {
  4686. nothing: function() {},
  4687. activate: function(text, value) {
  4688. value = (value !== undefined)
  4689. ? value
  4690. : text
  4691. ;
  4692. module.set.selected(value, $(this));
  4693. if(module.is.multiple() && !module.is.allFiltered()) {
  4694. return;
  4695. }
  4696. else {
  4697. module.hideAndClear();
  4698. }
  4699. },
  4700. select: function(text, value) {
  4701. // mimics action.activate but does not select text
  4702. module.action.activate.call(this);
  4703. },
  4704. combo: function(text, value) {
  4705. value = (value !== undefined)
  4706. ? value
  4707. : text
  4708. ;
  4709. module.set.selected(value, $(this));
  4710. module.hideAndClear();
  4711. },
  4712. hide: function() {
  4713. module.hideAndClear();
  4714. }
  4715. },
  4716. get: {
  4717. id: function() {
  4718. return id;
  4719. },
  4720. text: function() {
  4721. return $text.text();
  4722. },
  4723. query: function() {
  4724. return $.trim($search.val());
  4725. },
  4726. searchWidth: function(characterCount) {
  4727. return (characterCount * settings.glyphWidth) + 'em';
  4728. },
  4729. selectionCount: function() {
  4730. var
  4731. values = module.get.values()
  4732. ;
  4733. return ( module.is.multiple() )
  4734. ? $.isArray(values)
  4735. ? values.length
  4736. : 0
  4737. : (module.get.value() !== '')
  4738. ? 1
  4739. : 0
  4740. ;
  4741. },
  4742. transition: function($subMenu) {
  4743. return (settings.transition == 'auto')
  4744. ? module.is.upward($subMenu)
  4745. ? 'slide up'
  4746. : 'slide down'
  4747. : settings.transition
  4748. ;
  4749. },
  4750. userValues: function() {
  4751. var
  4752. values = module.get.values()
  4753. ;
  4754. if(!values) {
  4755. return false;
  4756. }
  4757. values = $.isArray(values)
  4758. ? values
  4759. : [values]
  4760. ;
  4761. return $.grep(values, function(value) {
  4762. return (module.get.item(value) === false);
  4763. });
  4764. },
  4765. uniqueArray: function(array) {
  4766. return $.grep(array, function (value, index) {
  4767. return $.inArray(value, array) === index;
  4768. });
  4769. },
  4770. caretPosition: function() {
  4771. var
  4772. input = $search.get(0),
  4773. range,
  4774. rangeLength
  4775. ;
  4776. if('selectionStart' in input) {
  4777. return input.selectionStart;
  4778. }
  4779. else if (document.selection) {
  4780. input.focus();
  4781. range = document.selection.createRange();
  4782. rangeLength = range.text.length;
  4783. range.moveStart('character', -input.value.length);
  4784. return range.text.length - rangeLength;
  4785. }
  4786. },
  4787. shortcutKeys: function() {
  4788. return {
  4789. backspace : 8,
  4790. delimiter : 188, // comma
  4791. deleteKey : 46,
  4792. enter : 13,
  4793. escape : 27,
  4794. pageUp : 33,
  4795. pageDown : 34,
  4796. leftArrow : 37,
  4797. upArrow : 38,
  4798. rightArrow : 39,
  4799. downArrow : 40
  4800. };
  4801. },
  4802. value: function() {
  4803. return ($input.length > 0)
  4804. ? $input.val()
  4805. : $module.data(metadata.value)
  4806. ;
  4807. },
  4808. values: function() {
  4809. var
  4810. value = module.get.value()
  4811. ;
  4812. if(value === '') {
  4813. return '';
  4814. }
  4815. return (!$input.is('select') && module.is.multiple())
  4816. ? typeof value == 'string'
  4817. ? value.split(settings.delimiter)
  4818. : ''
  4819. : value
  4820. ;
  4821. },
  4822. remoteValues: function() {
  4823. var
  4824. values = module.get.values(),
  4825. remoteValues = false
  4826. ;
  4827. if(values) {
  4828. if(typeof values == 'string') {
  4829. values = [values];
  4830. }
  4831. remoteValues = {};
  4832. $.each(values, function(index, value) {
  4833. var
  4834. name = module.read.remoteData(value)
  4835. ;
  4836. module.verbose('Restoring value from session data', name, value);
  4837. remoteValues[value] = (name)
  4838. ? name
  4839. : value
  4840. ;
  4841. });
  4842. }
  4843. return remoteValues;
  4844. },
  4845. choiceText: function($choice, preserveHTML) {
  4846. preserveHTML = (preserveHTML !== undefined)
  4847. ? preserveHTML
  4848. : settings.preserveHTML
  4849. ;
  4850. if($choice) {
  4851. if($choice.find(selector.menu).length > 0) {
  4852. module.verbose('Retreiving text of element with sub-menu');
  4853. $choice = $choice.clone();
  4854. $choice.find(selector.menu).remove();
  4855. $choice.find(selector.menuIcon).remove();
  4856. }
  4857. return ($choice.data(metadata.text) !== undefined)
  4858. ? $choice.data(metadata.text)
  4859. : (preserveHTML)
  4860. ? $choice.html().trim()
  4861. : $choice.text().trim()
  4862. ;
  4863. }
  4864. },
  4865. choiceValue: function($choice, choiceText) {
  4866. choiceText = choiceText || module.get.choiceText($choice);
  4867. if(!$choice) {
  4868. return false;
  4869. }
  4870. return ($choice.data(metadata.value) !== undefined)
  4871. ? $choice.data(metadata.value)
  4872. : (typeof choiceText === 'string')
  4873. ? choiceText.toLowerCase().trim()
  4874. : choiceText
  4875. ;
  4876. },
  4877. inputEvent: function() {
  4878. var
  4879. input = $search[0]
  4880. ;
  4881. if(input) {
  4882. return (input.oninput !== undefined)
  4883. ? 'input'
  4884. : (input.onpropertychange !== undefined)
  4885. ? 'propertychange'
  4886. : 'keyup'
  4887. ;
  4888. }
  4889. return false;
  4890. },
  4891. selectValues: function() {
  4892. var
  4893. select = {}
  4894. ;
  4895. select.values = [];
  4896. $module
  4897. .find('option')
  4898. .each(function() {
  4899. var
  4900. $option = $(this),
  4901. name = $option.html(),
  4902. disabled = $option.attr('disabled'),
  4903. value = ( $option.attr('value') !== undefined )
  4904. ? $option.attr('value')
  4905. : name
  4906. ;
  4907. if(settings.placeholder === 'auto' && value === '') {
  4908. select.placeholder = name;
  4909. }
  4910. else {
  4911. select.values.push({
  4912. name : name,
  4913. value : value,
  4914. disabled : disabled
  4915. });
  4916. }
  4917. })
  4918. ;
  4919. if(settings.placeholder && settings.placeholder !== 'auto') {
  4920. module.debug('Setting placeholder value to', settings.placeholder);
  4921. select.placeholder = settings.placeholder;
  4922. }
  4923. if(settings.sortSelect) {
  4924. select.values.sort(function(a, b) {
  4925. return (a.name > b.name)
  4926. ? 1
  4927. : -1
  4928. ;
  4929. });
  4930. module.debug('Retrieved and sorted values from select', select);
  4931. }
  4932. else {
  4933. module.debug('Retreived values from select', select);
  4934. }
  4935. return select;
  4936. },
  4937. activeItem: function() {
  4938. return $item.filter('.' + className.active);
  4939. },
  4940. selectedItem: function() {
  4941. var
  4942. $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
  4943. ;
  4944. return ($selectedItem.length > 0)
  4945. ? $selectedItem
  4946. : $item.eq(0)
  4947. ;
  4948. },
  4949. itemWithAdditions: function(value) {
  4950. var
  4951. $items = module.get.item(value),
  4952. $userItems = module.create.userChoice(value),
  4953. hasUserItems = ($userItems && $userItems.length > 0)
  4954. ;
  4955. if(hasUserItems) {
  4956. $items = ($items.length > 0)
  4957. ? $items.add($userItems)
  4958. : $userItems
  4959. ;
  4960. }
  4961. return $items;
  4962. },
  4963. item: function(value, strict) {
  4964. var
  4965. $selectedItem = false,
  4966. shouldSearch,
  4967. isMultiple
  4968. ;
  4969. value = (value !== undefined)
  4970. ? value
  4971. : ( module.get.values() !== undefined)
  4972. ? module.get.values()
  4973. : module.get.text()
  4974. ;
  4975. shouldSearch = (isMultiple)
  4976. ? (value.length > 0)
  4977. : (value !== undefined && value !== '' && value !== null)
  4978. ;
  4979. isMultiple = (module.is.multiple() && $.isArray(value));
  4980. strict = (value === '' || value === 0)
  4981. ? true
  4982. : strict || false
  4983. ;
  4984. if(shouldSearch) {
  4985. $item
  4986. .each(function() {
  4987. var
  4988. $choice = $(this),
  4989. optionText = module.get.choiceText($choice),
  4990. optionValue = module.get.choiceValue($choice, optionText)
  4991. ;
  4992. // safe early exit
  4993. if(optionValue === null || optionValue === undefined) {
  4994. return;
  4995. }
  4996. if(isMultiple) {
  4997. if($.inArray(optionValue.toString(), value) !== -1 || $.inArray(optionText, value) !== -1) {
  4998. $selectedItem = ($selectedItem)
  4999. ? $selectedItem.add($choice)
  5000. : $choice
  5001. ;
  5002. }
  5003. }
  5004. else if(strict) {
  5005. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  5006. if( optionValue === value || optionText === value) {
  5007. $selectedItem = $choice;
  5008. return true;
  5009. }
  5010. }
  5011. else {
  5012. if( optionValue.toString() == value.toString() || optionText == value) {
  5013. module.verbose('Found select item by value', optionValue, value);
  5014. $selectedItem = $choice;
  5015. return true;
  5016. }
  5017. }
  5018. })
  5019. ;
  5020. }
  5021. return $selectedItem;
  5022. }
  5023. },
  5024. check: {
  5025. maxSelections: function(selectionCount) {
  5026. if(settings.maxSelections) {
  5027. selectionCount = (selectionCount !== undefined)
  5028. ? selectionCount
  5029. : module.get.selectionCount()
  5030. ;
  5031. if(selectionCount >= settings.maxSelections) {
  5032. module.debug('Maximum selection count reached');
  5033. $item.addClass(className.filtered);
  5034. module.add.message(message.maxSelections);
  5035. return true;
  5036. }
  5037. else {
  5038. module.verbose('No longer at maximum selection count');
  5039. module.remove.message();
  5040. module.remove.filteredItem();
  5041. if(module.is.searchSelection()) {
  5042. module.filterItems();
  5043. }
  5044. return false;
  5045. }
  5046. }
  5047. return true;
  5048. }
  5049. },
  5050. restore: {
  5051. defaults: function() {
  5052. module.restore.defaultText();
  5053. module.restore.defaultValue();
  5054. },
  5055. defaultText: function() {
  5056. var
  5057. defaultText = $module.data(metadata.defaultText)
  5058. ;
  5059. module.debug('Restoring default text', defaultText);
  5060. module.set.text(defaultText);
  5061. $text.addClass(className.placeholder);
  5062. },
  5063. defaultValue: function() {
  5064. var
  5065. defaultValue = $module.data(metadata.defaultValue)
  5066. ;
  5067. if(defaultValue !== undefined) {
  5068. module.debug('Restoring default value', defaultValue);
  5069. if(defaultValue !== '') {
  5070. module.set.value(defaultValue);
  5071. module.set.selected();
  5072. }
  5073. else {
  5074. module.remove.activeItem();
  5075. module.remove.selectedItem();
  5076. }
  5077. }
  5078. },
  5079. labels: function() {
  5080. if(settings.allowAdditions) {
  5081. if(!settings.useLabels) {
  5082. module.error(error.labels);
  5083. settings.useLabels = true;
  5084. }
  5085. module.debug('Restoring selected values');
  5086. module.create.userLabels();
  5087. }
  5088. module.check.maxSelections();
  5089. },
  5090. selected: function() {
  5091. module.restore.values();
  5092. if(module.is.multiple()) {
  5093. module.debug('Restoring previously selected values and labels');
  5094. module.restore.labels();
  5095. }
  5096. else {
  5097. module.debug('Restoring previously selected values');
  5098. }
  5099. },
  5100. values: function() {
  5101. // prevents callbacks from occuring on initial load
  5102. module.set.initialLoad();
  5103. if(settings.apiSettings) {
  5104. if(settings.saveRemoteData) {
  5105. module.restore.remoteValues();
  5106. }
  5107. else {
  5108. module.clearValue();
  5109. }
  5110. }
  5111. else {
  5112. module.set.selected();
  5113. }
  5114. module.remove.initialLoad();
  5115. },
  5116. remoteValues: function() {
  5117. var
  5118. values = module.get.remoteValues()
  5119. ;
  5120. module.debug('Recreating selected from session data', values);
  5121. if(values) {
  5122. if( module.is.single() ) {
  5123. $.each(values, function(value, name) {
  5124. module.set.text(name);
  5125. });
  5126. }
  5127. else {
  5128. $.each(values, function(value, name) {
  5129. module.add.label(value, name);
  5130. });
  5131. }
  5132. }
  5133. }
  5134. },
  5135. read: {
  5136. remoteData: function(value) {
  5137. var
  5138. name
  5139. ;
  5140. if(window.Storage === undefined) {
  5141. module.error(error.noStorage);
  5142. return;
  5143. }
  5144. name = sessionStorage.getItem(value);
  5145. return (name !== undefined)
  5146. ? name
  5147. : false
  5148. ;
  5149. }
  5150. },
  5151. save: {
  5152. defaults: function() {
  5153. module.save.defaultText();
  5154. module.save.placeholderText();
  5155. module.save.defaultValue();
  5156. },
  5157. defaultValue: function() {
  5158. var
  5159. value = module.get.value()
  5160. ;
  5161. module.verbose('Saving default value as', value);
  5162. $module.data(metadata.defaultValue, value);
  5163. },
  5164. defaultText: function() {
  5165. var
  5166. text = module.get.text()
  5167. ;
  5168. module.verbose('Saving default text as', text);
  5169. $module.data(metadata.defaultText, text);
  5170. },
  5171. placeholderText: function() {
  5172. var
  5173. text
  5174. ;
  5175. if($text.hasClass(className.placeholder)) {
  5176. text = module.get.text();
  5177. module.verbose('Saving placeholder text as', text);
  5178. $module.data(metadata.placeholderText, text);
  5179. }
  5180. },
  5181. remoteData: function(name, value) {
  5182. if(window.Storage === undefined) {
  5183. module.error(error.noStorage);
  5184. return;
  5185. }
  5186. module.verbose('Saving remote data to session storage', value, name);
  5187. sessionStorage.setItem(value, name);
  5188. }
  5189. },
  5190. clear: function() {
  5191. if(module.is.multiple()) {
  5192. module.remove.labels();
  5193. }
  5194. else {
  5195. module.remove.activeItem();
  5196. module.remove.selectedItem();
  5197. }
  5198. module.set.placeholderText();
  5199. module.clearValue();
  5200. },
  5201. clearValue: function() {
  5202. module.set.value('');
  5203. },
  5204. scrollPage: function(direction, $selectedItem) {
  5205. var
  5206. $selectedItem = $selectedItem || module.get.selectedItem(),
  5207. $menu = $selectedItem.closest(selector.menu),
  5208. menuHeight = $menu.outerHeight(),
  5209. currentScroll = $menu.scrollTop(),
  5210. itemHeight = $item.eq(0).outerHeight(),
  5211. itemsPerPage = Math.floor(menuHeight / itemHeight),
  5212. maxScroll = $menu.prop('scrollHeight'),
  5213. newScroll = (direction == 'up')
  5214. ? currentScroll - (itemHeight * itemsPerPage)
  5215. : currentScroll + (itemHeight * itemsPerPage),
  5216. $selectableItem = $item.not(selector.unselectable),
  5217. isWithinRange,
  5218. $nextSelectedItem,
  5219. elementIndex
  5220. ;
  5221. elementIndex = (direction == 'up')
  5222. ? $selectableItem.index($selectedItem) - itemsPerPage
  5223. : $selectableItem.index($selectedItem) + itemsPerPage
  5224. ;
  5225. isWithinRange = (direction == 'up')
  5226. ? (elementIndex >= 0)
  5227. : (elementIndex < $selectableItem.length)
  5228. ;
  5229. $nextSelectedItem = (isWithinRange)
  5230. ? $selectableItem.eq(elementIndex)
  5231. : (direction == 'up')
  5232. ? $selectableItem.first()
  5233. : $selectableItem.last()
  5234. ;
  5235. if($nextSelectedItem.length > 0) {
  5236. module.debug('Scrolling page', direction, $nextSelectedItem);
  5237. $selectedItem
  5238. .removeClass(className.selected)
  5239. ;
  5240. $nextSelectedItem
  5241. .addClass(className.selected)
  5242. ;
  5243. $menu
  5244. .scrollTop(newScroll)
  5245. ;
  5246. }
  5247. },
  5248. set: {
  5249. filtered: function() {
  5250. var
  5251. isMultiple = module.is.multiple(),
  5252. isSearch = module.is.searchSelection(),
  5253. isSearchMultiple = (isMultiple && isSearch),
  5254. searchValue = (isSearch)
  5255. ? module.get.query()
  5256. : '',
  5257. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
  5258. searchWidth = module.get.searchWidth(searchValue.length),
  5259. valueIsSet = searchValue !== ''
  5260. ;
  5261. if(isMultiple && hasSearchValue) {
  5262. module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
  5263. $search.css('width', searchWidth);
  5264. }
  5265. if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
  5266. module.verbose('Hiding placeholder text');
  5267. $text.addClass(className.filtered);
  5268. }
  5269. else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
  5270. module.verbose('Showing placeholder text');
  5271. $text.removeClass(className.filtered);
  5272. }
  5273. },
  5274. loading: function() {
  5275. $module.addClass(className.loading);
  5276. },
  5277. placeholderText: function(text) {
  5278. text = text || $module.data(metadata.placeholderText);
  5279. if(text) {
  5280. module.debug('Restoring placeholder text');
  5281. module.set.text(text);
  5282. $text.addClass(className.placeholder);
  5283. }
  5284. },
  5285. tabbable: function() {
  5286. if( module.has.search() ) {
  5287. module.debug('Added tabindex to searchable dropdown');
  5288. $search
  5289. .val('')
  5290. .attr('tabindex', 0)
  5291. ;
  5292. $menu
  5293. .attr('tabindex', -1)
  5294. ;
  5295. }
  5296. else {
  5297. module.debug('Added tabindex to dropdown');
  5298. if(!$module.attr('tabindex') ) {
  5299. $module
  5300. .attr('tabindex', 0)
  5301. ;
  5302. $menu
  5303. .attr('tabindex', -1)
  5304. ;
  5305. }
  5306. }
  5307. },
  5308. initialLoad: function() {
  5309. module.verbose('Setting initial load');
  5310. initialLoad = true;
  5311. },
  5312. scrollPosition: function($item, forceScroll) {
  5313. var
  5314. edgeTolerance = 5,
  5315. $menu,
  5316. hasActive,
  5317. offset,
  5318. itemHeight,
  5319. itemOffset,
  5320. menuOffset,
  5321. menuScroll,
  5322. menuHeight,
  5323. abovePage,
  5324. belowPage
  5325. ;
  5326. $item = $item || module.get.selectedItem();
  5327. $menu = $item.closest(selector.menu);
  5328. hasActive = ($item && $item.length > 0);
  5329. forceScroll = (forceScroll !== undefined)
  5330. ? forceScroll
  5331. : false
  5332. ;
  5333. if($item && $menu.length > 0 && hasActive) {
  5334. itemOffset = $item.position().top;
  5335. $menu.addClass(className.loading);
  5336. menuScroll = $menu.scrollTop();
  5337. menuOffset = $menu.offset().top;
  5338. itemOffset = $item.offset().top;
  5339. offset = menuScroll - menuOffset + itemOffset;
  5340. if(!forceScroll) {
  5341. menuHeight = $menu.height();
  5342. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  5343. abovePage = ((offset - edgeTolerance) < menuScroll);
  5344. }
  5345. module.debug('Scrolling to active item', offset);
  5346. if(forceScroll || abovePage || belowPage) {
  5347. $menu.scrollTop(offset);
  5348. }
  5349. $menu.removeClass(className.loading);
  5350. }
  5351. },
  5352. text: function(text) {
  5353. if(settings.action !== 'select') {
  5354. if(settings.action == 'combo') {
  5355. module.debug('Changing combo button text', text, $combo);
  5356. if(settings.preserveHTML) {
  5357. $combo.html(text);
  5358. }
  5359. else {
  5360. $combo.text(text);
  5361. }
  5362. }
  5363. else {
  5364. module.debug('Changing text', text, $text);
  5365. $text
  5366. .removeClass(className.filtered)
  5367. .removeClass(className.placeholder)
  5368. ;
  5369. if(settings.preserveHTML) {
  5370. $text.html(text);
  5371. }
  5372. else {
  5373. $text.text(text);
  5374. }
  5375. }
  5376. }
  5377. },
  5378. selectedLetter: function(letter) {
  5379. var
  5380. $selectedItem = $item.filter('.' + className.selected),
  5381. $nextValue = false
  5382. ;
  5383. $item
  5384. .each(function(){
  5385. var
  5386. $choice = $(this),
  5387. text = module.get.choiceText($choice, false),
  5388. firstLetter = String(text).charAt(0).toLowerCase(),
  5389. matchedLetter = letter.toLowerCase()
  5390. ;
  5391. if(firstLetter == matchedLetter) {
  5392. $nextValue = $choice;
  5393. return false;
  5394. }
  5395. })
  5396. ;
  5397. if($nextValue) {
  5398. module.verbose('Scrolling to next value with letter', letter);
  5399. module.set.scrollPosition($nextValue);
  5400. $selectedItem.removeClass(className.selected);
  5401. $nextValue.addClass(className.selected);
  5402. }
  5403. },
  5404. direction: function($menu) {
  5405. if(settings.direction == 'auto') {
  5406. if(module.is.onScreen($menu)) {
  5407. module.remove.upward($menu);
  5408. }
  5409. else {
  5410. module.set.upward($menu);
  5411. }
  5412. }
  5413. else if(settings.direction == 'upward') {
  5414. module.set.upward($menu);
  5415. }
  5416. },
  5417. upward: function($menu) {
  5418. var $element = $menu || $module;
  5419. $element.addClass(className.upward);
  5420. },
  5421. value: function(value, text, $selected) {
  5422. var
  5423. hasInput = ($input.length > 0),
  5424. isAddition = !module.has.value(value),
  5425. currentValue = module.get.values(),
  5426. stringValue = (typeof value == 'number')
  5427. ? value.toString()
  5428. : value,
  5429. newValue
  5430. ;
  5431. if(hasInput) {
  5432. if(stringValue == currentValue) {
  5433. module.verbose('Skipping value update already same value', value, currentValue);
  5434. if(!module.is.initialLoad()) {
  5435. return;
  5436. }
  5437. }
  5438. module.debug('Updating input value', value, currentValue);
  5439. $input
  5440. .val(value)
  5441. .trigger('change')
  5442. ;
  5443. }
  5444. else {
  5445. module.verbose('Storing value in metadata', value, $input);
  5446. if(value !== currentValue) {
  5447. $module.data(metadata.value, value);
  5448. }
  5449. }
  5450. if(settings.fireOnInit === false && module.is.initialLoad()) {
  5451. module.verbose('No callback on initial load', settings.onChange);
  5452. }
  5453. else {
  5454. settings.onChange.call(element, value, text, $selected);
  5455. }
  5456. },
  5457. active: function() {
  5458. $module
  5459. .addClass(className.active)
  5460. ;
  5461. },
  5462. multiple: function() {
  5463. $module.addClass(className.multiple);
  5464. },
  5465. visible: function() {
  5466. $module.addClass(className.visible);
  5467. },
  5468. selected: function(value, $selectedItem) {
  5469. var
  5470. isMultiple = module.is.multiple(),
  5471. $userSelectedItem
  5472. ;
  5473. $selectedItem = (settings.allowAdditions)
  5474. ? $selectedItem || module.get.itemWithAdditions(value)
  5475. : $selectedItem || module.get.item(value)
  5476. ;
  5477. if(!$selectedItem) {
  5478. return;
  5479. }
  5480. module.debug('Setting selected menu item to', $selectedItem);
  5481. if(module.is.single()) {
  5482. module.remove.activeItem();
  5483. module.remove.selectedItem();
  5484. }
  5485. else if(settings.useLabels) {
  5486. module.remove.selectedItem();
  5487. }
  5488. // select each item
  5489. $selectedItem
  5490. .each(function() {
  5491. var
  5492. $selected = $(this),
  5493. selectedText = module.get.choiceText($selected),
  5494. selectedValue = module.get.choiceValue($selected, selectedText),
  5495. isFiltered = $selected.hasClass(className.filtered),
  5496. isActive = $selected.hasClass(className.active),
  5497. isUserValue = $selected.hasClass(className.addition),
  5498. shouldAnimate = (isMultiple && $selectedItem.length == 1)
  5499. ;
  5500. if(isMultiple) {
  5501. if(!isActive || isUserValue) {
  5502. if(settings.apiSettings && settings.saveRemoteData) {
  5503. module.save.remoteData(selectedText, selectedValue);
  5504. }
  5505. if(settings.useLabels) {
  5506. module.add.value(selectedValue, selectedText, $selected);
  5507. module.add.label(selectedValue, selectedText, shouldAnimate);
  5508. $selected.addClass(className.active);
  5509. module.filterActive();
  5510. module.select.nextAvailable($selectedItem);
  5511. }
  5512. else {
  5513. module.add.value(selectedValue, selectedText, $selected);
  5514. module.set.text(module.add.variables(message.count));
  5515. $selected.addClass(className.active);
  5516. }
  5517. }
  5518. else if(!isFiltered) {
  5519. module.debug('Selected active value, removing label');
  5520. module.remove.selected(selectedValue);
  5521. }
  5522. }
  5523. else {
  5524. if(settings.apiSettings && settings.saveRemoteData) {
  5525. module.save.remoteData(selectedText, selectedValue);
  5526. }
  5527. module.set.value(selectedValue, selectedText, $selected);
  5528. module.set.text(selectedText);
  5529. $selected
  5530. .addClass(className.active)
  5531. .addClass(className.selected)
  5532. ;
  5533. }
  5534. })
  5535. ;
  5536. }
  5537. },
  5538. add: {
  5539. label: function(value, text, shouldAnimate) {
  5540. var
  5541. $next = module.is.searchSelection()
  5542. ? $search
  5543. : $text,
  5544. $label
  5545. ;
  5546. $label = $('<a />')
  5547. .addClass(className.label)
  5548. .attr('data-value', value)
  5549. .html(templates.label(value, text))
  5550. ;
  5551. $label = settings.onLabelCreate.call($label, value, text);
  5552. if(module.has.label(value)) {
  5553. module.debug('Label already exists, skipping', value);
  5554. return;
  5555. }
  5556. if(settings.label.variation) {
  5557. $label.addClass(settings.label.variation);
  5558. }
  5559. if(shouldAnimate === true) {
  5560. module.debug('Animating in label', $label);
  5561. $label
  5562. .addClass(className.hidden)
  5563. .insertBefore($next)
  5564. .transition(settings.label.transition, settings.label.duration)
  5565. ;
  5566. }
  5567. else {
  5568. module.debug('Adding selection label', $label);
  5569. $label
  5570. .insertBefore($next)
  5571. ;
  5572. }
  5573. },
  5574. message: function(message) {
  5575. var
  5576. $message = $menu.children(selector.message),
  5577. html = settings.templates.message(module.add.variables(message))
  5578. ;
  5579. if($message.length > 0) {
  5580. $message
  5581. .html(html)
  5582. ;
  5583. }
  5584. else {
  5585. $message = $('<div/>')
  5586. .html(html)
  5587. .addClass(className.message)
  5588. .appendTo($menu)
  5589. ;
  5590. }
  5591. },
  5592. optionValue: function(value) {
  5593. var
  5594. $option = $input.find('option[value="' + value + '"]'),
  5595. hasOption = ($option.length > 0)
  5596. ;
  5597. if(hasOption) {
  5598. return;
  5599. }
  5600. // temporarily disconnect observer
  5601. if(selectObserver) {
  5602. selectObserver.disconnect();
  5603. module.verbose('Temporarily disconnecting mutation observer', value);
  5604. }
  5605. $('<option/>')
  5606. .prop('value', value)
  5607. .html(value)
  5608. .appendTo($input)
  5609. ;
  5610. module.verbose('Adding user addition as an <option>', value);
  5611. if(selectObserver) {
  5612. selectObserver.observe($input[0], {
  5613. childList : true,
  5614. subtree : true
  5615. });
  5616. }
  5617. },
  5618. userSuggestion: function(value) {
  5619. var
  5620. $addition = $menu.children(selector.addition),
  5621. alreadyHasValue = module.get.item(value),
  5622. hasUserSuggestion = $addition.length > 0,
  5623. html
  5624. ;
  5625. if(module.has.maxSelections()) {
  5626. return;
  5627. }
  5628. if(value === '' || alreadyHasValue) {
  5629. $addition.remove();
  5630. return;
  5631. }
  5632. $item
  5633. .removeClass(className.selected)
  5634. ;
  5635. if(hasUserSuggestion) {
  5636. html = settings.templates.addition(value);
  5637. $addition
  5638. .html(html)
  5639. .data(metadata.value, value)
  5640. .removeClass(className.filtered)
  5641. .addClass(className.selected)
  5642. ;
  5643. module.verbose('Replacing user suggestion with new value', $addition);
  5644. }
  5645. else {
  5646. $addition = module.create.userChoice(value);
  5647. $addition
  5648. .prependTo($menu)
  5649. .addClass(className.selected)
  5650. ;
  5651. module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
  5652. }
  5653. },
  5654. variables: function(message) {
  5655. var
  5656. hasCount = (message.search('{count}') !== -1),
  5657. hasMaxCount = (message.search('{maxCount}') !== -1),
  5658. hasTerm = (message.search('{term}') !== -1),
  5659. values,
  5660. count,
  5661. query
  5662. ;
  5663. module.verbose('Adding templated variables to message', message);
  5664. if(hasCount) {
  5665. count = module.get.selectionCount();
  5666. message = message.replace('{count}', count);
  5667. }
  5668. if(hasMaxCount) {
  5669. count = module.get.selectionCount();
  5670. message = message.replace('{maxCount}', settings.maxSelections);
  5671. }
  5672. if(hasTerm) {
  5673. query = module.get.query();
  5674. message = message.replace('{term}', query);
  5675. }
  5676. return message;
  5677. },
  5678. value: function(addedValue, addedText, $selectedItem) {
  5679. var
  5680. currentValue = module.get.values(),
  5681. newValue
  5682. ;
  5683. if(addedValue === '') {
  5684. module.debug('Cannot select blank values from multiselect');
  5685. return;
  5686. }
  5687. // extend currently array
  5688. if($.isArray(currentValue)) {
  5689. newValue = currentValue.concat([addedValue]);
  5690. newValue = module.get.uniqueArray(newValue);
  5691. }
  5692. else {
  5693. newValue = [addedValue];
  5694. }
  5695. // add values
  5696. if( $input.is('select')) {
  5697. if(settings.allowAdditions) {
  5698. module.add.optionValue(addedValue);
  5699. module.debug('Adding value to select', addedValue, newValue, $input);
  5700. }
  5701. }
  5702. else {
  5703. newValue = newValue.join(settings.delimiter);
  5704. module.debug('Setting hidden input to delimited value', newValue, $input);
  5705. }
  5706. if(settings.fireOnInit === false && module.is.initialLoad()) {
  5707. module.verbose('No callback on initial load', settings.onAdd);
  5708. }
  5709. else {
  5710. settings.onAdd.call(element, addedValue, addedText, $selectedItem);
  5711. }
  5712. module.set.value(newValue, addedValue, addedText, $selectedItem);
  5713. module.check.maxSelections();
  5714. }
  5715. },
  5716. remove: {
  5717. active: function() {
  5718. $module.removeClass(className.active);
  5719. },
  5720. activeLabel: function() {
  5721. $module.find(selector.label).removeClass(className.active);
  5722. },
  5723. loading: function() {
  5724. $module.removeClass(className.loading);
  5725. },
  5726. initialLoad: function() {
  5727. initialLoad = false;
  5728. },
  5729. upward: function($menu) {
  5730. var $element = $menu || $module;
  5731. $element.removeClass(className.upward);
  5732. },
  5733. visible: function() {
  5734. $module.removeClass(className.visible);
  5735. },
  5736. activeItem: function() {
  5737. $item.removeClass(className.active);
  5738. },
  5739. filteredItem: function() {
  5740. if( module.has.maxSelections() ) {
  5741. return;
  5742. }
  5743. if(settings.useLabels) {
  5744. $item.not('.' + className.active).removeClass(className.filtered);
  5745. }
  5746. else {
  5747. $item.removeClass(className.filtered);
  5748. }
  5749. },
  5750. message: function() {
  5751. $menu.children(selector.message).remove();
  5752. },
  5753. searchTerm: function() {
  5754. module.verbose('Cleared search term');
  5755. $search.val('');
  5756. module.set.filtered();
  5757. },
  5758. selected: function(value, $selectedItem) {
  5759. $selectedItem = (settings.allowAdditions)
  5760. ? $selectedItem || module.get.itemWithAdditions(value)
  5761. : $selectedItem || module.get.item(value)
  5762. ;
  5763. if(!$selectedItem) {
  5764. return false;
  5765. }
  5766. $selectedItem
  5767. .each(function() {
  5768. var
  5769. $selected = $(this),
  5770. selectedText = module.get.choiceText($selected),
  5771. selectedValue = module.get.choiceValue($selected, selectedText)
  5772. ;
  5773. if(module.is.multiple()) {
  5774. if(settings.useLabels) {
  5775. module.remove.value(selectedValue, selectedText, $selected);
  5776. module.remove.label(selectedValue);
  5777. }
  5778. else {
  5779. module.remove.value(selectedValue, selectedText, $selected);
  5780. module.set.text(module.add.variables(message.count));
  5781. }
  5782. }
  5783. else {
  5784. module.remove.value(selectedValue, selectedText, $selected);
  5785. }
  5786. $selected
  5787. .removeClass(className.filtered)
  5788. .removeClass(className.active)
  5789. ;
  5790. if(settings.useLabels) {
  5791. $selected.removeClass(className.selected);
  5792. }
  5793. })
  5794. ;
  5795. },
  5796. selectedItem: function() {
  5797. $item.removeClass(className.selected);
  5798. },
  5799. value: function(removedValue, removedText, $removedItem) {
  5800. var
  5801. values = $input.val(),
  5802. newValue
  5803. ;
  5804. if( $input.is('select') ) {
  5805. module.verbose('Input is <select> removing selected option', removedValue);
  5806. newValue = module.remove.arrayValue(removedValue, values);
  5807. }
  5808. else {
  5809. module.verbose('Removing from delimited values', removedValue);
  5810. values = values.split(settings.delimiter);
  5811. newValue = module.remove.arrayValue(removedValue, values);
  5812. newValue = newValue.join(settings.delimiter);
  5813. }
  5814. if(settings.fireOnInit === false && module.is.initialLoad()) {
  5815. module.verbose('No callback on initial load', settings.onRemove);
  5816. }
  5817. else {
  5818. settings.onRemove.call(element, removedValue, removedText, $removedItem);
  5819. }
  5820. module.set.value(newValue, removedText, $removedItem);
  5821. module.check.maxSelections();
  5822. },
  5823. arrayValue: function(removedValue, values) {
  5824. values = $.grep(values, function(value){
  5825. return (removedValue != value);
  5826. });
  5827. module.verbose('Removed value from delimited string', removedValue, values);
  5828. return values;
  5829. },
  5830. label: function(value) {
  5831. var
  5832. $labels = $module.find(selector.label),
  5833. $removedLabel = $labels.filter('[data-value="' + value +'"]'),
  5834. labelCount = $labels.length,
  5835. isLastLabel = ($labels.index($removedLabel) + 1 == labelCount),
  5836. shouldAnimate = ( (!module.is.searchSelection() || !module.is.focusedOnSearch()) && isLastLabel)
  5837. ;
  5838. if(shouldAnimate) {
  5839. module.verbose('Animating and removing label', $removedLabel);
  5840. $removedLabel
  5841. .transition(settings.label.transition, settings.label.duration, function() {
  5842. $removedLabel.remove();
  5843. })
  5844. ;
  5845. }
  5846. else {
  5847. module.verbose('Removing label', $removedLabel);
  5848. $removedLabel.remove();
  5849. }
  5850. },
  5851. activeLabels: function($activeLabels) {
  5852. $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
  5853. module.verbose('Removing active label selections', $activeLabels);
  5854. module.remove.labels($activeLabels);
  5855. },
  5856. labels: function($labels) {
  5857. $labels = $labels || $module.find(selector.label);
  5858. module.verbose('Removing labels', $labels);
  5859. $labels
  5860. .each(function(){
  5861. var
  5862. value = $(this).data('value'),
  5863. isUserValue = module.is.userValue(value)
  5864. ;
  5865. if(isUserValue) {
  5866. module.remove.value(value);
  5867. module.remove.label(value);
  5868. }
  5869. else {
  5870. // selected will also remove label
  5871. module.remove.selected(value);
  5872. }
  5873. })
  5874. ;
  5875. },
  5876. tabbable: function() {
  5877. if( module.has.search() ) {
  5878. module.debug('Searchable dropdown initialized');
  5879. $search
  5880. .attr('tabindex', '-1')
  5881. ;
  5882. $menu
  5883. .attr('tabindex', '-1')
  5884. ;
  5885. }
  5886. else {
  5887. module.debug('Simple selection dropdown initialized');
  5888. $module
  5889. .attr('tabindex', '-1')
  5890. ;
  5891. $menu
  5892. .attr('tabindex', '-1')
  5893. ;
  5894. }
  5895. }
  5896. },
  5897. has: {
  5898. search: function() {
  5899. return ($search.length > 0);
  5900. },
  5901. input: function() {
  5902. return ($input.length > 0);
  5903. },
  5904. menu: function() {
  5905. return ($menu.length > 0);
  5906. },
  5907. message: function() {
  5908. return ($menu.children(selector.message).length !== 0);
  5909. },
  5910. label: function(value) {
  5911. var
  5912. $labels = $module.find(selector.label)
  5913. ;
  5914. return ($labels.filter('[data-value="' + value +'"]').length > 0);
  5915. },
  5916. maxSelections: function() {
  5917. return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
  5918. },
  5919. allResultsFiltered: function() {
  5920. return ($item.filter(selector.unselectable).length === $item.length);
  5921. },
  5922. value: function(value) {
  5923. var
  5924. values = module.get.values(),
  5925. hasValue = $.isArray(values)
  5926. ? values && ($.inArray(value, values) !== -1)
  5927. : (values == value)
  5928. ;
  5929. return (hasValue)
  5930. ? true
  5931. : false
  5932. ;
  5933. }
  5934. },
  5935. is: {
  5936. active: function() {
  5937. return $module.hasClass(className.active);
  5938. },
  5939. alreadySetup: function() {
  5940. return ($module.is('select') && $module.parent(selector.dropdown).length > 0 && $module.prev().length === 0);
  5941. },
  5942. animating: function($subMenu) {
  5943. return ($subMenu)
  5944. ? $subMenu.transition && $subMenu.transition('is animating')
  5945. : $menu.transition && $menu.transition('is animating')
  5946. ;
  5947. },
  5948. focused: function() {
  5949. return (document.activeElement === $module[0]);
  5950. },
  5951. focusedOnSearch: function() {
  5952. return (document.activeElement === $search[0]);
  5953. },
  5954. allFiltered: function() {
  5955. return( (module.is.multiple() || module.has.search()) && !module.has.message() && module.has.allResultsFiltered() );
  5956. },
  5957. hidden: function($subMenu) {
  5958. return !module.is.visible($subMenu);
  5959. },
  5960. initialLoad: function() {
  5961. return initialLoad;
  5962. },
  5963. onScreen: function($subMenu) {
  5964. var
  5965. $currentMenu = $subMenu || $menu,
  5966. canOpenDownward = true,
  5967. onScreen = {},
  5968. calculations
  5969. ;
  5970. $currentMenu.addClass(className.loading);
  5971. calculations = {
  5972. context: {
  5973. scrollTop : $context.scrollTop(),
  5974. height : $context.outerHeight()
  5975. },
  5976. menu : {
  5977. offset: $currentMenu.offset(),
  5978. height: $currentMenu.outerHeight()
  5979. }
  5980. };
  5981. onScreen = {
  5982. above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.menu.height,
  5983. below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top + calculations.menu.height
  5984. };
  5985. if(onScreen.below) {
  5986. module.verbose('Dropdown can fit in context downward', onScreen);
  5987. canOpenDownward = true;
  5988. }
  5989. else if(!onScreen.below && !onScreen.above) {
  5990. module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
  5991. canOpenDownward = true;
  5992. }
  5993. else {
  5994. module.verbose('Dropdown cannot fit below, opening upward', onScreen);
  5995. canOpenDownward = false;
  5996. }
  5997. $currentMenu.removeClass(className.loading);
  5998. return canOpenDownward;
  5999. },
  6000. inObject: function(needle, object) {
  6001. var
  6002. found = false
  6003. ;
  6004. $.each(object, function(index, property) {
  6005. if(property == needle) {
  6006. found = true;
  6007. return true;
  6008. }
  6009. });
  6010. return found;
  6011. },
  6012. multiple: function() {
  6013. return $module.hasClass(className.multiple);
  6014. },
  6015. single: function() {
  6016. return !module.is.multiple();
  6017. },
  6018. selectMutation: function(mutations) {
  6019. var
  6020. selectChanged = false
  6021. ;
  6022. $.each(mutations, function(index, mutation) {
  6023. if(mutation.target && $(mutation.target).is('select')) {
  6024. selectChanged = true;
  6025. return true;
  6026. }
  6027. });
  6028. return selectChanged;
  6029. },
  6030. search: function() {
  6031. return $module.hasClass(className.search);
  6032. },
  6033. searchSelection: function() {
  6034. return ( module.has.search() && $search.closest(selector.menu).length === 0 );
  6035. },
  6036. selection: function() {
  6037. return $module.hasClass(className.selection);
  6038. },
  6039. userValue: function(value) {
  6040. return ($.inArray(value, module.get.userValues()) !== -1);
  6041. },
  6042. upward: function($menu) {
  6043. var $element = $menu || $module;
  6044. return $element.hasClass(className.upward);
  6045. },
  6046. visible: function($subMenu) {
  6047. return ($subMenu)
  6048. ? $subMenu.hasClass(className.visible)
  6049. : $menu.hasClass(className.visible)
  6050. ;
  6051. }
  6052. },
  6053. can: {
  6054. click: function() {
  6055. return (hasTouch || settings.on == 'click');
  6056. },
  6057. show: function() {
  6058. return !$module.hasClass(className.disabled) && $item.length > 0;
  6059. },
  6060. useAPI: function() {
  6061. return $.fn.api !== undefined;
  6062. }
  6063. },
  6064. animate: {
  6065. show: function(callback, $subMenu) {
  6066. var
  6067. $currentMenu = $subMenu || $menu,
  6068. start = ($subMenu)
  6069. ? function() {}
  6070. : function() {
  6071. module.hideSubMenus();
  6072. module.hideOthers();
  6073. module.set.active();
  6074. },
  6075. transition
  6076. ;
  6077. callback = $.isFunction(callback)
  6078. ? callback
  6079. : function(){}
  6080. ;
  6081. module.verbose('Doing menu show animation', $currentMenu);
  6082. module.set.direction($subMenu);
  6083. transition = module.get.transition($subMenu);
  6084. if( module.is.selection() ) {
  6085. module.set.scrollPosition(module.get.selectedItem(), true);
  6086. }
  6087. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  6088. if(transition == 'none') {
  6089. start();
  6090. $currentMenu.transition('show');
  6091. callback.call(element);
  6092. }
  6093. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  6094. $currentMenu
  6095. .transition({
  6096. animation : transition + ' in',
  6097. debug : settings.debug,
  6098. verbose : settings.verbose,
  6099. duration : settings.duration,
  6100. queue : true,
  6101. onStart : start,
  6102. onComplete : function() {
  6103. callback.call(element);
  6104. }
  6105. })
  6106. ;
  6107. }
  6108. else {
  6109. module.error(error.noTransition, transition);
  6110. }
  6111. }
  6112. },
  6113. hide: function(callback, $subMenu) {
  6114. var
  6115. $currentMenu = $subMenu || $menu,
  6116. duration = ($subMenu)
  6117. ? (settings.duration * 0.9)
  6118. : settings.duration,
  6119. start = ($subMenu)
  6120. ? function() {}
  6121. : function() {
  6122. if( module.can.click() ) {
  6123. module.unbind.intent();
  6124. }
  6125. module.remove.active();
  6126. },
  6127. transition = module.get.transition($subMenu)
  6128. ;
  6129. callback = $.isFunction(callback)
  6130. ? callback
  6131. : function(){}
  6132. ;
  6133. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  6134. module.verbose('Doing menu hide animation', $currentMenu);
  6135. if(transition == 'none') {
  6136. start();
  6137. $currentMenu.transition('hide');
  6138. callback.call(element);
  6139. }
  6140. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  6141. $currentMenu
  6142. .transition({
  6143. animation : transition + ' out',
  6144. duration : settings.duration,
  6145. debug : settings.debug,
  6146. verbose : settings.verbose,
  6147. queue : true,
  6148. onStart : start,
  6149. onComplete : function() {
  6150. if(settings.direction == 'auto') {
  6151. module.remove.upward($subMenu);
  6152. }
  6153. callback.call(element);
  6154. }
  6155. })
  6156. ;
  6157. }
  6158. else {
  6159. module.error(error.transition);
  6160. }
  6161. }
  6162. }
  6163. },
  6164. hideAndClear: function() {
  6165. if(module.has.search()) {
  6166. module.remove.searchTerm();
  6167. module.hide(function() {
  6168. module.remove.filteredItem();
  6169. });
  6170. }
  6171. else {
  6172. module.hide();
  6173. }
  6174. },
  6175. delay: {
  6176. show: function() {
  6177. module.verbose('Delaying show event to ensure user intent');
  6178. clearTimeout(module.timer);
  6179. module.timer = setTimeout(module.show, settings.delay.show);
  6180. },
  6181. hide: function() {
  6182. module.verbose('Delaying hide event to ensure user intent');
  6183. clearTimeout(module.timer);
  6184. module.timer = setTimeout(module.hide, settings.delay.hide);
  6185. }
  6186. },
  6187. escape: {
  6188. regExp: function(text) {
  6189. text = String(text);
  6190. return text.replace(regExp.escape, '\\$&');
  6191. }
  6192. },
  6193. setting: function(name, value) {
  6194. module.debug('Changing setting', name, value);
  6195. if( $.isPlainObject(name) ) {
  6196. $.extend(true, settings, name);
  6197. }
  6198. else if(value !== undefined) {
  6199. settings[name] = value;
  6200. }
  6201. else {
  6202. return settings[name];
  6203. }
  6204. },
  6205. internal: function(name, value) {
  6206. if( $.isPlainObject(name) ) {
  6207. $.extend(true, module, name);
  6208. }
  6209. else if(value !== undefined) {
  6210. module[name] = value;
  6211. }
  6212. else {
  6213. return module[name];
  6214. }
  6215. },
  6216. debug: function() {
  6217. if(settings.debug) {
  6218. if(settings.performance) {
  6219. module.performance.log(arguments);
  6220. }
  6221. else {
  6222. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  6223. module.debug.apply(console, arguments);
  6224. }
  6225. }
  6226. },
  6227. verbose: function() {
  6228. if(settings.verbose && settings.debug) {
  6229. if(settings.performance) {
  6230. module.performance.log(arguments);
  6231. }
  6232. else {
  6233. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  6234. module.verbose.apply(console, arguments);
  6235. }
  6236. }
  6237. },
  6238. error: function() {
  6239. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  6240. module.error.apply(console, arguments);
  6241. },
  6242. performance: {
  6243. log: function(message) {
  6244. var
  6245. currentTime,
  6246. executionTime,
  6247. previousTime
  6248. ;
  6249. if(settings.performance) {
  6250. currentTime = new Date().getTime();
  6251. previousTime = time || currentTime;
  6252. executionTime = currentTime - previousTime;
  6253. time = currentTime;
  6254. performance.push({
  6255. 'Name' : message[0],
  6256. 'Arguments' : [].slice.call(message, 1) || '',
  6257. 'Element' : element,
  6258. 'Execution Time' : executionTime
  6259. });
  6260. }
  6261. clearTimeout(module.performance.timer);
  6262. module.performance.timer = setTimeout(module.performance.display, 500);
  6263. },
  6264. display: function() {
  6265. var
  6266. title = settings.name + ':',
  6267. totalTime = 0
  6268. ;
  6269. time = false;
  6270. clearTimeout(module.performance.timer);
  6271. $.each(performance, function(index, data) {
  6272. totalTime += data['Execution Time'];
  6273. });
  6274. title += ' ' + totalTime + 'ms';
  6275. if(moduleSelector) {
  6276. title += ' \'' + moduleSelector + '\'';
  6277. }
  6278. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  6279. console.groupCollapsed(title);
  6280. if(console.table) {
  6281. console.table(performance);
  6282. }
  6283. else {
  6284. $.each(performance, function(index, data) {
  6285. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  6286. });
  6287. }
  6288. console.groupEnd();
  6289. }
  6290. performance = [];
  6291. }
  6292. },
  6293. invoke: function(query, passedArguments, context) {
  6294. var
  6295. object = instance,
  6296. maxDepth,
  6297. found,
  6298. response
  6299. ;
  6300. passedArguments = passedArguments || queryArguments;
  6301. context = element || context;
  6302. if(typeof query == 'string' && object !== undefined) {
  6303. query = query.split(/[\. ]/);
  6304. maxDepth = query.length - 1;
  6305. $.each(query, function(depth, value) {
  6306. var camelCaseValue = (depth != maxDepth)
  6307. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  6308. : query
  6309. ;
  6310. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  6311. object = object[camelCaseValue];
  6312. }
  6313. else if( object[camelCaseValue] !== undefined ) {
  6314. found = object[camelCaseValue];
  6315. return false;
  6316. }
  6317. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  6318. object = object[value];
  6319. }
  6320. else if( object[value] !== undefined ) {
  6321. found = object[value];
  6322. return false;
  6323. }
  6324. else {
  6325. module.error(error.method, query);
  6326. return false;
  6327. }
  6328. });
  6329. }
  6330. if ( $.isFunction( found ) ) {
  6331. response = found.apply(context, passedArguments);
  6332. }
  6333. else if(found !== undefined) {
  6334. response = found;
  6335. }
  6336. if($.isArray(returnedValue)) {
  6337. returnedValue.push(response);
  6338. }
  6339. else if(returnedValue !== undefined) {
  6340. returnedValue = [returnedValue, response];
  6341. }
  6342. else if(response !== undefined) {
  6343. returnedValue = response;
  6344. }
  6345. return found;
  6346. }
  6347. };
  6348. if(methodInvoked) {
  6349. if(instance === undefined) {
  6350. module.initialize();
  6351. }
  6352. module.invoke(query);
  6353. }
  6354. else {
  6355. if(instance !== undefined) {
  6356. instance.invoke('destroy');
  6357. }
  6358. module.initialize();
  6359. }
  6360. })
  6361. ;
  6362. return (returnedValue !== undefined)
  6363. ? returnedValue
  6364. : $allModules
  6365. ;
  6366. };
  6367. $.fn.dropdown.settings = {
  6368. debug : false,
  6369. verbose : false,
  6370. performance : true,
  6371. on : 'click', // what event should show menu action on item selection
  6372. action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
  6373. apiSettings : false,
  6374. saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
  6375. throttle : 200, // How long to wait after last user input to search remotely
  6376. context : window, // Context to use when determining if on screen
  6377. direction : 'auto', // Whether dropdown should always open in one direction
  6378. keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
  6379. match : 'both', // what to match against with search selection (both, text, or label)
  6380. fullTextSearch : false, // search anywhere in value
  6381. placeholder : 'auto', // whether to convert blank <select> values to placeholder text
  6382. preserveHTML : true, // preserve html when selecting value
  6383. sortSelect : false, // sort selection on init
  6384. forceSelection : true, // force a choice on blur with search selection
  6385. allowAdditions : false, // whether multiple select should allow user added values
  6386. maxSelections : false, // When set to a number limits the number of selections to this count
  6387. useLabels : true, // whether multiple select should filter currently active selections from choices
  6388. delimiter : ',', // when multiselect uses normal <input> the values will be delmited with this character
  6389. showOnFocus : true, // show menu on focus
  6390. allowTab : true, // add tabindex to element
  6391. allowCategorySelection : false, // allow elements with sub-menus to be selected
  6392. fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
  6393. transition : 'auto', // auto transition will slide down or up based on direction
  6394. duration : 200, // duration of transition
  6395. glyphWidth : 1.0714, // widest glyph width in em (W is 1.0714 em) used to calculate multiselect input width
  6396. // label settings on multi-select
  6397. label: {
  6398. transition : 'scale',
  6399. duration : 200,
  6400. variation : false
  6401. },
  6402. // delay before event
  6403. delay : {
  6404. hide : 300,
  6405. show : 200,
  6406. search : 20,
  6407. touch : 50
  6408. },
  6409. /* Callbacks */
  6410. onChange : function(value, text, $selected){},
  6411. onAdd : function(value, text, $selected){},
  6412. onRemove : function(value, text, $selected){},
  6413. onLabelSelect : function($selectedLabels){},
  6414. onLabelCreate : function(value, text) { return $(this); },
  6415. onNoResults : function(searchTerm) { return true; },
  6416. onShow : function(){},
  6417. onHide : function(){},
  6418. /* Component */
  6419. name : 'Dropdown',
  6420. namespace : 'dropdown',
  6421. message: {
  6422. addResult : 'Add <b>{term}</b>',
  6423. count : '{count} selected',
  6424. maxSelections : 'Max {maxCount} selections',
  6425. noResults : 'No results found.',
  6426. serverError : 'There was an error contacting the server'
  6427. },
  6428. error : {
  6429. action : 'You called a dropdown action that was not defined',
  6430. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  6431. labels : 'Allowing user additions currently requires the use of labels.',
  6432. method : 'The method you called is not defined.',
  6433. noAPI : 'The API module is required to load resources remotely',
  6434. noStorage : 'Saving remote data requires session storage',
  6435. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>'
  6436. },
  6437. regExp : {
  6438. escape : /[-[\]{}()*+?.,\\^$|#\s]/g,
  6439. },
  6440. metadata : {
  6441. defaultText : 'defaultText',
  6442. defaultValue : 'defaultValue',
  6443. placeholderText : 'placeholder',
  6444. text : 'text',
  6445. value : 'value'
  6446. },
  6447. selector : {
  6448. addition : '.addition',
  6449. dropdown : '.ui.dropdown',
  6450. icon : '> .dropdown.icon',
  6451. input : '> input[type="hidden"], > select',
  6452. item : '.item',
  6453. label : '> .label',
  6454. remove : '> .label > .delete.icon',
  6455. siblingLabel : '.label',
  6456. menu : '.menu',
  6457. message : '.message',
  6458. menuIcon : '.dropdown.icon',
  6459. search : 'input.search, .menu > .search > input',
  6460. text : '> .text:not(.icon)',
  6461. unselectable : '.disabled, .filtered'
  6462. },
  6463. className : {
  6464. active : 'active',
  6465. addition : 'addition',
  6466. animating : 'animating',
  6467. disabled : 'disabled',
  6468. dropdown : 'ui dropdown',
  6469. filtered : 'filtered',
  6470. hidden : 'hidden transition',
  6471. item : 'item',
  6472. label : 'ui label',
  6473. loading : 'loading',
  6474. menu : 'menu',
  6475. message : 'message',
  6476. multiple : 'multiple',
  6477. placeholder : 'default',
  6478. search : 'search',
  6479. selected : 'selected',
  6480. selection : 'selection',
  6481. upward : 'upward',
  6482. visible : 'visible'
  6483. }
  6484. };
  6485. /* Templates */
  6486. $.fn.dropdown.settings.templates = {
  6487. // generates dropdown from select values
  6488. dropdown: function(select) {
  6489. var
  6490. placeholder = select.placeholder || false,
  6491. values = select.values || {},
  6492. html = ''
  6493. ;
  6494. html += '<i class="dropdown icon"></i>';
  6495. if(select.placeholder) {
  6496. html += '<div class="default text">' + placeholder + '</div>';
  6497. }
  6498. else {
  6499. html += '<div class="text"></div>';
  6500. }
  6501. html += '<div class="menu">';
  6502. $.each(select.values, function(index, option) {
  6503. html += (option.disabled)
  6504. ? '<div class="disabled item" data-value="' + option.value + '">' + option.name + '</div>'
  6505. : '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'
  6506. ;
  6507. });
  6508. html += '</div>';
  6509. return html;
  6510. },
  6511. // generates just menu from select
  6512. menu: function(response) {
  6513. var
  6514. values = response.values || {},
  6515. html = ''
  6516. ;
  6517. $.each(response.values, function(index, option) {
  6518. html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>';
  6519. });
  6520. return html;
  6521. },
  6522. // generates label for multiselect
  6523. label: function(value, text) {
  6524. return text + '<i class="delete icon"></i>';
  6525. },
  6526. // generates messages like "No results"
  6527. message: function(message) {
  6528. return message;
  6529. },
  6530. // generates user addition to selection menu
  6531. addition: function(choice) {
  6532. return choice;
  6533. }
  6534. };
  6535. })( jQuery, window , document );
  6536. /*!
  6537. * # Semantic UI 2.0.0 - Video
  6538. * http://github.com/semantic-org/semantic-ui/
  6539. *
  6540. *
  6541. * Copyright 2015 Contributors
  6542. * Released under the MIT license
  6543. * http://opensource.org/licenses/MIT
  6544. *
  6545. */
  6546. ;(function ($, window, document, undefined) {
  6547. "use strict";
  6548. $.fn.embed = function(parameters) {
  6549. var
  6550. $allModules = $(this),
  6551. moduleSelector = $allModules.selector || '',
  6552. time = new Date().getTime(),
  6553. performance = [],
  6554. query = arguments[0],
  6555. methodInvoked = (typeof query == 'string'),
  6556. queryArguments = [].slice.call(arguments, 1),
  6557. returnedValue
  6558. ;
  6559. $allModules
  6560. .each(function() {
  6561. var
  6562. settings = ( $.isPlainObject(parameters) )
  6563. ? $.extend(true, {}, $.fn.embed.settings, parameters)
  6564. : $.extend({}, $.fn.embed.settings),
  6565. selector = settings.selector,
  6566. className = settings.className,
  6567. sources = settings.sources,
  6568. error = settings.error,
  6569. metadata = settings.metadata,
  6570. namespace = settings.namespace,
  6571. templates = settings.templates,
  6572. eventNamespace = '.' + namespace,
  6573. moduleNamespace = 'module-' + namespace,
  6574. $window = $(window),
  6575. $module = $(this),
  6576. $placeholder = $module.find(selector.placeholder),
  6577. $icon = $module.find(selector.icon),
  6578. $embed = $module.find(selector.embed),
  6579. element = this,
  6580. instance = $module.data(moduleNamespace),
  6581. module
  6582. ;
  6583. module = {
  6584. initialize: function() {
  6585. module.debug('Initializing embed');
  6586. module.determine.autoplay();
  6587. module.create();
  6588. module.bind.events();
  6589. module.instantiate();
  6590. },
  6591. instantiate: function() {
  6592. module.verbose('Storing instance of module', module);
  6593. instance = module;
  6594. $module
  6595. .data(moduleNamespace, module)
  6596. ;
  6597. },
  6598. destroy: function() {
  6599. module.verbose('Destroying previous instance of embed');
  6600. module.reset();
  6601. $module
  6602. .removeData(moduleNamespace)
  6603. .off(eventNamespace)
  6604. ;
  6605. },
  6606. refresh: function() {
  6607. module.verbose('Refreshing selector cache');
  6608. $placeholder = $module.find(selector.placeholder);
  6609. $icon = $module.find(selector.icon);
  6610. $embed = $module.find(selector.embed);
  6611. },
  6612. bind: {
  6613. events: function() {
  6614. if( module.has.placeholder() ) {
  6615. module.debug('Adding placeholder events');
  6616. console.log($module, selector.placeholder);
  6617. $module
  6618. .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
  6619. .on('click' + eventNamespace, selector.icon, module.createAndShow)
  6620. ;
  6621. }
  6622. }
  6623. },
  6624. create: function() {
  6625. var
  6626. placeholder = module.get.placeholder()
  6627. ;
  6628. if(placeholder) {
  6629. module.createPlaceholder();
  6630. }
  6631. else {
  6632. module.createAndShow();
  6633. }
  6634. },
  6635. createPlaceholder: function(placeholder) {
  6636. var
  6637. icon = module.get.icon(),
  6638. url = module.get.url(),
  6639. embed = module.generate.embed(url)
  6640. ;
  6641. placeholder = placeholder || module.get.placeholder();
  6642. $module.html( templates.placeholder(placeholder, icon) );
  6643. module.debug('Creating placeholder for embed', placeholder, icon);
  6644. },
  6645. createEmbed: function(url) {
  6646. module.refresh();
  6647. url = url || module.get.url();
  6648. console.log(url);
  6649. $embed = $('<div/>')
  6650. .addClass(className.embed)
  6651. .html( module.generate.embed(url) )
  6652. .appendTo($module)
  6653. ;
  6654. settings.onCreate.call(element, url);
  6655. module.debug('Creating embed object', $embed);
  6656. },
  6657. createAndShow: function() {
  6658. console.log('cands');
  6659. module.createEmbed();
  6660. module.show();
  6661. },
  6662. // sets new embed
  6663. change: function(source, id, url) {
  6664. module.debug('Changing video to ', source, id, url);
  6665. $module
  6666. .data(metadata.source, source)
  6667. .data(metadata.id, id)
  6668. .data(metadata.url, url)
  6669. ;
  6670. module.create();
  6671. },
  6672. // clears embed
  6673. reset: function() {
  6674. module.debug('Clearing embed and showing placeholder');
  6675. module.remove.active();
  6676. module.remove.embed();
  6677. module.showPlaceholder();
  6678. settings.onReset.call(element);
  6679. },
  6680. // shows current embed
  6681. show: function() {
  6682. module.debug('Showing embed');
  6683. module.set.active();
  6684. settings.onDisplay.call(element);
  6685. },
  6686. hide: function() {
  6687. module.debug('Hiding embed');
  6688. module.showPlaceholder();
  6689. },
  6690. showPlaceholder: function() {
  6691. module.debug('Showing placeholder image');
  6692. module.remove.active();
  6693. settings.onPlaceholderDisplay.call(element);
  6694. },
  6695. get: {
  6696. id: function() {
  6697. return settings.id || $module.data(metadata.id);
  6698. },
  6699. placeholder: function() {
  6700. return settings.placeholder || $module.data(metadata.placeholder);
  6701. },
  6702. icon: function() {
  6703. return (settings.icon)
  6704. ? settings.icon
  6705. : ($module.data(metadata.icon) !== undefined)
  6706. ? $module.data(metadata.icon)
  6707. : module.determine.icon()
  6708. ;
  6709. },
  6710. source: function(url) {
  6711. return (settings.source)
  6712. ? settings.source
  6713. : ($module.data(metadata.source) !== undefined)
  6714. ? $module.data(metadata.source)
  6715. : module.determine.source()
  6716. ;
  6717. },
  6718. type: function() {
  6719. var source = module.get.source();
  6720. return (sources[source] !== undefined)
  6721. ? sources[source].type
  6722. : false
  6723. ;
  6724. },
  6725. url: function() {
  6726. return (settings.url)
  6727. ? settings.url
  6728. : ($module.data(metadata.url) !== undefined)
  6729. ? $module.data(metadata.url)
  6730. : module.determine.url()
  6731. ;
  6732. }
  6733. },
  6734. determine: {
  6735. autoplay: function() {
  6736. if(module.should.autoplay()) {
  6737. settings.autoplay = true;
  6738. }
  6739. },
  6740. source: function(url) {
  6741. var
  6742. matchedSource = false
  6743. ;
  6744. url = url || module.get.url();
  6745. if(url) {
  6746. $.each(sources, function(name, source) {
  6747. if(url.search(source.domain) !== -1) {
  6748. matchedSource = name;
  6749. return false;
  6750. }
  6751. });
  6752. }
  6753. return matchedSource;
  6754. },
  6755. icon: function() {
  6756. var
  6757. source = module.get.source()
  6758. ;
  6759. return (sources[source] !== undefined)
  6760. ? sources[source].icon
  6761. : false
  6762. ;
  6763. },
  6764. url: function() {
  6765. var
  6766. id = settings.id || $module.data(metadata.id),
  6767. source = settings.source || $module.data(metadata.source),
  6768. url
  6769. ;
  6770. url = (sources[source] !== undefined)
  6771. ? sources[source].url.replace('{id}', id)
  6772. : false
  6773. ;
  6774. if(url) {
  6775. $module.data(metadata.url, url);
  6776. }
  6777. return url;
  6778. }
  6779. },
  6780. set: {
  6781. active: function() {
  6782. $module.addClass(className.active);
  6783. }
  6784. },
  6785. remove: {
  6786. active: function() {
  6787. $module.removeClass(className.active);
  6788. },
  6789. embed: function() {
  6790. $embed.empty();
  6791. }
  6792. },
  6793. encode: {
  6794. parameters: function(parameters) {
  6795. var
  6796. urlString = [],
  6797. index
  6798. ;
  6799. for (index in parameters) {
  6800. urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
  6801. }
  6802. return urlString.join('&amp;');
  6803. }
  6804. },
  6805. generate: {
  6806. embed: function(url) {
  6807. module.debug('Generating embed html');
  6808. var
  6809. source = module.get.source(),
  6810. html,
  6811. parameters
  6812. ;
  6813. url = module.get.url(url);
  6814. if(url) {
  6815. parameters = module.generate.parameters(source);
  6816. html = templates.iframe(url, parameters);
  6817. }
  6818. else {
  6819. module.error(error.noURL, $module);
  6820. }
  6821. return html;
  6822. },
  6823. parameters: function(source, extraParameters) {
  6824. var
  6825. parameters = (sources[source] && sources[source].parameters !== undefined)
  6826. ? sources[source].parameters(settings)
  6827. : {}
  6828. ;
  6829. extraParameters = extraParameters || settings.parameters;
  6830. if(extraParameters) {
  6831. parameters = $.extend({}, parameters, extraParameters);
  6832. }
  6833. parameters = settings.onEmbed(parameters);
  6834. return module.encode.parameters(parameters);
  6835. }
  6836. },
  6837. has: {
  6838. placeholder: function() {
  6839. return settings.placeholder || $module.data(metadata.placeholder);
  6840. }
  6841. },
  6842. should: {
  6843. autoplay: function() {
  6844. return (settings.autoplay === 'auto')
  6845. ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
  6846. : settings.autoplay
  6847. ;
  6848. }
  6849. },
  6850. is: {
  6851. video: function() {
  6852. return module.get.type() == 'video';
  6853. }
  6854. },
  6855. setting: function(name, value) {
  6856. module.debug('Changing setting', name, value);
  6857. if( $.isPlainObject(name) ) {
  6858. $.extend(true, settings, name);
  6859. }
  6860. else if(value !== undefined) {
  6861. settings[name] = value;
  6862. }
  6863. else {
  6864. return settings[name];
  6865. }
  6866. },
  6867. internal: function(name, value) {
  6868. if( $.isPlainObject(name) ) {
  6869. $.extend(true, module, name);
  6870. }
  6871. else if(value !== undefined) {
  6872. module[name] = value;
  6873. }
  6874. else {
  6875. return module[name];
  6876. }
  6877. },
  6878. debug: function() {
  6879. if(settings.debug) {
  6880. if(settings.performance) {
  6881. module.performance.log(arguments);
  6882. }
  6883. else {
  6884. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  6885. module.debug.apply(console, arguments);
  6886. }
  6887. }
  6888. },
  6889. verbose: function() {
  6890. if(settings.verbose && settings.debug) {
  6891. if(settings.performance) {
  6892. module.performance.log(arguments);
  6893. }
  6894. else {
  6895. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  6896. module.verbose.apply(console, arguments);
  6897. }
  6898. }
  6899. },
  6900. error: function() {
  6901. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  6902. module.error.apply(console, arguments);
  6903. },
  6904. performance: {
  6905. log: function(message) {
  6906. var
  6907. currentTime,
  6908. executionTime,
  6909. previousTime
  6910. ;
  6911. if(settings.performance) {
  6912. currentTime = new Date().getTime();
  6913. previousTime = time || currentTime;
  6914. executionTime = currentTime - previousTime;
  6915. time = currentTime;
  6916. performance.push({
  6917. 'Name' : message[0],
  6918. 'Arguments' : [].slice.call(message, 1) || '',
  6919. 'Element' : element,
  6920. 'Execution Time' : executionTime
  6921. });
  6922. }
  6923. clearTimeout(module.performance.timer);
  6924. module.performance.timer = setTimeout(module.performance.display, 500);
  6925. },
  6926. display: function() {
  6927. var
  6928. title = settings.name + ':',
  6929. totalTime = 0
  6930. ;
  6931. time = false;
  6932. clearTimeout(module.performance.timer);
  6933. $.each(performance, function(index, data) {
  6934. totalTime += data['Execution Time'];
  6935. });
  6936. title += ' ' + totalTime + 'ms';
  6937. if(moduleSelector) {
  6938. title += ' \'' + moduleSelector + '\'';
  6939. }
  6940. if($allModules.length > 1) {
  6941. title += ' ' + '(' + $allModules.length + ')';
  6942. }
  6943. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  6944. console.groupCollapsed(title);
  6945. if(console.table) {
  6946. console.table(performance);
  6947. }
  6948. else {
  6949. $.each(performance, function(index, data) {
  6950. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  6951. });
  6952. }
  6953. console.groupEnd();
  6954. }
  6955. performance = [];
  6956. }
  6957. },
  6958. invoke: function(query, passedArguments, context) {
  6959. var
  6960. object = instance,
  6961. maxDepth,
  6962. found,
  6963. response
  6964. ;
  6965. passedArguments = passedArguments || queryArguments;
  6966. context = element || context;
  6967. if(typeof query == 'string' && object !== undefined) {
  6968. query = query.split(/[\. ]/);
  6969. maxDepth = query.length - 1;
  6970. $.each(query, function(depth, value) {
  6971. var camelCaseValue = (depth != maxDepth)
  6972. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  6973. : query
  6974. ;
  6975. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  6976. object = object[camelCaseValue];
  6977. }
  6978. else if( object[camelCaseValue] !== undefined ) {
  6979. found = object[camelCaseValue];
  6980. return false;
  6981. }
  6982. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  6983. object = object[value];
  6984. }
  6985. else if( object[value] !== undefined ) {
  6986. found = object[value];
  6987. return false;
  6988. }
  6989. else {
  6990. module.error(error.method, query);
  6991. return false;
  6992. }
  6993. });
  6994. }
  6995. if ( $.isFunction( found ) ) {
  6996. response = found.apply(context, passedArguments);
  6997. }
  6998. else if(found !== undefined) {
  6999. response = found;
  7000. }
  7001. if($.isArray(returnedValue)) {
  7002. returnedValue.push(response);
  7003. }
  7004. else if(returnedValue !== undefined) {
  7005. returnedValue = [returnedValue, response];
  7006. }
  7007. else if(response !== undefined) {
  7008. returnedValue = response;
  7009. }
  7010. return found;
  7011. }
  7012. };
  7013. if(methodInvoked) {
  7014. if(instance === undefined) {
  7015. module.initialize();
  7016. }
  7017. module.invoke(query);
  7018. }
  7019. else {
  7020. if(instance !== undefined) {
  7021. instance.invoke('destroy');
  7022. }
  7023. module.initialize();
  7024. }
  7025. })
  7026. ;
  7027. return (returnedValue !== undefined)
  7028. ? returnedValue
  7029. : this
  7030. ;
  7031. };
  7032. $.fn.embed.settings = {
  7033. name : 'Embed',
  7034. namespace : 'embed',
  7035. debug : false,
  7036. verbose : false,
  7037. performance : true,
  7038. icon : false,
  7039. source : false,
  7040. url : false,
  7041. id : false,
  7042. // standard video settings
  7043. autoplay : 'auto',
  7044. color : '#444444',
  7045. hd : true,
  7046. brandedUI : false,
  7047. // additional parameters to include with the embed
  7048. parameters: false,
  7049. onDisplay : function() {},
  7050. onPlaceholderDisplay : function() {},
  7051. onReset : function() {},
  7052. onCreate : function(url) {},
  7053. onEmbed : function(parameters) {
  7054. return parameters;
  7055. },
  7056. metadata : {
  7057. id : 'id',
  7058. icon : 'icon',
  7059. placeholder : 'placeholder',
  7060. source : 'source',
  7061. url : 'url'
  7062. },
  7063. error : {
  7064. noURL : 'No URL specified',
  7065. method : 'The method you called is not defined'
  7066. },
  7067. className : {
  7068. active : 'active',
  7069. embed : 'embed'
  7070. },
  7071. selector : {
  7072. embed : '.embed',
  7073. placeholder : '.placeholder',
  7074. icon : '.icon'
  7075. },
  7076. sources: {
  7077. youtube: {
  7078. name : 'youtube',
  7079. type : 'video',
  7080. icon : 'video play',
  7081. domain : 'youtube.com',
  7082. url : '//www.youtube.com/embed/{id}',
  7083. parameters: function(settings) {
  7084. return {
  7085. autohide : !settings.brandedUI,
  7086. autoplay : settings.autoplay,
  7087. color : settings.colors || undefined,
  7088. hq : settings.hd,
  7089. jsapi : settings.api,
  7090. modestbranding : !settings.brandedUI
  7091. };
  7092. }
  7093. },
  7094. vimeo: {
  7095. name : 'vimeo',
  7096. type : 'video',
  7097. icon : 'video play',
  7098. domain : 'vimeo.com',
  7099. url : '//player.vimeo.com/video/{id}',
  7100. parameters: function(settings) {
  7101. return {
  7102. api : settings.api,
  7103. autoplay : settings.autoplay,
  7104. byline : settings.brandedUI,
  7105. color : settings.colors || undefined,
  7106. portrait : settings.brandedUI,
  7107. title : settings.brandedUI
  7108. };
  7109. }
  7110. }
  7111. },
  7112. templates: {
  7113. iframe : function(url, parameters) {
  7114. return ''
  7115. + '<iframe src="' + url + '?=' + parameters + '"'
  7116. + ' width="100%" height="100%"'
  7117. + ' frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  7118. ;
  7119. },
  7120. placeholder : function(image, icon) {
  7121. var
  7122. html = ''
  7123. ;
  7124. if(icon) {
  7125. html += '<i class="' + icon + ' icon"></i>';
  7126. }
  7127. if(image) {
  7128. html += '<img class="placeholder" src="' + image + '">';
  7129. }
  7130. return html;
  7131. }
  7132. },
  7133. // NOT YET IMPLEMENTED
  7134. api : true,
  7135. onPause : function() {},
  7136. onPlay : function() {},
  7137. onStop : function() {}
  7138. };
  7139. })( jQuery, window , document );
  7140. /*!
  7141. * # Semantic UI 2.0.0 - Modal
  7142. * http://github.com/semantic-org/semantic-ui/
  7143. *
  7144. *
  7145. * Copyright 2015 Contributors
  7146. * Released under the MIT license
  7147. * http://opensource.org/licenses/MIT
  7148. *
  7149. */
  7150. ;(function ( $, window, document, undefined ) {
  7151. "use strict";
  7152. $.fn.modal = function(parameters) {
  7153. var
  7154. $allModules = $(this),
  7155. $window = $(window),
  7156. $document = $(document),
  7157. $body = $('body'),
  7158. moduleSelector = $allModules.selector || '',
  7159. time = new Date().getTime(),
  7160. performance = [],
  7161. query = arguments[0],
  7162. methodInvoked = (typeof query == 'string'),
  7163. queryArguments = [].slice.call(arguments, 1),
  7164. requestAnimationFrame = window.requestAnimationFrame
  7165. || window.mozRequestAnimationFrame
  7166. || window.webkitRequestAnimationFrame
  7167. || window.msRequestAnimationFrame
  7168. || function(callback) { setTimeout(callback, 0); },
  7169. returnedValue
  7170. ;
  7171. $allModules
  7172. .each(function() {
  7173. var
  7174. settings = ( $.isPlainObject(parameters) )
  7175. ? $.extend(true, {}, $.fn.modal.settings, parameters)
  7176. : $.extend({}, $.fn.modal.settings),
  7177. selector = settings.selector,
  7178. className = settings.className,
  7179. namespace = settings.namespace,
  7180. error = settings.error,
  7181. eventNamespace = '.' + namespace,
  7182. moduleNamespace = 'module-' + namespace,
  7183. $module = $(this),
  7184. $context = $(settings.context),
  7185. $close = $module.find(selector.close),
  7186. $allModals,
  7187. $otherModals,
  7188. $focusedElement,
  7189. $dimmable,
  7190. $dimmer,
  7191. element = this,
  7192. instance = $module.data(moduleNamespace),
  7193. elementNamespace,
  7194. id,
  7195. observer,
  7196. module
  7197. ;
  7198. module = {
  7199. initialize: function() {
  7200. module.verbose('Initializing dimmer', $context);
  7201. module.create.id();
  7202. module.create.dimmer();
  7203. module.refreshModals();
  7204. module.bind.events();
  7205. if(settings.observeChanges) {
  7206. module.observeChanges();
  7207. }
  7208. module.instantiate();
  7209. },
  7210. instantiate: function() {
  7211. module.verbose('Storing instance of modal');
  7212. instance = module;
  7213. $module
  7214. .data(moduleNamespace, instance)
  7215. ;
  7216. },
  7217. create: {
  7218. dimmer: function() {
  7219. var
  7220. defaultSettings = {
  7221. debug : settings.debug,
  7222. dimmerName : 'modals',
  7223. duration : {
  7224. show : settings.duration,
  7225. hide : settings.duration
  7226. }
  7227. },
  7228. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  7229. ;
  7230. if(settings.inverted) {
  7231. dimmerSettings.variation = (dimmerSettings.variation !== undefined)
  7232. ? dimmerSettings.variation + ' inverted'
  7233. : 'inverted'
  7234. ;
  7235. }
  7236. if($.fn.dimmer === undefined) {
  7237. module.error(error.dimmer);
  7238. return;
  7239. }
  7240. module.debug('Creating dimmer with settings', dimmerSettings);
  7241. $dimmable = $context.dimmer(dimmerSettings);
  7242. if(settings.detachable) {
  7243. module.verbose('Modal is detachable, moving content into dimmer');
  7244. $dimmable.dimmer('add content', $module);
  7245. }
  7246. else {
  7247. module.set.undetached();
  7248. }
  7249. if(settings.blurring) {
  7250. $dimmable.addClass(className.blurring);
  7251. }
  7252. $dimmer = $dimmable.dimmer('get dimmer');
  7253. },
  7254. id: function() {
  7255. id = (Math.random().toString(16) + '000000000').substr(2,8);
  7256. elementNamespace = '.' + id;
  7257. module.verbose('Creating unique id for element', id);
  7258. }
  7259. },
  7260. destroy: function() {
  7261. module.verbose('Destroying previous modal');
  7262. $module
  7263. .removeData(moduleNamespace)
  7264. .off(eventNamespace)
  7265. ;
  7266. $window.off(elementNamespace);
  7267. $close.off(eventNamespace);
  7268. $context.dimmer('destroy');
  7269. },
  7270. observeChanges: function() {
  7271. if('MutationObserver' in window) {
  7272. observer = new MutationObserver(function(mutations) {
  7273. module.debug('DOM tree modified, refreshing');
  7274. module.refresh();
  7275. });
  7276. observer.observe(element, {
  7277. childList : true,
  7278. subtree : true
  7279. });
  7280. module.debug('Setting up mutation observer', observer);
  7281. }
  7282. },
  7283. refresh: function() {
  7284. module.remove.scrolling();
  7285. module.cacheSizes();
  7286. module.set.screenHeight();
  7287. module.set.type();
  7288. module.set.position();
  7289. },
  7290. refreshModals: function() {
  7291. $otherModals = $module.siblings(selector.modal);
  7292. $allModals = $otherModals.add($module);
  7293. },
  7294. attachEvents: function(selector, event) {
  7295. var
  7296. $toggle = $(selector)
  7297. ;
  7298. event = $.isFunction(module[event])
  7299. ? module[event]
  7300. : module.toggle
  7301. ;
  7302. if($toggle.length > 0) {
  7303. module.debug('Attaching modal events to element', selector, event);
  7304. $toggle
  7305. .off(eventNamespace)
  7306. .on('click' + eventNamespace, event)
  7307. ;
  7308. }
  7309. else {
  7310. module.error(error.notFound, selector);
  7311. }
  7312. },
  7313. bind: {
  7314. events: function() {
  7315. module.verbose('Attaching events');
  7316. $module
  7317. .on('click' + eventNamespace, selector.close, module.event.close)
  7318. .on('click' + eventNamespace, selector.approve, module.event.approve)
  7319. .on('click' + eventNamespace, selector.deny, module.event.deny)
  7320. ;
  7321. $window
  7322. .on('resize' + elementNamespace, module.event.resize)
  7323. ;
  7324. }
  7325. },
  7326. get: {
  7327. id: function() {
  7328. return (Math.random().toString(16) + '000000000').substr(2,8);
  7329. }
  7330. },
  7331. event: {
  7332. approve: function() {
  7333. if(settings.onApprove.call(element, $(this)) === false) {
  7334. module.verbose('Approve callback returned false cancelling hide');
  7335. return;
  7336. }
  7337. module.hide();
  7338. },
  7339. deny: function() {
  7340. if(settings.onDeny.call(element, $(this)) === false) {
  7341. module.verbose('Deny callback returned false cancelling hide');
  7342. return;
  7343. }
  7344. module.hide();
  7345. },
  7346. close: function() {
  7347. module.hide();
  7348. },
  7349. click: function(event) {
  7350. var
  7351. $target = $(event.target),
  7352. isInModal = ($target.closest(selector.modal).length > 0),
  7353. isInDOM = $.contains(document.documentElement, event.target)
  7354. ;
  7355. if(!isInModal && isInDOM) {
  7356. module.debug('Dimmer clicked, hiding all modals');
  7357. if( module.is.active() ) {
  7358. module.remove.clickaway();
  7359. if(settings.allowMultiple) {
  7360. module.hide();
  7361. }
  7362. else {
  7363. module.hideAll();
  7364. }
  7365. }
  7366. }
  7367. },
  7368. debounce: function(method, delay) {
  7369. clearTimeout(module.timer);
  7370. module.timer = setTimeout(method, delay);
  7371. },
  7372. keyboard: function(event) {
  7373. var
  7374. keyCode = event.which,
  7375. escapeKey = 27
  7376. ;
  7377. if(keyCode == escapeKey) {
  7378. if(settings.closable) {
  7379. module.debug('Escape key pressed hiding modal');
  7380. module.hide();
  7381. }
  7382. else {
  7383. module.debug('Escape key pressed, but closable is set to false');
  7384. }
  7385. event.preventDefault();
  7386. }
  7387. },
  7388. resize: function() {
  7389. if( $dimmable.dimmer('is active') ) {
  7390. requestAnimationFrame(module.refresh);
  7391. }
  7392. }
  7393. },
  7394. toggle: function() {
  7395. if( module.is.active() || module.is.animating() ) {
  7396. module.hide();
  7397. }
  7398. else {
  7399. module.show();
  7400. }
  7401. },
  7402. show: function(callback) {
  7403. callback = $.isFunction(callback)
  7404. ? callback
  7405. : function(){}
  7406. ;
  7407. module.refreshModals();
  7408. module.showModal(callback);
  7409. },
  7410. hide: function(callback) {
  7411. callback = $.isFunction(callback)
  7412. ? callback
  7413. : function(){}
  7414. ;
  7415. module.refreshModals();
  7416. module.hideModal(callback);
  7417. },
  7418. showModal: function(callback) {
  7419. callback = $.isFunction(callback)
  7420. ? callback
  7421. : function(){}
  7422. ;
  7423. if( module.is.animating() || !module.is.active() ) {
  7424. module.showDimmer();
  7425. module.cacheSizes();
  7426. module.set.position();
  7427. module.set.screenHeight();
  7428. module.set.type();
  7429. module.set.clickaway();
  7430. if( !settings.allowMultiple && module.others.active() ) {
  7431. module.hideOthers(module.showModal);
  7432. }
  7433. else {
  7434. settings.onShow.call(element);
  7435. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  7436. module.debug('Showing modal with css animations');
  7437. $module
  7438. .transition({
  7439. debug : settings.debug,
  7440. animation : settings.transition + ' in',
  7441. queue : settings.queue,
  7442. duration : settings.duration,
  7443. useFailSafe : true,
  7444. onComplete : function() {
  7445. settings.onVisible.apply(element);
  7446. module.add.keyboardShortcuts();
  7447. module.save.focus();
  7448. module.set.active();
  7449. module.set.autofocus();
  7450. callback();
  7451. }
  7452. })
  7453. ;
  7454. }
  7455. else {
  7456. module.error(error.noTransition);
  7457. }
  7458. }
  7459. }
  7460. else {
  7461. module.debug('Modal is already visible');
  7462. }
  7463. },
  7464. hideModal: function(callback, keepDimmed) {
  7465. callback = $.isFunction(callback)
  7466. ? callback
  7467. : function(){}
  7468. ;
  7469. module.debug('Hiding modal');
  7470. settings.onHide.call(element);
  7471. if( module.is.animating() || module.is.active() ) {
  7472. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  7473. module.remove.active();
  7474. $module
  7475. .transition({
  7476. debug : settings.debug,
  7477. animation : settings.transition + ' out',
  7478. queue : settings.queue,
  7479. duration : settings.duration,
  7480. useFailSafe : true,
  7481. onStart : function() {
  7482. if(!module.others.active() && !keepDimmed) {
  7483. module.hideDimmer();
  7484. }
  7485. module.remove.keyboardShortcuts();
  7486. },
  7487. onComplete : function() {
  7488. settings.onHidden.call(element);
  7489. module.restore.focus();
  7490. callback();
  7491. }
  7492. })
  7493. ;
  7494. }
  7495. else {
  7496. module.error(error.noTransition);
  7497. }
  7498. }
  7499. },
  7500. showDimmer: function() {
  7501. if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
  7502. module.debug('Showing dimmer');
  7503. $dimmable.dimmer('show');
  7504. }
  7505. else {
  7506. module.debug('Dimmer already visible');
  7507. }
  7508. },
  7509. hideDimmer: function() {
  7510. if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
  7511. $dimmable.dimmer('hide', function() {
  7512. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  7513. module.remove.clickaway();
  7514. module.remove.screenHeight();
  7515. }
  7516. });
  7517. }
  7518. else {
  7519. module.debug('Dimmer is not visible cannot hide');
  7520. return;
  7521. }
  7522. },
  7523. hideAll: function(callback) {
  7524. var
  7525. $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
  7526. ;
  7527. callback = $.isFunction(callback)
  7528. ? callback
  7529. : function(){}
  7530. ;
  7531. if( $visibleModals.length > 0 ) {
  7532. module.debug('Hiding all visible modals');
  7533. module.hideDimmer();
  7534. $visibleModals
  7535. .modal('hide modal', callback)
  7536. ;
  7537. }
  7538. },
  7539. hideOthers: function(callback) {
  7540. var
  7541. $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
  7542. ;
  7543. callback = $.isFunction(callback)
  7544. ? callback
  7545. : function(){}
  7546. ;
  7547. if( $visibleModals.length > 0 ) {
  7548. module.debug('Hiding other modals', $otherModals);
  7549. $visibleModals
  7550. .modal('hide modal', callback, true)
  7551. ;
  7552. }
  7553. },
  7554. others: {
  7555. active: function() {
  7556. return ($otherModals.filter('.' + className.active).length > 0);
  7557. },
  7558. animating: function() {
  7559. return ($otherModals.filter('.' + className.animating).length > 0);
  7560. }
  7561. },
  7562. add: {
  7563. keyboardShortcuts: function() {
  7564. module.verbose('Adding keyboard shortcuts');
  7565. $document
  7566. .on('keyup' + eventNamespace, module.event.keyboard)
  7567. ;
  7568. }
  7569. },
  7570. save: {
  7571. focus: function() {
  7572. $focusedElement = $(document.activeElement).blur();
  7573. }
  7574. },
  7575. restore: {
  7576. focus: function() {
  7577. if($focusedElement && $focusedElement.length > 0) {
  7578. $focusedElement.focus();
  7579. }
  7580. }
  7581. },
  7582. remove: {
  7583. active: function() {
  7584. $module.removeClass(className.active);
  7585. },
  7586. clickaway: function() {
  7587. if(settings.closable) {
  7588. $dimmer
  7589. .off('click' + elementNamespace)
  7590. ;
  7591. }
  7592. },
  7593. screenHeight: function() {
  7594. if(module.cache.height > module.cache.pageHeight) {
  7595. module.debug('Removing page height');
  7596. $body
  7597. .css('height', '')
  7598. ;
  7599. }
  7600. },
  7601. keyboardShortcuts: function() {
  7602. module.verbose('Removing keyboard shortcuts');
  7603. $document
  7604. .off('keyup' + eventNamespace)
  7605. ;
  7606. },
  7607. scrolling: function() {
  7608. $dimmable.removeClass(className.scrolling);
  7609. $module.removeClass(className.scrolling);
  7610. }
  7611. },
  7612. cacheSizes: function() {
  7613. var
  7614. modalHeight = $module.outerHeight()
  7615. ;
  7616. if(module.cache === undefined || modalHeight !== 0) {
  7617. module.cache = {
  7618. pageHeight : $(document).outerHeight(),
  7619. height : modalHeight + settings.offset,
  7620. contextHeight : (settings.context == 'body')
  7621. ? $(window).height()
  7622. : $dimmable.height()
  7623. };
  7624. }
  7625. module.debug('Caching modal and container sizes', module.cache);
  7626. },
  7627. can: {
  7628. fit: function() {
  7629. return ( ( module.cache.height + (settings.padding * 2) ) < module.cache.contextHeight);
  7630. }
  7631. },
  7632. is: {
  7633. active: function() {
  7634. return $module.hasClass(className.active);
  7635. },
  7636. animating: function() {
  7637. return $module.transition('is supported')
  7638. ? $module.transition('is animating')
  7639. : $module.is(':visible')
  7640. ;
  7641. },
  7642. scrolling: function() {
  7643. return $dimmable.hasClass(className.scrolling);
  7644. },
  7645. modernBrowser: function() {
  7646. // appName for IE11 reports 'Netscape' can no longer use
  7647. return !(window.ActiveXObject || "ActiveXObject" in window);
  7648. }
  7649. },
  7650. set: {
  7651. autofocus: function() {
  7652. if(settings.autofocus) {
  7653. var
  7654. $inputs = $module.filter(':input').filter(':visible'),
  7655. $autofocus = $inputs.filter('[autofocus]'),
  7656. $input = ($autofocus.length > 0)
  7657. ? $autofocus.first()
  7658. : $inputs.first()
  7659. ;
  7660. if($input.length > 0) {
  7661. $input.focus();
  7662. }
  7663. }
  7664. },
  7665. clickaway: function() {
  7666. if(settings.closable) {
  7667. $dimmer
  7668. .on('click' + elementNamespace, module.event.click)
  7669. ;
  7670. }
  7671. },
  7672. screenHeight: function() {
  7673. if( module.can.fit() ) {
  7674. $body.css('height', '');
  7675. }
  7676. else {
  7677. module.debug('Modal is taller than page content, resizing page height');
  7678. $body
  7679. .css('height', module.cache.height + (settings.padding * 2) )
  7680. ;
  7681. }
  7682. },
  7683. active: function() {
  7684. $module.addClass(className.active);
  7685. },
  7686. scrolling: function() {
  7687. $dimmable.addClass(className.scrolling);
  7688. $module.addClass(className.scrolling);
  7689. },
  7690. type: function() {
  7691. if(module.can.fit()) {
  7692. module.verbose('Modal fits on screen');
  7693. if(!module.others.active() && !module.others.animating()) {
  7694. module.remove.scrolling();
  7695. }
  7696. }
  7697. else {
  7698. module.verbose('Modal cannot fit on screen setting to scrolling');
  7699. module.set.scrolling();
  7700. }
  7701. },
  7702. position: function() {
  7703. module.verbose('Centering modal on page', module.cache);
  7704. if(module.can.fit()) {
  7705. $module
  7706. .css({
  7707. top: '',
  7708. marginTop: -(module.cache.height / 2)
  7709. })
  7710. ;
  7711. }
  7712. else {
  7713. $module
  7714. .css({
  7715. marginTop : '',
  7716. top : $document.scrollTop()
  7717. })
  7718. ;
  7719. }
  7720. },
  7721. undetached: function() {
  7722. $dimmable.addClass(className.undetached);
  7723. }
  7724. },
  7725. setting: function(name, value) {
  7726. module.debug('Changing setting', name, value);
  7727. if( $.isPlainObject(name) ) {
  7728. $.extend(true, settings, name);
  7729. }
  7730. else if(value !== undefined) {
  7731. settings[name] = value;
  7732. }
  7733. else {
  7734. return settings[name];
  7735. }
  7736. },
  7737. internal: function(name, value) {
  7738. if( $.isPlainObject(name) ) {
  7739. $.extend(true, module, name);
  7740. }
  7741. else if(value !== undefined) {
  7742. module[name] = value;
  7743. }
  7744. else {
  7745. return module[name];
  7746. }
  7747. },
  7748. debug: function() {
  7749. if(settings.debug) {
  7750. if(settings.performance) {
  7751. module.performance.log(arguments);
  7752. }
  7753. else {
  7754. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7755. module.debug.apply(console, arguments);
  7756. }
  7757. }
  7758. },
  7759. verbose: function() {
  7760. if(settings.verbose && settings.debug) {
  7761. if(settings.performance) {
  7762. module.performance.log(arguments);
  7763. }
  7764. else {
  7765. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7766. module.verbose.apply(console, arguments);
  7767. }
  7768. }
  7769. },
  7770. error: function() {
  7771. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  7772. module.error.apply(console, arguments);
  7773. },
  7774. performance: {
  7775. log: function(message) {
  7776. var
  7777. currentTime,
  7778. executionTime,
  7779. previousTime
  7780. ;
  7781. if(settings.performance) {
  7782. currentTime = new Date().getTime();
  7783. previousTime = time || currentTime;
  7784. executionTime = currentTime - previousTime;
  7785. time = currentTime;
  7786. performance.push({
  7787. 'Name' : message[0],
  7788. 'Arguments' : [].slice.call(message, 1) || '',
  7789. 'Element' : element,
  7790. 'Execution Time' : executionTime
  7791. });
  7792. }
  7793. clearTimeout(module.performance.timer);
  7794. module.performance.timer = setTimeout(module.performance.display, 500);
  7795. },
  7796. display: function() {
  7797. var
  7798. title = settings.name + ':',
  7799. totalTime = 0
  7800. ;
  7801. time = false;
  7802. clearTimeout(module.performance.timer);
  7803. $.each(performance, function(index, data) {
  7804. totalTime += data['Execution Time'];
  7805. });
  7806. title += ' ' + totalTime + 'ms';
  7807. if(moduleSelector) {
  7808. title += ' \'' + moduleSelector + '\'';
  7809. }
  7810. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  7811. console.groupCollapsed(title);
  7812. if(console.table) {
  7813. console.table(performance);
  7814. }
  7815. else {
  7816. $.each(performance, function(index, data) {
  7817. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  7818. });
  7819. }
  7820. console.groupEnd();
  7821. }
  7822. performance = [];
  7823. }
  7824. },
  7825. invoke: function(query, passedArguments, context) {
  7826. var
  7827. object = instance,
  7828. maxDepth,
  7829. found,
  7830. response
  7831. ;
  7832. passedArguments = passedArguments || queryArguments;
  7833. context = element || context;
  7834. if(typeof query == 'string' && object !== undefined) {
  7835. query = query.split(/[\. ]/);
  7836. maxDepth = query.length - 1;
  7837. $.each(query, function(depth, value) {
  7838. var camelCaseValue = (depth != maxDepth)
  7839. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  7840. : query
  7841. ;
  7842. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  7843. object = object[camelCaseValue];
  7844. }
  7845. else if( object[camelCaseValue] !== undefined ) {
  7846. found = object[camelCaseValue];
  7847. return false;
  7848. }
  7849. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  7850. object = object[value];
  7851. }
  7852. else if( object[value] !== undefined ) {
  7853. found = object[value];
  7854. return false;
  7855. }
  7856. else {
  7857. return false;
  7858. }
  7859. });
  7860. }
  7861. if ( $.isFunction( found ) ) {
  7862. response = found.apply(context, passedArguments);
  7863. }
  7864. else if(found !== undefined) {
  7865. response = found;
  7866. }
  7867. if($.isArray(returnedValue)) {
  7868. returnedValue.push(response);
  7869. }
  7870. else if(returnedValue !== undefined) {
  7871. returnedValue = [returnedValue, response];
  7872. }
  7873. else if(response !== undefined) {
  7874. returnedValue = response;
  7875. }
  7876. return found;
  7877. }
  7878. };
  7879. if(methodInvoked) {
  7880. if(instance === undefined) {
  7881. module.initialize();
  7882. }
  7883. module.invoke(query);
  7884. }
  7885. else {
  7886. if(instance !== undefined) {
  7887. instance.invoke('destroy');
  7888. }
  7889. module.initialize();
  7890. }
  7891. })
  7892. ;
  7893. return (returnedValue !== undefined)
  7894. ? returnedValue
  7895. : this
  7896. ;
  7897. };
  7898. $.fn.modal.settings = {
  7899. name : 'Modal',
  7900. namespace : 'modal',
  7901. debug : false,
  7902. verbose : false,
  7903. performance : true,
  7904. observeChanges : false,
  7905. allowMultiple : false,
  7906. detachable : true,
  7907. closable : true,
  7908. autofocus : true,
  7909. inverted : false,
  7910. blurring : false,
  7911. dimmerSettings : {
  7912. closable : false,
  7913. useCSS : true
  7914. },
  7915. context : 'body',
  7916. queue : false,
  7917. duration : 500,
  7918. offset : 0,
  7919. transition : 'scale',
  7920. // padding with edge of page
  7921. padding : 50,
  7922. // called before show animation
  7923. onShow : function(){},
  7924. // called after show animation
  7925. onVisible : function(){},
  7926. // called before hide animation
  7927. onHide : function(){},
  7928. // called after hide animation
  7929. onHidden : function(){},
  7930. // called after approve selector match
  7931. onApprove : function(){ return true; },
  7932. // called after deny selector match
  7933. onDeny : function(){ return true; },
  7934. selector : {
  7935. close : '.close',
  7936. approve : '.actions .positive, .actions .approve, .actions .ok',
  7937. deny : '.actions .negative, .actions .deny, .actions .cancel',
  7938. modal : '.ui.modal'
  7939. },
  7940. error : {
  7941. dimmer : 'UI Dimmer, a required component is not included in this page',
  7942. method : 'The method you called is not defined.',
  7943. notFound : 'The element you specified could not be found'
  7944. },
  7945. className : {
  7946. active : 'active',
  7947. animating : 'animating',
  7948. blurring : 'blurring',
  7949. scrolling : 'scrolling',
  7950. undetached : 'undetached'
  7951. }
  7952. };
  7953. })( jQuery, window , document );
  7954. /*!
  7955. * # Semantic UI 2.0.0 - Nag
  7956. * http://github.com/semantic-org/semantic-ui/
  7957. *
  7958. *
  7959. * Copyright 2015 Contributors
  7960. * Released under the MIT license
  7961. * http://opensource.org/licenses/MIT
  7962. *
  7963. */
  7964. ;(function ($, window, document, undefined) {
  7965. "use strict";
  7966. $.fn.nag = function(parameters) {
  7967. var
  7968. $allModules = $(this),
  7969. moduleSelector = $allModules.selector || '',
  7970. time = new Date().getTime(),
  7971. performance = [],
  7972. query = arguments[0],
  7973. methodInvoked = (typeof query == 'string'),
  7974. queryArguments = [].slice.call(arguments, 1),
  7975. returnedValue
  7976. ;
  7977. $allModules
  7978. .each(function() {
  7979. var
  7980. settings = ( $.isPlainObject(parameters) )
  7981. ? $.extend(true, {}, $.fn.nag.settings, parameters)
  7982. : $.extend({}, $.fn.nag.settings),
  7983. className = settings.className,
  7984. selector = settings.selector,
  7985. error = settings.error,
  7986. namespace = settings.namespace,
  7987. eventNamespace = '.' + namespace,
  7988. moduleNamespace = namespace + '-module',
  7989. $module = $(this),
  7990. $close = $module.find(selector.close),
  7991. $context = (settings.context)
  7992. ? $(settings.context)
  7993. : $('body'),
  7994. element = this,
  7995. instance = $module.data(moduleNamespace),
  7996. moduleOffset,
  7997. moduleHeight,
  7998. contextWidth,
  7999. contextHeight,
  8000. contextOffset,
  8001. yOffset,
  8002. yPosition,
  8003. timer,
  8004. module,
  8005. requestAnimationFrame = window.requestAnimationFrame
  8006. || window.mozRequestAnimationFrame
  8007. || window.webkitRequestAnimationFrame
  8008. || window.msRequestAnimationFrame
  8009. || function(callback) { setTimeout(callback, 0); }
  8010. ;
  8011. module = {
  8012. initialize: function() {
  8013. module.verbose('Initializing element');
  8014. $module
  8015. .on('click' + eventNamespace, selector.close, module.dismiss)
  8016. .data(moduleNamespace, module)
  8017. ;
  8018. if(settings.detachable && $module.parent()[0] !== $context[0]) {
  8019. $module
  8020. .detach()
  8021. .prependTo($context)
  8022. ;
  8023. }
  8024. if(settings.displayTime > 0) {
  8025. setTimeout(module.hide, settings.displayTime);
  8026. }
  8027. module.show();
  8028. },
  8029. destroy: function() {
  8030. module.verbose('Destroying instance');
  8031. $module
  8032. .removeData(moduleNamespace)
  8033. .off(eventNamespace)
  8034. ;
  8035. },
  8036. show: function() {
  8037. if( module.should.show() && !$module.is(':visible') ) {
  8038. module.debug('Showing nag', settings.animation.show);
  8039. if(settings.animation.show == 'fade') {
  8040. $module
  8041. .fadeIn(settings.duration, settings.easing)
  8042. ;
  8043. }
  8044. else {
  8045. $module
  8046. .slideDown(settings.duration, settings.easing)
  8047. ;
  8048. }
  8049. }
  8050. },
  8051. hide: function() {
  8052. module.debug('Showing nag', settings.animation.hide);
  8053. if(settings.animation.show == 'fade') {
  8054. $module
  8055. .fadeIn(settings.duration, settings.easing)
  8056. ;
  8057. }
  8058. else {
  8059. $module
  8060. .slideUp(settings.duration, settings.easing)
  8061. ;
  8062. }
  8063. },
  8064. onHide: function() {
  8065. module.debug('Removing nag', settings.animation.hide);
  8066. $module.remove();
  8067. if (settings.onHide) {
  8068. settings.onHide();
  8069. }
  8070. },
  8071. dismiss: function(event) {
  8072. if(settings.storageMethod) {
  8073. module.storage.set(settings.key, settings.value);
  8074. }
  8075. module.hide();
  8076. event.stopImmediatePropagation();
  8077. event.preventDefault();
  8078. },
  8079. should: {
  8080. show: function() {
  8081. if(settings.persist) {
  8082. module.debug('Persistent nag is set, can show nag');
  8083. return true;
  8084. }
  8085. if( module.storage.get(settings.key) != settings.value.toString() ) {
  8086. module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
  8087. return true;
  8088. }
  8089. module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
  8090. return false;
  8091. }
  8092. },
  8093. get: {
  8094. storageOptions: function() {
  8095. var
  8096. options = {}
  8097. ;
  8098. if(settings.expires) {
  8099. options.expires = settings.expires;
  8100. }
  8101. if(settings.domain) {
  8102. options.domain = settings.domain;
  8103. }
  8104. if(settings.path) {
  8105. options.path = settings.path;
  8106. }
  8107. return options;
  8108. }
  8109. },
  8110. clear: function() {
  8111. module.storage.remove(settings.key);
  8112. },
  8113. storage: {
  8114. set: function(key, value) {
  8115. var
  8116. options = module.get.storageOptions()
  8117. ;
  8118. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  8119. window.localStorage.setItem(key, value);
  8120. module.debug('Value stored using local storage', key, value);
  8121. }
  8122. else if($.cookie !== undefined) {
  8123. $.cookie(key, value, options);
  8124. module.debug('Value stored using cookie', key, value, options);
  8125. }
  8126. else {
  8127. module.error(error.noCookieStorage);
  8128. return;
  8129. }
  8130. },
  8131. get: function(key, value) {
  8132. var
  8133. storedValue
  8134. ;
  8135. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  8136. storedValue = window.localStorage.getItem(key);
  8137. }
  8138. // get by cookie
  8139. else if($.cookie !== undefined) {
  8140. storedValue = $.cookie(key);
  8141. }
  8142. else {
  8143. module.error(error.noCookieStorage);
  8144. }
  8145. if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
  8146. storedValue = undefined;
  8147. }
  8148. return storedValue;
  8149. },
  8150. remove: function(key) {
  8151. var
  8152. options = module.get.storageOptions()
  8153. ;
  8154. if(settings.storageMethod == 'local' && window.store !== undefined) {
  8155. window.localStorage.removeItem(key);
  8156. }
  8157. // store by cookie
  8158. else if($.cookie !== undefined) {
  8159. $.removeCookie(key, options);
  8160. }
  8161. else {
  8162. module.error(error.noStorage);
  8163. }
  8164. }
  8165. },
  8166. setting: function(name, value) {
  8167. module.debug('Changing setting', name, value);
  8168. if( $.isPlainObject(name) ) {
  8169. $.extend(true, settings, name);
  8170. }
  8171. else if(value !== undefined) {
  8172. settings[name] = value;
  8173. }
  8174. else {
  8175. return settings[name];
  8176. }
  8177. },
  8178. internal: function(name, value) {
  8179. if( $.isPlainObject(name) ) {
  8180. $.extend(true, module, name);
  8181. }
  8182. else if(value !== undefined) {
  8183. module[name] = value;
  8184. }
  8185. else {
  8186. return module[name];
  8187. }
  8188. },
  8189. debug: function() {
  8190. if(settings.debug) {
  8191. if(settings.performance) {
  8192. module.performance.log(arguments);
  8193. }
  8194. else {
  8195. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8196. module.debug.apply(console, arguments);
  8197. }
  8198. }
  8199. },
  8200. verbose: function() {
  8201. if(settings.verbose && settings.debug) {
  8202. if(settings.performance) {
  8203. module.performance.log(arguments);
  8204. }
  8205. else {
  8206. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8207. module.verbose.apply(console, arguments);
  8208. }
  8209. }
  8210. },
  8211. error: function() {
  8212. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  8213. module.error.apply(console, arguments);
  8214. },
  8215. performance: {
  8216. log: function(message) {
  8217. var
  8218. currentTime,
  8219. executionTime,
  8220. previousTime
  8221. ;
  8222. if(settings.performance) {
  8223. currentTime = new Date().getTime();
  8224. previousTime = time || currentTime;
  8225. executionTime = currentTime - previousTime;
  8226. time = currentTime;
  8227. performance.push({
  8228. 'Name' : message[0],
  8229. 'Arguments' : [].slice.call(message, 1) || '',
  8230. 'Element' : element,
  8231. 'Execution Time' : executionTime
  8232. });
  8233. }
  8234. clearTimeout(module.performance.timer);
  8235. module.performance.timer = setTimeout(module.performance.display, 500);
  8236. },
  8237. display: function() {
  8238. var
  8239. title = settings.name + ':',
  8240. totalTime = 0
  8241. ;
  8242. time = false;
  8243. clearTimeout(module.performance.timer);
  8244. $.each(performance, function(index, data) {
  8245. totalTime += data['Execution Time'];
  8246. });
  8247. title += ' ' + totalTime + 'ms';
  8248. if(moduleSelector) {
  8249. title += ' \'' + moduleSelector + '\'';
  8250. }
  8251. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  8252. console.groupCollapsed(title);
  8253. if(console.table) {
  8254. console.table(performance);
  8255. }
  8256. else {
  8257. $.each(performance, function(index, data) {
  8258. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  8259. });
  8260. }
  8261. console.groupEnd();
  8262. }
  8263. performance = [];
  8264. }
  8265. },
  8266. invoke: function(query, passedArguments, context) {
  8267. var
  8268. object = instance,
  8269. maxDepth,
  8270. found,
  8271. response
  8272. ;
  8273. passedArguments = passedArguments || queryArguments;
  8274. context = element || context;
  8275. if(typeof query == 'string' && object !== undefined) {
  8276. query = query.split(/[\. ]/);
  8277. maxDepth = query.length - 1;
  8278. $.each(query, function(depth, value) {
  8279. var camelCaseValue = (depth != maxDepth)
  8280. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  8281. : query
  8282. ;
  8283. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  8284. object = object[camelCaseValue];
  8285. }
  8286. else if( object[camelCaseValue] !== undefined ) {
  8287. found = object[camelCaseValue];
  8288. return false;
  8289. }
  8290. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  8291. object = object[value];
  8292. }
  8293. else if( object[value] !== undefined ) {
  8294. found = object[value];
  8295. return false;
  8296. }
  8297. else {
  8298. module.error(error.method, query);
  8299. return false;
  8300. }
  8301. });
  8302. }
  8303. if ( $.isFunction( found ) ) {
  8304. response = found.apply(context, passedArguments);
  8305. }
  8306. else if(found !== undefined) {
  8307. response = found;
  8308. }
  8309. if($.isArray(returnedValue)) {
  8310. returnedValue.push(response);
  8311. }
  8312. else if(returnedValue !== undefined) {
  8313. returnedValue = [returnedValue, response];
  8314. }
  8315. else if(response !== undefined) {
  8316. returnedValue = response;
  8317. }
  8318. return found;
  8319. }
  8320. };
  8321. if(methodInvoked) {
  8322. if(instance === undefined) {
  8323. module.initialize();
  8324. }
  8325. module.invoke(query);
  8326. }
  8327. else {
  8328. if(instance !== undefined) {
  8329. instance.invoke('destroy');
  8330. }
  8331. module.initialize();
  8332. }
  8333. })
  8334. ;
  8335. return (returnedValue !== undefined)
  8336. ? returnedValue
  8337. : this
  8338. ;
  8339. };
  8340. $.fn.nag.settings = {
  8341. name : 'Nag',
  8342. debug : false,
  8343. verbose : false,
  8344. performance : true,
  8345. namespace : 'Nag',
  8346. // allows cookie to be overriden
  8347. persist : false,
  8348. // set to zero to require manually dismissal, otherwise hides on its own
  8349. displayTime : 0,
  8350. animation : {
  8351. show : 'slide',
  8352. hide : 'slide'
  8353. },
  8354. context : false,
  8355. detachable : false,
  8356. expires : 30,
  8357. domain : false,
  8358. path : '/',
  8359. // type of storage to use
  8360. storageMethod : 'cookie',
  8361. // value to store in dismissed localstorage/cookie
  8362. key : 'nag',
  8363. value : 'dismiss',
  8364. error: {
  8365. noCookieStorage : '$.cookie is not included. A storage solution is required.',
  8366. noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
  8367. method : 'The method you called is not defined.'
  8368. },
  8369. className : {
  8370. bottom : 'bottom',
  8371. fixed : 'fixed'
  8372. },
  8373. selector : {
  8374. close : '.close.icon'
  8375. },
  8376. speed : 500,
  8377. easing : 'easeOutQuad',
  8378. onHide: function() {}
  8379. };
  8380. })( jQuery, window , document );
  8381. /*!
  8382. * # Semantic UI 2.0.0 - Popup
  8383. * http://github.com/semantic-org/semantic-ui/
  8384. *
  8385. *
  8386. * Copyright 2015 Contributors
  8387. * Released under the MIT license
  8388. * http://opensource.org/licenses/MIT
  8389. *
  8390. */
  8391. ;(function ($, window, document, undefined) {
  8392. "use strict";
  8393. $.fn.popup = function(parameters) {
  8394. var
  8395. $allModules = $(this),
  8396. $document = $(document),
  8397. $window = $(window),
  8398. $body = $('body'),
  8399. moduleSelector = $allModules.selector || '',
  8400. hasTouch = ('ontouchstart' in document.documentElement),
  8401. time = new Date().getTime(),
  8402. performance = [],
  8403. query = arguments[0],
  8404. methodInvoked = (typeof query == 'string'),
  8405. queryArguments = [].slice.call(arguments, 1),
  8406. returnedValue
  8407. ;
  8408. $allModules
  8409. .each(function() {
  8410. var
  8411. settings = ( $.isPlainObject(parameters) )
  8412. ? $.extend(true, {}, $.fn.popup.settings, parameters)
  8413. : $.extend({}, $.fn.popup.settings),
  8414. selector = settings.selector,
  8415. className = settings.className,
  8416. error = settings.error,
  8417. metadata = settings.metadata,
  8418. namespace = settings.namespace,
  8419. eventNamespace = '.' + settings.namespace,
  8420. moduleNamespace = 'module-' + namespace,
  8421. $module = $(this),
  8422. $context = $(settings.context),
  8423. $target = (settings.target)
  8424. ? $(settings.target)
  8425. : $module,
  8426. $popup,
  8427. $offsetParent,
  8428. searchDepth = 0,
  8429. triedPositions = false,
  8430. openedWithTouch = false,
  8431. element = this,
  8432. instance = $module.data(moduleNamespace),
  8433. elementNamespace,
  8434. id,
  8435. module
  8436. ;
  8437. module = {
  8438. // binds events
  8439. initialize: function() {
  8440. module.debug('Initializing', $module);
  8441. module.createID();
  8442. module.bind.events();
  8443. if( !module.exists() && settings.preserve) {
  8444. module.create();
  8445. }
  8446. module.instantiate();
  8447. },
  8448. instantiate: function() {
  8449. module.verbose('Storing instance', module);
  8450. instance = module;
  8451. $module
  8452. .data(moduleNamespace, instance)
  8453. ;
  8454. },
  8455. refresh: function() {
  8456. if(settings.popup) {
  8457. $popup = $(settings.popup).eq(0);
  8458. }
  8459. else {
  8460. if(settings.inline) {
  8461. $popup = $target.next(selector.popup).eq(0);
  8462. settings.popup = $popup;
  8463. }
  8464. }
  8465. if(settings.popup) {
  8466. $popup.addClass(className.loading);
  8467. $offsetParent = module.get.offsetParent();
  8468. $popup.removeClass(className.loading);
  8469. if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
  8470. module.debug('Moving popup to the same offset parent as activating element');
  8471. $popup
  8472. .detach()
  8473. .appendTo($offsetParent)
  8474. ;
  8475. }
  8476. }
  8477. else {
  8478. $offsetParent = (settings.inline)
  8479. ? module.get.offsetParent($target)
  8480. : module.has.popup()
  8481. ? module.get.offsetParent($popup)
  8482. : $body
  8483. ;
  8484. }
  8485. if( $offsetParent.is('html') ) {
  8486. module.debug('Setting page as offset parent');
  8487. $offsetParent = $body;
  8488. }
  8489. },
  8490. reposition: function() {
  8491. module.refresh();
  8492. module.set.position();
  8493. },
  8494. destroy: function() {
  8495. module.debug('Destroying previous module');
  8496. // remove element only if was created dynamically
  8497. if($popup && !settings.preserve) {
  8498. module.removePopup();
  8499. }
  8500. // clear all timeouts
  8501. clearTimeout(module.hideTimer);
  8502. clearTimeout(module.showTimer);
  8503. // remove events
  8504. $window.off(elementNamespace);
  8505. $module
  8506. .off(eventNamespace)
  8507. .removeData(moduleNamespace)
  8508. ;
  8509. },
  8510. event: {
  8511. start: function(event) {
  8512. var
  8513. delay = ($.isPlainObject(settings.delay))
  8514. ? settings.delay.show
  8515. : settings.delay
  8516. ;
  8517. clearTimeout(module.hideTimer);
  8518. module.showTimer = setTimeout(module.show, delay);
  8519. },
  8520. end: function() {
  8521. var
  8522. delay = ($.isPlainObject(settings.delay))
  8523. ? settings.delay.hide
  8524. : settings.delay
  8525. ;
  8526. clearTimeout(module.showTimer);
  8527. module.hideTimer = setTimeout(module.hide, delay);
  8528. },
  8529. touchstart: function(event) {
  8530. openedWithTouch = true;
  8531. module.event.start();
  8532. },
  8533. resize: function() {
  8534. if( module.is.visible() ) {
  8535. module.set.position();
  8536. }
  8537. },
  8538. hideGracefully: function(event) {
  8539. // don't close on clicks inside popup
  8540. if(event && $(event.target).closest(selector.popup).length === 0) {
  8541. module.debug('Click occurred outside popup hiding popup');
  8542. module.hide();
  8543. }
  8544. else {
  8545. module.debug('Click was inside popup, keeping popup open');
  8546. }
  8547. }
  8548. },
  8549. // generates popup html from metadata
  8550. create: function() {
  8551. var
  8552. html = module.get.html(),
  8553. variation = module.get.variation(),
  8554. title = module.get.title(),
  8555. content = module.get.content()
  8556. ;
  8557. if(html || content || title) {
  8558. module.debug('Creating pop-up html');
  8559. if(!html) {
  8560. html = settings.templates.popup({
  8561. title : title,
  8562. content : content
  8563. });
  8564. }
  8565. $popup = $('<div/>')
  8566. .addClass(className.popup)
  8567. .addClass(variation)
  8568. .data(metadata.activator, $module)
  8569. .html(html)
  8570. ;
  8571. if(variation) {
  8572. $popup
  8573. .addClass(variation)
  8574. ;
  8575. }
  8576. if(settings.inline) {
  8577. module.verbose('Inserting popup element inline', $popup);
  8578. $popup
  8579. .insertAfter($module)
  8580. ;
  8581. }
  8582. else {
  8583. module.verbose('Appending popup element to body', $popup);
  8584. $popup
  8585. .appendTo( $context )
  8586. ;
  8587. }
  8588. module.refresh();
  8589. if(settings.hoverable) {
  8590. module.bind.popup();
  8591. }
  8592. settings.onCreate.call($popup, element);
  8593. }
  8594. else if($target.next(selector.popup).length !== 0) {
  8595. module.verbose('Pre-existing popup found');
  8596. settings.inline = true;
  8597. settings.popups = $target.next(selector.popup).data(metadata.activator, $module);
  8598. module.refresh();
  8599. if(settings.hoverable) {
  8600. module.bind.popup();
  8601. }
  8602. }
  8603. else if(settings.popup) {
  8604. $(settings.popup).data(metadata.activator, $module);
  8605. module.verbose('Used popup specified in settings');
  8606. module.refresh();
  8607. if(settings.hoverable) {
  8608. module.bind.popup();
  8609. }
  8610. }
  8611. else {
  8612. module.debug('No content specified skipping display', element);
  8613. }
  8614. },
  8615. createID: function() {
  8616. id = (Math.random().toString(16) + '000000000').substr(2,8);
  8617. elementNamespace = '.' + id;
  8618. module.verbose('Creating unique id for element', id);
  8619. },
  8620. // determines popup state
  8621. toggle: function() {
  8622. module.debug('Toggling pop-up');
  8623. if( module.is.hidden() ) {
  8624. module.debug('Popup is hidden, showing pop-up');
  8625. module.unbind.close();
  8626. module.show();
  8627. }
  8628. else {
  8629. module.debug('Popup is visible, hiding pop-up');
  8630. module.hide();
  8631. }
  8632. },
  8633. show: function(callback) {
  8634. callback = callback || function(){};
  8635. module.debug('Showing pop-up', settings.transition);
  8636. if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
  8637. if( !module.exists() ) {
  8638. module.create();
  8639. }
  8640. if(settings.onShow.call($popup, element) === false) {
  8641. module.debug('onShow callback returned false, cancelling popup animation');
  8642. return;
  8643. }
  8644. else if(!settings.preserve && !settings.popup) {
  8645. module.refresh();
  8646. }
  8647. if( $popup && module.set.position() ) {
  8648. module.save.conditions();
  8649. if(settings.exclusive) {
  8650. module.hideAll();
  8651. }
  8652. module.animate.show(callback);
  8653. }
  8654. }
  8655. },
  8656. hide: function(callback) {
  8657. callback = callback || function(){};
  8658. if( module.is.visible() || module.is.animating() ) {
  8659. if(settings.onHide.call($popup, element) === false) {
  8660. module.debug('onHide callback returned false, cancelling popup animation');
  8661. return;
  8662. }
  8663. module.remove.visible();
  8664. module.unbind.close();
  8665. module.restore.conditions();
  8666. module.animate.hide(callback);
  8667. }
  8668. },
  8669. hideAll: function() {
  8670. $(selector.popup)
  8671. .filter('.' + className.visible)
  8672. .each(function() {
  8673. $(this)
  8674. .data(metadata.activator)
  8675. .popup('hide')
  8676. ;
  8677. })
  8678. ;
  8679. },
  8680. exists: function() {
  8681. if(!$popup) {
  8682. return false;
  8683. }
  8684. if(settings.inline || settings.popup) {
  8685. return ( module.has.popup() );
  8686. }
  8687. else {
  8688. return ( $popup.closest($context).length >= 1 )
  8689. ? true
  8690. : false
  8691. ;
  8692. }
  8693. },
  8694. removePopup: function() {
  8695. module.debug('Removing popup', $popup);
  8696. if( module.has.popup() && !settings.popup) {
  8697. $popup.remove();
  8698. $popup = undefined;
  8699. }
  8700. settings.onRemove.call($popup, element);
  8701. },
  8702. save: {
  8703. conditions: function() {
  8704. module.cache = {
  8705. title: $module.attr('title')
  8706. };
  8707. if (module.cache.title) {
  8708. $module.removeAttr('title');
  8709. }
  8710. module.verbose('Saving original attributes', module.cache.title);
  8711. }
  8712. },
  8713. restore: {
  8714. conditions: function() {
  8715. if(module.cache && module.cache.title) {
  8716. $module.attr('title', module.cache.title);
  8717. module.verbose('Restoring original attributes', module.cache.title);
  8718. }
  8719. return true;
  8720. }
  8721. },
  8722. animate: {
  8723. show: function(callback) {
  8724. callback = $.isFunction(callback) ? callback : function(){};
  8725. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8726. module.set.visible();
  8727. $popup
  8728. .transition({
  8729. animation : settings.transition + ' in',
  8730. queue : false,
  8731. debug : settings.debug,
  8732. verbose : settings.verbose,
  8733. duration : settings.duration,
  8734. onComplete : function() {
  8735. module.bind.close();
  8736. callback.call($popup, element);
  8737. settings.onVisible.call($popup, element);
  8738. }
  8739. })
  8740. ;
  8741. }
  8742. else {
  8743. module.error(error.noTransition);
  8744. }
  8745. },
  8746. hide: function(callback) {
  8747. callback = $.isFunction(callback) ? callback : function(){};
  8748. module.debug('Hiding pop-up');
  8749. if(settings.onShow.call($popup, element) === false) {
  8750. module.debug('onShow callback returned false, cancelling popup animation');
  8751. return;
  8752. }
  8753. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8754. $popup
  8755. .transition({
  8756. animation : settings.transition + ' out',
  8757. queue : false,
  8758. duration : settings.duration,
  8759. debug : settings.debug,
  8760. verbose : settings.verbose,
  8761. onComplete : function() {
  8762. module.reset();
  8763. callback.call($popup, element);
  8764. settings.onHidden.call($popup, element);
  8765. }
  8766. })
  8767. ;
  8768. }
  8769. else {
  8770. module.error(error.noTransition);
  8771. }
  8772. }
  8773. },
  8774. get: {
  8775. html: function() {
  8776. $module.removeData(metadata.html);
  8777. return $module.data(metadata.html) || settings.html;
  8778. },
  8779. title: function() {
  8780. $module.removeData(metadata.title);
  8781. return $module.data(metadata.title) || settings.title;
  8782. },
  8783. content: function() {
  8784. $module.removeData(metadata.content);
  8785. return $module.data(metadata.content) || $module.attr('title') || settings.content;
  8786. },
  8787. variation: function() {
  8788. $module.removeData(metadata.variation);
  8789. return $module.data(metadata.variation) || settings.variation;
  8790. },
  8791. calculations: function() {
  8792. var
  8793. targetElement = $target[0],
  8794. targetPosition = (settings.inline || settings.popup)
  8795. ? $target.position()
  8796. : $target.offset(),
  8797. calculations = {},
  8798. screen
  8799. ;
  8800. calculations = {
  8801. // element which is launching popup
  8802. target : {
  8803. element : $target[0],
  8804. width : $target.outerWidth(),
  8805. height : $target.outerHeight(),
  8806. top : targetPosition.top,
  8807. left : targetPosition.left,
  8808. margin : {}
  8809. },
  8810. // popup itself
  8811. popup : {
  8812. width : $popup.outerWidth(),
  8813. height : $popup.outerHeight()
  8814. },
  8815. // offset container (or 3d context)
  8816. parent : {
  8817. width : $offsetParent.outerWidth(),
  8818. height : $offsetParent.outerHeight()
  8819. },
  8820. // screen boundaries
  8821. screen : {
  8822. scroll: {
  8823. top : $window.scrollTop(),
  8824. left : $window.scrollLeft()
  8825. },
  8826. width : $window.width(),
  8827. height : $window.height()
  8828. }
  8829. };
  8830. // add in margins if inline
  8831. calculations.target.margin.top = (settings.inline)
  8832. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
  8833. : 0
  8834. ;
  8835. calculations.target.margin.left = (settings.inline)
  8836. ? module.is.rtl()
  8837. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
  8838. : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left') , 10)
  8839. : 0
  8840. ;
  8841. // calculate screen boundaries
  8842. screen = calculations.screen;
  8843. calculations.boundary = {
  8844. top : screen.scroll.top,
  8845. bottom : screen.scroll.top + screen.height,
  8846. left : screen.scroll.left,
  8847. right : screen.scroll.left + screen.width
  8848. };
  8849. return calculations;
  8850. },
  8851. id: function() {
  8852. return id;
  8853. },
  8854. startEvent: function() {
  8855. if(settings.on == 'hover') {
  8856. return 'mouseenter';
  8857. }
  8858. else if(settings.on == 'focus') {
  8859. return 'focus';
  8860. }
  8861. return false;
  8862. },
  8863. scrollEvent: function() {
  8864. return 'scroll';
  8865. },
  8866. endEvent: function() {
  8867. if(settings.on == 'hover') {
  8868. return 'mouseleave';
  8869. }
  8870. else if(settings.on == 'focus') {
  8871. return 'blur';
  8872. }
  8873. return false;
  8874. },
  8875. offsetParent: function($target) {
  8876. var
  8877. element = ($target !== undefined)
  8878. ? $target[0]
  8879. : $module[0],
  8880. parentNode = element.parentNode,
  8881. $node = $(parentNode)
  8882. ;
  8883. if(parentNode) {
  8884. var
  8885. is2D = ($node.css('transform') === 'none'),
  8886. isStatic = ($node.css('position') === 'static'),
  8887. isHTML = $node.is('html')
  8888. ;
  8889. while(parentNode && !isHTML && isStatic && is2D) {
  8890. parentNode = parentNode.parentNode;
  8891. $node = $(parentNode);
  8892. is2D = ($node.css('transform') === 'none');
  8893. isStatic = ($node.css('position') === 'static');
  8894. isHTML = $node.is('html');
  8895. }
  8896. }
  8897. return ($node && $node.length > 0)
  8898. ? $node
  8899. : $()
  8900. ;
  8901. },
  8902. offstagePosition: function(position, calculations) {
  8903. var
  8904. offset = $popup.offset(),
  8905. offstage = {},
  8906. offstagePositions = [],
  8907. popup,
  8908. boundary
  8909. ;
  8910. position = position || false;
  8911. calculations = calculations || module.get.calculations();
  8912. // shorthand
  8913. popup = calculations.popup;
  8914. boundary = calculations.boundary;
  8915. if(offset && position) {
  8916. offstage = {
  8917. top : (offset.top < boundary.top),
  8918. bottom : (offset.top + popup.height > boundary.bottom),
  8919. right : (offset.left + popup.width > boundary.right),
  8920. left : (offset.left < boundary.left)
  8921. };
  8922. module.verbose('Offstage positions determined', offset, offstage);
  8923. }
  8924. // return only boundaries that have been surpassed
  8925. $.each(offstage, function(direction, isOffstage) {
  8926. if(isOffstage) {
  8927. offstagePositions.push(direction);
  8928. }
  8929. });
  8930. return (offstagePositions.length > 0)
  8931. ? offstagePositions.join(' ')
  8932. : false
  8933. ;
  8934. },
  8935. positions: function() {
  8936. return {
  8937. 'top left' : false,
  8938. 'top center' : false,
  8939. 'top right' : false,
  8940. 'bottom left' : false,
  8941. 'bottom center' : false,
  8942. 'bottom right' : false,
  8943. 'left center' : false,
  8944. 'right center' : false
  8945. };
  8946. },
  8947. nextPosition: function(position) {
  8948. var
  8949. positions = position.split(' '),
  8950. verticalPosition = positions[0],
  8951. horizontalPosition = positions[1],
  8952. opposite = {
  8953. top : 'bottom',
  8954. bottom : 'top',
  8955. left : 'right',
  8956. right : 'left'
  8957. },
  8958. adjacent = {
  8959. left : 'center',
  8960. center : 'right',
  8961. right : 'left'
  8962. },
  8963. backup = {
  8964. 'top left' : 'top center',
  8965. 'top center' : 'top right',
  8966. 'top right' : 'right center',
  8967. 'right center' : 'bottom right',
  8968. 'bottom right' : 'bottom center',
  8969. 'bottom center' : 'bottom left',
  8970. 'bottom left' : 'left center',
  8971. 'left center' : 'top left'
  8972. },
  8973. adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
  8974. oppositeTried = false,
  8975. adjacentTried = false,
  8976. nextPosition = false
  8977. ;
  8978. if(!triedPositions) {
  8979. module.verbose('All available positions available');
  8980. triedPositions = module.get.positions();
  8981. }
  8982. module.debug('Recording last position tried', position);
  8983. triedPositions[position] = true;
  8984. if(settings.prefer === 'opposite') {
  8985. nextPosition = [opposite[verticalPosition], horizontalPosition];
  8986. nextPosition = nextPosition.join(' ');
  8987. oppositeTried = (triedPositions[nextPosition] === true);
  8988. module.debug('Trying opposite strategy', nextPosition);
  8989. }
  8990. if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
  8991. nextPosition = [verticalPosition, adjacent[horizontalPosition]];
  8992. nextPosition = nextPosition.join(' ');
  8993. adjacentTried = (triedPositions[nextPosition] === true);
  8994. module.debug('Trying adjacent strategy', nextPosition);
  8995. }
  8996. if(adjacentTried || oppositeTried) {
  8997. module.debug('Using backup position', nextPosition);
  8998. nextPosition = backup[position];
  8999. }
  9000. return nextPosition;
  9001. }
  9002. },
  9003. set: {
  9004. position: function(position, calculations) {
  9005. // exit conditions
  9006. if($target.length === 0 || $popup.length === 0) {
  9007. module.error(error.notFound);
  9008. return;
  9009. }
  9010. var
  9011. offset,
  9012. distanceAway,
  9013. target,
  9014. popup,
  9015. parent,
  9016. computedPosition,
  9017. positioning,
  9018. offstagePosition
  9019. ;
  9020. calculations = calculations || module.get.calculations();
  9021. position = position || $module.data(metadata.position) || settings.position;
  9022. offset = $module.data(metadata.offset) || settings.offset;
  9023. distanceAway = settings.distanceAway;
  9024. // shorthand
  9025. target = calculations.target;
  9026. popup = calculations.popup;
  9027. parent = calculations.parent;
  9028. if(target.top === 0 && target.left === 0) {
  9029. module.debug('Popup target is hidden, no action taken');
  9030. return false;
  9031. }
  9032. if(settings.inline) {
  9033. module.debug('Adding margin to calculation', target.margin);
  9034. if(position == 'left center' || position == 'right center') {
  9035. offset += target.margin.top;
  9036. distanceAway += -target.margin.left;
  9037. }
  9038. else if (position == 'top left' || position == 'top center' || position == 'top right') {
  9039. offset += target.margin.left;
  9040. distanceAway -= target.margin.top;
  9041. }
  9042. else {
  9043. offset += target.margin.left;
  9044. distanceAway += target.margin.top;
  9045. }
  9046. }
  9047. module.debug('Determining popup position from calculations', position, calculations);
  9048. if (module.is.rtl()) {
  9049. position = position.replace(/left|right/g, function (match) {
  9050. return (match == 'left')
  9051. ? 'right'
  9052. : 'left'
  9053. ;
  9054. });
  9055. module.debug('RTL: Popup position updated', position);
  9056. }
  9057. if(searchDepth == settings.maxSearchDepth && settings.lastResort) {
  9058. module.debug('Using "last resort" position to display', settings.lastResort);
  9059. position = settings.lastResort;
  9060. }
  9061. switch (position) {
  9062. case 'top left':
  9063. positioning = {
  9064. top : 'auto',
  9065. bottom : parent.height - target.top + distanceAway,
  9066. left : target.left + offset,
  9067. right : 'auto'
  9068. };
  9069. break;
  9070. case 'top center':
  9071. positioning = {
  9072. bottom : parent.height - target.top + distanceAway,
  9073. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  9074. top : 'auto',
  9075. right : 'auto'
  9076. };
  9077. break;
  9078. case 'top right':
  9079. positioning = {
  9080. bottom : parent.height - target.top + distanceAway,
  9081. right : parent.width - target.left - target.width - offset,
  9082. top : 'auto',
  9083. left : 'auto'
  9084. };
  9085. break;
  9086. case 'left center':
  9087. positioning = {
  9088. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  9089. right : parent.width - target.left + distanceAway,
  9090. left : 'auto',
  9091. bottom : 'auto'
  9092. };
  9093. break;
  9094. case 'right center':
  9095. positioning = {
  9096. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  9097. left : target.left + target.width + distanceAway,
  9098. bottom : 'auto',
  9099. right : 'auto'
  9100. };
  9101. break;
  9102. case 'bottom left':
  9103. positioning = {
  9104. top : target.top + target.height + distanceAway,
  9105. left : target.left + offset,
  9106. bottom : 'auto',
  9107. right : 'auto'
  9108. };
  9109. break;
  9110. case 'bottom center':
  9111. positioning = {
  9112. top : target.top + target.height + distanceAway,
  9113. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  9114. bottom : 'auto',
  9115. right : 'auto'
  9116. };
  9117. break;
  9118. case 'bottom right':
  9119. positioning = {
  9120. top : target.top + target.height + distanceAway,
  9121. right : parent.width - target.left - target.width - offset,
  9122. left : 'auto',
  9123. bottom : 'auto'
  9124. };
  9125. break;
  9126. }
  9127. if(positioning === undefined) {
  9128. module.error(error.invalidPosition, position);
  9129. }
  9130. module.debug('Calculated popup positioning values', positioning);
  9131. // tentatively place on stage
  9132. $popup
  9133. .css(positioning)
  9134. .removeClass(className.position)
  9135. .addClass(position)
  9136. .addClass(className.loading)
  9137. ;
  9138. // check if is offstage
  9139. offstagePosition = module.get.offstagePosition(position, calculations);
  9140. // recursively find new positioning
  9141. if(offstagePosition) {
  9142. module.debug('Popup cant fit into viewport', position, offstagePosition);
  9143. if(searchDepth < settings.maxSearchDepth) {
  9144. searchDepth++;
  9145. position = module.get.nextPosition(position);
  9146. module.debug('Trying new position', position);
  9147. return ($popup)
  9148. ? module.set.position(position, calculations)
  9149. : false
  9150. ;
  9151. }
  9152. else if(!settings.lastResort) {
  9153. module.debug('Popup could not find a position in view', $popup);
  9154. // module.error(error.cannotPlace, element);
  9155. module.remove.attempts();
  9156. module.remove.loading();
  9157. module.reset();
  9158. return false;
  9159. }
  9160. }
  9161. module.debug('Position is on stage', position);
  9162. module.remove.attempts();
  9163. module.set.fluidWidth(calculations);
  9164. module.remove.loading();
  9165. return true;
  9166. },
  9167. fluidWidth: function(calculations) {
  9168. calculations = calculations || module.get.calculations();
  9169. if( settings.setFluidWidth && $popup.hasClass(className.fluid) ) {
  9170. $popup.css('width', calculations.parent.width);
  9171. }
  9172. },
  9173. visible: function() {
  9174. $module.addClass(className.visible);
  9175. }
  9176. },
  9177. remove: {
  9178. loading: function() {
  9179. $popup.removeClass(className.loading);
  9180. },
  9181. visible: function() {
  9182. $module.removeClass(className.visible);
  9183. },
  9184. attempts: function() {
  9185. module.verbose('Resetting all searched positions');
  9186. searchDepth = 0;
  9187. triedPositions = false;
  9188. }
  9189. },
  9190. bind: {
  9191. events: function() {
  9192. module.debug('Binding popup events to module');
  9193. if(settings.on == 'click') {
  9194. $module
  9195. .on('click' + eventNamespace, module.toggle)
  9196. ;
  9197. }
  9198. if(settings.on == 'hover' && hasTouch) {
  9199. $module
  9200. .on('touchstart' + eventNamespace, module.event.touchstart)
  9201. ;
  9202. }
  9203. else if( module.get.startEvent() ) {
  9204. $module
  9205. .on(module.get.startEvent() + eventNamespace, module.event.start)
  9206. .on(module.get.endEvent() + eventNamespace, module.event.end)
  9207. ;
  9208. }
  9209. if(settings.target) {
  9210. module.debug('Target set to element', $target);
  9211. }
  9212. $window.on('resize' + elementNamespace, module.event.resize);
  9213. },
  9214. popup: function() {
  9215. module.verbose('Allowing hover events on popup to prevent closing');
  9216. if( $popup && module.has.popup() ) {
  9217. $popup
  9218. .on('mouseenter' + eventNamespace, module.event.start)
  9219. .on('mouseleave' + eventNamespace, module.event.end)
  9220. ;
  9221. }
  9222. },
  9223. close: function() {
  9224. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  9225. $document
  9226. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  9227. ;
  9228. $context
  9229. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  9230. ;
  9231. }
  9232. if(settings.on == 'hover' && openedWithTouch) {
  9233. module.verbose('Binding popup close event to document');
  9234. $document
  9235. .on('touchstart' + elementNamespace, function(event) {
  9236. module.verbose('Touched away from popup');
  9237. module.event.hideGracefully.call(element, event);
  9238. })
  9239. ;
  9240. }
  9241. if(settings.on == 'click' && settings.closable) {
  9242. module.verbose('Binding popup close event to document');
  9243. $document
  9244. .on('click' + elementNamespace, function(event) {
  9245. module.verbose('Clicked away from popup');
  9246. module.event.hideGracefully.call(element, event);
  9247. })
  9248. ;
  9249. }
  9250. }
  9251. },
  9252. unbind: {
  9253. close: function() {
  9254. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  9255. $document
  9256. .off('scroll' + elementNamespace, module.hide)
  9257. ;
  9258. $context
  9259. .off('scroll' + elementNamespace, module.hide)
  9260. ;
  9261. }
  9262. if(settings.on == 'hover' && openedWithTouch) {
  9263. $document
  9264. .off('touchstart' + elementNamespace)
  9265. ;
  9266. openedWithTouch = false;
  9267. }
  9268. if(settings.on == 'click' && settings.closable) {
  9269. module.verbose('Removing close event from document');
  9270. $document
  9271. .off('click' + elementNamespace)
  9272. ;
  9273. }
  9274. }
  9275. },
  9276. has: {
  9277. popup: function() {
  9278. return ($popup && $popup.length > 0);
  9279. }
  9280. },
  9281. is: {
  9282. active: function() {
  9283. return $module.hasClass(className.active);
  9284. },
  9285. animating: function() {
  9286. return ( $popup && $popup.hasClass(className.animating) );
  9287. },
  9288. visible: function() {
  9289. return $popup && $popup.hasClass(className.visible);
  9290. },
  9291. dropdown: function() {
  9292. return $module.hasClass(className.dropdown);
  9293. },
  9294. hidden: function() {
  9295. return !module.is.visible();
  9296. },
  9297. rtl: function () {
  9298. return $module.css('direction') == 'rtl';
  9299. }
  9300. },
  9301. reset: function() {
  9302. module.remove.visible();
  9303. if(settings.preserve) {
  9304. if($.fn.transition !== undefined) {
  9305. $popup
  9306. .transition('remove transition')
  9307. ;
  9308. }
  9309. }
  9310. else {
  9311. module.removePopup();
  9312. }
  9313. },
  9314. setting: function(name, value) {
  9315. if( $.isPlainObject(name) ) {
  9316. $.extend(true, settings, name);
  9317. }
  9318. else if(value !== undefined) {
  9319. settings[name] = value;
  9320. }
  9321. else {
  9322. return settings[name];
  9323. }
  9324. },
  9325. internal: function(name, value) {
  9326. if( $.isPlainObject(name) ) {
  9327. $.extend(true, module, name);
  9328. }
  9329. else if(value !== undefined) {
  9330. module[name] = value;
  9331. }
  9332. else {
  9333. return module[name];
  9334. }
  9335. },
  9336. debug: function() {
  9337. if(settings.debug) {
  9338. if(settings.performance) {
  9339. module.performance.log(arguments);
  9340. }
  9341. else {
  9342. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9343. module.debug.apply(console, arguments);
  9344. }
  9345. }
  9346. },
  9347. verbose: function() {
  9348. if(settings.verbose && settings.debug) {
  9349. if(settings.performance) {
  9350. module.performance.log(arguments);
  9351. }
  9352. else {
  9353. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9354. module.verbose.apply(console, arguments);
  9355. }
  9356. }
  9357. },
  9358. error: function() {
  9359. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  9360. module.error.apply(console, arguments);
  9361. },
  9362. performance: {
  9363. log: function(message) {
  9364. var
  9365. currentTime,
  9366. executionTime,
  9367. previousTime
  9368. ;
  9369. if(settings.performance) {
  9370. currentTime = new Date().getTime();
  9371. previousTime = time || currentTime;
  9372. executionTime = currentTime - previousTime;
  9373. time = currentTime;
  9374. performance.push({
  9375. 'Name' : message[0],
  9376. 'Arguments' : [].slice.call(message, 1) || '',
  9377. 'Element' : element,
  9378. 'Execution Time' : executionTime
  9379. });
  9380. }
  9381. clearTimeout(module.performance.timer);
  9382. module.performance.timer = setTimeout(module.performance.display, 500);
  9383. },
  9384. display: function() {
  9385. var
  9386. title = settings.name + ':',
  9387. totalTime = 0
  9388. ;
  9389. time = false;
  9390. clearTimeout(module.performance.timer);
  9391. $.each(performance, function(index, data) {
  9392. totalTime += data['Execution Time'];
  9393. });
  9394. title += ' ' + totalTime + 'ms';
  9395. if(moduleSelector) {
  9396. title += ' \'' + moduleSelector + '\'';
  9397. }
  9398. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  9399. console.groupCollapsed(title);
  9400. if(console.table) {
  9401. console.table(performance);
  9402. }
  9403. else {
  9404. $.each(performance, function(index, data) {
  9405. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  9406. });
  9407. }
  9408. console.groupEnd();
  9409. }
  9410. performance = [];
  9411. }
  9412. },
  9413. invoke: function(query, passedArguments, context) {
  9414. var
  9415. object = instance,
  9416. maxDepth,
  9417. found,
  9418. response
  9419. ;
  9420. passedArguments = passedArguments || queryArguments;
  9421. context = element || context;
  9422. if(typeof query == 'string' && object !== undefined) {
  9423. query = query.split(/[\. ]/);
  9424. maxDepth = query.length - 1;
  9425. $.each(query, function(depth, value) {
  9426. var camelCaseValue = (depth != maxDepth)
  9427. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  9428. : query
  9429. ;
  9430. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  9431. object = object[camelCaseValue];
  9432. }
  9433. else if( object[camelCaseValue] !== undefined ) {
  9434. found = object[camelCaseValue];
  9435. return false;
  9436. }
  9437. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  9438. object = object[value];
  9439. }
  9440. else if( object[value] !== undefined ) {
  9441. found = object[value];
  9442. return false;
  9443. }
  9444. else {
  9445. return false;
  9446. }
  9447. });
  9448. }
  9449. if ( $.isFunction( found ) ) {
  9450. response = found.apply(context, passedArguments);
  9451. }
  9452. else if(found !== undefined) {
  9453. response = found;
  9454. }
  9455. if($.isArray(returnedValue)) {
  9456. returnedValue.push(response);
  9457. }
  9458. else if(returnedValue !== undefined) {
  9459. returnedValue = [returnedValue, response];
  9460. }
  9461. else if(response !== undefined) {
  9462. returnedValue = response;
  9463. }
  9464. return found;
  9465. }
  9466. };
  9467. if(methodInvoked) {
  9468. if(instance === undefined) {
  9469. module.initialize();
  9470. }
  9471. module.invoke(query);
  9472. }
  9473. else {
  9474. if(instance !== undefined) {
  9475. instance.invoke('destroy');
  9476. }
  9477. module.initialize();
  9478. }
  9479. })
  9480. ;
  9481. return (returnedValue !== undefined)
  9482. ? returnedValue
  9483. : this
  9484. ;
  9485. };
  9486. $.fn.popup.settings = {
  9487. name : 'Popup',
  9488. // module settings
  9489. debug : false,
  9490. verbose : false,
  9491. performance : true,
  9492. namespace : 'popup',
  9493. // callback only when element added to dom
  9494. onCreate : function(){},
  9495. // callback before element removed from dom
  9496. onRemove : function(){},
  9497. // callback before show animation
  9498. onShow : function(){},
  9499. // callback after show animation
  9500. onVisible : function(){},
  9501. // callback before hide animation
  9502. onHide : function(){},
  9503. // callback after hide animation
  9504. onHidden : function(){},
  9505. // when to show popup
  9506. on : 'hover',
  9507. // whether to add touchstart events when using hover
  9508. addTouchEvents : true,
  9509. // default position relative to element
  9510. position : 'top left',
  9511. // name of variation to use
  9512. variation : '',
  9513. // whether popup should be moved to context
  9514. movePopup : true,
  9515. // element which popup should be relative to
  9516. target : false,
  9517. // jq selector or element that should be used as popup
  9518. popup : false,
  9519. // popup should remain inline next to activator
  9520. inline : false,
  9521. // popup should be removed from page on hide
  9522. preserve : true,
  9523. // popup should not close when being hovered on
  9524. hoverable : false,
  9525. // explicitly set content
  9526. content : false,
  9527. // explicitly set html
  9528. html : false,
  9529. // explicitly set title
  9530. title : false,
  9531. // whether automatically close on clickaway when on click
  9532. closable : true,
  9533. // automatically hide on scroll
  9534. hideOnScroll : 'auto',
  9535. // hide other popups on show
  9536. exclusive : false,
  9537. // context to attach popups
  9538. context : 'body',
  9539. // position to prefer when calculating new position
  9540. prefer : 'opposite',
  9541. // specify position to appear even if it doesn't fit
  9542. lastResort : false,
  9543. // delay used to prevent accidental refiring of animations due to user error
  9544. delay : {
  9545. show : 50,
  9546. hide : 70
  9547. },
  9548. // whether fluid variation should assign width explicitly
  9549. setFluidWidth : true,
  9550. // transition settings
  9551. duration : 200,
  9552. transition : 'scale',
  9553. // distance away from activating element in px
  9554. distanceAway : 0,
  9555. // offset on aligning axis from calculated position
  9556. offset : 0,
  9557. // maximum times to look for a position before failing (9 positions total)
  9558. maxSearchDepth : 20,
  9559. error: {
  9560. invalidPosition : 'The position you specified is not a valid position',
  9561. cannotPlace : 'No visible position could be found for the popup',
  9562. method : 'The method you called is not defined.',
  9563. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  9564. notFound : 'The target or popup you specified does not exist on the page'
  9565. },
  9566. metadata: {
  9567. activator : 'activator',
  9568. content : 'content',
  9569. html : 'html',
  9570. offset : 'offset',
  9571. position : 'position',
  9572. title : 'title',
  9573. variation : 'variation'
  9574. },
  9575. className : {
  9576. active : 'active',
  9577. animating : 'animating',
  9578. dropdown : 'dropdown',
  9579. fluid : 'fluid',
  9580. loading : 'loading',
  9581. popup : 'ui popup',
  9582. position : 'top left center bottom right',
  9583. visible : 'visible'
  9584. },
  9585. selector : {
  9586. popup : '.ui.popup'
  9587. },
  9588. templates: {
  9589. escape: function(string) {
  9590. var
  9591. badChars = /[&<>"'`]/g,
  9592. shouldEscape = /[&<>"'`]/,
  9593. escape = {
  9594. "&": "&amp;",
  9595. "<": "&lt;",
  9596. ">": "&gt;",
  9597. '"': "&quot;",
  9598. "'": "&#x27;",
  9599. "`": "&#x60;"
  9600. },
  9601. escapedChar = function(chr) {
  9602. return escape[chr];
  9603. }
  9604. ;
  9605. if(shouldEscape.test(string)) {
  9606. return string.replace(badChars, escapedChar);
  9607. }
  9608. return string;
  9609. },
  9610. popup: function(text) {
  9611. var
  9612. html = '',
  9613. escape = $.fn.popup.settings.templates.escape
  9614. ;
  9615. if(typeof text !== undefined) {
  9616. if(typeof text.title !== undefined && text.title) {
  9617. text.title = escape(text.title);
  9618. html += '<div class="header">' + text.title + '</div>';
  9619. }
  9620. if(typeof text.content !== undefined && text.content) {
  9621. text.content = escape(text.content);
  9622. html += '<div class="content">' + text.content + '</div>';
  9623. }
  9624. }
  9625. return html;
  9626. }
  9627. }
  9628. };
  9629. })( jQuery, window , document );
  9630. /*!
  9631. * # Semantic UI 2.0.0 - Progress
  9632. * http://github.com/semantic-org/semantic-ui/
  9633. *
  9634. *
  9635. * Copyright 2015 Contributors
  9636. * Released under the MIT license
  9637. * http://opensource.org/licenses/MIT
  9638. *
  9639. */
  9640. ;(function ( $, window, document, undefined ) {
  9641. "use strict";
  9642. $.fn.progress = function(parameters) {
  9643. var
  9644. $allModules = $(this),
  9645. moduleSelector = $allModules.selector || '',
  9646. time = new Date().getTime(),
  9647. performance = [],
  9648. query = arguments[0],
  9649. methodInvoked = (typeof query == 'string'),
  9650. queryArguments = [].slice.call(arguments, 1),
  9651. returnedValue
  9652. ;
  9653. $allModules
  9654. .each(function() {
  9655. var
  9656. settings = ( $.isPlainObject(parameters) )
  9657. ? $.extend(true, {}, $.fn.progress.settings, parameters)
  9658. : $.extend({}, $.fn.progress.settings),
  9659. className = settings.className,
  9660. metadata = settings.metadata,
  9661. namespace = settings.namespace,
  9662. selector = settings.selector,
  9663. error = settings.error,
  9664. eventNamespace = '.' + namespace,
  9665. moduleNamespace = 'module-' + namespace,
  9666. $module = $(this),
  9667. $bar = $(this).find(selector.bar),
  9668. $progress = $(this).find(selector.progress),
  9669. $label = $(this).find(selector.label),
  9670. element = this,
  9671. instance = $module.data(moduleNamespace),
  9672. animating = false,
  9673. transitionEnd,
  9674. module
  9675. ;
  9676. module = {
  9677. initialize: function() {
  9678. module.debug('Initializing progress bar', settings);
  9679. module.set.duration();
  9680. module.set.transitionEvent();
  9681. module.read.metadata();
  9682. module.read.settings();
  9683. module.instantiate();
  9684. },
  9685. instantiate: function() {
  9686. module.verbose('Storing instance of progress', module);
  9687. instance = module;
  9688. $module
  9689. .data(moduleNamespace, module)
  9690. ;
  9691. },
  9692. destroy: function() {
  9693. module.verbose('Destroying previous progress for', $module);
  9694. clearInterval(instance.interval);
  9695. module.remove.state();
  9696. $module.removeData(moduleNamespace);
  9697. instance = undefined;
  9698. },
  9699. reset: function() {
  9700. module.set.percent(0);
  9701. },
  9702. complete: function() {
  9703. if(module.percent === undefined || module.percent < 100) {
  9704. module.set.percent(100);
  9705. }
  9706. },
  9707. read: {
  9708. metadata: function() {
  9709. var
  9710. data = {
  9711. percent : $module.data(metadata.percent),
  9712. total : $module.data(metadata.total),
  9713. value : $module.data(metadata.value)
  9714. }
  9715. ;
  9716. if(data.percent) {
  9717. module.debug('Current percent value set from metadata', data.percent);
  9718. module.set.percent(data.percent);
  9719. }
  9720. if(data.total) {
  9721. module.debug('Total value set from metadata', data.total);
  9722. module.set.total(data.total);
  9723. }
  9724. if(data.value) {
  9725. module.debug('Current value set from metadata', data.value);
  9726. module.set.value(data.value);
  9727. }
  9728. },
  9729. settings: function() {
  9730. if(settings.total !== false) {
  9731. module.debug('Current total set in settings', settings.total);
  9732. module.set.total(settings.total);
  9733. }
  9734. if(settings.value !== false) {
  9735. module.debug('Current value set in settings', settings.value);
  9736. module.set.value(settings.value);
  9737. module.set.progress(module.value);
  9738. }
  9739. if(settings.percent !== false) {
  9740. module.debug('Current percent set in settings', settings.percent);
  9741. module.set.percent(settings.percent);
  9742. }
  9743. }
  9744. },
  9745. increment: function(incrementValue) {
  9746. var
  9747. maxValue,
  9748. startValue,
  9749. newValue
  9750. ;
  9751. if( module.has.total() ) {
  9752. startValue = module.get.value();
  9753. incrementValue = incrementValue || 1;
  9754. newValue = startValue + incrementValue;
  9755. maxValue = module.get.total();
  9756. module.debug('Incrementing value', startValue, newValue, maxValue);
  9757. if(newValue > maxValue ) {
  9758. module.debug('Value cannot increment above total', maxValue);
  9759. newValue = maxValue;
  9760. }
  9761. }
  9762. else {
  9763. startValue = module.get.percent();
  9764. incrementValue = incrementValue || module.get.randomValue();
  9765. newValue = startValue + incrementValue;
  9766. maxValue = 100;
  9767. module.debug('Incrementing percentage by', startValue, newValue);
  9768. if(newValue > maxValue ) {
  9769. module.debug('Value cannot increment above 100 percent');
  9770. newValue = maxValue;
  9771. }
  9772. }
  9773. module.set.progress(newValue);
  9774. },
  9775. decrement: function(decrementValue) {
  9776. var
  9777. total = module.get.total(),
  9778. startValue,
  9779. newValue
  9780. ;
  9781. if(total) {
  9782. startValue = module.get.value();
  9783. decrementValue = decrementValue || 1;
  9784. newValue = startValue - decrementValue;
  9785. module.debug('Decrementing value by', decrementValue, startValue);
  9786. }
  9787. else {
  9788. startValue = module.get.percent();
  9789. decrementValue = decrementValue || module.get.randomValue();
  9790. newValue = startValue - decrementValue;
  9791. module.debug('Decrementing percentage by', decrementValue, startValue);
  9792. }
  9793. if(newValue < 0) {
  9794. module.debug('Value cannot decrement below 0');
  9795. newValue = 0;
  9796. }
  9797. module.set.progress(newValue);
  9798. },
  9799. has: {
  9800. total: function() {
  9801. return (module.get.total() !== false);
  9802. }
  9803. },
  9804. get: {
  9805. text: function(templateText) {
  9806. var
  9807. value = module.value || 0,
  9808. total = module.total || 0,
  9809. percent = (animating)
  9810. ? module.get.displayPercent()
  9811. : module.percent || 0,
  9812. left = (module.total > 0)
  9813. ? (total - value)
  9814. : (100 - percent)
  9815. ;
  9816. templateText = templateText || '';
  9817. templateText = templateText
  9818. .replace('{value}', value)
  9819. .replace('{total}', total)
  9820. .replace('{left}', left)
  9821. .replace('{percent}', percent)
  9822. ;
  9823. module.debug('Adding variables to progress bar text', templateText);
  9824. return templateText;
  9825. },
  9826. randomValue: function() {
  9827. module.debug('Generating random increment percentage');
  9828. return Math.floor((Math.random() * settings.random.max) + settings.random.min);
  9829. },
  9830. numericValue: function(value) {
  9831. return (typeof value === 'string')
  9832. ? (value.replace(/[^\d.]/g, '') !== '')
  9833. ? +(value.replace(/[^\d.]/g, ''))
  9834. : false
  9835. : value
  9836. ;
  9837. },
  9838. transitionEnd: function() {
  9839. var
  9840. element = document.createElement('element'),
  9841. transitions = {
  9842. 'transition' :'transitionend',
  9843. 'OTransition' :'oTransitionEnd',
  9844. 'MozTransition' :'transitionend',
  9845. 'WebkitTransition' :'webkitTransitionEnd'
  9846. },
  9847. transition
  9848. ;
  9849. for(transition in transitions){
  9850. if( element.style[transition] !== undefined ){
  9851. return transitions[transition];
  9852. }
  9853. }
  9854. },
  9855. // gets current displayed percentage (if animating values this is the intermediary value)
  9856. displayPercent: function() {
  9857. var
  9858. barWidth = $bar.width(),
  9859. totalWidth = $module.width(),
  9860. minDisplay = parseInt($bar.css('min-width'), 10),
  9861. displayPercent = (barWidth > minDisplay)
  9862. ? (barWidth / totalWidth * 100)
  9863. : module.percent
  9864. ;
  9865. return (settings.precision > 0)
  9866. ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
  9867. : Math.round(displayPercent)
  9868. ;
  9869. },
  9870. percent: function() {
  9871. return module.percent || 0;
  9872. },
  9873. value: function() {
  9874. return module.value || 0;
  9875. },
  9876. total: function() {
  9877. return module.total || false;
  9878. }
  9879. },
  9880. is: {
  9881. success: function() {
  9882. return $module.hasClass(className.success);
  9883. },
  9884. warning: function() {
  9885. return $module.hasClass(className.warning);
  9886. },
  9887. error: function() {
  9888. return $module.hasClass(className.error);
  9889. },
  9890. active: function() {
  9891. return $module.hasClass(className.active);
  9892. },
  9893. visible: function() {
  9894. return $module.is(':visible');
  9895. }
  9896. },
  9897. remove: {
  9898. state: function() {
  9899. module.verbose('Removing stored state');
  9900. delete module.total;
  9901. delete module.percent;
  9902. delete module.value;
  9903. },
  9904. active: function() {
  9905. module.verbose('Removing active state');
  9906. $module.removeClass(className.active);
  9907. },
  9908. success: function() {
  9909. module.verbose('Removing success state');
  9910. $module.removeClass(className.success);
  9911. },
  9912. warning: function() {
  9913. module.verbose('Removing warning state');
  9914. $module.removeClass(className.warning);
  9915. },
  9916. error: function() {
  9917. module.verbose('Removing error state');
  9918. $module.removeClass(className.error);
  9919. }
  9920. },
  9921. set: {
  9922. barWidth: function(value) {
  9923. if(value > 100) {
  9924. module.error(error.tooHigh, value);
  9925. }
  9926. else if (value < 0) {
  9927. module.error(error.tooLow, value);
  9928. }
  9929. else {
  9930. $bar
  9931. .css('width', value + '%')
  9932. ;
  9933. $module
  9934. .attr('data-percent', parseInt(value, 10))
  9935. ;
  9936. }
  9937. },
  9938. duration: function(duration) {
  9939. duration = duration || settings.duration;
  9940. duration = (typeof duration == 'number')
  9941. ? duration + 'ms'
  9942. : duration
  9943. ;
  9944. module.verbose('Setting progress bar transition duration', duration);
  9945. $bar
  9946. .css({
  9947. 'transition-duration': duration
  9948. })
  9949. ;
  9950. },
  9951. percent: function(percent) {
  9952. percent = (typeof percent == 'string')
  9953. ? +(percent.replace('%', ''))
  9954. : percent
  9955. ;
  9956. // round display percentage
  9957. percent = (settings.precision > 0)
  9958. ? Math.round(percent * (10 * settings.precision)) / (10 * settings.precision)
  9959. : Math.round(percent)
  9960. ;
  9961. module.percent = percent;
  9962. if( !module.has.total() ) {
  9963. module.value = (settings.precision > 0)
  9964. ? Math.round( (percent / 100) * module.total * (10 * settings.precision)) / (10 * settings.precision)
  9965. : Math.round( (percent / 100) * module.total * 10) / 10
  9966. ;
  9967. if(settings.limitValues) {
  9968. module.value = (module.value > 100)
  9969. ? 100
  9970. : (module.value < 0)
  9971. ? 0
  9972. : module.value
  9973. ;
  9974. }
  9975. }
  9976. module.set.barWidth(percent);
  9977. module.set.labelInterval();
  9978. module.set.labels();
  9979. settings.onChange.call(element, percent, module.value, module.total);
  9980. },
  9981. labelInterval: function() {
  9982. var
  9983. animationCallback = function() {
  9984. module.verbose('Bar finished animating, removing continuous label updates');
  9985. clearInterval(module.interval);
  9986. animating = false;
  9987. module.set.labels();
  9988. }
  9989. ;
  9990. clearInterval(module.interval);
  9991. $bar.one(transitionEnd + eventNamespace, animationCallback);
  9992. module.timer = setTimeout(animationCallback, settings.duration + 100);
  9993. animating = true;
  9994. module.interval = setInterval(module.set.labels, settings.framerate);
  9995. },
  9996. labels: function() {
  9997. module.verbose('Setting both bar progress and outer label text');
  9998. module.set.barLabel();
  9999. module.set.state();
  10000. },
  10001. label: function(text) {
  10002. text = text || '';
  10003. if(text) {
  10004. text = module.get.text(text);
  10005. module.debug('Setting label to text', text);
  10006. $label.text(text);
  10007. }
  10008. },
  10009. state: function(percent) {
  10010. percent = (percent !== undefined)
  10011. ? percent
  10012. : module.percent
  10013. ;
  10014. if(percent === 100) {
  10015. if(settings.autoSuccess && !(module.is.warning() || module.is.error())) {
  10016. module.set.success();
  10017. module.debug('Automatically triggering success at 100%');
  10018. }
  10019. else {
  10020. module.verbose('Reached 100% removing active state');
  10021. module.remove.active();
  10022. }
  10023. }
  10024. else if(percent > 0) {
  10025. module.verbose('Adjusting active progress bar label', percent);
  10026. module.set.active();
  10027. }
  10028. else {
  10029. module.remove.active();
  10030. module.set.label(settings.text.active);
  10031. }
  10032. },
  10033. barLabel: function(text) {
  10034. if(text !== undefined) {
  10035. $progress.text( module.get.text(text) );
  10036. }
  10037. else if(settings.label == 'ratio' && module.total) {
  10038. module.debug('Adding ratio to bar label');
  10039. $progress.text( module.get.text(settings.text.ratio) );
  10040. }
  10041. else if(settings.label == 'percent') {
  10042. module.debug('Adding percentage to bar label');
  10043. $progress.text( module.get.text(settings.text.percent) );
  10044. }
  10045. },
  10046. active: function(text) {
  10047. text = text || settings.text.active;
  10048. module.debug('Setting active state');
  10049. if(settings.showActivity && !module.is.active() ) {
  10050. $module.addClass(className.active);
  10051. }
  10052. module.remove.warning();
  10053. module.remove.error();
  10054. module.remove.success();
  10055. if(text) {
  10056. module.set.label(text);
  10057. }
  10058. settings.onActive.call(element, module.value, module.total);
  10059. },
  10060. success : function(text) {
  10061. text = text || settings.text.success;
  10062. module.debug('Setting success state');
  10063. $module.addClass(className.success);
  10064. module.remove.active();
  10065. module.remove.warning();
  10066. module.remove.error();
  10067. module.complete();
  10068. if(text) {
  10069. module.set.label(text);
  10070. }
  10071. settings.onSuccess.call(element, module.total);
  10072. },
  10073. warning : function(text) {
  10074. text = text || settings.text.warning;
  10075. module.debug('Setting warning state');
  10076. $module.addClass(className.warning);
  10077. module.remove.active();
  10078. module.remove.success();
  10079. module.remove.error();
  10080. module.complete();
  10081. if(text) {
  10082. module.set.label(text);
  10083. }
  10084. settings.onWarning.call(element, module.value, module.total);
  10085. },
  10086. error : function(text) {
  10087. text = text || settings.text.error;
  10088. module.debug('Setting error state');
  10089. $module.addClass(className.error);
  10090. module.remove.active();
  10091. module.remove.success();
  10092. module.remove.warning();
  10093. module.complete();
  10094. if(text) {
  10095. module.set.label(text);
  10096. }
  10097. settings.onError.call(element, module.value, module.total);
  10098. },
  10099. transitionEvent: function() {
  10100. transitionEnd = module.get.transitionEnd();
  10101. },
  10102. total: function(totalValue) {
  10103. module.total = totalValue;
  10104. },
  10105. value: function(value) {
  10106. module.value = value;
  10107. },
  10108. progress: function(value) {
  10109. var
  10110. numericValue = module.get.numericValue(value),
  10111. percentComplete
  10112. ;
  10113. if(numericValue === false) {
  10114. module.error(error.nonNumeric, value);
  10115. }
  10116. if( module.has.total() ) {
  10117. module.set.value(numericValue);
  10118. percentComplete = (numericValue / module.total) * 100;
  10119. module.debug('Calculating percent complete from total', percentComplete);
  10120. module.set.percent( percentComplete );
  10121. }
  10122. else {
  10123. percentComplete = numericValue;
  10124. module.debug('Setting value to exact percentage value', percentComplete);
  10125. module.set.percent( percentComplete );
  10126. }
  10127. }
  10128. },
  10129. setting: function(name, value) {
  10130. module.debug('Changing setting', name, value);
  10131. if( $.isPlainObject(name) ) {
  10132. $.extend(true, settings, name);
  10133. }
  10134. else if(value !== undefined) {
  10135. settings[name] = value;
  10136. }
  10137. else {
  10138. return settings[name];
  10139. }
  10140. },
  10141. internal: function(name, value) {
  10142. if( $.isPlainObject(name) ) {
  10143. $.extend(true, module, name);
  10144. }
  10145. else if(value !== undefined) {
  10146. module[name] = value;
  10147. }
  10148. else {
  10149. return module[name];
  10150. }
  10151. },
  10152. debug: function() {
  10153. if(settings.debug) {
  10154. if(settings.performance) {
  10155. module.performance.log(arguments);
  10156. }
  10157. else {
  10158. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10159. module.debug.apply(console, arguments);
  10160. }
  10161. }
  10162. },
  10163. verbose: function() {
  10164. if(settings.verbose && settings.debug) {
  10165. if(settings.performance) {
  10166. module.performance.log(arguments);
  10167. }
  10168. else {
  10169. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10170. module.verbose.apply(console, arguments);
  10171. }
  10172. }
  10173. },
  10174. error: function() {
  10175. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  10176. module.error.apply(console, arguments);
  10177. },
  10178. performance: {
  10179. log: function(message) {
  10180. var
  10181. currentTime,
  10182. executionTime,
  10183. previousTime
  10184. ;
  10185. if(settings.performance) {
  10186. currentTime = new Date().getTime();
  10187. previousTime = time || currentTime;
  10188. executionTime = currentTime - previousTime;
  10189. time = currentTime;
  10190. performance.push({
  10191. 'Name' : message[0],
  10192. 'Arguments' : [].slice.call(message, 1) || '',
  10193. 'Element' : element,
  10194. 'Execution Time' : executionTime
  10195. });
  10196. }
  10197. clearTimeout(module.performance.timer);
  10198. module.performance.timer = setTimeout(module.performance.display, 500);
  10199. },
  10200. display: function() {
  10201. var
  10202. title = settings.name + ':',
  10203. totalTime = 0
  10204. ;
  10205. time = false;
  10206. clearTimeout(module.performance.timer);
  10207. $.each(performance, function(index, data) {
  10208. totalTime += data['Execution Time'];
  10209. });
  10210. title += ' ' + totalTime + 'ms';
  10211. if(moduleSelector) {
  10212. title += ' \'' + moduleSelector + '\'';
  10213. }
  10214. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  10215. console.groupCollapsed(title);
  10216. if(console.table) {
  10217. console.table(performance);
  10218. }
  10219. else {
  10220. $.each(performance, function(index, data) {
  10221. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  10222. });
  10223. }
  10224. console.groupEnd();
  10225. }
  10226. performance = [];
  10227. }
  10228. },
  10229. invoke: function(query, passedArguments, context) {
  10230. var
  10231. object = instance,
  10232. maxDepth,
  10233. found,
  10234. response
  10235. ;
  10236. passedArguments = passedArguments || queryArguments;
  10237. context = element || context;
  10238. if(typeof query == 'string' && object !== undefined) {
  10239. query = query.split(/[\. ]/);
  10240. maxDepth = query.length - 1;
  10241. $.each(query, function(depth, value) {
  10242. var camelCaseValue = (depth != maxDepth)
  10243. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  10244. : query
  10245. ;
  10246. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  10247. object = object[camelCaseValue];
  10248. }
  10249. else if( object[camelCaseValue] !== undefined ) {
  10250. found = object[camelCaseValue];
  10251. return false;
  10252. }
  10253. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  10254. object = object[value];
  10255. }
  10256. else if( object[value] !== undefined ) {
  10257. found = object[value];
  10258. return false;
  10259. }
  10260. else {
  10261. module.error(error.method, query);
  10262. return false;
  10263. }
  10264. });
  10265. }
  10266. if ( $.isFunction( found ) ) {
  10267. response = found.apply(context, passedArguments);
  10268. }
  10269. else if(found !== undefined) {
  10270. response = found;
  10271. }
  10272. if($.isArray(returnedValue)) {
  10273. returnedValue.push(response);
  10274. }
  10275. else if(returnedValue !== undefined) {
  10276. returnedValue = [returnedValue, response];
  10277. }
  10278. else if(response !== undefined) {
  10279. returnedValue = response;
  10280. }
  10281. return found;
  10282. }
  10283. };
  10284. if(methodInvoked) {
  10285. if(instance === undefined) {
  10286. module.initialize();
  10287. }
  10288. module.invoke(query);
  10289. }
  10290. else {
  10291. if(instance !== undefined) {
  10292. instance.invoke('destroy');
  10293. }
  10294. module.initialize();
  10295. }
  10296. })
  10297. ;
  10298. return (returnedValue !== undefined)
  10299. ? returnedValue
  10300. : this
  10301. ;
  10302. };
  10303. $.fn.progress.settings = {
  10304. name : 'Progress',
  10305. namespace : 'progress',
  10306. debug : true,
  10307. verbose : false,
  10308. performance : true,
  10309. random : {
  10310. min : 2,
  10311. max : 5
  10312. },
  10313. duration : 300,
  10314. autoSuccess : true,
  10315. showActivity : true,
  10316. limitValues : true,
  10317. label : 'percent',
  10318. precision : 0,
  10319. framerate : (1000 / 30), /// 30 fps
  10320. percent : false,
  10321. total : false,
  10322. value : false,
  10323. onChange : function(percent, value, total){},
  10324. onSuccess : function(total){},
  10325. onActive : function(value, total){},
  10326. onError : function(value, total){},
  10327. onWarning : function(value, total){},
  10328. error : {
  10329. method : 'The method you called is not defined.',
  10330. nonNumeric : 'Progress value is non numeric',
  10331. tooHigh : 'Value specified is above 100%',
  10332. tooLow : 'Value specified is below 0%'
  10333. },
  10334. regExp: {
  10335. variable: /\{\$*[A-z0-9]+\}/g
  10336. },
  10337. metadata: {
  10338. percent : 'percent',
  10339. total : 'total',
  10340. value : 'value'
  10341. },
  10342. selector : {
  10343. bar : '> .bar',
  10344. label : '> .label',
  10345. progress : '.bar > .progress'
  10346. },
  10347. text : {
  10348. active : false,
  10349. error : false,
  10350. success : false,
  10351. warning : false,
  10352. percent : '{percent}%',
  10353. ratio : '{value} of {total}'
  10354. },
  10355. className : {
  10356. active : 'active',
  10357. error : 'error',
  10358. success : 'success',
  10359. warning : 'warning'
  10360. }
  10361. };
  10362. })( jQuery, window , document );
  10363. /*!
  10364. * # Semantic UI 2.0.0 - Rating
  10365. * http://github.com/semantic-org/semantic-ui/
  10366. *
  10367. *
  10368. * Copyright 2015 Contributors
  10369. * Released under the MIT license
  10370. * http://opensource.org/licenses/MIT
  10371. *
  10372. */
  10373. ;(function ($, window, document, undefined) {
  10374. "use strict";
  10375. $.fn.rating = function(parameters) {
  10376. var
  10377. $allModules = $(this),
  10378. moduleSelector = $allModules.selector || '',
  10379. time = new Date().getTime(),
  10380. performance = [],
  10381. query = arguments[0],
  10382. methodInvoked = (typeof query == 'string'),
  10383. queryArguments = [].slice.call(arguments, 1),
  10384. returnedValue
  10385. ;
  10386. $allModules
  10387. .each(function() {
  10388. var
  10389. settings = ( $.isPlainObject(parameters) )
  10390. ? $.extend(true, {}, $.fn.rating.settings, parameters)
  10391. : $.extend({}, $.fn.rating.settings),
  10392. namespace = settings.namespace,
  10393. className = settings.className,
  10394. metadata = settings.metadata,
  10395. selector = settings.selector,
  10396. error = settings.error,
  10397. eventNamespace = '.' + namespace,
  10398. moduleNamespace = 'module-' + namespace,
  10399. element = this,
  10400. instance = $(this).data(moduleNamespace),
  10401. $module = $(this),
  10402. $icon = $module.find(selector.icon),
  10403. module
  10404. ;
  10405. module = {
  10406. initialize: function() {
  10407. module.verbose('Initializing rating module', settings);
  10408. if($icon.length === 0) {
  10409. module.setup.layout();
  10410. }
  10411. if(settings.interactive) {
  10412. module.enable();
  10413. }
  10414. else {
  10415. module.disable();
  10416. }
  10417. module.set.rating( module.get.initialRating() );
  10418. module.instantiate();
  10419. },
  10420. instantiate: function() {
  10421. module.verbose('Instantiating module', settings);
  10422. instance = module;
  10423. $module
  10424. .data(moduleNamespace, module)
  10425. ;
  10426. },
  10427. destroy: function() {
  10428. module.verbose('Destroying previous instance', instance);
  10429. module.remove.events();
  10430. $module
  10431. .removeData(moduleNamespace)
  10432. ;
  10433. },
  10434. refresh: function() {
  10435. $icon = $module.find(selector.icon);
  10436. },
  10437. setup: {
  10438. layout: function() {
  10439. var
  10440. maxRating = module.get.maxRating(),
  10441. html = $.fn.rating.settings.templates.icon(maxRating)
  10442. ;
  10443. module.debug('Generating icon html dynamically');
  10444. $module
  10445. .html(html)
  10446. ;
  10447. module.refresh();
  10448. }
  10449. },
  10450. event: {
  10451. mouseenter: function() {
  10452. var
  10453. $activeIcon = $(this)
  10454. ;
  10455. $activeIcon
  10456. .nextAll()
  10457. .removeClass(className.selected)
  10458. ;
  10459. $module
  10460. .addClass(className.selected)
  10461. ;
  10462. $activeIcon
  10463. .addClass(className.selected)
  10464. .prevAll()
  10465. .addClass(className.selected)
  10466. ;
  10467. },
  10468. mouseleave: function() {
  10469. $module
  10470. .removeClass(className.selected)
  10471. ;
  10472. $icon
  10473. .removeClass(className.selected)
  10474. ;
  10475. },
  10476. click: function() {
  10477. var
  10478. $activeIcon = $(this),
  10479. currentRating = module.get.rating(),
  10480. rating = $icon.index($activeIcon) + 1,
  10481. canClear = (settings.clearable == 'auto')
  10482. ? ($icon.length === 1)
  10483. : settings.clearable
  10484. ;
  10485. if(canClear && currentRating == rating) {
  10486. module.clearRating();
  10487. }
  10488. else {
  10489. module.set.rating( rating );
  10490. }
  10491. }
  10492. },
  10493. clearRating: function() {
  10494. module.debug('Clearing current rating');
  10495. module.set.rating(0);
  10496. },
  10497. bind: {
  10498. events: function() {
  10499. module.verbose('Binding events');
  10500. $module
  10501. .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
  10502. .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
  10503. .on('click' + eventNamespace, selector.icon, module.event.click)
  10504. ;
  10505. }
  10506. },
  10507. remove: {
  10508. events: function() {
  10509. module.verbose('Removing events');
  10510. $module
  10511. .off(eventNamespace)
  10512. ;
  10513. }
  10514. },
  10515. enable: function() {
  10516. module.debug('Setting rating to interactive mode');
  10517. module.bind.events();
  10518. $module
  10519. .removeClass(className.disabled)
  10520. ;
  10521. },
  10522. disable: function() {
  10523. module.debug('Setting rating to read-only mode');
  10524. module.remove.events();
  10525. $module
  10526. .addClass(className.disabled)
  10527. ;
  10528. },
  10529. get: {
  10530. initialRating: function() {
  10531. if($module.data(metadata.rating) !== undefined) {
  10532. $module.removeData(metadata.rating);
  10533. return $module.data(metadata.rating);
  10534. }
  10535. return settings.initialRating;
  10536. },
  10537. maxRating: function() {
  10538. if($module.data(metadata.maxRating) !== undefined) {
  10539. $module.removeData(metadata.maxRating);
  10540. return $module.data(metadata.maxRating);
  10541. }
  10542. return settings.maxRating;
  10543. },
  10544. rating: function() {
  10545. var
  10546. currentRating = $icon.filter('.' + className.active).length
  10547. ;
  10548. module.verbose('Current rating retrieved', currentRating);
  10549. return currentRating;
  10550. }
  10551. },
  10552. set: {
  10553. rating: function(rating) {
  10554. var
  10555. ratingIndex = (rating - 1 >= 0)
  10556. ? (rating - 1)
  10557. : 0,
  10558. $activeIcon = $icon.eq(ratingIndex)
  10559. ;
  10560. $module
  10561. .removeClass(className.selected)
  10562. ;
  10563. $icon
  10564. .removeClass(className.selected)
  10565. .removeClass(className.active)
  10566. ;
  10567. if(rating > 0) {
  10568. module.verbose('Setting current rating to', rating);
  10569. $activeIcon
  10570. .prevAll()
  10571. .andSelf()
  10572. .addClass(className.active)
  10573. ;
  10574. }
  10575. settings.onRate.call(element, rating);
  10576. }
  10577. },
  10578. setting: function(name, value) {
  10579. module.debug('Changing setting', name, value);
  10580. if( $.isPlainObject(name) ) {
  10581. $.extend(true, settings, name);
  10582. }
  10583. else if(value !== undefined) {
  10584. settings[name] = value;
  10585. }
  10586. else {
  10587. return settings[name];
  10588. }
  10589. },
  10590. internal: function(name, value) {
  10591. if( $.isPlainObject(name) ) {
  10592. $.extend(true, module, name);
  10593. }
  10594. else if(value !== undefined) {
  10595. module[name] = value;
  10596. }
  10597. else {
  10598. return module[name];
  10599. }
  10600. },
  10601. debug: function() {
  10602. if(settings.debug) {
  10603. if(settings.performance) {
  10604. module.performance.log(arguments);
  10605. }
  10606. else {
  10607. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10608. module.debug.apply(console, arguments);
  10609. }
  10610. }
  10611. },
  10612. verbose: function() {
  10613. if(settings.verbose && settings.debug) {
  10614. if(settings.performance) {
  10615. module.performance.log(arguments);
  10616. }
  10617. else {
  10618. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10619. module.verbose.apply(console, arguments);
  10620. }
  10621. }
  10622. },
  10623. error: function() {
  10624. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  10625. module.error.apply(console, arguments);
  10626. },
  10627. performance: {
  10628. log: function(message) {
  10629. var
  10630. currentTime,
  10631. executionTime,
  10632. previousTime
  10633. ;
  10634. if(settings.performance) {
  10635. currentTime = new Date().getTime();
  10636. previousTime = time || currentTime;
  10637. executionTime = currentTime - previousTime;
  10638. time = currentTime;
  10639. performance.push({
  10640. 'Name' : message[0],
  10641. 'Arguments' : [].slice.call(message, 1) || '',
  10642. 'Element' : element,
  10643. 'Execution Time' : executionTime
  10644. });
  10645. }
  10646. clearTimeout(module.performance.timer);
  10647. module.performance.timer = setTimeout(module.performance.display, 500);
  10648. },
  10649. display: function() {
  10650. var
  10651. title = settings.name + ':',
  10652. totalTime = 0
  10653. ;
  10654. time = false;
  10655. clearTimeout(module.performance.timer);
  10656. $.each(performance, function(index, data) {
  10657. totalTime += data['Execution Time'];
  10658. });
  10659. title += ' ' + totalTime + 'ms';
  10660. if(moduleSelector) {
  10661. title += ' \'' + moduleSelector + '\'';
  10662. }
  10663. if($allModules.length > 1) {
  10664. title += ' ' + '(' + $allModules.length + ')';
  10665. }
  10666. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  10667. console.groupCollapsed(title);
  10668. if(console.table) {
  10669. console.table(performance);
  10670. }
  10671. else {
  10672. $.each(performance, function(index, data) {
  10673. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  10674. });
  10675. }
  10676. console.groupEnd();
  10677. }
  10678. performance = [];
  10679. }
  10680. },
  10681. invoke: function(query, passedArguments, context) {
  10682. var
  10683. object = instance,
  10684. maxDepth,
  10685. found,
  10686. response
  10687. ;
  10688. passedArguments = passedArguments || queryArguments;
  10689. context = element || context;
  10690. if(typeof query == 'string' && object !== undefined) {
  10691. query = query.split(/[\. ]/);
  10692. maxDepth = query.length - 1;
  10693. $.each(query, function(depth, value) {
  10694. var camelCaseValue = (depth != maxDepth)
  10695. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  10696. : query
  10697. ;
  10698. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  10699. object = object[camelCaseValue];
  10700. }
  10701. else if( object[camelCaseValue] !== undefined ) {
  10702. found = object[camelCaseValue];
  10703. return false;
  10704. }
  10705. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  10706. object = object[value];
  10707. }
  10708. else if( object[value] !== undefined ) {
  10709. found = object[value];
  10710. return false;
  10711. }
  10712. else {
  10713. return false;
  10714. }
  10715. });
  10716. }
  10717. if ( $.isFunction( found ) ) {
  10718. response = found.apply(context, passedArguments);
  10719. }
  10720. else if(found !== undefined) {
  10721. response = found;
  10722. }
  10723. if($.isArray(returnedValue)) {
  10724. returnedValue.push(response);
  10725. }
  10726. else if(returnedValue !== undefined) {
  10727. returnedValue = [returnedValue, response];
  10728. }
  10729. else if(response !== undefined) {
  10730. returnedValue = response;
  10731. }
  10732. return found;
  10733. }
  10734. };
  10735. if(methodInvoked) {
  10736. if(instance === undefined) {
  10737. module.initialize();
  10738. }
  10739. module.invoke(query);
  10740. }
  10741. else {
  10742. if(instance !== undefined) {
  10743. instance.invoke('destroy');
  10744. }
  10745. module.initialize();
  10746. }
  10747. })
  10748. ;
  10749. return (returnedValue !== undefined)
  10750. ? returnedValue
  10751. : this
  10752. ;
  10753. };
  10754. $.fn.rating.settings = {
  10755. name : 'Rating',
  10756. namespace : 'rating',
  10757. debug : false,
  10758. verbose : false,
  10759. performance : true,
  10760. initialRating : 0,
  10761. interactive : true,
  10762. maxRating : 4,
  10763. clearable : 'auto',
  10764. onRate : function(rating){},
  10765. error : {
  10766. method : 'The method you called is not defined',
  10767. noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
  10768. },
  10769. metadata: {
  10770. rating : 'rating',
  10771. maxRating : 'maxRating'
  10772. },
  10773. className : {
  10774. active : 'active',
  10775. disabled : 'disabled',
  10776. selected : 'selected',
  10777. loading : 'loading'
  10778. },
  10779. selector : {
  10780. icon : '.icon'
  10781. },
  10782. templates: {
  10783. icon: function(maxRating) {
  10784. var
  10785. icon = 1,
  10786. html = ''
  10787. ;
  10788. while(icon <= maxRating) {
  10789. html += '<i class="icon"></i>';
  10790. icon++;
  10791. }
  10792. return html;
  10793. }
  10794. }
  10795. };
  10796. })( jQuery, window , document );
  10797. /*!
  10798. * # Semantic UI 2.0.0 - Search
  10799. * http://github.com/semantic-org/semantic-ui/
  10800. *
  10801. *
  10802. * Copyright 2015 Contributors
  10803. * Released under the MIT license
  10804. * http://opensource.org/licenses/MIT
  10805. *
  10806. */
  10807. ;(function ($, window, document, undefined) {
  10808. "use strict";
  10809. $.fn.search = function(parameters) {
  10810. var
  10811. $allModules = $(this),
  10812. moduleSelector = $allModules.selector || '',
  10813. time = new Date().getTime(),
  10814. performance = [],
  10815. query = arguments[0],
  10816. methodInvoked = (typeof query == 'string'),
  10817. queryArguments = [].slice.call(arguments, 1),
  10818. returnedValue
  10819. ;
  10820. $(this)
  10821. .each(function() {
  10822. var
  10823. settings = ( $.isPlainObject(parameters) )
  10824. ? $.extend(true, {}, $.fn.search.settings, parameters)
  10825. : $.extend({}, $.fn.search.settings),
  10826. className = settings.className,
  10827. metadata = settings.metadata,
  10828. regExp = settings.regExp,
  10829. selector = settings.selector,
  10830. error = settings.error,
  10831. namespace = settings.namespace,
  10832. eventNamespace = '.' + namespace,
  10833. moduleNamespace = namespace + '-module',
  10834. $module = $(this),
  10835. $prompt = $module.find(selector.prompt),
  10836. $searchButton = $module.find(selector.searchButton),
  10837. $results = $module.find(selector.results),
  10838. $result = $module.find(selector.result),
  10839. $category = $module.find(selector.category),
  10840. element = this,
  10841. instance = $module.data(moduleNamespace),
  10842. module
  10843. ;
  10844. module = {
  10845. initialize: function() {
  10846. module.verbose('Initializing module');
  10847. module.determine.searchFields();
  10848. module.bind.events();
  10849. module.set.type();
  10850. module.create.results();
  10851. module.instantiate();
  10852. },
  10853. instantiate: function() {
  10854. module.verbose('Storing instance of module', module);
  10855. instance = module;
  10856. $module
  10857. .data(moduleNamespace, module)
  10858. ;
  10859. },
  10860. destroy: function() {
  10861. module.verbose('Destroying instance');
  10862. $module
  10863. .off(eventNamespace)
  10864. .removeData(moduleNamespace)
  10865. ;
  10866. },
  10867. bind: {
  10868. events: function() {
  10869. module.verbose('Binding events to search');
  10870. if(settings.automatic) {
  10871. $module
  10872. .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
  10873. ;
  10874. $prompt
  10875. .attr('autocomplete', 'off')
  10876. ;
  10877. }
  10878. $module
  10879. // prompt
  10880. .on('focus' + eventNamespace, selector.prompt, module.event.focus)
  10881. .on('blur' + eventNamespace, selector.prompt, module.event.blur)
  10882. .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
  10883. // search button
  10884. .on('click' + eventNamespace, selector.searchButton, module.query)
  10885. // results
  10886. .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
  10887. .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
  10888. .on('click' + eventNamespace, selector.result, module.event.result.click)
  10889. ;
  10890. }
  10891. },
  10892. determine: {
  10893. searchFields: function() {
  10894. // this makes sure $.extend does not add specified search fields to default fields
  10895. // this is the only setting which should not extend defaults
  10896. if(parameters && parameters.searchFields !== undefined) {
  10897. settings.searchFields = parameters.searchFields;
  10898. }
  10899. }
  10900. },
  10901. event: {
  10902. input: function() {
  10903. clearTimeout(module.timer);
  10904. module.timer = setTimeout(module.query, settings.searchDelay);
  10905. },
  10906. focus: function() {
  10907. module.set.focus();
  10908. if( module.has.minimumCharacters() ) {
  10909. module.query();
  10910. module.showResults();
  10911. }
  10912. },
  10913. blur: function(event) {
  10914. var
  10915. pageLostFocus = (document.activeElement === this)
  10916. ;
  10917. if(!pageLostFocus && !module.resultsClicked) {
  10918. module.cancel.query();
  10919. module.remove.focus();
  10920. module.timer = setTimeout(module.hideResults, settings.hideDelay);
  10921. }
  10922. },
  10923. result: {
  10924. mousedown: function() {
  10925. module.resultsClicked = true;
  10926. },
  10927. mouseup: function() {
  10928. module.resultsClicked = false;
  10929. },
  10930. click: function(event) {
  10931. module.debug('Search result selected');
  10932. var
  10933. $result = $(this),
  10934. $title = $result.find(selector.title).eq(0),
  10935. $link = $result.find('a[href]').eq(0),
  10936. href = $link.attr('href') || false,
  10937. target = $link.attr('target') || false,
  10938. title = $title.html(),
  10939. // title is used for result lookup
  10940. value = ($title.length > 0)
  10941. ? $title.text()
  10942. : false,
  10943. results = module.get.results(),
  10944. result = $result.data(metadata.result) || module.get.result(value, results),
  10945. returnedValue
  10946. ;
  10947. if( $.isFunction(settings.onSelect) ) {
  10948. if(settings.onSelect.call(element, result, results) === false) {
  10949. module.debug('Custom onSelect callback cancelled default select action');
  10950. return;
  10951. }
  10952. }
  10953. module.hideResults();
  10954. if(value) {
  10955. module.set.value(value);
  10956. }
  10957. if(href) {
  10958. module.verbose('Opening search link found in result', $link);
  10959. if(target == '_blank' || event.ctrlKey) {
  10960. window.open(href);
  10961. }
  10962. else {
  10963. window.location.href = (href);
  10964. }
  10965. }
  10966. }
  10967. }
  10968. },
  10969. handleKeyboard: function(event) {
  10970. var
  10971. // force selector refresh
  10972. $result = $module.find(selector.result),
  10973. $category = $module.find(selector.category),
  10974. currentIndex = $result.index( $result.filter('.' + className.active) ),
  10975. resultSize = $result.length,
  10976. keyCode = event.which,
  10977. keys = {
  10978. backspace : 8,
  10979. enter : 13,
  10980. escape : 27,
  10981. upArrow : 38,
  10982. downArrow : 40
  10983. },
  10984. newIndex
  10985. ;
  10986. // search shortcuts
  10987. if(keyCode == keys.escape) {
  10988. module.verbose('Escape key pressed, blurring search field');
  10989. $prompt
  10990. .trigger('blur')
  10991. ;
  10992. }
  10993. if( module.is.visible() ) {
  10994. if(keyCode == keys.enter) {
  10995. module.verbose('Enter key pressed, selecting active result');
  10996. if( $result.filter('.' + className.active).length > 0 ) {
  10997. module.event.result.click.call($result.filter('.' + className.active), event);
  10998. event.preventDefault();
  10999. return false;
  11000. }
  11001. }
  11002. else if(keyCode == keys.upArrow) {
  11003. module.verbose('Up key pressed, changing active result');
  11004. newIndex = (currentIndex - 1 < 0)
  11005. ? currentIndex
  11006. : currentIndex - 1
  11007. ;
  11008. $category
  11009. .removeClass(className.active)
  11010. ;
  11011. $result
  11012. .removeClass(className.active)
  11013. .eq(newIndex)
  11014. .addClass(className.active)
  11015. .closest($category)
  11016. .addClass(className.active)
  11017. ;
  11018. event.preventDefault();
  11019. }
  11020. else if(keyCode == keys.downArrow) {
  11021. module.verbose('Down key pressed, changing active result');
  11022. newIndex = (currentIndex + 1 >= resultSize)
  11023. ? currentIndex
  11024. : currentIndex + 1
  11025. ;
  11026. $category
  11027. .removeClass(className.active)
  11028. ;
  11029. $result
  11030. .removeClass(className.active)
  11031. .eq(newIndex)
  11032. .addClass(className.active)
  11033. .closest($category)
  11034. .addClass(className.active)
  11035. ;
  11036. event.preventDefault();
  11037. }
  11038. }
  11039. else {
  11040. // query shortcuts
  11041. if(keyCode == keys.enter) {
  11042. module.verbose('Enter key pressed, executing query');
  11043. module.query();
  11044. module.set.buttonPressed();
  11045. $prompt.one('keyup', module.remove.buttonFocus);
  11046. }
  11047. }
  11048. },
  11049. setup: {
  11050. api: function() {
  11051. var
  11052. apiSettings = {
  11053. debug : settings.debug,
  11054. on : false,
  11055. cache : 'local',
  11056. action : 'search',
  11057. onError : module.error
  11058. },
  11059. searchHTML
  11060. ;
  11061. module.verbose('First request, initializing API');
  11062. $module.api(apiSettings);
  11063. }
  11064. },
  11065. can: {
  11066. useAPI: function() {
  11067. return $.fn.api !== undefined;
  11068. },
  11069. transition: function() {
  11070. return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
  11071. }
  11072. },
  11073. is: {
  11074. empty: function() {
  11075. return ($results.html() === '');
  11076. },
  11077. visible: function() {
  11078. return ($results.filter(':visible').length > 0);
  11079. },
  11080. focused: function() {
  11081. return ($prompt.filter(':focus').length > 0);
  11082. }
  11083. },
  11084. get: {
  11085. inputEvent: function() {
  11086. var
  11087. prompt = $prompt[0],
  11088. inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
  11089. ? 'input'
  11090. : (prompt !== undefined && prompt.onpropertychange !== undefined)
  11091. ? 'propertychange'
  11092. : 'keyup'
  11093. ;
  11094. return inputEvent;
  11095. },
  11096. value: function() {
  11097. return $prompt.val();
  11098. },
  11099. results: function() {
  11100. var
  11101. results = $module.data(metadata.results)
  11102. ;
  11103. return results;
  11104. },
  11105. result: function(value, results) {
  11106. var
  11107. lookupFields = ['title', 'id'],
  11108. result = false
  11109. ;
  11110. value = (value !== undefined)
  11111. ? value
  11112. : module.get.value()
  11113. ;
  11114. results = (results !== undefined)
  11115. ? results
  11116. : module.get.results()
  11117. ;
  11118. if(settings.type === 'category') {
  11119. module.debug('Finding result that matches', value);
  11120. $.each(results, function(index, category) {
  11121. if($.isArray(category.results)) {
  11122. result = module.search.object(value, category.results, lookupFields)[0];
  11123. // dont continue searching if a result is found
  11124. if(result) {
  11125. return false;
  11126. }
  11127. }
  11128. });
  11129. }
  11130. else {
  11131. module.debug('Finding result in results object', value);
  11132. result = module.search.object(value, results, lookupFields)[0];
  11133. }
  11134. return result || false;
  11135. },
  11136. },
  11137. set: {
  11138. focus: function() {
  11139. $module.addClass(className.focus);
  11140. },
  11141. loading: function() {
  11142. $module.addClass(className.loading);
  11143. },
  11144. value: function(value) {
  11145. module.verbose('Setting search input value', value);
  11146. $prompt
  11147. .val(value)
  11148. ;
  11149. },
  11150. type: function(type) {
  11151. type = type || settings.type;
  11152. if(settings.type == 'category') {
  11153. $module.addClass(settings.type);
  11154. }
  11155. },
  11156. buttonPressed: function() {
  11157. $searchButton.addClass(className.pressed);
  11158. }
  11159. },
  11160. remove: {
  11161. loading: function() {
  11162. $module.removeClass(className.loading);
  11163. },
  11164. focus: function() {
  11165. $module.removeClass(className.focus);
  11166. },
  11167. buttonPressed: function() {
  11168. $searchButton.removeClass(className.pressed);
  11169. }
  11170. },
  11171. query: function() {
  11172. var
  11173. searchTerm = module.get.value(),
  11174. cache = module.read.cache(searchTerm)
  11175. ;
  11176. if( module.has.minimumCharacters() ) {
  11177. if(cache) {
  11178. module.debug('Reading result from cache', searchTerm);
  11179. module.save.results(cache.results);
  11180. module.addResults(cache.html);
  11181. module.inject.id(cache.results);
  11182. }
  11183. else {
  11184. module.debug('Querying for', searchTerm);
  11185. if($.isPlainObject(settings.source) || $.isArray(settings.source)) {
  11186. module.search.local(searchTerm);
  11187. }
  11188. else if( module.can.useAPI() ) {
  11189. module.search.remote(searchTerm);
  11190. }
  11191. else {
  11192. module.error(error.source);
  11193. }
  11194. settings.onSearchQuery.call(element, searchTerm);
  11195. }
  11196. }
  11197. else {
  11198. module.hideResults();
  11199. }
  11200. },
  11201. search: {
  11202. local: function(searchTerm) {
  11203. var
  11204. results = module.search.object(searchTerm, settings.content),
  11205. searchHTML
  11206. ;
  11207. module.set.loading();
  11208. module.save.results(results);
  11209. module.debug('Returned local search results', results);
  11210. searchHTML = module.generateResults({
  11211. results: results
  11212. });
  11213. module.remove.loading();
  11214. module.addResults(searchHTML);
  11215. module.inject.id(results);
  11216. module.write.cache(searchTerm, {
  11217. html : searchHTML,
  11218. results : results
  11219. });
  11220. },
  11221. remote: function(searchTerm) {
  11222. var
  11223. apiSettings = {
  11224. onSuccess : function(response) {
  11225. module.parse.response.call(element, response, searchTerm);
  11226. },
  11227. onFailure: function() {
  11228. module.displayMessage(error.serverError);
  11229. },
  11230. urlData: {
  11231. query: searchTerm
  11232. }
  11233. }
  11234. ;
  11235. if( !$module.api('get request') ) {
  11236. module.setup.api();
  11237. }
  11238. $.extend(true, apiSettings, settings.apiSettings);
  11239. module.debug('Executing search', apiSettings);
  11240. module.cancel.query();
  11241. $module
  11242. .api('setting', apiSettings)
  11243. .api('query')
  11244. ;
  11245. },
  11246. object: function(searchTerm, source, searchFields) {
  11247. var
  11248. results = [],
  11249. fuzzyResults = [],
  11250. searchExp = searchTerm.toString().replace(regExp.escape, '\\$&'),
  11251. matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
  11252. // avoid duplicates when pushing results
  11253. addResult = function(array, result) {
  11254. var
  11255. notResult = ($.inArray(result, results) == -1),
  11256. notFuzzyResult = ($.inArray(result, fuzzyResults) == -1)
  11257. ;
  11258. if(notResult && notFuzzyResult) {
  11259. array.push(result);
  11260. }
  11261. }
  11262. ;
  11263. source = source || settings.source;
  11264. searchFields = (searchFields !== undefined)
  11265. ? searchFields
  11266. : settings.searchFields
  11267. ;
  11268. // search fields should be array to loop correctly
  11269. if(!$.isArray(searchFields)) {
  11270. searchFields = [searchFields];
  11271. }
  11272. // exit conditions if no source
  11273. if(source === undefined || source === false) {
  11274. module.error(error.source);
  11275. return [];
  11276. }
  11277. // iterate through search fields looking for matches
  11278. $.each(searchFields, function(index, field) {
  11279. $.each(source, function(label, content) {
  11280. var
  11281. fieldExists = (typeof content[field] == 'string')
  11282. ;
  11283. if(fieldExists) {
  11284. if( content[field].search(matchRegExp) !== -1) {
  11285. // content starts with value (first in results)
  11286. addResult(results, content);
  11287. }
  11288. else if(settings.searchFullText && module.fuzzySearch(searchTerm, content[field]) ) {
  11289. // content fuzzy matches (last in results)
  11290. addResult(fuzzyResults, content);
  11291. }
  11292. }
  11293. });
  11294. });
  11295. return $.merge(results, fuzzyResults);
  11296. }
  11297. },
  11298. fuzzySearch: function(query, term) {
  11299. var
  11300. termLength = term.length,
  11301. queryLength = query.length
  11302. ;
  11303. if(typeof query !== 'string') {
  11304. return false;
  11305. }
  11306. query = query.toLowerCase();
  11307. term = term.toLowerCase();
  11308. if(queryLength > termLength) {
  11309. return false;
  11310. }
  11311. if(queryLength === termLength) {
  11312. return (query === term);
  11313. }
  11314. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  11315. var
  11316. queryCharacter = query.charCodeAt(characterIndex)
  11317. ;
  11318. while(nextCharacterIndex < termLength) {
  11319. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  11320. continue search;
  11321. }
  11322. }
  11323. return false;
  11324. }
  11325. return true;
  11326. },
  11327. parse: {
  11328. response: function(response, searchTerm) {
  11329. var
  11330. searchHTML = module.generateResults(response)
  11331. ;
  11332. module.verbose('Parsing server response', response);
  11333. if(response !== undefined) {
  11334. if(searchTerm !== undefined && response.results !== undefined) {
  11335. module.addResults(searchHTML);
  11336. module.inject.id(response.results);
  11337. module.write.cache(searchTerm, {
  11338. html : searchHTML,
  11339. results : response.results
  11340. });
  11341. module.save.results(response.results);
  11342. }
  11343. }
  11344. }
  11345. },
  11346. cancel: {
  11347. query: function() {
  11348. if( module.can.useAPI() ) {
  11349. $module.api('abort');
  11350. }
  11351. }
  11352. },
  11353. has: {
  11354. minimumCharacters: function() {
  11355. var
  11356. searchTerm = module.get.value(),
  11357. numCharacters = searchTerm.length
  11358. ;
  11359. return (numCharacters >= settings.minCharacters);
  11360. }
  11361. },
  11362. clear: {
  11363. cache: function(value) {
  11364. var
  11365. cache = $module.data(metadata.cache)
  11366. ;
  11367. if(!value) {
  11368. module.debug('Clearing cache', value);
  11369. $module.removeData(metadata.cache);
  11370. }
  11371. else if(value && cache && cache[value]) {
  11372. module.debug('Removing value from cache', value);
  11373. delete cache[value];
  11374. $module.data(metadata.cache, cache);
  11375. }
  11376. }
  11377. },
  11378. read: {
  11379. cache: function(name) {
  11380. var
  11381. cache = $module.data(metadata.cache)
  11382. ;
  11383. if(settings.cache) {
  11384. module.verbose('Checking cache for generated html for query', name);
  11385. return (typeof cache == 'object') && (cache[name] !== undefined)
  11386. ? cache[name]
  11387. : false
  11388. ;
  11389. }
  11390. return false;
  11391. }
  11392. },
  11393. create: {
  11394. id: function(resultIndex, categoryIndex) {
  11395. var
  11396. resultID = (resultIndex + 1), // not zero indexed
  11397. categoryID = (categoryIndex + 1),
  11398. firstCharCode,
  11399. letterID,
  11400. id
  11401. ;
  11402. if(categoryIndex !== undefined) {
  11403. // start char code for "A"
  11404. letterID = String.fromCharCode(97 + categoryIndex);
  11405. id = letterID + resultID;
  11406. module.verbose('Creating category result id', id);
  11407. }
  11408. else {
  11409. id = resultID;
  11410. module.verbose('Creating result id', id);
  11411. }
  11412. return id;
  11413. },
  11414. results: function() {
  11415. if($results.length === 0) {
  11416. $results = $('<div />')
  11417. .addClass(className.results)
  11418. .appendTo($module)
  11419. ;
  11420. }
  11421. }
  11422. },
  11423. inject: {
  11424. result: function(result, resultIndex, categoryIndex) {
  11425. module.verbose('Injecting result into results');
  11426. var
  11427. $selectedResult = (categoryIndex !== undefined)
  11428. ? $results
  11429. .children().eq(categoryIndex)
  11430. .children(selector.result).eq(resultIndex)
  11431. : $results
  11432. .children(selector.result).eq(resultIndex)
  11433. ;
  11434. module.verbose('Injecting results metadata', $selectedResult);
  11435. $selectedResult
  11436. .data(metadata.result, result)
  11437. ;
  11438. },
  11439. id: function(results) {
  11440. module.debug('Injecting unique ids into results');
  11441. var
  11442. // since results may be object, we must use counters
  11443. categoryIndex = 0,
  11444. resultIndex = 0
  11445. ;
  11446. if(settings.type === 'category') {
  11447. // iterate through each category result
  11448. $.each(results, function(index, category) {
  11449. resultIndex = 0;
  11450. $.each(category.results, function(index, value) {
  11451. var
  11452. result = category.results[index]
  11453. ;
  11454. if(result.id === undefined) {
  11455. result.id = module.create.id(resultIndex, categoryIndex);
  11456. }
  11457. module.inject.result(result, resultIndex, categoryIndex);
  11458. resultIndex++;
  11459. });
  11460. categoryIndex++;
  11461. });
  11462. }
  11463. else {
  11464. // top level
  11465. $.each(results, function(index, value) {
  11466. var
  11467. result = results[index]
  11468. ;
  11469. if(result.id === undefined) {
  11470. result.id = module.create.id(resultIndex);
  11471. }
  11472. module.inject.result(result, resultIndex);
  11473. resultIndex++;
  11474. });
  11475. }
  11476. return results;
  11477. }
  11478. },
  11479. save: {
  11480. results: function(results) {
  11481. module.verbose('Saving current search results to metadata', results);
  11482. $module.data(metadata.results, results);
  11483. }
  11484. },
  11485. write: {
  11486. cache: function(name, value) {
  11487. var
  11488. cache = ($module.data(metadata.cache) !== undefined)
  11489. ? $module.data(metadata.cache)
  11490. : {}
  11491. ;
  11492. if(settings.cache) {
  11493. module.verbose('Writing generated html to cache', name, value);
  11494. cache[name] = value;
  11495. $module
  11496. .data(metadata.cache, cache)
  11497. ;
  11498. }
  11499. }
  11500. },
  11501. addResults: function(html) {
  11502. if( $.isFunction(settings.onResultsAdd) ) {
  11503. if( settings.onResultsAdd.call($results, html) === false ) {
  11504. module.debug('onResultsAdd callback cancelled default action');
  11505. return false;
  11506. }
  11507. }
  11508. $results
  11509. .html(html)
  11510. ;
  11511. module.showResults();
  11512. },
  11513. showResults: function() {
  11514. if( !module.is.visible() && module.is.focused() && !module.is.empty() ) {
  11515. if( module.can.transition() ) {
  11516. module.debug('Showing results with css animations');
  11517. $results
  11518. .transition({
  11519. animation : settings.transition + ' in',
  11520. debug : settings.debug,
  11521. verbose : settings.verbose,
  11522. duration : settings.duration,
  11523. queue : true
  11524. })
  11525. ;
  11526. }
  11527. else {
  11528. module.debug('Showing results with javascript');
  11529. $results
  11530. .stop()
  11531. .fadeIn(settings.duration, settings.easing)
  11532. ;
  11533. }
  11534. settings.onResultsOpen.call($results);
  11535. }
  11536. },
  11537. hideResults: function() {
  11538. if( module.is.visible() ) {
  11539. if( module.can.transition() ) {
  11540. module.debug('Hiding results with css animations');
  11541. $results
  11542. .transition({
  11543. animation : settings.transition + ' out',
  11544. debug : settings.debug,
  11545. verbose : settings.verbose,
  11546. duration : settings.duration,
  11547. queue : true
  11548. })
  11549. ;
  11550. }
  11551. else {
  11552. module.debug('Hiding results with javascript');
  11553. $results
  11554. .stop()
  11555. .fadeOut(settings.duration, settings.easing)
  11556. ;
  11557. }
  11558. settings.onResultsClose.call($results);
  11559. }
  11560. },
  11561. generateResults: function(response) {
  11562. module.debug('Generating html from response', response);
  11563. var
  11564. template = settings.templates[settings.type],
  11565. isProperObject = ($.isPlainObject(response.results) && !$.isEmptyObject(response.results)),
  11566. isProperArray = ($.isArray(response.results) && response.results.length > 0),
  11567. html = ''
  11568. ;
  11569. if(isProperObject || isProperArray ) {
  11570. if(settings.maxResults > 0) {
  11571. if(isProperObject) {
  11572. if(settings.type == 'standard') {
  11573. module.error(error.maxResults);
  11574. }
  11575. }
  11576. else {
  11577. response.results = response.results.slice(0, settings.maxResults);
  11578. }
  11579. }
  11580. if($.isFunction(template)) {
  11581. html = template(response);
  11582. }
  11583. else {
  11584. module.error(error.noTemplate, false);
  11585. }
  11586. }
  11587. else {
  11588. html = module.displayMessage(error.noResults, 'empty');
  11589. }
  11590. settings.onResults.call(element, response);
  11591. return html;
  11592. },
  11593. displayMessage: function(text, type) {
  11594. type = type || 'standard';
  11595. module.debug('Displaying message', text, type);
  11596. module.addResults( settings.templates.message(text, type) );
  11597. return settings.templates.message(text, type);
  11598. },
  11599. setting: function(name, value) {
  11600. if( $.isPlainObject(name) ) {
  11601. $.extend(true, settings, name);
  11602. }
  11603. else if(value !== undefined) {
  11604. settings[name] = value;
  11605. }
  11606. else {
  11607. return settings[name];
  11608. }
  11609. },
  11610. internal: function(name, value) {
  11611. if( $.isPlainObject(name) ) {
  11612. $.extend(true, module, name);
  11613. }
  11614. else if(value !== undefined) {
  11615. module[name] = value;
  11616. }
  11617. else {
  11618. return module[name];
  11619. }
  11620. },
  11621. debug: function() {
  11622. if(settings.debug) {
  11623. if(settings.performance) {
  11624. module.performance.log(arguments);
  11625. }
  11626. else {
  11627. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11628. module.debug.apply(console, arguments);
  11629. }
  11630. }
  11631. },
  11632. verbose: function() {
  11633. if(settings.verbose && settings.debug) {
  11634. if(settings.performance) {
  11635. module.performance.log(arguments);
  11636. }
  11637. else {
  11638. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11639. module.verbose.apply(console, arguments);
  11640. }
  11641. }
  11642. },
  11643. error: function() {
  11644. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  11645. module.error.apply(console, arguments);
  11646. },
  11647. performance: {
  11648. log: function(message) {
  11649. var
  11650. currentTime,
  11651. executionTime,
  11652. previousTime
  11653. ;
  11654. if(settings.performance) {
  11655. currentTime = new Date().getTime();
  11656. previousTime = time || currentTime;
  11657. executionTime = currentTime - previousTime;
  11658. time = currentTime;
  11659. performance.push({
  11660. 'Name' : message[0],
  11661. 'Arguments' : [].slice.call(message, 1) || '',
  11662. 'Element' : element,
  11663. 'Execution Time' : executionTime
  11664. });
  11665. }
  11666. clearTimeout(module.performance.timer);
  11667. module.performance.timer = setTimeout(module.performance.display, 500);
  11668. },
  11669. display: function() {
  11670. var
  11671. title = settings.name + ':',
  11672. totalTime = 0
  11673. ;
  11674. time = false;
  11675. clearTimeout(module.performance.timer);
  11676. $.each(performance, function(index, data) {
  11677. totalTime += data['Execution Time'];
  11678. });
  11679. title += ' ' + totalTime + 'ms';
  11680. if(moduleSelector) {
  11681. title += ' \'' + moduleSelector + '\'';
  11682. }
  11683. if($allModules.length > 1) {
  11684. title += ' ' + '(' + $allModules.length + ')';
  11685. }
  11686. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  11687. console.groupCollapsed(title);
  11688. if(console.table) {
  11689. console.table(performance);
  11690. }
  11691. else {
  11692. $.each(performance, function(index, data) {
  11693. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  11694. });
  11695. }
  11696. console.groupEnd();
  11697. }
  11698. performance = [];
  11699. }
  11700. },
  11701. invoke: function(query, passedArguments, context) {
  11702. var
  11703. object = instance,
  11704. maxDepth,
  11705. found,
  11706. response
  11707. ;
  11708. passedArguments = passedArguments || queryArguments;
  11709. context = element || context;
  11710. if(typeof query == 'string' && object !== undefined) {
  11711. query = query.split(/[\. ]/);
  11712. maxDepth = query.length - 1;
  11713. $.each(query, function(depth, value) {
  11714. var camelCaseValue = (depth != maxDepth)
  11715. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  11716. : query
  11717. ;
  11718. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  11719. object = object[camelCaseValue];
  11720. }
  11721. else if( object[camelCaseValue] !== undefined ) {
  11722. found = object[camelCaseValue];
  11723. return false;
  11724. }
  11725. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  11726. object = object[value];
  11727. }
  11728. else if( object[value] !== undefined ) {
  11729. found = object[value];
  11730. return false;
  11731. }
  11732. else {
  11733. return false;
  11734. }
  11735. });
  11736. }
  11737. if( $.isFunction( found ) ) {
  11738. response = found.apply(context, passedArguments);
  11739. }
  11740. else if(found !== undefined) {
  11741. response = found;
  11742. }
  11743. if($.isArray(returnedValue)) {
  11744. returnedValue.push(response);
  11745. }
  11746. else if(returnedValue !== undefined) {
  11747. returnedValue = [returnedValue, response];
  11748. }
  11749. else if(response !== undefined) {
  11750. returnedValue = response;
  11751. }
  11752. return found;
  11753. }
  11754. };
  11755. if(methodInvoked) {
  11756. if(instance === undefined) {
  11757. module.initialize();
  11758. }
  11759. module.invoke(query);
  11760. }
  11761. else {
  11762. if(instance !== undefined) {
  11763. instance.invoke('destroy');
  11764. }
  11765. module.initialize();
  11766. }
  11767. })
  11768. ;
  11769. return (returnedValue !== undefined)
  11770. ? returnedValue
  11771. : this
  11772. ;
  11773. };
  11774. $.fn.search.settings = {
  11775. name : 'Search',
  11776. namespace : 'search',
  11777. debug : false,
  11778. verbose : false,
  11779. performance : true,
  11780. type : 'standard',
  11781. // template to use (specified in settings.templates)
  11782. minCharacters : 1,
  11783. // minimum characters required to search
  11784. apiSettings : false,
  11785. // API config
  11786. source : false,
  11787. // object to search
  11788. searchFields : [
  11789. 'title',
  11790. 'description'
  11791. ],
  11792. // fields to search
  11793. searchFullText : true,
  11794. // whether to include fuzzy results in local search
  11795. automatic : true,
  11796. // whether to add events to prompt automatically
  11797. hideDelay : 0,
  11798. // delay before hiding menu after blur
  11799. searchDelay : 200,
  11800. // delay before searching
  11801. maxResults : 7,
  11802. // maximum results returned from local
  11803. cache : true,
  11804. // whether to store lookups in local cache
  11805. // transition settings
  11806. transition : 'scale',
  11807. duration : 200,
  11808. easing : 'easeOutExpo',
  11809. // callbacks
  11810. onSelect : false,
  11811. onResultsAdd : false,
  11812. onSearchQuery : function(){},
  11813. onResults : function(response){},
  11814. onResultsOpen : function(){},
  11815. onResultsClose : function(){},
  11816. className: {
  11817. active : 'active',
  11818. empty : 'empty',
  11819. focus : 'focus',
  11820. loading : 'loading',
  11821. results : 'results',
  11822. pressed : 'down'
  11823. },
  11824. error : {
  11825. source : 'Cannot search. No source used, and Semantic API module was not included',
  11826. noResults : 'Your search returned no results',
  11827. logging : 'Error in debug logging, exiting.',
  11828. noEndpoint : 'No search endpoint was specified',
  11829. noTemplate : 'A valid template name was not specified.',
  11830. serverError : 'There was an issue querying the server.',
  11831. maxResults : 'Results must be an array to use maxResults setting',
  11832. method : 'The method you called is not defined.'
  11833. },
  11834. metadata: {
  11835. cache : 'cache',
  11836. results : 'results',
  11837. result : 'result'
  11838. },
  11839. regExp: {
  11840. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  11841. beginsWith : '(?:\s|^)'
  11842. },
  11843. selector : {
  11844. prompt : '.prompt',
  11845. searchButton : '.search.button',
  11846. results : '.results',
  11847. category : '.category',
  11848. result : '.result',
  11849. title : '.title, .name'
  11850. },
  11851. templates: {
  11852. escape: function(string) {
  11853. var
  11854. badChars = /[&<>"'`]/g,
  11855. shouldEscape = /[&<>"'`]/,
  11856. escape = {
  11857. "&": "&amp;",
  11858. "<": "&lt;",
  11859. ">": "&gt;",
  11860. '"': "&quot;",
  11861. "'": "&#x27;",
  11862. "`": "&#x60;"
  11863. },
  11864. escapedChar = function(chr) {
  11865. return escape[chr];
  11866. }
  11867. ;
  11868. if(shouldEscape.test(string)) {
  11869. return string.replace(badChars, escapedChar);
  11870. }
  11871. return string;
  11872. },
  11873. message: function(message, type) {
  11874. var
  11875. html = ''
  11876. ;
  11877. if(message !== undefined && type !== undefined) {
  11878. html += ''
  11879. + '<div class="message ' + type + '">'
  11880. ;
  11881. // message type
  11882. if(type == 'empty') {
  11883. html += ''
  11884. + '<div class="header">No Results</div class="header">'
  11885. + '<div class="description">' + message + '</div class="description">'
  11886. ;
  11887. }
  11888. else {
  11889. html += ' <div class="description">' + message + '</div>';
  11890. }
  11891. html += '</div>';
  11892. }
  11893. return html;
  11894. },
  11895. category: function(response) {
  11896. var
  11897. html = '',
  11898. escape = $.fn.search.settings.templates.escape
  11899. ;
  11900. if(response.results !== undefined) {
  11901. // each category
  11902. $.each(response.results, function(index, category) {
  11903. if(category.results !== undefined && category.results.length > 0) {
  11904. html += ''
  11905. + '<div class="category">'
  11906. + '<div class="name">' + category.name + '</div>'
  11907. ;
  11908. // each item inside category
  11909. $.each(category.results, function(index, result) {
  11910. html += '<div class="result">';
  11911. if(result.url) {
  11912. html += '<a href="' + result.url + '"></a>';
  11913. }
  11914. if(result.image !== undefined) {
  11915. result.image = escape(result.image);
  11916. html += ''
  11917. + '<div class="image">'
  11918. + ' <img src="' + result.image + '" alt="">'
  11919. + '</div>'
  11920. ;
  11921. }
  11922. html += '<div class="content">';
  11923. if(result.price !== undefined) {
  11924. result.price = escape(result.price);
  11925. html += '<div class="price">' + result.price + '</div>';
  11926. }
  11927. if(result.title !== undefined) {
  11928. result.title = escape(result.title);
  11929. html += '<div class="title">' + result.title + '</div>';
  11930. }
  11931. if(result.description !== undefined) {
  11932. html += '<div class="description">' + result.description + '</div>';
  11933. }
  11934. html += ''
  11935. + '</div>'
  11936. + '</div>'
  11937. ;
  11938. });
  11939. html += ''
  11940. + '</div>'
  11941. ;
  11942. }
  11943. });
  11944. if(response.action) {
  11945. html += ''
  11946. + '<a href="' + response.action.url + '" class="action">'
  11947. + response.action.text
  11948. + '</a>';
  11949. }
  11950. return html;
  11951. }
  11952. return false;
  11953. },
  11954. standard: function(response) {
  11955. var
  11956. html = ''
  11957. ;
  11958. if(response.results !== undefined) {
  11959. // each result
  11960. $.each(response.results, function(index, result) {
  11961. if(result.url) {
  11962. html += '<a class="result" href="' + result.url + '">';
  11963. }
  11964. else {
  11965. html += '<a class="result">';
  11966. }
  11967. if(result.image !== undefined) {
  11968. html += ''
  11969. + '<div class="image">'
  11970. + ' <img src="' + result.image + '">'
  11971. + '</div>'
  11972. ;
  11973. }
  11974. html += '<div class="content">';
  11975. if(result.price !== undefined) {
  11976. html += '<div class="price">' + result.price + '</div>';
  11977. }
  11978. if(result.title !== undefined) {
  11979. html += '<div class="title">' + result.title + '</div>';
  11980. }
  11981. if(result.description !== undefined) {
  11982. html += '<div class="description">' + result.description + '</div>';
  11983. }
  11984. html += ''
  11985. + '</div>'
  11986. ;
  11987. html += '</a>';
  11988. });
  11989. if(response.action) {
  11990. html += ''
  11991. + '<a href="' + response.action.url + '" class="action">'
  11992. + response.action.text
  11993. + '</a>';
  11994. }
  11995. return html;
  11996. }
  11997. return false;
  11998. }
  11999. }
  12000. };
  12001. })( jQuery, window , document );
  12002. /*!
  12003. * # Semantic UI 2.0.0 - Shape
  12004. * http://github.com/semantic-org/semantic-ui/
  12005. *
  12006. *
  12007. * Copyright 2015 Contributors
  12008. * Released under the MIT license
  12009. * http://opensource.org/licenses/MIT
  12010. *
  12011. */
  12012. ;(function ( $, window, document, undefined ) {
  12013. "use strict";
  12014. $.fn.shape = function(parameters) {
  12015. var
  12016. $allModules = $(this),
  12017. $body = $('body'),
  12018. time = new Date().getTime(),
  12019. performance = [],
  12020. query = arguments[0],
  12021. methodInvoked = (typeof query == 'string'),
  12022. queryArguments = [].slice.call(arguments, 1),
  12023. requestAnimationFrame = window.requestAnimationFrame
  12024. || window.mozRequestAnimationFrame
  12025. || window.webkitRequestAnimationFrame
  12026. || window.msRequestAnimationFrame
  12027. || function(callback) { setTimeout(callback, 0); },
  12028. returnedValue
  12029. ;
  12030. $allModules
  12031. .each(function() {
  12032. var
  12033. moduleSelector = $allModules.selector || '',
  12034. settings = ( $.isPlainObject(parameters) )
  12035. ? $.extend(true, {}, $.fn.shape.settings, parameters)
  12036. : $.extend({}, $.fn.shape.settings),
  12037. // internal aliases
  12038. namespace = settings.namespace,
  12039. selector = settings.selector,
  12040. error = settings.error,
  12041. className = settings.className,
  12042. // define namespaces for modules
  12043. eventNamespace = '.' + namespace,
  12044. moduleNamespace = 'module-' + namespace,
  12045. // selector cache
  12046. $module = $(this),
  12047. $sides = $module.find(selector.sides),
  12048. $side = $module.find(selector.side),
  12049. // private variables
  12050. nextIndex = false,
  12051. $activeSide,
  12052. $nextSide,
  12053. // standard module
  12054. element = this,
  12055. instance = $module.data(moduleNamespace),
  12056. module
  12057. ;
  12058. module = {
  12059. initialize: function() {
  12060. module.verbose('Initializing module for', element);
  12061. module.set.defaultSide();
  12062. module.instantiate();
  12063. },
  12064. instantiate: function() {
  12065. module.verbose('Storing instance of module', module);
  12066. instance = module;
  12067. $module
  12068. .data(moduleNamespace, instance)
  12069. ;
  12070. },
  12071. destroy: function() {
  12072. module.verbose('Destroying previous module for', element);
  12073. $module
  12074. .removeData(moduleNamespace)
  12075. .off(eventNamespace)
  12076. ;
  12077. },
  12078. refresh: function() {
  12079. module.verbose('Refreshing selector cache for', element);
  12080. $module = $(element);
  12081. $sides = $(this).find(selector.shape);
  12082. $side = $(this).find(selector.side);
  12083. },
  12084. repaint: function() {
  12085. module.verbose('Forcing repaint event');
  12086. var
  12087. shape = $sides[0] || document.createElement('div'),
  12088. fakeAssignment = shape.offsetWidth
  12089. ;
  12090. },
  12091. animate: function(propertyObject, callback) {
  12092. module.verbose('Animating box with properties', propertyObject);
  12093. callback = callback || function(event) {
  12094. module.verbose('Executing animation callback');
  12095. if(event !== undefined) {
  12096. event.stopPropagation();
  12097. }
  12098. module.reset();
  12099. module.set.active();
  12100. };
  12101. settings.beforeChange.call($nextSide[0]);
  12102. if(module.get.transitionEvent()) {
  12103. module.verbose('Starting CSS animation');
  12104. $module
  12105. .addClass(className.animating)
  12106. ;
  12107. $sides
  12108. .css(propertyObject)
  12109. .one(module.get.transitionEvent(), callback)
  12110. ;
  12111. module.set.duration(settings.duration);
  12112. requestAnimationFrame(function() {
  12113. $module
  12114. .addClass(className.animating)
  12115. ;
  12116. $activeSide
  12117. .addClass(className.hidden)
  12118. ;
  12119. });
  12120. }
  12121. else {
  12122. callback();
  12123. }
  12124. },
  12125. queue: function(method) {
  12126. module.debug('Queueing animation of', method);
  12127. $sides
  12128. .one(module.get.transitionEvent(), function() {
  12129. module.debug('Executing queued animation');
  12130. setTimeout(function(){
  12131. $module.shape(method);
  12132. }, 0);
  12133. })
  12134. ;
  12135. },
  12136. reset: function() {
  12137. module.verbose('Animating states reset');
  12138. $module
  12139. .removeClass(className.animating)
  12140. .attr('style', '')
  12141. .removeAttr('style')
  12142. ;
  12143. // removeAttr style does not consistently work in safari
  12144. $sides
  12145. .attr('style', '')
  12146. .removeAttr('style')
  12147. ;
  12148. $side
  12149. .attr('style', '')
  12150. .removeAttr('style')
  12151. .removeClass(className.hidden)
  12152. ;
  12153. $nextSide
  12154. .removeClass(className.animating)
  12155. .attr('style', '')
  12156. .removeAttr('style')
  12157. ;
  12158. },
  12159. is: {
  12160. complete: function() {
  12161. return ($side.filter('.' + className.active)[0] == $nextSide[0]);
  12162. },
  12163. animating: function() {
  12164. return $module.hasClass(className.animating);
  12165. }
  12166. },
  12167. set: {
  12168. defaultSide: function() {
  12169. $activeSide = $module.find('.' + settings.className.active);
  12170. $nextSide = ( $activeSide.next(selector.side).length > 0 )
  12171. ? $activeSide.next(selector.side)
  12172. : $module.find(selector.side).first()
  12173. ;
  12174. nextIndex = false;
  12175. module.verbose('Active side set to', $activeSide);
  12176. module.verbose('Next side set to', $nextSide);
  12177. },
  12178. duration: function(duration) {
  12179. duration = duration || settings.duration;
  12180. duration = (typeof duration == 'number')
  12181. ? duration + 'ms'
  12182. : duration
  12183. ;
  12184. module.verbose('Setting animation duration', duration);
  12185. if(settings.duration || settings.duration === 0) {
  12186. $sides.add($side)
  12187. .css({
  12188. '-webkit-transition-duration': duration,
  12189. '-moz-transition-duration': duration,
  12190. '-ms-transition-duration': duration,
  12191. '-o-transition-duration': duration,
  12192. 'transition-duration': duration
  12193. })
  12194. ;
  12195. }
  12196. },
  12197. currentStageSize: function() {
  12198. var
  12199. $activeSide = $module.find('.' + settings.className.active),
  12200. width = $activeSide.outerWidth(true),
  12201. height = $activeSide.outerHeight(true)
  12202. ;
  12203. $module
  12204. .css({
  12205. width: width,
  12206. height: height
  12207. })
  12208. ;
  12209. },
  12210. stageSize: function() {
  12211. var
  12212. $clone = $module.clone().addClass(className.loading),
  12213. $activeSide = $clone.find('.' + settings.className.active),
  12214. $nextSide = (nextIndex)
  12215. ? $clone.find(selector.side).eq(nextIndex)
  12216. : ( $activeSide.next(selector.side).length > 0 )
  12217. ? $activeSide.next(selector.side)
  12218. : $clone.find(selector.side).first(),
  12219. newSize = {}
  12220. ;
  12221. module.set.currentStageSize();
  12222. $activeSide.removeClass(className.active);
  12223. $nextSide.addClass(className.active);
  12224. $clone.insertAfter($module);
  12225. newSize = {
  12226. width : $nextSide.outerWidth(true),
  12227. height : $nextSide.outerHeight(true)
  12228. };
  12229. $clone.remove();
  12230. $module
  12231. .css(newSize)
  12232. ;
  12233. module.verbose('Resizing stage to fit new content', newSize);
  12234. },
  12235. nextSide: function(selector) {
  12236. nextIndex = selector;
  12237. $nextSide = $side.filter(selector);
  12238. nextIndex = $side.index($nextSide);
  12239. if($nextSide.length === 0) {
  12240. module.set.defaultSide();
  12241. module.error(error.side);
  12242. }
  12243. module.verbose('Next side manually set to', $nextSide);
  12244. },
  12245. active: function() {
  12246. module.verbose('Setting new side to active', $nextSide);
  12247. $side
  12248. .removeClass(className.active)
  12249. ;
  12250. $nextSide
  12251. .addClass(className.active)
  12252. ;
  12253. settings.onChange.call($nextSide[0]);
  12254. module.set.defaultSide();
  12255. }
  12256. },
  12257. flip: {
  12258. up: function() {
  12259. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12260. module.debug('Side already visible', $nextSide);
  12261. return;
  12262. }
  12263. if( !module.is.animating()) {
  12264. module.debug('Flipping up', $nextSide);
  12265. module.set.stageSize();
  12266. module.stage.above();
  12267. module.animate( module.get.transform.up() );
  12268. }
  12269. else {
  12270. module.queue('flip up');
  12271. }
  12272. },
  12273. down: function() {
  12274. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12275. module.debug('Side already visible', $nextSide);
  12276. return;
  12277. }
  12278. if( !module.is.animating()) {
  12279. module.debug('Flipping down', $nextSide);
  12280. module.set.stageSize();
  12281. module.stage.below();
  12282. module.animate( module.get.transform.down() );
  12283. }
  12284. else {
  12285. module.queue('flip down');
  12286. }
  12287. },
  12288. left: function() {
  12289. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12290. module.debug('Side already visible', $nextSide);
  12291. return;
  12292. }
  12293. if( !module.is.animating()) {
  12294. module.debug('Flipping left', $nextSide);
  12295. module.set.stageSize();
  12296. module.stage.left();
  12297. module.animate(module.get.transform.left() );
  12298. }
  12299. else {
  12300. module.queue('flip left');
  12301. }
  12302. },
  12303. right: function() {
  12304. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12305. module.debug('Side already visible', $nextSide);
  12306. return;
  12307. }
  12308. if( !module.is.animating()) {
  12309. module.debug('Flipping right', $nextSide);
  12310. module.set.stageSize();
  12311. module.stage.right();
  12312. module.animate(module.get.transform.right() );
  12313. }
  12314. else {
  12315. module.queue('flip right');
  12316. }
  12317. },
  12318. over: function() {
  12319. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12320. module.debug('Side already visible', $nextSide);
  12321. return;
  12322. }
  12323. if( !module.is.animating()) {
  12324. module.debug('Flipping over', $nextSide);
  12325. module.set.stageSize();
  12326. module.stage.behind();
  12327. module.animate(module.get.transform.over() );
  12328. }
  12329. else {
  12330. module.queue('flip over');
  12331. }
  12332. },
  12333. back: function() {
  12334. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12335. module.debug('Side already visible', $nextSide);
  12336. return;
  12337. }
  12338. if( !module.is.animating()) {
  12339. module.debug('Flipping back', $nextSide);
  12340. module.set.stageSize();
  12341. module.stage.behind();
  12342. module.animate(module.get.transform.back() );
  12343. }
  12344. else {
  12345. module.queue('flip back');
  12346. }
  12347. }
  12348. },
  12349. get: {
  12350. transform: {
  12351. up: function() {
  12352. var
  12353. translate = {
  12354. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  12355. z: -($activeSide.outerHeight(true) / 2)
  12356. }
  12357. ;
  12358. return {
  12359. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)'
  12360. };
  12361. },
  12362. down: function() {
  12363. var
  12364. translate = {
  12365. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  12366. z: -($activeSide.outerHeight(true) / 2)
  12367. }
  12368. ;
  12369. return {
  12370. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)'
  12371. };
  12372. },
  12373. left: function() {
  12374. var
  12375. translate = {
  12376. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  12377. z : -($activeSide.outerWidth(true) / 2)
  12378. }
  12379. ;
  12380. return {
  12381. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)'
  12382. };
  12383. },
  12384. right: function() {
  12385. var
  12386. translate = {
  12387. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  12388. z : -($activeSide.outerWidth(true) / 2)
  12389. }
  12390. ;
  12391. return {
  12392. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)'
  12393. };
  12394. },
  12395. over: function() {
  12396. var
  12397. translate = {
  12398. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  12399. }
  12400. ;
  12401. return {
  12402. transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
  12403. };
  12404. },
  12405. back: function() {
  12406. var
  12407. translate = {
  12408. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  12409. }
  12410. ;
  12411. return {
  12412. transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
  12413. };
  12414. }
  12415. },
  12416. transitionEvent: function() {
  12417. var
  12418. element = document.createElement('element'),
  12419. transitions = {
  12420. 'transition' :'transitionend',
  12421. 'OTransition' :'oTransitionEnd',
  12422. 'MozTransition' :'transitionend',
  12423. 'WebkitTransition' :'webkitTransitionEnd'
  12424. },
  12425. transition
  12426. ;
  12427. for(transition in transitions){
  12428. if( element.style[transition] !== undefined ){
  12429. return transitions[transition];
  12430. }
  12431. }
  12432. },
  12433. nextSide: function() {
  12434. return ( $activeSide.next(selector.side).length > 0 )
  12435. ? $activeSide.next(selector.side)
  12436. : $module.find(selector.side).first()
  12437. ;
  12438. }
  12439. },
  12440. stage: {
  12441. above: function() {
  12442. var
  12443. box = {
  12444. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  12445. depth : {
  12446. active : ($nextSide.outerHeight(true) / 2),
  12447. next : ($activeSide.outerHeight(true) / 2)
  12448. }
  12449. }
  12450. ;
  12451. module.verbose('Setting the initial animation position as above', $nextSide, box);
  12452. $sides
  12453. .css({
  12454. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  12455. })
  12456. ;
  12457. $activeSide
  12458. .css({
  12459. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  12460. })
  12461. ;
  12462. $nextSide
  12463. .addClass(className.animating)
  12464. .css({
  12465. 'top' : box.origin + 'px',
  12466. 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)'
  12467. })
  12468. ;
  12469. },
  12470. below: function() {
  12471. var
  12472. box = {
  12473. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  12474. depth : {
  12475. active : ($nextSide.outerHeight(true) / 2),
  12476. next : ($activeSide.outerHeight(true) / 2)
  12477. }
  12478. }
  12479. ;
  12480. module.verbose('Setting the initial animation position as below', $nextSide, box);
  12481. $sides
  12482. .css({
  12483. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  12484. })
  12485. ;
  12486. $activeSide
  12487. .css({
  12488. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  12489. })
  12490. ;
  12491. $nextSide
  12492. .addClass(className.animating)
  12493. .css({
  12494. 'top' : box.origin + 'px',
  12495. 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)'
  12496. })
  12497. ;
  12498. },
  12499. left: function() {
  12500. var
  12501. height = {
  12502. active : $activeSide.outerWidth(true),
  12503. next : $nextSide.outerWidth(true)
  12504. },
  12505. box = {
  12506. origin : ( ( height.active - height.next ) / 2),
  12507. depth : {
  12508. active : (height.next / 2),
  12509. next : (height.active / 2)
  12510. }
  12511. }
  12512. ;
  12513. module.verbose('Setting the initial animation position as left', $nextSide, box);
  12514. $sides
  12515. .css({
  12516. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  12517. })
  12518. ;
  12519. $activeSide
  12520. .css({
  12521. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  12522. })
  12523. ;
  12524. $nextSide
  12525. .addClass(className.animating)
  12526. .css({
  12527. 'left' : box.origin + 'px',
  12528. 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)'
  12529. })
  12530. ;
  12531. },
  12532. right: function() {
  12533. var
  12534. height = {
  12535. active : $activeSide.outerWidth(true),
  12536. next : $nextSide.outerWidth(true)
  12537. },
  12538. box = {
  12539. origin : ( ( height.active - height.next ) / 2),
  12540. depth : {
  12541. active : (height.next / 2),
  12542. next : (height.active / 2)
  12543. }
  12544. }
  12545. ;
  12546. module.verbose('Setting the initial animation position as left', $nextSide, box);
  12547. $sides
  12548. .css({
  12549. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  12550. })
  12551. ;
  12552. $activeSide
  12553. .css({
  12554. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  12555. })
  12556. ;
  12557. $nextSide
  12558. .addClass(className.animating)
  12559. .css({
  12560. 'left' : box.origin + 'px',
  12561. 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)'
  12562. })
  12563. ;
  12564. },
  12565. behind: function() {
  12566. var
  12567. height = {
  12568. active : $activeSide.outerWidth(true),
  12569. next : $nextSide.outerWidth(true)
  12570. },
  12571. box = {
  12572. origin : ( ( height.active - height.next ) / 2),
  12573. depth : {
  12574. active : (height.next / 2),
  12575. next : (height.active / 2)
  12576. }
  12577. }
  12578. ;
  12579. module.verbose('Setting the initial animation position as behind', $nextSide, box);
  12580. $activeSide
  12581. .css({
  12582. 'transform' : 'rotateY(0deg)'
  12583. })
  12584. ;
  12585. $nextSide
  12586. .addClass(className.animating)
  12587. .css({
  12588. 'left' : box.origin + 'px',
  12589. 'transform' : 'rotateY(-180deg)'
  12590. })
  12591. ;
  12592. }
  12593. },
  12594. setting: function(name, value) {
  12595. module.debug('Changing setting', name, value);
  12596. if( $.isPlainObject(name) ) {
  12597. $.extend(true, settings, name);
  12598. }
  12599. else if(value !== undefined) {
  12600. settings[name] = value;
  12601. }
  12602. else {
  12603. return settings[name];
  12604. }
  12605. },
  12606. internal: function(name, value) {
  12607. if( $.isPlainObject(name) ) {
  12608. $.extend(true, module, name);
  12609. }
  12610. else if(value !== undefined) {
  12611. module[name] = value;
  12612. }
  12613. else {
  12614. return module[name];
  12615. }
  12616. },
  12617. debug: function() {
  12618. if(settings.debug) {
  12619. if(settings.performance) {
  12620. module.performance.log(arguments);
  12621. }
  12622. else {
  12623. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12624. module.debug.apply(console, arguments);
  12625. }
  12626. }
  12627. },
  12628. verbose: function() {
  12629. if(settings.verbose && settings.debug) {
  12630. if(settings.performance) {
  12631. module.performance.log(arguments);
  12632. }
  12633. else {
  12634. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12635. module.verbose.apply(console, arguments);
  12636. }
  12637. }
  12638. },
  12639. error: function() {
  12640. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  12641. module.error.apply(console, arguments);
  12642. },
  12643. performance: {
  12644. log: function(message) {
  12645. var
  12646. currentTime,
  12647. executionTime,
  12648. previousTime
  12649. ;
  12650. if(settings.performance) {
  12651. currentTime = new Date().getTime();
  12652. previousTime = time || currentTime;
  12653. executionTime = currentTime - previousTime;
  12654. time = currentTime;
  12655. performance.push({
  12656. 'Name' : message[0],
  12657. 'Arguments' : [].slice.call(message, 1) || '',
  12658. 'Element' : element,
  12659. 'Execution Time' : executionTime
  12660. });
  12661. }
  12662. clearTimeout(module.performance.timer);
  12663. module.performance.timer = setTimeout(module.performance.display, 500);
  12664. },
  12665. display: function() {
  12666. var
  12667. title = settings.name + ':',
  12668. totalTime = 0
  12669. ;
  12670. time = false;
  12671. clearTimeout(module.performance.timer);
  12672. $.each(performance, function(index, data) {
  12673. totalTime += data['Execution Time'];
  12674. });
  12675. title += ' ' + totalTime + 'ms';
  12676. if(moduleSelector) {
  12677. title += ' \'' + moduleSelector + '\'';
  12678. }
  12679. if($allModules.length > 1) {
  12680. title += ' ' + '(' + $allModules.length + ')';
  12681. }
  12682. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  12683. console.groupCollapsed(title);
  12684. if(console.table) {
  12685. console.table(performance);
  12686. }
  12687. else {
  12688. $.each(performance, function(index, data) {
  12689. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  12690. });
  12691. }
  12692. console.groupEnd();
  12693. }
  12694. performance = [];
  12695. }
  12696. },
  12697. invoke: function(query, passedArguments, context) {
  12698. var
  12699. object = instance,
  12700. maxDepth,
  12701. found,
  12702. response
  12703. ;
  12704. passedArguments = passedArguments || queryArguments;
  12705. context = element || context;
  12706. if(typeof query == 'string' && object !== undefined) {
  12707. query = query.split(/[\. ]/);
  12708. maxDepth = query.length - 1;
  12709. $.each(query, function(depth, value) {
  12710. var camelCaseValue = (depth != maxDepth)
  12711. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  12712. : query
  12713. ;
  12714. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  12715. object = object[camelCaseValue];
  12716. }
  12717. else if( object[camelCaseValue] !== undefined ) {
  12718. found = object[camelCaseValue];
  12719. return false;
  12720. }
  12721. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  12722. object = object[value];
  12723. }
  12724. else if( object[value] !== undefined ) {
  12725. found = object[value];
  12726. return false;
  12727. }
  12728. else {
  12729. return false;
  12730. }
  12731. });
  12732. }
  12733. if ( $.isFunction( found ) ) {
  12734. response = found.apply(context, passedArguments);
  12735. }
  12736. else if(found !== undefined) {
  12737. response = found;
  12738. }
  12739. if($.isArray(returnedValue)) {
  12740. returnedValue.push(response);
  12741. }
  12742. else if(returnedValue !== undefined) {
  12743. returnedValue = [returnedValue, response];
  12744. }
  12745. else if(response !== undefined) {
  12746. returnedValue = response;
  12747. }
  12748. return found;
  12749. }
  12750. };
  12751. if(methodInvoked) {
  12752. if(instance === undefined) {
  12753. module.initialize();
  12754. }
  12755. module.invoke(query);
  12756. }
  12757. else {
  12758. if(instance !== undefined) {
  12759. instance.invoke('destroy');
  12760. }
  12761. module.initialize();
  12762. }
  12763. })
  12764. ;
  12765. return (returnedValue !== undefined)
  12766. ? returnedValue
  12767. : this
  12768. ;
  12769. };
  12770. $.fn.shape.settings = {
  12771. // module info
  12772. name : 'Shape',
  12773. // debug content outputted to console
  12774. debug : false,
  12775. // verbose debug output
  12776. verbose : false,
  12777. // performance data output
  12778. performance: true,
  12779. // event namespace
  12780. namespace : 'shape',
  12781. // callback occurs on side change
  12782. beforeChange : function() {},
  12783. onChange : function() {},
  12784. // allow animation to same side
  12785. allowRepeats: false,
  12786. // animation duration
  12787. duration : false,
  12788. // possible errors
  12789. error: {
  12790. side : 'You tried to switch to a side that does not exist.',
  12791. method : 'The method you called is not defined'
  12792. },
  12793. // classnames used
  12794. className : {
  12795. animating : 'animating',
  12796. hidden : 'hidden',
  12797. loading : 'loading',
  12798. active : 'active'
  12799. },
  12800. // selectors used
  12801. selector : {
  12802. sides : '.sides',
  12803. side : '.side'
  12804. }
  12805. };
  12806. })( jQuery, window , document );
  12807. /*!
  12808. * # Semantic UI 2.0.0 - Sidebar
  12809. * http://github.com/semantic-org/semantic-ui/
  12810. *
  12811. *
  12812. * Copyright 2015 Contributors
  12813. * Released under the MIT license
  12814. * http://opensource.org/licenses/MIT
  12815. *
  12816. */
  12817. ;(function ( $, window, document, undefined ) {
  12818. "use strict";
  12819. $.fn.sidebar = function(parameters) {
  12820. var
  12821. $allModules = $(this),
  12822. $window = $(window),
  12823. $document = $(document),
  12824. $html = $('html'),
  12825. $head = $('head'),
  12826. moduleSelector = $allModules.selector || '',
  12827. time = new Date().getTime(),
  12828. performance = [],
  12829. query = arguments[0],
  12830. methodInvoked = (typeof query == 'string'),
  12831. queryArguments = [].slice.call(arguments, 1),
  12832. requestAnimationFrame = window.requestAnimationFrame
  12833. || window.mozRequestAnimationFrame
  12834. || window.webkitRequestAnimationFrame
  12835. || window.msRequestAnimationFrame
  12836. || function(callback) { setTimeout(callback, 0); },
  12837. returnedValue
  12838. ;
  12839. $allModules
  12840. .each(function() {
  12841. var
  12842. settings = ( $.isPlainObject(parameters) )
  12843. ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
  12844. : $.extend({}, $.fn.sidebar.settings),
  12845. selector = settings.selector,
  12846. className = settings.className,
  12847. namespace = settings.namespace,
  12848. regExp = settings.regExp,
  12849. error = settings.error,
  12850. eventNamespace = '.' + namespace,
  12851. moduleNamespace = 'module-' + namespace,
  12852. $module = $(this),
  12853. $context = $(settings.context),
  12854. $sidebars = $module.children(selector.sidebar),
  12855. $fixed = $context.children(selector.fixed),
  12856. $pusher = $context.children(selector.pusher),
  12857. $style,
  12858. element = this,
  12859. instance = $module.data(moduleNamespace),
  12860. elementNamespace,
  12861. id,
  12862. currentScroll,
  12863. transitionEvent,
  12864. module
  12865. ;
  12866. module = {
  12867. initialize: function() {
  12868. module.debug('Initializing sidebar', parameters);
  12869. module.create.id();
  12870. transitionEvent = module.get.transitionEvent();
  12871. if(module.is.ios()) {
  12872. module.set.ios();
  12873. }
  12874. // avoids locking rendering if initialized in onReady
  12875. if(settings.delaySetup) {
  12876. requestAnimationFrame(module.setup.layout);
  12877. }
  12878. else {
  12879. module.setup.layout();
  12880. }
  12881. requestAnimationFrame(function() {
  12882. module.setup.cache();
  12883. });
  12884. module.instantiate();
  12885. },
  12886. instantiate: function() {
  12887. module.verbose('Storing instance of module', module);
  12888. instance = module;
  12889. $module
  12890. .data(moduleNamespace, module)
  12891. ;
  12892. },
  12893. create: {
  12894. id: function() {
  12895. id = (Math.random().toString(16) + '000000000').substr(2,8);
  12896. elementNamespace = '.' + id;
  12897. module.verbose('Creating unique id for element', id);
  12898. }
  12899. },
  12900. destroy: function() {
  12901. module.verbose('Destroying previous module for', $module);
  12902. module.remove.direction();
  12903. $module
  12904. .off(eventNamespace)
  12905. .removeData(moduleNamespace)
  12906. ;
  12907. if(module.is.ios()) {
  12908. module.remove.ios();
  12909. }
  12910. // bound by uuid
  12911. $context.off(elementNamespace);
  12912. $window.off(elementNamespace);
  12913. $document.off(elementNamespace);
  12914. },
  12915. event: {
  12916. clickaway: function(event) {
  12917. var
  12918. clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
  12919. clickedContext = ($context.is(event.target))
  12920. ;
  12921. if(clickedInPusher) {
  12922. module.verbose('User clicked on dimmed page');
  12923. module.hide();
  12924. }
  12925. if(clickedContext) {
  12926. module.verbose('User clicked on dimmable context (scaled out page)');
  12927. module.hide();
  12928. }
  12929. },
  12930. touch: function(event) {
  12931. //event.stopPropagation();
  12932. },
  12933. containScroll: function(event) {
  12934. if(element.scrollTop <= 0) {
  12935. element.scrollTop = 1;
  12936. }
  12937. if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
  12938. element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
  12939. }
  12940. },
  12941. scroll: function(event) {
  12942. if( $(event.target).closest(selector.sidebar).length === 0 ) {
  12943. event.preventDefault();
  12944. }
  12945. }
  12946. },
  12947. bind: {
  12948. clickaway: function() {
  12949. module.verbose('Adding clickaway events to context', $context);
  12950. if(settings.closable) {
  12951. $context
  12952. .on('click' + elementNamespace, module.event.clickaway)
  12953. .on('touchend' + elementNamespace, module.event.clickaway)
  12954. ;
  12955. }
  12956. },
  12957. scrollLock: function() {
  12958. if(settings.scrollLock) {
  12959. module.debug('Disabling page scroll');
  12960. $window
  12961. .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
  12962. ;
  12963. }
  12964. module.verbose('Adding events to contain sidebar scroll');
  12965. $document
  12966. .on('touchmove' + elementNamespace, module.event.touch)
  12967. ;
  12968. $module
  12969. .on('scroll' + eventNamespace, module.event.containScroll)
  12970. ;
  12971. }
  12972. },
  12973. unbind: {
  12974. clickaway: function() {
  12975. module.verbose('Removing clickaway events from context', $context);
  12976. $context.off(elementNamespace);
  12977. },
  12978. scrollLock: function() {
  12979. module.verbose('Removing scroll lock from page');
  12980. $document.off(elementNamespace);
  12981. $window.off(elementNamespace);
  12982. $module.off('scroll' + eventNamespace);
  12983. }
  12984. },
  12985. add: {
  12986. inlineCSS: function() {
  12987. var
  12988. width = module.cache.width || $module.outerWidth(),
  12989. height = module.cache.height || $module.outerHeight(),
  12990. isRTL = module.is.rtl(),
  12991. direction = module.get.direction(),
  12992. distance = {
  12993. left : width,
  12994. right : -width,
  12995. top : height,
  12996. bottom : -height
  12997. },
  12998. style
  12999. ;
  13000. if(isRTL){
  13001. module.verbose('RTL detected, flipping widths');
  13002. distance.left = -width;
  13003. distance.right = width;
  13004. }
  13005. style = '<style>';
  13006. if(direction === 'left' || direction === 'right') {
  13007. module.debug('Adding CSS rules for animation distance', width);
  13008. style += ''
  13009. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  13010. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  13011. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  13012. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  13013. + ' }'
  13014. ;
  13015. }
  13016. else if(direction === 'top' || direction == 'bottom') {
  13017. style += ''
  13018. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  13019. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  13020. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  13021. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  13022. + ' }'
  13023. ;
  13024. }
  13025. /* IE is only browser not to create context with transforms */
  13026. /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
  13027. if( module.is.ie() ) {
  13028. if(direction === 'left' || direction === 'right') {
  13029. module.debug('Adding CSS rules for animation distance', width);
  13030. style += ''
  13031. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  13032. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  13033. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  13034. + ' }'
  13035. ;
  13036. }
  13037. else if(direction === 'top' || direction == 'bottom') {
  13038. style += ''
  13039. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  13040. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  13041. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  13042. + ' }'
  13043. ;
  13044. }
  13045. /* opposite sides visible forces content overlay */
  13046. style += ''
  13047. + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
  13048. + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
  13049. + ' -webkit-transform: translate3d(0px, 0, 0);'
  13050. + ' transform: translate3d(0px, 0, 0);'
  13051. + ' }'
  13052. ;
  13053. }
  13054. style += '</style>';
  13055. $style = $(style)
  13056. .appendTo($head)
  13057. ;
  13058. module.debug('Adding sizing css to head', $style);
  13059. }
  13060. },
  13061. refresh: function() {
  13062. module.verbose('Refreshing selector cache');
  13063. $context = $(settings.context);
  13064. $sidebars = $context.children(selector.sidebar);
  13065. $pusher = $context.children(selector.pusher);
  13066. $fixed = $context.children(selector.fixed);
  13067. module.clear.cache();
  13068. },
  13069. refreshSidebars: function() {
  13070. module.verbose('Refreshing other sidebars');
  13071. $sidebars = $context.children(selector.sidebar);
  13072. },
  13073. repaint: function() {
  13074. module.verbose('Forcing repaint event');
  13075. element.style.display = 'none';
  13076. var ignored = element.offsetHeight;
  13077. element.scrollTop = element.scrollTop;
  13078. element.style.display = '';
  13079. },
  13080. setup: {
  13081. cache: function() {
  13082. module.cache = {
  13083. width : $module.outerWidth(),
  13084. height : $module.outerHeight(),
  13085. rtl : ($module.css('direction') == 'rtl')
  13086. };
  13087. },
  13088. layout: function() {
  13089. if( $context.children(selector.pusher).length === 0 ) {
  13090. module.debug('Adding wrapper element for sidebar');
  13091. module.error(error.pusher);
  13092. $pusher = $('<div class="pusher" />');
  13093. $context
  13094. .children()
  13095. .not(selector.omitted)
  13096. .not($sidebars)
  13097. .wrapAll($pusher)
  13098. ;
  13099. module.refresh();
  13100. }
  13101. if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
  13102. module.debug('Moved sidebar to correct parent element');
  13103. module.error(error.movedSidebar, element);
  13104. $module.detach().prependTo($context);
  13105. module.refresh();
  13106. }
  13107. module.clear.cache();
  13108. module.set.pushable();
  13109. module.set.direction();
  13110. }
  13111. },
  13112. attachEvents: function(selector, event) {
  13113. var
  13114. $toggle = $(selector)
  13115. ;
  13116. event = $.isFunction(module[event])
  13117. ? module[event]
  13118. : module.toggle
  13119. ;
  13120. if($toggle.length > 0) {
  13121. module.debug('Attaching sidebar events to element', selector, event);
  13122. $toggle
  13123. .on('click' + eventNamespace, event)
  13124. ;
  13125. }
  13126. else {
  13127. module.error(error.notFound, selector);
  13128. }
  13129. },
  13130. show: function(callback) {
  13131. callback = $.isFunction(callback)
  13132. ? callback
  13133. : function(){}
  13134. ;
  13135. if(module.is.hidden()) {
  13136. module.refreshSidebars();
  13137. if(settings.overlay) {
  13138. module.error(error.overlay);
  13139. settings.transition = 'overlay';
  13140. }
  13141. module.refresh();
  13142. if(module.othersActive()) {
  13143. module.debug('Other sidebars currently visible');
  13144. if(settings.exclusive) {
  13145. // if not overlay queue animation after hide
  13146. if(settings.transition != 'overlay') {
  13147. module.hideOthers(module.show);
  13148. return;
  13149. }
  13150. else {
  13151. module.hideOthers();
  13152. }
  13153. }
  13154. else {
  13155. settings.transition = 'overlay';
  13156. }
  13157. }
  13158. module.pushPage(function() {
  13159. callback.call(element);
  13160. settings.onShow.call(element);
  13161. });
  13162. settings.onChange.call(element);
  13163. settings.onVisible.call(element);
  13164. }
  13165. else {
  13166. module.debug('Sidebar is already visible');
  13167. }
  13168. },
  13169. hide: function(callback) {
  13170. callback = $.isFunction(callback)
  13171. ? callback
  13172. : function(){}
  13173. ;
  13174. if(module.is.visible() || module.is.animating()) {
  13175. module.debug('Hiding sidebar', callback);
  13176. module.refreshSidebars();
  13177. module.pullPage(function() {
  13178. callback.call(element);
  13179. settings.onHidden.call(element);
  13180. });
  13181. settings.onChange.call(element);
  13182. settings.onHide.call(element);
  13183. }
  13184. },
  13185. othersAnimating: function() {
  13186. return ($sidebars.not($module).filter('.' + className.animating).length > 0);
  13187. },
  13188. othersVisible: function() {
  13189. return ($sidebars.not($module).filter('.' + className.visible).length > 0);
  13190. },
  13191. othersActive: function() {
  13192. return(module.othersVisible() || module.othersAnimating());
  13193. },
  13194. hideOthers: function(callback) {
  13195. var
  13196. $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
  13197. sidebarCount = $otherSidebars.length,
  13198. callbackCount = 0
  13199. ;
  13200. callback = callback || function(){};
  13201. $otherSidebars
  13202. .sidebar('hide', function() {
  13203. callbackCount++;
  13204. if(callbackCount == sidebarCount) {
  13205. callback();
  13206. }
  13207. })
  13208. ;
  13209. },
  13210. toggle: function() {
  13211. module.verbose('Determining toggled direction');
  13212. if(module.is.hidden()) {
  13213. module.show();
  13214. }
  13215. else {
  13216. module.hide();
  13217. }
  13218. },
  13219. pushPage: function(callback) {
  13220. var
  13221. transition = module.get.transition(),
  13222. $transition = (transition === 'overlay' || module.othersActive())
  13223. ? $module
  13224. : $pusher,
  13225. animate,
  13226. dim,
  13227. transitionEnd
  13228. ;
  13229. callback = $.isFunction(callback)
  13230. ? callback
  13231. : function(){}
  13232. ;
  13233. if(settings.transition == 'scale down') {
  13234. module.scrollToTop();
  13235. }
  13236. module.set.transition(transition);
  13237. module.repaint();
  13238. animate = function() {
  13239. module.bind.clickaway();
  13240. module.add.inlineCSS();
  13241. module.set.animating();
  13242. module.set.visible();
  13243. };
  13244. dim = function() {
  13245. module.set.dimmed();
  13246. };
  13247. transitionEnd = function(event) {
  13248. if( event.target == $transition[0] ) {
  13249. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  13250. module.remove.animating();
  13251. module.bind.scrollLock();
  13252. callback.call(element);
  13253. }
  13254. };
  13255. $transition.off(transitionEvent + elementNamespace);
  13256. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  13257. requestAnimationFrame(animate);
  13258. if(settings.dimPage && !module.othersVisible()) {
  13259. requestAnimationFrame(dim);
  13260. }
  13261. },
  13262. pullPage: function(callback) {
  13263. var
  13264. transition = module.get.transition(),
  13265. $transition = (transition == 'overlay' || module.othersActive())
  13266. ? $module
  13267. : $pusher,
  13268. animate,
  13269. transitionEnd
  13270. ;
  13271. callback = $.isFunction(callback)
  13272. ? callback
  13273. : function(){}
  13274. ;
  13275. module.verbose('Removing context push state', module.get.direction());
  13276. module.unbind.clickaway();
  13277. module.unbind.scrollLock();
  13278. animate = function() {
  13279. module.set.transition(transition);
  13280. module.set.animating();
  13281. module.remove.visible();
  13282. if(settings.dimPage && !module.othersVisible()) {
  13283. $pusher.removeClass(className.dimmed);
  13284. }
  13285. };
  13286. transitionEnd = function(event) {
  13287. if( event.target == $transition[0] ) {
  13288. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  13289. module.remove.animating();
  13290. module.remove.transition();
  13291. module.remove.inlineCSS();
  13292. if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
  13293. module.scrollBack();
  13294. }
  13295. callback.call(element);
  13296. }
  13297. };
  13298. $transition.off(transitionEvent + elementNamespace);
  13299. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  13300. requestAnimationFrame(animate);
  13301. },
  13302. scrollToTop: function() {
  13303. module.verbose('Scrolling to top of page to avoid animation issues');
  13304. currentScroll = $(window).scrollTop();
  13305. $module.scrollTop(0);
  13306. window.scrollTo(0, 0);
  13307. },
  13308. scrollBack: function() {
  13309. module.verbose('Scrolling back to original page position');
  13310. window.scrollTo(0, currentScroll);
  13311. },
  13312. clear: {
  13313. cache: function() {
  13314. module.verbose('Clearing cached dimensions');
  13315. module.cache = {};
  13316. }
  13317. },
  13318. set: {
  13319. // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
  13320. ios: function() {
  13321. $html.addClass(className.ios);
  13322. },
  13323. // container
  13324. pushed: function() {
  13325. $context.addClass(className.pushed);
  13326. },
  13327. pushable: function() {
  13328. $context.addClass(className.pushable);
  13329. },
  13330. // pusher
  13331. dimmed: function() {
  13332. $pusher.addClass(className.dimmed);
  13333. },
  13334. // sidebar
  13335. active: function() {
  13336. $module.addClass(className.active);
  13337. },
  13338. animating: function() {
  13339. $module.addClass(className.animating);
  13340. },
  13341. transition: function(transition) {
  13342. transition = transition || module.get.transition();
  13343. $module.addClass(transition);
  13344. },
  13345. direction: function(direction) {
  13346. direction = direction || module.get.direction();
  13347. $module.addClass(className[direction]);
  13348. },
  13349. visible: function() {
  13350. $module.addClass(className.visible);
  13351. },
  13352. overlay: function() {
  13353. $module.addClass(className.overlay);
  13354. }
  13355. },
  13356. remove: {
  13357. inlineCSS: function() {
  13358. module.debug('Removing inline css styles', $style);
  13359. if($style && $style.length > 0) {
  13360. $style.remove();
  13361. }
  13362. },
  13363. // ios scroll on html not document
  13364. ios: function() {
  13365. $html.removeClass(className.ios);
  13366. },
  13367. // context
  13368. pushed: function() {
  13369. $context.removeClass(className.pushed);
  13370. },
  13371. pushable: function() {
  13372. $context.removeClass(className.pushable);
  13373. },
  13374. // sidebar
  13375. active: function() {
  13376. $module.removeClass(className.active);
  13377. },
  13378. animating: function() {
  13379. $module.removeClass(className.animating);
  13380. },
  13381. transition: function(transition) {
  13382. transition = transition || module.get.transition();
  13383. $module.removeClass(transition);
  13384. },
  13385. direction: function(direction) {
  13386. direction = direction || module.get.direction();
  13387. $module.removeClass(className[direction]);
  13388. },
  13389. visible: function() {
  13390. $module.removeClass(className.visible);
  13391. },
  13392. overlay: function() {
  13393. $module.removeClass(className.overlay);
  13394. }
  13395. },
  13396. get: {
  13397. direction: function() {
  13398. if($module.hasClass(className.top)) {
  13399. return className.top;
  13400. }
  13401. else if($module.hasClass(className.right)) {
  13402. return className.right;
  13403. }
  13404. else if($module.hasClass(className.bottom)) {
  13405. return className.bottom;
  13406. }
  13407. return className.left;
  13408. },
  13409. transition: function() {
  13410. var
  13411. direction = module.get.direction(),
  13412. transition
  13413. ;
  13414. transition = ( module.is.mobile() )
  13415. ? (settings.mobileTransition == 'auto')
  13416. ? settings.defaultTransition.mobile[direction]
  13417. : settings.mobileTransition
  13418. : (settings.transition == 'auto')
  13419. ? settings.defaultTransition.computer[direction]
  13420. : settings.transition
  13421. ;
  13422. module.verbose('Determined transition', transition);
  13423. return transition;
  13424. },
  13425. transitionEvent: function() {
  13426. var
  13427. element = document.createElement('element'),
  13428. transitions = {
  13429. 'transition' :'transitionend',
  13430. 'OTransition' :'oTransitionEnd',
  13431. 'MozTransition' :'transitionend',
  13432. 'WebkitTransition' :'webkitTransitionEnd'
  13433. },
  13434. transition
  13435. ;
  13436. for(transition in transitions){
  13437. if( element.style[transition] !== undefined ){
  13438. return transitions[transition];
  13439. }
  13440. }
  13441. }
  13442. },
  13443. is: {
  13444. ie: function() {
  13445. var
  13446. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  13447. isIE = ('ActiveXObject' in window)
  13448. ;
  13449. return (isIE11 || isIE);
  13450. },
  13451. ios: function() {
  13452. var
  13453. userAgent = navigator.userAgent,
  13454. isIOS = userAgent.match(regExp.ios),
  13455. isMobileChrome = userAgent.match(regExp.mobileChrome)
  13456. ;
  13457. if(isIOS && !isMobileChrome) {
  13458. module.verbose('Browser was found to be iOS', userAgent);
  13459. return true;
  13460. }
  13461. else {
  13462. return false;
  13463. }
  13464. },
  13465. mobile: function() {
  13466. var
  13467. userAgent = navigator.userAgent,
  13468. isMobile = userAgent.match(regExp.mobile)
  13469. ;
  13470. if(isMobile) {
  13471. module.verbose('Browser was found to be mobile', userAgent);
  13472. return true;
  13473. }
  13474. else {
  13475. module.verbose('Browser is not mobile, using regular transition', userAgent);
  13476. return false;
  13477. }
  13478. },
  13479. hidden: function() {
  13480. return !module.is.visible();
  13481. },
  13482. visible: function() {
  13483. return $module.hasClass(className.visible);
  13484. },
  13485. // alias
  13486. open: function() {
  13487. return module.is.visible();
  13488. },
  13489. closed: function() {
  13490. return module.is.hidden();
  13491. },
  13492. vertical: function() {
  13493. return $module.hasClass(className.top);
  13494. },
  13495. animating: function() {
  13496. return $context.hasClass(className.animating);
  13497. },
  13498. rtl: function () {
  13499. if(module.cache.rtl === undefined) {
  13500. module.cache.rtl = ($module.css('direction') == 'rtl');
  13501. }
  13502. return module.cache.rtl;
  13503. }
  13504. },
  13505. setting: function(name, value) {
  13506. module.debug('Changing setting', name, value);
  13507. if( $.isPlainObject(name) ) {
  13508. $.extend(true, settings, name);
  13509. }
  13510. else if(value !== undefined) {
  13511. settings[name] = value;
  13512. }
  13513. else {
  13514. return settings[name];
  13515. }
  13516. },
  13517. internal: function(name, value) {
  13518. if( $.isPlainObject(name) ) {
  13519. $.extend(true, module, name);
  13520. }
  13521. else if(value !== undefined) {
  13522. module[name] = value;
  13523. }
  13524. else {
  13525. return module[name];
  13526. }
  13527. },
  13528. debug: function() {
  13529. if(settings.debug) {
  13530. if(settings.performance) {
  13531. module.performance.log(arguments);
  13532. }
  13533. else {
  13534. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13535. module.debug.apply(console, arguments);
  13536. }
  13537. }
  13538. },
  13539. verbose: function() {
  13540. if(settings.verbose && settings.debug) {
  13541. if(settings.performance) {
  13542. module.performance.log(arguments);
  13543. }
  13544. else {
  13545. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13546. module.verbose.apply(console, arguments);
  13547. }
  13548. }
  13549. },
  13550. error: function() {
  13551. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  13552. module.error.apply(console, arguments);
  13553. },
  13554. performance: {
  13555. log: function(message) {
  13556. var
  13557. currentTime,
  13558. executionTime,
  13559. previousTime
  13560. ;
  13561. if(settings.performance) {
  13562. currentTime = new Date().getTime();
  13563. previousTime = time || currentTime;
  13564. executionTime = currentTime - previousTime;
  13565. time = currentTime;
  13566. performance.push({
  13567. 'Name' : message[0],
  13568. 'Arguments' : [].slice.call(message, 1) || '',
  13569. 'Element' : element,
  13570. 'Execution Time' : executionTime
  13571. });
  13572. }
  13573. clearTimeout(module.performance.timer);
  13574. module.performance.timer = setTimeout(module.performance.display, 500);
  13575. },
  13576. display: function() {
  13577. var
  13578. title = settings.name + ':',
  13579. totalTime = 0
  13580. ;
  13581. time = false;
  13582. clearTimeout(module.performance.timer);
  13583. $.each(performance, function(index, data) {
  13584. totalTime += data['Execution Time'];
  13585. });
  13586. title += ' ' + totalTime + 'ms';
  13587. if(moduleSelector) {
  13588. title += ' \'' + moduleSelector + '\'';
  13589. }
  13590. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  13591. console.groupCollapsed(title);
  13592. if(console.table) {
  13593. console.table(performance);
  13594. }
  13595. else {
  13596. $.each(performance, function(index, data) {
  13597. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  13598. });
  13599. }
  13600. console.groupEnd();
  13601. }
  13602. performance = [];
  13603. }
  13604. },
  13605. invoke: function(query, passedArguments, context) {
  13606. var
  13607. object = instance,
  13608. maxDepth,
  13609. found,
  13610. response
  13611. ;
  13612. passedArguments = passedArguments || queryArguments;
  13613. context = element || context;
  13614. if(typeof query == 'string' && object !== undefined) {
  13615. query = query.split(/[\. ]/);
  13616. maxDepth = query.length - 1;
  13617. $.each(query, function(depth, value) {
  13618. var camelCaseValue = (depth != maxDepth)
  13619. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  13620. : query
  13621. ;
  13622. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  13623. object = object[camelCaseValue];
  13624. }
  13625. else if( object[camelCaseValue] !== undefined ) {
  13626. found = object[camelCaseValue];
  13627. return false;
  13628. }
  13629. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  13630. object = object[value];
  13631. }
  13632. else if( object[value] !== undefined ) {
  13633. found = object[value];
  13634. return false;
  13635. }
  13636. else {
  13637. module.error(error.method, query);
  13638. return false;
  13639. }
  13640. });
  13641. }
  13642. if ( $.isFunction( found ) ) {
  13643. response = found.apply(context, passedArguments);
  13644. }
  13645. else if(found !== undefined) {
  13646. response = found;
  13647. }
  13648. if($.isArray(returnedValue)) {
  13649. returnedValue.push(response);
  13650. }
  13651. else if(returnedValue !== undefined) {
  13652. returnedValue = [returnedValue, response];
  13653. }
  13654. else if(response !== undefined) {
  13655. returnedValue = response;
  13656. }
  13657. return found;
  13658. }
  13659. }
  13660. ;
  13661. if(methodInvoked) {
  13662. if(instance === undefined) {
  13663. module.initialize();
  13664. }
  13665. module.invoke(query);
  13666. }
  13667. else {
  13668. if(instance !== undefined) {
  13669. module.invoke('destroy');
  13670. }
  13671. module.initialize();
  13672. }
  13673. });
  13674. return (returnedValue !== undefined)
  13675. ? returnedValue
  13676. : this
  13677. ;
  13678. };
  13679. $.fn.sidebar.settings = {
  13680. name : 'Sidebar',
  13681. namespace : 'sidebar',
  13682. debug : false,
  13683. verbose : false,
  13684. performance : true,
  13685. transition : 'auto',
  13686. mobileTransition : 'auto',
  13687. defaultTransition : {
  13688. computer: {
  13689. left : 'uncover',
  13690. right : 'uncover',
  13691. top : 'overlay',
  13692. bottom : 'overlay'
  13693. },
  13694. mobile: {
  13695. left : 'uncover',
  13696. right : 'uncover',
  13697. top : 'overlay',
  13698. bottom : 'overlay'
  13699. }
  13700. },
  13701. context : 'body',
  13702. exclusive : false,
  13703. closable : true,
  13704. dimPage : true,
  13705. scrollLock : false,
  13706. returnScroll : false,
  13707. delaySetup : false,
  13708. duration : 500,
  13709. onChange : function(){},
  13710. onShow : function(){},
  13711. onHide : function(){},
  13712. onHidden : function(){},
  13713. onVisible : function(){},
  13714. className : {
  13715. active : 'active',
  13716. animating : 'animating',
  13717. dimmed : 'dimmed',
  13718. ios : 'ios',
  13719. pushable : 'pushable',
  13720. pushed : 'pushed',
  13721. right : 'right',
  13722. top : 'top',
  13723. left : 'left',
  13724. bottom : 'bottom',
  13725. visible : 'visible'
  13726. },
  13727. selector: {
  13728. fixed : '.fixed',
  13729. omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
  13730. pusher : '.pusher',
  13731. sidebar : '.ui.sidebar'
  13732. },
  13733. regExp: {
  13734. ios : /(iPad|iPhone|iPod)/g,
  13735. mobileChrome : /(CriOS)/g,
  13736. 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
  13737. },
  13738. error : {
  13739. method : 'The method you called is not defined.',
  13740. pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
  13741. movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
  13742. overlay : 'The overlay setting is no longer supported, use animation: overlay',
  13743. notFound : 'There were no elements that matched the specified selector'
  13744. }
  13745. };
  13746. })( jQuery, window , document );
  13747. /*!
  13748. * # Semantic UI 2.0.0 - Sticky
  13749. * http://github.com/semantic-org/semantic-ui/
  13750. *
  13751. *
  13752. * Copyright 2015 Contributors
  13753. * Released under the MIT license
  13754. * http://opensource.org/licenses/MIT
  13755. *
  13756. */
  13757. ;(function ( $, window, document, undefined ) {
  13758. "use strict";
  13759. $.fn.sticky = function(parameters) {
  13760. var
  13761. $allModules = $(this),
  13762. moduleSelector = $allModules.selector || '',
  13763. time = new Date().getTime(),
  13764. performance = [],
  13765. query = arguments[0],
  13766. methodInvoked = (typeof query == 'string'),
  13767. queryArguments = [].slice.call(arguments, 1),
  13768. returnedValue
  13769. ;
  13770. $allModules
  13771. .each(function() {
  13772. var
  13773. settings = ( $.isPlainObject(parameters) )
  13774. ? $.extend(true, {}, $.fn.sticky.settings, parameters)
  13775. : $.extend({}, $.fn.sticky.settings),
  13776. className = settings.className,
  13777. namespace = settings.namespace,
  13778. error = settings.error,
  13779. eventNamespace = '.' + namespace,
  13780. moduleNamespace = 'module-' + namespace,
  13781. $module = $(this),
  13782. $window = $(window),
  13783. $scroll = $(settings.scrollContext),
  13784. $container,
  13785. $context,
  13786. selector = $module.selector || '',
  13787. instance = $module.data(moduleNamespace),
  13788. requestAnimationFrame = window.requestAnimationFrame
  13789. || window.mozRequestAnimationFrame
  13790. || window.webkitRequestAnimationFrame
  13791. || window.msRequestAnimationFrame
  13792. || function(callback) { setTimeout(callback, 0); },
  13793. element = this,
  13794. observer,
  13795. module
  13796. ;
  13797. module = {
  13798. initialize: function() {
  13799. module.determineContainer();
  13800. module.determineContext();
  13801. module.verbose('Initializing sticky', settings, $container);
  13802. module.save.positions();
  13803. module.checkErrors();
  13804. module.bind.events();
  13805. if(settings.observeChanges) {
  13806. module.observeChanges();
  13807. }
  13808. module.instantiate();
  13809. },
  13810. instantiate: function() {
  13811. module.verbose('Storing instance of module', module);
  13812. instance = module;
  13813. $module
  13814. .data(moduleNamespace, module)
  13815. ;
  13816. },
  13817. destroy: function() {
  13818. module.verbose('Destroying previous instance');
  13819. module.reset();
  13820. if(observer) {
  13821. observer.disconnect();
  13822. }
  13823. $window
  13824. .off('load' + eventNamespace, module.event.load)
  13825. .off('resize' + eventNamespace, module.event.resize)
  13826. ;
  13827. $scroll
  13828. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  13829. ;
  13830. $module.removeData(moduleNamespace);
  13831. },
  13832. observeChanges: function() {
  13833. var
  13834. context = $context[0]
  13835. ;
  13836. if('MutationObserver' in window) {
  13837. observer = new MutationObserver(function(mutations) {
  13838. clearTimeout(module.timer);
  13839. module.timer = setTimeout(function() {
  13840. module.verbose('DOM tree modified, updating sticky menu', mutations);
  13841. module.refresh();
  13842. }, 100);
  13843. });
  13844. observer.observe(element, {
  13845. childList : true,
  13846. subtree : true
  13847. });
  13848. observer.observe(context, {
  13849. childList : true,
  13850. subtree : true
  13851. });
  13852. module.debug('Setting up mutation observer', observer);
  13853. }
  13854. },
  13855. determineContainer: function() {
  13856. $container = $module.offsetParent();
  13857. },
  13858. determineContext: function() {
  13859. if(settings.context) {
  13860. $context = $(settings.context);
  13861. }
  13862. else {
  13863. $context = $container;
  13864. }
  13865. if($context.length === 0) {
  13866. module.error(error.invalidContext, settings.context, $module);
  13867. return;
  13868. }
  13869. },
  13870. checkErrors: function() {
  13871. if( module.is.hidden() ) {
  13872. module.error(error.visible, $module);
  13873. }
  13874. if(module.cache.element.height > module.cache.context.height) {
  13875. module.reset();
  13876. module.error(error.elementSize, $module);
  13877. return;
  13878. }
  13879. },
  13880. bind: {
  13881. events: function() {
  13882. $window
  13883. .on('load' + eventNamespace, module.event.load)
  13884. .on('resize' + eventNamespace, module.event.resize)
  13885. ;
  13886. // pub/sub pattern
  13887. $scroll
  13888. .off('scroll' + eventNamespace)
  13889. .on('scroll' + eventNamespace, module.event.scroll)
  13890. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  13891. ;
  13892. }
  13893. },
  13894. event: {
  13895. load: function() {
  13896. module.verbose('Page contents finished loading');
  13897. requestAnimationFrame(module.refresh);
  13898. },
  13899. resize: function() {
  13900. module.verbose('Window resized');
  13901. requestAnimationFrame(module.refresh);
  13902. },
  13903. scroll: function() {
  13904. requestAnimationFrame(function() {
  13905. $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
  13906. });
  13907. },
  13908. scrollchange: function(event, scrollPosition) {
  13909. module.stick(scrollPosition);
  13910. settings.onScroll.call(element);
  13911. }
  13912. },
  13913. refresh: function(hardRefresh) {
  13914. module.reset();
  13915. if(!settings.context) {
  13916. module.determineContext();
  13917. }
  13918. if(hardRefresh) {
  13919. module.determineContainer();
  13920. }
  13921. module.save.positions();
  13922. module.stick();
  13923. settings.onReposition.call(element);
  13924. },
  13925. supports: {
  13926. sticky: function() {
  13927. var
  13928. $element = $('<div/>'),
  13929. element = $element[0]
  13930. ;
  13931. $element.addClass(className.supported);
  13932. return($element.css('position').match('sticky'));
  13933. }
  13934. },
  13935. save: {
  13936. lastScroll: function(scroll) {
  13937. module.lastScroll = scroll;
  13938. },
  13939. elementScroll: function(scroll) {
  13940. module.elementScroll = scroll;
  13941. },
  13942. positions: function() {
  13943. var
  13944. window = {
  13945. height: $window.height()
  13946. },
  13947. element = {
  13948. margin: {
  13949. top : parseInt($module.css('margin-top'), 10),
  13950. bottom : parseInt($module.css('margin-bottom'), 10),
  13951. },
  13952. offset : $module.offset(),
  13953. width : $module.outerWidth(),
  13954. height : $module.outerHeight()
  13955. },
  13956. context = {
  13957. offset : $context.offset(),
  13958. height : $context.outerHeight(),
  13959. bottomPadding : parseInt($context.css('padding-bottom'), 10)
  13960. },
  13961. container = {
  13962. height: $container.outerHeight()
  13963. }
  13964. ;
  13965. module.cache = {
  13966. fits : ( element.height < window.height ),
  13967. window: {
  13968. height: window.height
  13969. },
  13970. element: {
  13971. margin : element.margin,
  13972. top : element.offset.top - element.margin.top,
  13973. left : element.offset.left,
  13974. width : element.width,
  13975. height : element.height,
  13976. bottom : element.offset.top + element.height
  13977. },
  13978. context: {
  13979. top : context.offset.top,
  13980. height : context.height,
  13981. bottomPadding : context.bottomPadding,
  13982. bottom : context.offset.top + context.height - context.bottomPadding
  13983. }
  13984. };
  13985. module.set.containerSize();
  13986. module.set.size();
  13987. module.stick();
  13988. module.debug('Caching element positions', module.cache);
  13989. }
  13990. },
  13991. get: {
  13992. direction: function(scroll) {
  13993. var
  13994. direction = 'down'
  13995. ;
  13996. scroll = scroll || $scroll.scrollTop();
  13997. if(module.lastScroll !== undefined) {
  13998. if(module.lastScroll < scroll) {
  13999. direction = 'down';
  14000. }
  14001. else if(module.lastScroll > scroll) {
  14002. direction = 'up';
  14003. }
  14004. }
  14005. return direction;
  14006. },
  14007. scrollChange: function(scroll) {
  14008. scroll = scroll || $scroll.scrollTop();
  14009. return (module.lastScroll)
  14010. ? (scroll - module.lastScroll)
  14011. : 0
  14012. ;
  14013. },
  14014. currentElementScroll: function() {
  14015. if(module.elementScroll) {
  14016. return module.elementScroll;
  14017. }
  14018. return ( module.is.top() )
  14019. ? Math.abs(parseInt($module.css('top'), 10)) || 0
  14020. : Math.abs(parseInt($module.css('bottom'), 10)) || 0
  14021. ;
  14022. },
  14023. elementScroll: function(scroll) {
  14024. scroll = scroll || $scroll.scrollTop();
  14025. var
  14026. element = module.cache.element,
  14027. window = module.cache.window,
  14028. delta = module.get.scrollChange(scroll),
  14029. maxScroll = (element.height - window.height + settings.offset),
  14030. elementScroll = module.get.currentElementScroll(),
  14031. possibleScroll = (elementScroll + delta)
  14032. ;
  14033. if(module.cache.fits || possibleScroll < 0) {
  14034. elementScroll = 0;
  14035. }
  14036. else if(possibleScroll > maxScroll ) {
  14037. elementScroll = maxScroll;
  14038. }
  14039. else {
  14040. elementScroll = possibleScroll;
  14041. }
  14042. return elementScroll;
  14043. }
  14044. },
  14045. remove: {
  14046. lastScroll: function() {
  14047. delete module.lastScroll;
  14048. },
  14049. elementScroll: function(scroll) {
  14050. delete module.elementScroll;
  14051. },
  14052. offset: function() {
  14053. $module.css('margin-top', '');
  14054. }
  14055. },
  14056. set: {
  14057. offset: function() {
  14058. module.verbose('Setting offset on element', settings.offset);
  14059. $module
  14060. .css('margin-top', settings.offset)
  14061. ;
  14062. },
  14063. containerSize: function() {
  14064. var
  14065. tagName = $container.get(0).tagName
  14066. ;
  14067. if(tagName === 'HTML' || tagName == 'body') {
  14068. // this can trigger for too many reasons
  14069. //module.error(error.container, tagName, $module);
  14070. module.determineContainer();
  14071. }
  14072. else {
  14073. if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
  14074. module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
  14075. $container.css({
  14076. height: module.cache.context.height
  14077. });
  14078. }
  14079. }
  14080. },
  14081. minimumSize: function() {
  14082. var
  14083. element = module.cache.element
  14084. ;
  14085. $container
  14086. .css('min-height', element.height)
  14087. ;
  14088. },
  14089. scroll: function(scroll) {
  14090. module.debug('Setting scroll on element', scroll);
  14091. if(module.elementScroll == scroll) {
  14092. return;
  14093. }
  14094. if( module.is.top() ) {
  14095. $module
  14096. .css('bottom', '')
  14097. .css('top', -scroll)
  14098. ;
  14099. }
  14100. if( module.is.bottom() ) {
  14101. $module
  14102. .css('top', '')
  14103. .css('bottom', scroll)
  14104. ;
  14105. }
  14106. },
  14107. size: function() {
  14108. if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
  14109. $module
  14110. .css({
  14111. width : module.cache.element.width,
  14112. height : module.cache.element.height
  14113. })
  14114. ;
  14115. }
  14116. }
  14117. },
  14118. is: {
  14119. top: function() {
  14120. return $module.hasClass(className.top);
  14121. },
  14122. bottom: function() {
  14123. return $module.hasClass(className.bottom);
  14124. },
  14125. initialPosition: function() {
  14126. return (!module.is.fixed() && !module.is.bound());
  14127. },
  14128. hidden: function() {
  14129. return (!$module.is(':visible'));
  14130. },
  14131. bound: function() {
  14132. return $module.hasClass(className.bound);
  14133. },
  14134. fixed: function() {
  14135. return $module.hasClass(className.fixed);
  14136. }
  14137. },
  14138. stick: function(scroll) {
  14139. var
  14140. cachedPosition = scroll || $scroll.scrollTop(),
  14141. cache = module.cache,
  14142. fits = cache.fits,
  14143. element = cache.element,
  14144. window = cache.window,
  14145. context = cache.context,
  14146. offset = (module.is.bottom() && settings.pushing)
  14147. ? settings.bottomOffset
  14148. : settings.offset,
  14149. scroll = {
  14150. top : cachedPosition + offset,
  14151. bottom : cachedPosition + offset + window.height
  14152. },
  14153. direction = module.get.direction(scroll.top),
  14154. elementScroll = (fits)
  14155. ? 0
  14156. : module.get.elementScroll(scroll.top),
  14157. // shorthand
  14158. doesntFit = !fits,
  14159. elementVisible = (element.height !== 0)
  14160. ;
  14161. if(elementVisible) {
  14162. if( module.is.initialPosition() ) {
  14163. if(scroll.top > context.bottom) {
  14164. module.debug('Element bottom of container');
  14165. module.bindBottom();
  14166. }
  14167. else if(scroll.top > element.top) {
  14168. module.debug('Element passed, fixing element to page');
  14169. module.fixTop();
  14170. }
  14171. }
  14172. else if( module.is.fixed() ) {
  14173. // currently fixed top
  14174. if( module.is.top() ) {
  14175. if( scroll.top < element.top ) {
  14176. module.debug('Fixed element reached top of container');
  14177. module.setInitialPosition();
  14178. }
  14179. else if( (element.height + scroll.top - elementScroll) > context.bottom ) {
  14180. module.debug('Fixed element reached bottom of container');
  14181. module.bindBottom();
  14182. }
  14183. // scroll element if larger than screen
  14184. else if(doesntFit) {
  14185. module.set.scroll(elementScroll);
  14186. }
  14187. }
  14188. // currently fixed bottom
  14189. else if(module.is.bottom() ) {
  14190. // top edge
  14191. if( (scroll.bottom - element.height) < element.top) {
  14192. module.debug('Bottom fixed rail has reached top of container');
  14193. module.setInitialPosition();
  14194. }
  14195. // bottom edge
  14196. else if(scroll.bottom > context.bottom) {
  14197. module.debug('Bottom fixed rail has reached bottom of container');
  14198. module.bindBottom();
  14199. }
  14200. // scroll element if larger than screen
  14201. else if(doesntFit) {
  14202. module.set.scroll(elementScroll);
  14203. }
  14204. }
  14205. }
  14206. else if( module.is.bottom() ) {
  14207. if(settings.pushing) {
  14208. if(module.is.bound() && scroll.bottom < context.bottom ) {
  14209. module.debug('Fixing bottom attached element to bottom of browser.');
  14210. module.fixBottom();
  14211. }
  14212. }
  14213. else {
  14214. if(module.is.bound() && (scroll.top < context.bottom - element.height) ) {
  14215. module.debug('Fixing bottom attached element to top of browser.');
  14216. module.fixTop();
  14217. }
  14218. }
  14219. }
  14220. }
  14221. // save current scroll for next run
  14222. module.save.lastScroll(scroll.top);
  14223. module.save.elementScroll(elementScroll);
  14224. },
  14225. bindTop: function() {
  14226. module.debug('Binding element to top of parent container');
  14227. module.remove.offset();
  14228. $module
  14229. .css({
  14230. left : '',
  14231. top : '',
  14232. marginBottom : ''
  14233. })
  14234. .removeClass(className.fixed)
  14235. .removeClass(className.bottom)
  14236. .addClass(className.bound)
  14237. .addClass(className.top)
  14238. ;
  14239. settings.onTop.call(element);
  14240. settings.onUnstick.call(element);
  14241. },
  14242. bindBottom: function() {
  14243. module.debug('Binding element to bottom of parent container');
  14244. module.remove.offset();
  14245. $module
  14246. .css({
  14247. left : '',
  14248. top : '',
  14249. marginBottom : module.cache.context.bottomPadding
  14250. })
  14251. .removeClass(className.fixed)
  14252. .removeClass(className.top)
  14253. .addClass(className.bound)
  14254. .addClass(className.bottom)
  14255. ;
  14256. settings.onBottom.call(element);
  14257. settings.onUnstick.call(element);
  14258. },
  14259. setInitialPosition: function() {
  14260. module.unfix();
  14261. module.unbind();
  14262. },
  14263. fixTop: function() {
  14264. module.debug('Fixing element to top of page');
  14265. module.set.minimumSize();
  14266. module.set.offset();
  14267. $module
  14268. .css({
  14269. left : module.cache.element.left,
  14270. bottom : '',
  14271. marginBottom : ''
  14272. })
  14273. .removeClass(className.bound)
  14274. .removeClass(className.bottom)
  14275. .addClass(className.fixed)
  14276. .addClass(className.top)
  14277. ;
  14278. settings.onStick.call(element);
  14279. },
  14280. fixBottom: function() {
  14281. module.debug('Sticking element to bottom of page');
  14282. module.set.minimumSize();
  14283. module.set.offset();
  14284. $module
  14285. .css({
  14286. left : module.cache.element.left,
  14287. bottom : '',
  14288. marginBottom : ''
  14289. })
  14290. .removeClass(className.bound)
  14291. .removeClass(className.top)
  14292. .addClass(className.fixed)
  14293. .addClass(className.bottom)
  14294. ;
  14295. settings.onStick.call(element);
  14296. },
  14297. unbind: function() {
  14298. module.debug('Removing absolute position on element');
  14299. module.remove.offset();
  14300. $module
  14301. .removeClass(className.bound)
  14302. .removeClass(className.top)
  14303. .removeClass(className.bottom)
  14304. ;
  14305. },
  14306. unfix: function() {
  14307. module.debug('Removing fixed position on element');
  14308. module.remove.offset();
  14309. $module
  14310. .removeClass(className.fixed)
  14311. .removeClass(className.top)
  14312. .removeClass(className.bottom)
  14313. ;
  14314. settings.onUnstick.call(element);
  14315. },
  14316. reset: function() {
  14317. module.debug('Reseting elements position');
  14318. module.unbind();
  14319. module.unfix();
  14320. module.resetCSS();
  14321. module.remove.offset();
  14322. module.remove.lastScroll();
  14323. },
  14324. resetCSS: function() {
  14325. $module
  14326. .css({
  14327. width : '',
  14328. height : ''
  14329. })
  14330. ;
  14331. $container
  14332. .css({
  14333. height: ''
  14334. })
  14335. ;
  14336. },
  14337. setting: function(name, value) {
  14338. if( $.isPlainObject(name) ) {
  14339. $.extend(true, settings, name);
  14340. }
  14341. else if(value !== undefined) {
  14342. settings[name] = value;
  14343. }
  14344. else {
  14345. return settings[name];
  14346. }
  14347. },
  14348. internal: function(name, value) {
  14349. if( $.isPlainObject(name) ) {
  14350. $.extend(true, module, name);
  14351. }
  14352. else if(value !== undefined) {
  14353. module[name] = value;
  14354. }
  14355. else {
  14356. return module[name];
  14357. }
  14358. },
  14359. debug: function() {
  14360. if(settings.debug) {
  14361. if(settings.performance) {
  14362. module.performance.log(arguments);
  14363. }
  14364. else {
  14365. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14366. module.debug.apply(console, arguments);
  14367. }
  14368. }
  14369. },
  14370. verbose: function() {
  14371. if(settings.verbose && settings.debug) {
  14372. if(settings.performance) {
  14373. module.performance.log(arguments);
  14374. }
  14375. else {
  14376. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14377. module.verbose.apply(console, arguments);
  14378. }
  14379. }
  14380. },
  14381. error: function() {
  14382. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  14383. module.error.apply(console, arguments);
  14384. },
  14385. performance: {
  14386. log: function(message) {
  14387. var
  14388. currentTime,
  14389. executionTime,
  14390. previousTime
  14391. ;
  14392. if(settings.performance) {
  14393. currentTime = new Date().getTime();
  14394. previousTime = time || currentTime;
  14395. executionTime = currentTime - previousTime;
  14396. time = currentTime;
  14397. performance.push({
  14398. 'Name' : message[0],
  14399. 'Arguments' : [].slice.call(message, 1) || '',
  14400. 'Element' : element,
  14401. 'Execution Time' : executionTime
  14402. });
  14403. }
  14404. clearTimeout(module.performance.timer);
  14405. module.performance.timer = setTimeout(module.performance.display, 0);
  14406. },
  14407. display: function() {
  14408. var
  14409. title = settings.name + ':',
  14410. totalTime = 0
  14411. ;
  14412. time = false;
  14413. clearTimeout(module.performance.timer);
  14414. $.each(performance, function(index, data) {
  14415. totalTime += data['Execution Time'];
  14416. });
  14417. title += ' ' + totalTime + 'ms';
  14418. if(moduleSelector) {
  14419. title += ' \'' + moduleSelector + '\'';
  14420. }
  14421. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  14422. console.groupCollapsed(title);
  14423. if(console.table) {
  14424. console.table(performance);
  14425. }
  14426. else {
  14427. $.each(performance, function(index, data) {
  14428. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  14429. });
  14430. }
  14431. console.groupEnd();
  14432. }
  14433. performance = [];
  14434. }
  14435. },
  14436. invoke: function(query, passedArguments, context) {
  14437. var
  14438. object = instance,
  14439. maxDepth,
  14440. found,
  14441. response
  14442. ;
  14443. passedArguments = passedArguments || queryArguments;
  14444. context = element || context;
  14445. if(typeof query == 'string' && object !== undefined) {
  14446. query = query.split(/[\. ]/);
  14447. maxDepth = query.length - 1;
  14448. $.each(query, function(depth, value) {
  14449. var camelCaseValue = (depth != maxDepth)
  14450. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  14451. : query
  14452. ;
  14453. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  14454. object = object[camelCaseValue];
  14455. }
  14456. else if( object[camelCaseValue] !== undefined ) {
  14457. found = object[camelCaseValue];
  14458. return false;
  14459. }
  14460. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  14461. object = object[value];
  14462. }
  14463. else if( object[value] !== undefined ) {
  14464. found = object[value];
  14465. return false;
  14466. }
  14467. else {
  14468. return false;
  14469. }
  14470. });
  14471. }
  14472. if ( $.isFunction( found ) ) {
  14473. response = found.apply(context, passedArguments);
  14474. }
  14475. else if(found !== undefined) {
  14476. response = found;
  14477. }
  14478. if($.isArray(returnedValue)) {
  14479. returnedValue.push(response);
  14480. }
  14481. else if(returnedValue !== undefined) {
  14482. returnedValue = [returnedValue, response];
  14483. }
  14484. else if(response !== undefined) {
  14485. returnedValue = response;
  14486. }
  14487. return found;
  14488. }
  14489. };
  14490. if(methodInvoked) {
  14491. if(instance === undefined) {
  14492. module.initialize();
  14493. }
  14494. module.invoke(query);
  14495. }
  14496. else {
  14497. if(instance !== undefined) {
  14498. instance.invoke('destroy');
  14499. }
  14500. module.initialize();
  14501. }
  14502. })
  14503. ;
  14504. return (returnedValue !== undefined)
  14505. ? returnedValue
  14506. : this
  14507. ;
  14508. };
  14509. $.fn.sticky.settings = {
  14510. name : 'Sticky',
  14511. namespace : 'sticky',
  14512. debug : false,
  14513. verbose : true,
  14514. performance : true,
  14515. // whether to stick in the opposite direction on scroll up
  14516. pushing : false,
  14517. context : false,
  14518. // Context to watch scroll events
  14519. scrollContext : window,
  14520. // Offset to adjust scroll
  14521. offset : 0,
  14522. // Offset to adjust scroll when attached to bottom of screen
  14523. bottomOffset : 0,
  14524. jitter : 5, // will only set container height if difference between context and container is larger than this number
  14525. // Whether to automatically observe changes with Mutation Observers
  14526. observeChanges : false,
  14527. // Called when position is recalculated
  14528. onReposition : function(){},
  14529. // Called on each scroll
  14530. onScroll : function(){},
  14531. // Called when element is stuck to viewport
  14532. onStick : function(){},
  14533. // Called when element is unstuck from viewport
  14534. onUnstick : function(){},
  14535. // Called when element reaches top of context
  14536. onTop : function(){},
  14537. // Called when element reaches bottom of context
  14538. onBottom : function(){},
  14539. error : {
  14540. container : 'Sticky element must be inside a relative container',
  14541. visible : 'Element is hidden, you must call refresh after element becomes visible',
  14542. method : 'The method you called is not defined.',
  14543. invalidContext : 'Context specified does not exist',
  14544. elementSize : 'Sticky element is larger than its container, cannot create sticky.'
  14545. },
  14546. className : {
  14547. bound : 'bound',
  14548. fixed : 'fixed',
  14549. supported : 'native',
  14550. top : 'top',
  14551. bottom : 'bottom'
  14552. }
  14553. };
  14554. })( jQuery, window , document );
  14555. /*!
  14556. * # Semantic UI 2.0.0 - Tab
  14557. * http://github.com/semantic-org/semantic-ui/
  14558. *
  14559. *
  14560. * Copyright 2015 Contributors
  14561. * Released under the MIT license
  14562. * http://opensource.org/licenses/MIT
  14563. *
  14564. */
  14565. ;(function ($, window, document, undefined) {
  14566. "use strict";
  14567. $.fn.tab = function(parameters) {
  14568. var
  14569. // use window context if none specified
  14570. $allModules = $.isFunction(this)
  14571. ? $(window)
  14572. : $(this),
  14573. moduleSelector = $allModules.selector || '',
  14574. time = new Date().getTime(),
  14575. performance = [],
  14576. query = arguments[0],
  14577. methodInvoked = (typeof query == 'string'),
  14578. queryArguments = [].slice.call(arguments, 1),
  14579. initializedHistory = false,
  14580. returnedValue
  14581. ;
  14582. $allModules
  14583. .each(function() {
  14584. var
  14585. settings = ( $.isPlainObject(parameters) )
  14586. ? $.extend(true, {}, $.fn.tab.settings, parameters)
  14587. : $.extend({}, $.fn.tab.settings),
  14588. className = settings.className,
  14589. metadata = settings.metadata,
  14590. selector = settings.selector,
  14591. error = settings.error,
  14592. eventNamespace = '.' + settings.namespace,
  14593. moduleNamespace = 'module-' + settings.namespace,
  14594. $module = $(this),
  14595. $context,
  14596. $tabs,
  14597. cache = {},
  14598. firstLoad = true,
  14599. recursionDepth = 0,
  14600. element = this,
  14601. instance = $module.data(moduleNamespace),
  14602. activeTabPath,
  14603. parameterArray,
  14604. module,
  14605. historyEvent
  14606. ;
  14607. module = {
  14608. initialize: function() {
  14609. module.debug('Initializing tab menu item', $module);
  14610. module.fix.callbacks();
  14611. module.determineTabs();
  14612. module.debug('Determining tabs', settings.context, $tabs);
  14613. // set up automatic routing
  14614. if(settings.auto) {
  14615. module.set.auto();
  14616. }
  14617. module.bind.events();
  14618. if(settings.history && !initializedHistory) {
  14619. module.initializeHistory();
  14620. initializedHistory = true;
  14621. }
  14622. module.instantiate();
  14623. },
  14624. instantiate: function () {
  14625. module.verbose('Storing instance of module', module);
  14626. instance = module;
  14627. $module
  14628. .data(moduleNamespace, module)
  14629. ;
  14630. },
  14631. destroy: function() {
  14632. module.debug('Destroying tabs', $module);
  14633. $module
  14634. .removeData(moduleNamespace)
  14635. .off(eventNamespace)
  14636. ;
  14637. },
  14638. bind: {
  14639. events: function() {
  14640. // if using $.tab dont add events
  14641. if( !$.isWindow( element ) ) {
  14642. module.debug('Attaching tab activation events to element', $module);
  14643. $module
  14644. .on('click' + eventNamespace, module.event.click)
  14645. ;
  14646. }
  14647. }
  14648. },
  14649. determineTabs: function() {
  14650. var
  14651. $reference
  14652. ;
  14653. // determine tab context
  14654. if(settings.context === 'parent') {
  14655. if($module.closest(selector.ui).length > 0) {
  14656. $reference = $module.closest(selector.ui);
  14657. module.verbose('Using closest UI element as parent', $reference);
  14658. }
  14659. else {
  14660. $reference = $module;
  14661. }
  14662. $context = $reference.parent();
  14663. module.verbose('Determined parent element for creating context', $context);
  14664. }
  14665. else if(settings.context) {
  14666. $context = $(settings.context);
  14667. module.verbose('Using selector for tab context', settings.context, $context);
  14668. }
  14669. else {
  14670. $context = $('body');
  14671. }
  14672. // find tabs
  14673. if(settings.childrenOnly) {
  14674. $tabs = $context.children(selector.tabs);
  14675. module.debug('Searching tab context children for tabs', $context, $tabs);
  14676. }
  14677. else {
  14678. $tabs = $context.find(selector.tabs);
  14679. module.debug('Searching tab context for tabs', $context, $tabs);
  14680. }
  14681. },
  14682. fix: {
  14683. callbacks: function() {
  14684. if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
  14685. if(parameters.onTabLoad) {
  14686. parameters.onLoad = parameters.onTabLoad;
  14687. delete parameters.onTabLoad;
  14688. module.error(error.legacyLoad, parameters.onLoad);
  14689. }
  14690. if(parameters.onTabInit) {
  14691. parameters.onFirstLoad = parameters.onTabInit;
  14692. delete parameters.onTabInit;
  14693. module.error(error.legacyInit, parameters.onFirstLoad);
  14694. }
  14695. settings = $.extend(true, {}, $.fn.tab.settings, parameters);
  14696. }
  14697. }
  14698. },
  14699. initializeHistory: function() {
  14700. module.debug('Initializing page state');
  14701. if( $.address === undefined ) {
  14702. module.error(error.state);
  14703. return false;
  14704. }
  14705. else {
  14706. if(settings.historyType == 'state') {
  14707. module.debug('Using HTML5 to manage state');
  14708. if(settings.path !== false) {
  14709. $.address
  14710. .history(true)
  14711. .state(settings.path)
  14712. ;
  14713. }
  14714. else {
  14715. module.error(error.path);
  14716. return false;
  14717. }
  14718. }
  14719. $.address
  14720. .bind('change', module.event.history.change)
  14721. ;
  14722. }
  14723. },
  14724. event: {
  14725. click: function(event) {
  14726. var
  14727. tabPath = $(this).data(metadata.tab)
  14728. ;
  14729. if(tabPath !== undefined) {
  14730. if(settings.history) {
  14731. module.verbose('Updating page state', event);
  14732. $.address.value(tabPath);
  14733. }
  14734. else {
  14735. module.verbose('Changing tab', event);
  14736. module.changeTab(tabPath);
  14737. }
  14738. event.preventDefault();
  14739. }
  14740. else {
  14741. module.debug('No tab specified');
  14742. }
  14743. },
  14744. history: {
  14745. change: function(event) {
  14746. var
  14747. tabPath = event.pathNames.join('/') || module.get.initialPath(),
  14748. pageTitle = settings.templates.determineTitle(tabPath) || false
  14749. ;
  14750. module.performance.display();
  14751. module.debug('History change event', tabPath, event);
  14752. historyEvent = event;
  14753. if(tabPath !== undefined) {
  14754. module.changeTab(tabPath);
  14755. }
  14756. if(pageTitle) {
  14757. $.address.title(pageTitle);
  14758. }
  14759. }
  14760. }
  14761. },
  14762. refresh: function() {
  14763. if(activeTabPath) {
  14764. module.debug('Refreshing tab', activeTabPath);
  14765. module.changeTab(activeTabPath);
  14766. }
  14767. },
  14768. cache: {
  14769. read: function(cacheKey) {
  14770. return (cacheKey !== undefined)
  14771. ? cache[cacheKey]
  14772. : false
  14773. ;
  14774. },
  14775. add: function(cacheKey, content) {
  14776. cacheKey = cacheKey || activeTabPath;
  14777. module.debug('Adding cached content for', cacheKey);
  14778. cache[cacheKey] = content;
  14779. },
  14780. remove: function(cacheKey) {
  14781. cacheKey = cacheKey || activeTabPath;
  14782. module.debug('Removing cached content for', cacheKey);
  14783. delete cache[cacheKey];
  14784. }
  14785. },
  14786. set: {
  14787. auto: function() {
  14788. var
  14789. url = (typeof settings.path == 'string')
  14790. ? settings.path.replace(/\/$/, '') + '/{$tab}'
  14791. : '/{$tab}'
  14792. ;
  14793. module.verbose('Setting up automatic tab retrieval from server', url);
  14794. if($.isPlainObject(settings.apiSettings)) {
  14795. settings.apiSettings.url = url;
  14796. }
  14797. else {
  14798. settings.apiSettings = {
  14799. url: url
  14800. };
  14801. }
  14802. },
  14803. loading: function(tabPath) {
  14804. var
  14805. $tab = module.get.tabElement(tabPath),
  14806. isLoading = $tab.hasClass(className.loading)
  14807. ;
  14808. if(!isLoading) {
  14809. module.verbose('Setting loading state for', $tab);
  14810. $tab
  14811. .addClass(className.loading)
  14812. .siblings($tabs)
  14813. .removeClass(className.active + ' ' + className.loading)
  14814. ;
  14815. if($tab.length > 0) {
  14816. settings.onRequest.call($tab[0], tabPath);
  14817. }
  14818. }
  14819. },
  14820. state: function(state) {
  14821. $.address.value(state);
  14822. }
  14823. },
  14824. changeTab: function(tabPath) {
  14825. var
  14826. pushStateAvailable = (window.history && window.history.pushState),
  14827. shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
  14828. remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
  14829. // only add default path if not remote content
  14830. pathArray = (remoteContent && !shouldIgnoreLoad)
  14831. ? module.utilities.pathToArray(tabPath)
  14832. : module.get.defaultPathArray(tabPath)
  14833. ;
  14834. tabPath = module.utilities.arrayToPath(pathArray);
  14835. $.each(pathArray, function(index, tab) {
  14836. var
  14837. currentPathArray = pathArray.slice(0, index + 1),
  14838. currentPath = module.utilities.arrayToPath(currentPathArray),
  14839. isTab = module.is.tab(currentPath),
  14840. isLastIndex = (index + 1 == pathArray.length),
  14841. $tab = module.get.tabElement(currentPath),
  14842. $anchor,
  14843. nextPathArray,
  14844. nextPath,
  14845. isLastTab
  14846. ;
  14847. module.verbose('Looking for tab', tab);
  14848. if(isTab) {
  14849. module.verbose('Tab was found', tab);
  14850. // scope up
  14851. activeTabPath = currentPath;
  14852. parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
  14853. if(isLastIndex) {
  14854. isLastTab = true;
  14855. }
  14856. else {
  14857. nextPathArray = pathArray.slice(0, index + 2);
  14858. nextPath = module.utilities.arrayToPath(nextPathArray);
  14859. isLastTab = ( !module.is.tab(nextPath) );
  14860. if(isLastTab) {
  14861. module.verbose('Tab parameters found', nextPathArray);
  14862. }
  14863. }
  14864. if(isLastTab && remoteContent) {
  14865. if(!shouldIgnoreLoad) {
  14866. module.activate.navigation(currentPath);
  14867. module.fetch.content(currentPath, tabPath);
  14868. }
  14869. else {
  14870. module.debug('Ignoring remote content on first tab load', currentPath);
  14871. firstLoad = false;
  14872. module.cache.add(tabPath, $tab.html());
  14873. module.activate.all(currentPath);
  14874. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  14875. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  14876. }
  14877. return false;
  14878. }
  14879. else {
  14880. module.debug('Opened local tab', currentPath);
  14881. module.activate.all(currentPath);
  14882. if( !module.cache.read(currentPath) ) {
  14883. module.cache.add(currentPath, true);
  14884. module.debug('First time tab loaded calling tab init');
  14885. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  14886. }
  14887. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  14888. }
  14889. }
  14890. else if(tabPath.search('/') == -1 && tabPath !== '') {
  14891. // look for in page anchor
  14892. $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
  14893. currentPath = $anchor.closest('[data-tab]').data('tab');
  14894. $tab = module.get.tabElement(currentPath);
  14895. // if anchor exists use parent tab
  14896. if($anchor && $anchor.length > 0 && currentPath) {
  14897. module.debug('Anchor link used, opening parent tab', $tab, $anchor);
  14898. if( !$tab.hasClass(className.active) ) {
  14899. setTimeout(function() {
  14900. module.scrollTo($anchor);
  14901. }, 0);
  14902. }
  14903. module.activate.all(currentPath);
  14904. if( !module.cache.read(currentPath) ) {
  14905. module.cache.add(currentPath, true);
  14906. module.debug('First time tab loaded calling tab init');
  14907. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  14908. }
  14909. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  14910. return false;
  14911. }
  14912. }
  14913. else {
  14914. module.error(error.missingTab, $module, $context, currentPath);
  14915. return false;
  14916. }
  14917. });
  14918. },
  14919. scrollTo: function($element) {
  14920. var
  14921. scrollOffset = ($element && $element.length > 0)
  14922. ? $element.offset().top
  14923. : false
  14924. ;
  14925. if(scrollOffset !== false) {
  14926. module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
  14927. $(document).scrollTop(scrollOffset);
  14928. }
  14929. },
  14930. update: {
  14931. content: function(tabPath, html, evaluateScripts) {
  14932. var
  14933. $tab = module.get.tabElement(tabPath),
  14934. tab = $tab[0]
  14935. ;
  14936. evaluateScripts = (evaluateScripts !== undefined)
  14937. ? evaluateScripts
  14938. : settings.evaluateScripts
  14939. ;
  14940. if(evaluateScripts) {
  14941. module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
  14942. $tab.html(html);
  14943. }
  14944. else {
  14945. module.debug('Updating HTML', tabPath, html);
  14946. tab.innerHTML = html;
  14947. }
  14948. }
  14949. },
  14950. fetch: {
  14951. content: function(tabPath, fullTabPath) {
  14952. var
  14953. $tab = module.get.tabElement(tabPath),
  14954. apiSettings = {
  14955. dataType : 'html',
  14956. on : 'now',
  14957. cache : 'local',
  14958. onSuccess : function(response) {
  14959. module.cache.add(fullTabPath, response);
  14960. module.update.content(tabPath, response);
  14961. if(tabPath == activeTabPath) {
  14962. module.debug('Content loaded', tabPath);
  14963. module.activate.tab(tabPath);
  14964. }
  14965. else {
  14966. module.debug('Content loaded in background', tabPath);
  14967. }
  14968. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  14969. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  14970. },
  14971. urlData: {
  14972. tab: fullTabPath
  14973. }
  14974. },
  14975. request = $tab.api('get request') || false,
  14976. existingRequest = ( request && request.state() === 'pending' ),
  14977. requestSettings,
  14978. cachedContent
  14979. ;
  14980. fullTabPath = fullTabPath || tabPath;
  14981. cachedContent = module.cache.read(fullTabPath);
  14982. if(settings.cache && cachedContent) {
  14983. module.activate.tab(tabPath);
  14984. module.debug('Adding cached content', fullTabPath);
  14985. if(settings.evaluateScripts == 'once') {
  14986. module.update.content(tabPath, cachedContent, false);
  14987. }
  14988. else {
  14989. module.update.content(tabPath, cachedContent);
  14990. }
  14991. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  14992. }
  14993. else if(existingRequest) {
  14994. module.set.loading(tabPath);
  14995. module.debug('Content is already loading', fullTabPath);
  14996. }
  14997. else if($.api !== undefined) {
  14998. requestSettings = $.extend(true, {
  14999. headers: {
  15000. 'X-Remote': true
  15001. }
  15002. }, settings.apiSettings, apiSettings);
  15003. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  15004. $tab.api(requestSettings);
  15005. }
  15006. else {
  15007. module.error(error.api);
  15008. }
  15009. }
  15010. },
  15011. activate: {
  15012. all: function(tabPath) {
  15013. module.activate.tab(tabPath);
  15014. module.activate.navigation(tabPath);
  15015. },
  15016. tab: function(tabPath) {
  15017. var
  15018. $tab = module.get.tabElement(tabPath),
  15019. isActive = $tab.hasClass(className.active)
  15020. ;
  15021. module.verbose('Showing tab content for', $tab);
  15022. if(!isActive) {
  15023. $tab
  15024. .addClass(className.active)
  15025. .siblings($tabs)
  15026. .removeClass(className.active + ' ' + className.loading)
  15027. ;
  15028. if($tab.length > 0) {
  15029. settings.onVisible.call($tab[0], tabPath);
  15030. }
  15031. }
  15032. },
  15033. navigation: function(tabPath) {
  15034. var
  15035. $navigation = module.get.navElement(tabPath),
  15036. isActive = $navigation.hasClass(className.active)
  15037. ;
  15038. module.verbose('Activating tab navigation for', $navigation, tabPath);
  15039. if(!isActive) {
  15040. $navigation
  15041. .addClass(className.active)
  15042. .siblings($allModules)
  15043. .removeClass(className.active + ' ' + className.loading)
  15044. ;
  15045. }
  15046. }
  15047. },
  15048. deactivate: {
  15049. all: function() {
  15050. module.deactivate.navigation();
  15051. module.deactivate.tabs();
  15052. },
  15053. navigation: function() {
  15054. $allModules
  15055. .removeClass(className.active)
  15056. ;
  15057. },
  15058. tabs: function() {
  15059. $tabs
  15060. .removeClass(className.active + ' ' + className.loading)
  15061. ;
  15062. }
  15063. },
  15064. is: {
  15065. tab: function(tabName) {
  15066. return (tabName !== undefined)
  15067. ? ( module.get.tabElement(tabName).length > 0 )
  15068. : false
  15069. ;
  15070. }
  15071. },
  15072. get: {
  15073. initialPath: function() {
  15074. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  15075. },
  15076. path: function() {
  15077. return $.address.value();
  15078. },
  15079. // adds default tabs to tab path
  15080. defaultPathArray: function(tabPath) {
  15081. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  15082. },
  15083. defaultPath: function(tabPath) {
  15084. var
  15085. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0),
  15086. defaultTab = $defaultNav.data(metadata.tab) || false
  15087. ;
  15088. if( defaultTab ) {
  15089. module.debug('Found default tab', defaultTab);
  15090. if(recursionDepth < settings.maxDepth) {
  15091. recursionDepth++;
  15092. return module.get.defaultPath(defaultTab);
  15093. }
  15094. module.error(error.recursion);
  15095. }
  15096. else {
  15097. module.debug('No default tabs found for', tabPath, $tabs);
  15098. }
  15099. recursionDepth = 0;
  15100. return tabPath;
  15101. },
  15102. navElement: function(tabPath) {
  15103. tabPath = tabPath || activeTabPath;
  15104. return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  15105. },
  15106. tabElement: function(tabPath) {
  15107. var
  15108. $fullPathTab,
  15109. $simplePathTab,
  15110. tabPathArray,
  15111. lastTab
  15112. ;
  15113. tabPath = tabPath || activeTabPath;
  15114. tabPathArray = module.utilities.pathToArray(tabPath);
  15115. lastTab = module.utilities.last(tabPathArray);
  15116. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]');
  15117. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  15118. return ($fullPathTab.length > 0)
  15119. ? $fullPathTab
  15120. : $simplePathTab
  15121. ;
  15122. },
  15123. tab: function() {
  15124. return activeTabPath;
  15125. }
  15126. },
  15127. utilities: {
  15128. filterArray: function(keepArray, removeArray) {
  15129. return $.grep(keepArray, function(keepValue) {
  15130. return ( $.inArray(keepValue, removeArray) == -1);
  15131. });
  15132. },
  15133. last: function(array) {
  15134. return $.isArray(array)
  15135. ? array[ array.length - 1]
  15136. : false
  15137. ;
  15138. },
  15139. pathToArray: function(pathName) {
  15140. if(pathName === undefined) {
  15141. pathName = activeTabPath;
  15142. }
  15143. return typeof pathName == 'string'
  15144. ? pathName.split('/')
  15145. : [pathName]
  15146. ;
  15147. },
  15148. arrayToPath: function(pathArray) {
  15149. return $.isArray(pathArray)
  15150. ? pathArray.join('/')
  15151. : false
  15152. ;
  15153. }
  15154. },
  15155. setting: function(name, value) {
  15156. module.debug('Changing setting', name, value);
  15157. if( $.isPlainObject(name) ) {
  15158. $.extend(true, settings, name);
  15159. }
  15160. else if(value !== undefined) {
  15161. settings[name] = value;
  15162. }
  15163. else {
  15164. return settings[name];
  15165. }
  15166. },
  15167. internal: function(name, value) {
  15168. if( $.isPlainObject(name) ) {
  15169. $.extend(true, module, name);
  15170. }
  15171. else if(value !== undefined) {
  15172. module[name] = value;
  15173. }
  15174. else {
  15175. return module[name];
  15176. }
  15177. },
  15178. debug: function() {
  15179. if(settings.debug) {
  15180. if(settings.performance) {
  15181. module.performance.log(arguments);
  15182. }
  15183. else {
  15184. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15185. module.debug.apply(console, arguments);
  15186. }
  15187. }
  15188. },
  15189. verbose: function() {
  15190. if(settings.verbose && settings.debug) {
  15191. if(settings.performance) {
  15192. module.performance.log(arguments);
  15193. }
  15194. else {
  15195. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15196. module.verbose.apply(console, arguments);
  15197. }
  15198. }
  15199. },
  15200. error: function() {
  15201. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  15202. module.error.apply(console, arguments);
  15203. },
  15204. performance: {
  15205. log: function(message) {
  15206. var
  15207. currentTime,
  15208. executionTime,
  15209. previousTime
  15210. ;
  15211. if(settings.performance) {
  15212. currentTime = new Date().getTime();
  15213. previousTime = time || currentTime;
  15214. executionTime = currentTime - previousTime;
  15215. time = currentTime;
  15216. performance.push({
  15217. 'Name' : message[0],
  15218. 'Arguments' : [].slice.call(message, 1) || '',
  15219. 'Element' : element,
  15220. 'Execution Time' : executionTime
  15221. });
  15222. }
  15223. clearTimeout(module.performance.timer);
  15224. module.performance.timer = setTimeout(module.performance.display, 500);
  15225. },
  15226. display: function() {
  15227. var
  15228. title = settings.name + ':',
  15229. totalTime = 0
  15230. ;
  15231. time = false;
  15232. clearTimeout(module.performance.timer);
  15233. $.each(performance, function(index, data) {
  15234. totalTime += data['Execution Time'];
  15235. });
  15236. title += ' ' + totalTime + 'ms';
  15237. if(moduleSelector) {
  15238. title += ' \'' + moduleSelector + '\'';
  15239. }
  15240. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  15241. console.groupCollapsed(title);
  15242. if(console.table) {
  15243. console.table(performance);
  15244. }
  15245. else {
  15246. $.each(performance, function(index, data) {
  15247. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  15248. });
  15249. }
  15250. console.groupEnd();
  15251. }
  15252. performance = [];
  15253. }
  15254. },
  15255. invoke: function(query, passedArguments, context) {
  15256. var
  15257. object = instance,
  15258. maxDepth,
  15259. found,
  15260. response
  15261. ;
  15262. passedArguments = passedArguments || queryArguments;
  15263. context = element || context;
  15264. if(typeof query == 'string' && object !== undefined) {
  15265. query = query.split(/[\. ]/);
  15266. maxDepth = query.length - 1;
  15267. $.each(query, function(depth, value) {
  15268. var camelCaseValue = (depth != maxDepth)
  15269. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  15270. : query
  15271. ;
  15272. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  15273. object = object[camelCaseValue];
  15274. }
  15275. else if( object[camelCaseValue] !== undefined ) {
  15276. found = object[camelCaseValue];
  15277. return false;
  15278. }
  15279. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  15280. object = object[value];
  15281. }
  15282. else if( object[value] !== undefined ) {
  15283. found = object[value];
  15284. return false;
  15285. }
  15286. else {
  15287. module.error(error.method, query);
  15288. return false;
  15289. }
  15290. });
  15291. }
  15292. if ( $.isFunction( found ) ) {
  15293. response = found.apply(context, passedArguments);
  15294. }
  15295. else if(found !== undefined) {
  15296. response = found;
  15297. }
  15298. if($.isArray(returnedValue)) {
  15299. returnedValue.push(response);
  15300. }
  15301. else if(returnedValue !== undefined) {
  15302. returnedValue = [returnedValue, response];
  15303. }
  15304. else if(response !== undefined) {
  15305. returnedValue = response;
  15306. }
  15307. return found;
  15308. }
  15309. };
  15310. if(methodInvoked) {
  15311. if(instance === undefined) {
  15312. module.initialize();
  15313. }
  15314. module.invoke(query);
  15315. }
  15316. else {
  15317. if(instance !== undefined) {
  15318. instance.invoke('destroy');
  15319. }
  15320. module.initialize();
  15321. }
  15322. })
  15323. ;
  15324. return (returnedValue !== undefined)
  15325. ? returnedValue
  15326. : this
  15327. ;
  15328. };
  15329. // shortcut for tabbed content with no defined navigation
  15330. $.tab = function() {
  15331. $(window).tab.apply(this, arguments);
  15332. };
  15333. $.fn.tab.settings = {
  15334. name : 'Tab',
  15335. namespace : 'tab',
  15336. debug : false,
  15337. verbose : false,
  15338. performance : true,
  15339. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  15340. history : false, // use browser history
  15341. historyType : 'hash', // #/ or html5 state
  15342. path : false, // base path of url
  15343. context : false, // specify a context that tabs must appear inside
  15344. childrenOnly : false, // use only tabs that are children of context
  15345. maxDepth : 25, // max depth a tab can be nested
  15346. alwaysRefresh : false, // load tab content new every tab click
  15347. cache : true, // cache the content requests to pull locally
  15348. ignoreFirstLoad : false, // don't load remote content on first load
  15349. apiSettings : false, // settings for api call
  15350. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  15351. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  15352. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  15353. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  15354. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  15355. templates : {
  15356. determineTitle: function(tabArray) {} // returns page title for path
  15357. },
  15358. error: {
  15359. api : 'You attempted to load content without API module',
  15360. method : 'The method you called is not defined',
  15361. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  15362. noContent : 'The tab you specified is missing a content url.',
  15363. path : 'History enabled, but no path was specified',
  15364. recursion : 'Max recursive depth reached',
  15365. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  15366. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  15367. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  15368. },
  15369. metadata : {
  15370. tab : 'tab',
  15371. loaded : 'loaded',
  15372. promise: 'promise'
  15373. },
  15374. className : {
  15375. loading : 'loading',
  15376. active : 'active'
  15377. },
  15378. selector : {
  15379. tabs : '.ui.tab',
  15380. ui : '.ui'
  15381. }
  15382. };
  15383. })( jQuery, window , document );
  15384. /*!
  15385. * # Semantic UI 2.0.0 - Transition
  15386. * http://github.com/semantic-org/semantic-ui/
  15387. *
  15388. *
  15389. * Copyright 2015 Contributors
  15390. * Released under the MIT license
  15391. * http://opensource.org/licenses/MIT
  15392. *
  15393. */
  15394. ;(function ( $, window, document, undefined ) {
  15395. "use strict";
  15396. $.fn.transition = function() {
  15397. var
  15398. $allModules = $(this),
  15399. moduleSelector = $allModules.selector || '',
  15400. time = new Date().getTime(),
  15401. performance = [],
  15402. moduleArguments = arguments,
  15403. query = moduleArguments[0],
  15404. queryArguments = [].slice.call(arguments, 1),
  15405. methodInvoked = (typeof query === 'string'),
  15406. requestAnimationFrame = window.requestAnimationFrame
  15407. || window.mozRequestAnimationFrame
  15408. || window.webkitRequestAnimationFrame
  15409. || window.msRequestAnimationFrame
  15410. || function(callback) { setTimeout(callback, 0); },
  15411. returnedValue
  15412. ;
  15413. $allModules
  15414. .each(function(index) {
  15415. var
  15416. $module = $(this),
  15417. element = this,
  15418. // set at run time
  15419. settings,
  15420. instance,
  15421. error,
  15422. className,
  15423. metadata,
  15424. animationEnd,
  15425. animationName,
  15426. namespace,
  15427. moduleNamespace,
  15428. eventNamespace,
  15429. module
  15430. ;
  15431. module = {
  15432. initialize: function() {
  15433. // get full settings
  15434. settings = module.get.settings.apply(element, moduleArguments);
  15435. // shorthand
  15436. className = settings.className;
  15437. error = settings.error;
  15438. metadata = settings.metadata;
  15439. // define namespace
  15440. eventNamespace = '.' + settings.namespace;
  15441. moduleNamespace = 'module-' + settings.namespace;
  15442. instance = $module.data(moduleNamespace) || module;
  15443. // get vendor specific events
  15444. animationEnd = module.get.animationEndEvent();
  15445. if(methodInvoked) {
  15446. methodInvoked = module.invoke(query);
  15447. }
  15448. // method not invoked, lets run an animation
  15449. if(methodInvoked === false) {
  15450. module.verbose('Converted arguments into settings object', settings);
  15451. if(settings.interval) {
  15452. module.delay(settings.animate);
  15453. }
  15454. else {
  15455. module.animate();
  15456. }
  15457. module.instantiate();
  15458. }
  15459. },
  15460. instantiate: function() {
  15461. module.verbose('Storing instance of module', module);
  15462. instance = module;
  15463. $module
  15464. .data(moduleNamespace, instance)
  15465. ;
  15466. },
  15467. destroy: function() {
  15468. module.verbose('Destroying previous module for', element);
  15469. $module
  15470. .removeData(moduleNamespace)
  15471. ;
  15472. },
  15473. refresh: function() {
  15474. module.verbose('Refreshing display type on next animation');
  15475. delete module.displayType;
  15476. },
  15477. forceRepaint: function() {
  15478. module.verbose('Forcing element repaint');
  15479. var
  15480. $parentElement = $module.parent(),
  15481. $nextElement = $module.next()
  15482. ;
  15483. if($nextElement.length === 0) {
  15484. $module.detach().appendTo($parentElement);
  15485. }
  15486. else {
  15487. $module.detach().insertBefore($nextElement);
  15488. }
  15489. },
  15490. repaint: function() {
  15491. module.verbose('Repainting element');
  15492. var
  15493. fakeAssignment = element.offsetWidth
  15494. ;
  15495. },
  15496. delay: function(interval) {
  15497. var
  15498. direction = module.get.animationDirection(),
  15499. shouldReverse,
  15500. delay
  15501. ;
  15502. if(!direction) {
  15503. direction = module.can.transition()
  15504. ? module.get.direction()
  15505. : 'static'
  15506. ;
  15507. }
  15508. interval = (interval !== undefined)
  15509. ? interval
  15510. : settings.interval
  15511. ;
  15512. shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
  15513. delay = (shouldReverse || settings.reverse == true)
  15514. ? ($allModules.length - index) * settings.interval
  15515. : index * settings.interval
  15516. ;
  15517. module.debug('Delaying animation by', delay);
  15518. setTimeout(module.animate, delay);
  15519. },
  15520. animate: function(overrideSettings) {
  15521. settings = overrideSettings || settings;
  15522. if(!module.is.supported()) {
  15523. module.error(error.support);
  15524. return false;
  15525. }
  15526. module.debug('Preparing animation', settings.animation);
  15527. if(module.is.animating()) {
  15528. if(settings.queue) {
  15529. if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
  15530. module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
  15531. }
  15532. else {
  15533. module.queue(settings.animation);
  15534. }
  15535. return false;
  15536. }
  15537. else if(!settings.allowRepeats && module.is.occurring()) {
  15538. module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
  15539. return false;
  15540. }
  15541. else {
  15542. module.debug('New animation started, completing previous early', settings.animation);
  15543. instance.complete();
  15544. }
  15545. }
  15546. if( module.can.animate() ) {
  15547. module.set.animating(settings.animation);
  15548. }
  15549. else {
  15550. module.error(error.noAnimation, settings.animation, element);
  15551. }
  15552. },
  15553. reset: function() {
  15554. module.debug('Resetting animation to beginning conditions');
  15555. module.remove.animationCallbacks();
  15556. module.restore.conditions();
  15557. module.remove.animating();
  15558. },
  15559. queue: function(animation) {
  15560. module.debug('Queueing animation of', animation);
  15561. module.queuing = true;
  15562. $module
  15563. .one(animationEnd + '.queue' + eventNamespace, function() {
  15564. module.queuing = false;
  15565. module.repaint();
  15566. module.animate.apply(this, settings);
  15567. })
  15568. ;
  15569. },
  15570. complete: function (event) {
  15571. module.debug('Animation complete', settings.animation);
  15572. module.remove.completeCallback();
  15573. module.remove.failSafe();
  15574. if(!module.is.looping()) {
  15575. if( module.is.outward() ) {
  15576. module.verbose('Animation is outward, hiding element');
  15577. module.restore.conditions();
  15578. module.hide();
  15579. }
  15580. else if( module.is.inward() ) {
  15581. module.verbose('Animation is outward, showing element');
  15582. module.restore.conditions();
  15583. module.show();
  15584. }
  15585. else {
  15586. module.restore.conditions();
  15587. }
  15588. }
  15589. },
  15590. force: {
  15591. visible: function() {
  15592. var
  15593. style = $module.attr('style'),
  15594. userStyle = module.get.userStyle(),
  15595. displayType = module.get.displayType(),
  15596. overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
  15597. currentDisplay = $module.css('display'),
  15598. emptyStyle = (style === undefined || style === '')
  15599. ;
  15600. if(currentDisplay !== displayType) {
  15601. module.verbose('Overriding default display to show element', displayType);
  15602. $module
  15603. .attr('style', overrideStyle)
  15604. ;
  15605. }
  15606. else if(emptyStyle) {
  15607. $module.removeAttr('style');
  15608. }
  15609. },
  15610. hidden: function() {
  15611. var
  15612. style = $module.attr('style'),
  15613. currentDisplay = $module.css('display'),
  15614. emptyStyle = (style === undefined || style === '')
  15615. ;
  15616. if(currentDisplay !== 'none' && !module.is.hidden()) {
  15617. module.verbose('Overriding default display to hide element');
  15618. $module
  15619. .css('display', 'none')
  15620. ;
  15621. }
  15622. else if(emptyStyle) {
  15623. $module
  15624. .removeAttr('style')
  15625. ;
  15626. }
  15627. }
  15628. },
  15629. has: {
  15630. direction: function(animation) {
  15631. var
  15632. hasDirection = false
  15633. ;
  15634. animation = animation || settings.animation;
  15635. if(typeof animation === 'string') {
  15636. animation = animation.split(' ');
  15637. $.each(animation, function(index, word){
  15638. if(word === className.inward || word === className.outward) {
  15639. hasDirection = true;
  15640. }
  15641. });
  15642. }
  15643. return hasDirection;
  15644. },
  15645. inlineDisplay: function() {
  15646. var
  15647. style = $module.attr('style') || ''
  15648. ;
  15649. return $.isArray(style.match(/display.*?;/, ''));
  15650. }
  15651. },
  15652. set: {
  15653. animating: function(animation) {
  15654. var
  15655. animationClass,
  15656. direction
  15657. ;
  15658. // remove previous callbacks
  15659. module.remove.completeCallback();
  15660. // determine exact animation
  15661. animation = animation || settings.animation;
  15662. animationClass = module.get.animationClass(animation);
  15663. // save animation class in cache to restore class names
  15664. module.save.animation(animationClass);
  15665. // override display if necessary so animation appears visibly
  15666. module.force.visible();
  15667. module.remove.hidden();
  15668. module.remove.direction();
  15669. module.start.animation(animationClass);
  15670. },
  15671. duration: function(animationName, duration) {
  15672. duration = duration || settings.duration;
  15673. duration = (typeof duration == 'number')
  15674. ? duration + 'ms'
  15675. : duration
  15676. ;
  15677. if(duration || duration === 0) {
  15678. module.verbose('Setting animation duration', duration);
  15679. $module
  15680. .css({
  15681. 'animation-duration': duration
  15682. })
  15683. ;
  15684. }
  15685. },
  15686. direction: function(direction) {
  15687. direction = direction || module.get.direction();
  15688. if(direction == className.inward) {
  15689. module.set.inward();
  15690. }
  15691. else {
  15692. module.set.outward();
  15693. }
  15694. },
  15695. looping: function() {
  15696. module.debug('Transition set to loop');
  15697. $module
  15698. .addClass(className.looping)
  15699. ;
  15700. },
  15701. hidden: function() {
  15702. $module
  15703. .addClass(className.transition)
  15704. .addClass(className.hidden)
  15705. ;
  15706. },
  15707. inward: function() {
  15708. module.debug('Setting direction to inward');
  15709. $module
  15710. .removeClass(className.outward)
  15711. .addClass(className.inward)
  15712. ;
  15713. },
  15714. outward: function() {
  15715. module.debug('Setting direction to outward');
  15716. $module
  15717. .removeClass(className.inward)
  15718. .addClass(className.outward)
  15719. ;
  15720. },
  15721. visible: function() {
  15722. $module
  15723. .addClass(className.transition)
  15724. .addClass(className.visible)
  15725. ;
  15726. }
  15727. },
  15728. start: {
  15729. animation: function(animationClass) {
  15730. animationClass = animationClass || module.get.animationClass();
  15731. module.debug('Starting tween', animationClass);
  15732. $module
  15733. .addClass(animationClass)
  15734. .one(animationEnd + '.complete' + eventNamespace, module.complete)
  15735. ;
  15736. if(settings.useFailSafe) {
  15737. module.add.failSafe();
  15738. }
  15739. module.set.duration(settings.duration);
  15740. settings.onStart.call(this);
  15741. }
  15742. },
  15743. save: {
  15744. animation: function(animation) {
  15745. if(!module.cache) {
  15746. module.cache = {};
  15747. }
  15748. module.cache.animation = animation;
  15749. },
  15750. displayType: function(displayType) {
  15751. if(displayType !== 'none') {
  15752. $module.data(metadata.displayType, displayType);
  15753. }
  15754. },
  15755. transitionExists: function(animation, exists) {
  15756. $.fn.transition.exists[animation] = exists;
  15757. module.verbose('Saving existence of transition', animation, exists);
  15758. }
  15759. },
  15760. restore: {
  15761. conditions: function() {
  15762. var
  15763. animation = module.get.currentAnimation()
  15764. ;
  15765. if(animation) {
  15766. $module
  15767. .removeClass(animation)
  15768. ;
  15769. module.verbose('Removing animation class', module.cache);
  15770. }
  15771. module.remove.duration();
  15772. }
  15773. },
  15774. add: {
  15775. failSafe: function() {
  15776. var
  15777. duration = module.get.duration()
  15778. ;
  15779. module.timer = setTimeout(function() {
  15780. $module.triggerHandler(animationEnd);
  15781. }, duration + settings.failSafeDelay);
  15782. module.verbose('Adding fail safe timer', module.timer);
  15783. }
  15784. },
  15785. remove: {
  15786. animating: function() {
  15787. $module.removeClass(className.animating);
  15788. },
  15789. animationCallbacks: function() {
  15790. module.remove.queueCallback();
  15791. module.remove.completeCallback();
  15792. },
  15793. queueCallback: function() {
  15794. $module.off('.queue' + eventNamespace);
  15795. },
  15796. completeCallback: function() {
  15797. $module.off('.complete' + eventNamespace);
  15798. },
  15799. display: function() {
  15800. $module.css('display', '');
  15801. },
  15802. direction: function() {
  15803. $module
  15804. .removeClass(className.inward)
  15805. .removeClass(className.outward)
  15806. ;
  15807. },
  15808. duration: function() {
  15809. $module
  15810. .css('animation-duration', '')
  15811. ;
  15812. },
  15813. failSafe: function() {
  15814. module.verbose('Removing fail safe timer', module.timer);
  15815. if(module.timer) {
  15816. clearTimeout(module.timer);
  15817. }
  15818. },
  15819. hidden: function() {
  15820. $module.removeClass(className.hidden);
  15821. },
  15822. visible: function() {
  15823. $module.removeClass(className.visible);
  15824. },
  15825. looping: function() {
  15826. module.debug('Transitions are no longer looping');
  15827. if( module.is.looping() ) {
  15828. module.reset();
  15829. $module
  15830. .removeClass(className.looping)
  15831. ;
  15832. }
  15833. },
  15834. transition: function() {
  15835. $module
  15836. .removeClass(className.visible)
  15837. .removeClass(className.hidden)
  15838. ;
  15839. }
  15840. },
  15841. get: {
  15842. settings: function(animation, duration, onComplete) {
  15843. // single settings object
  15844. if(typeof animation == 'object') {
  15845. return $.extend(true, {}, $.fn.transition.settings, animation);
  15846. }
  15847. // all arguments provided
  15848. else if(typeof onComplete == 'function') {
  15849. return $.extend({}, $.fn.transition.settings, {
  15850. animation : animation,
  15851. onComplete : onComplete,
  15852. duration : duration
  15853. });
  15854. }
  15855. // only duration provided
  15856. else if(typeof duration == 'string' || typeof duration == 'number') {
  15857. return $.extend({}, $.fn.transition.settings, {
  15858. animation : animation,
  15859. duration : duration
  15860. });
  15861. }
  15862. // duration is actually settings object
  15863. else if(typeof duration == 'object') {
  15864. return $.extend({}, $.fn.transition.settings, duration, {
  15865. animation : animation
  15866. });
  15867. }
  15868. // duration is actually callback
  15869. else if(typeof duration == 'function') {
  15870. return $.extend({}, $.fn.transition.settings, {
  15871. animation : animation,
  15872. onComplete : duration
  15873. });
  15874. }
  15875. // only animation provided
  15876. else {
  15877. return $.extend({}, $.fn.transition.settings, {
  15878. animation : animation
  15879. });
  15880. }
  15881. return $.fn.transition.settings;
  15882. },
  15883. animationClass: function(animation) {
  15884. var
  15885. animationClass = animation || settings.animation,
  15886. directionClass = (module.can.transition() && !module.has.direction())
  15887. ? module.get.direction() + ' '
  15888. : ''
  15889. ;
  15890. return className.animating + ' '
  15891. + className.transition + ' '
  15892. + directionClass
  15893. + animationClass
  15894. ;
  15895. },
  15896. currentAnimation: function() {
  15897. return module.cache.animation || false;
  15898. },
  15899. currentDirection: function() {
  15900. return module.is.inward()
  15901. ? className.inward
  15902. : className.outward
  15903. ;
  15904. },
  15905. direction: function() {
  15906. return module.is.hidden() || !module.is.visible()
  15907. ? className.inward
  15908. : className.outward
  15909. ;
  15910. },
  15911. animationDirection: function(animation) {
  15912. var
  15913. direction
  15914. ;
  15915. animation = animation || settings.animation;
  15916. if(typeof animation === 'string') {
  15917. animation = animation.split(' ');
  15918. // search animation name for out/in class
  15919. $.each(animation, function(index, word){
  15920. if(word === className.inward) {
  15921. direction = className.inward;
  15922. }
  15923. else if(word === className.outward) {
  15924. direction = className.outward;
  15925. }
  15926. });
  15927. }
  15928. // return found direction
  15929. if(direction) {
  15930. return direction;
  15931. }
  15932. return false;
  15933. },
  15934. duration: function(duration) {
  15935. duration = duration || settings.duration;
  15936. if(duration === false) {
  15937. duration = $module.css('animation-duration') || 0;
  15938. }
  15939. return (typeof duration === 'string')
  15940. ? (duration.indexOf('ms') > -1)
  15941. ? parseFloat(duration)
  15942. : parseFloat(duration) * 1000
  15943. : duration
  15944. ;
  15945. },
  15946. displayType: function() {
  15947. if(settings.displayType) {
  15948. return settings.displayType;
  15949. }
  15950. if($module.data(metadata.displayType) === undefined) {
  15951. // create fake element to determine display state
  15952. module.can.transition(true);
  15953. }
  15954. return $module.data(metadata.displayType);
  15955. },
  15956. userStyle: function(style) {
  15957. style = style || $module.attr('style') || '';
  15958. return style.replace(/display.*?;/, '');;
  15959. },
  15960. transitionExists: function(animation) {
  15961. return $.fn.transition.exists[animation];
  15962. },
  15963. animationStartEvent: function() {
  15964. var
  15965. element = document.createElement('div'),
  15966. animations = {
  15967. 'animation' :'animationstart',
  15968. 'OAnimation' :'oAnimationStart',
  15969. 'MozAnimation' :'mozAnimationStart',
  15970. 'WebkitAnimation' :'webkitAnimationStart'
  15971. },
  15972. animation
  15973. ;
  15974. for(animation in animations){
  15975. if( element.style[animation] !== undefined ){
  15976. return animations[animation];
  15977. }
  15978. }
  15979. return false;
  15980. },
  15981. animationEndEvent: function() {
  15982. var
  15983. element = document.createElement('div'),
  15984. animations = {
  15985. 'animation' :'animationend',
  15986. 'OAnimation' :'oAnimationEnd',
  15987. 'MozAnimation' :'mozAnimationEnd',
  15988. 'WebkitAnimation' :'webkitAnimationEnd'
  15989. },
  15990. animation
  15991. ;
  15992. for(animation in animations){
  15993. if( element.style[animation] !== undefined ){
  15994. return animations[animation];
  15995. }
  15996. }
  15997. return false;
  15998. }
  15999. },
  16000. can: {
  16001. transition: function(forced) {
  16002. var
  16003. animation = settings.animation,
  16004. transitionExists = module.get.transitionExists(animation),
  16005. elementClass,
  16006. tagName,
  16007. $clone,
  16008. currentAnimation,
  16009. inAnimation,
  16010. directionExists,
  16011. displayType
  16012. ;
  16013. if( transitionExists === undefined || forced) {
  16014. module.verbose('Determining whether animation exists');
  16015. elementClass = $module.attr('class');
  16016. tagName = $module.prop('tagName');
  16017. $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
  16018. currentAnimation = $clone
  16019. .addClass(animation)
  16020. .removeClass(className.inward)
  16021. .removeClass(className.outward)
  16022. .addClass(className.animating)
  16023. .addClass(className.transition)
  16024. .css('animationName')
  16025. ;
  16026. inAnimation = $clone
  16027. .addClass(className.inward)
  16028. .css('animationName')
  16029. ;
  16030. displayType = $clone
  16031. .attr('class', elementClass)
  16032. .removeAttr('style')
  16033. .removeClass(className.hidden)
  16034. .removeClass(className.visible)
  16035. .show()
  16036. .css('display')
  16037. ;
  16038. module.verbose('Determining final display state', displayType);
  16039. module.save.displayType(displayType);
  16040. $clone.remove();
  16041. if(currentAnimation != inAnimation) {
  16042. module.debug('Direction exists for animation', animation);
  16043. directionExists = true;
  16044. }
  16045. else if(currentAnimation == 'none' || !currentAnimation) {
  16046. module.debug('No animation defined in css', animation);
  16047. return;
  16048. }
  16049. else {
  16050. module.debug('Static animation found', animation, displayType);
  16051. directionExists = false;
  16052. }
  16053. module.save.transitionExists(animation, directionExists);
  16054. }
  16055. return (transitionExists !== undefined)
  16056. ? transitionExists
  16057. : directionExists
  16058. ;
  16059. },
  16060. animate: function() {
  16061. // can transition does not return a value if animation does not exist
  16062. return (module.can.transition() !== undefined);
  16063. }
  16064. },
  16065. is: {
  16066. animating: function() {
  16067. return $module.hasClass(className.animating);
  16068. },
  16069. inward: function() {
  16070. return $module.hasClass(className.inward);
  16071. },
  16072. outward: function() {
  16073. return $module.hasClass(className.outward);
  16074. },
  16075. looping: function() {
  16076. return $module.hasClass(className.looping);
  16077. },
  16078. occurring: function(animation) {
  16079. animation = animation || settings.animation;
  16080. animation = '.' + animation.replace(' ', '.');
  16081. return ( $module.filter(animation).length > 0 );
  16082. },
  16083. visible: function() {
  16084. return $module.is(':visible');
  16085. },
  16086. hidden: function() {
  16087. return $module.css('visibility') === 'hidden';
  16088. },
  16089. supported: function() {
  16090. return(animationEnd !== false);
  16091. }
  16092. },
  16093. hide: function() {
  16094. module.verbose('Hiding element');
  16095. if( module.is.animating() ) {
  16096. module.reset();
  16097. }
  16098. element.blur(); // IE will trigger focus change if element is not blurred before hiding
  16099. module.remove.display();
  16100. module.remove.visible();
  16101. module.set.hidden();
  16102. settings.onHide.call(this);
  16103. settings.onComplete.call(this);
  16104. module.force.hidden();
  16105. // module.repaint();
  16106. },
  16107. show: function(display) {
  16108. module.verbose('Showing element', display);
  16109. module.remove.hidden();
  16110. module.set.visible();
  16111. settings.onShow.call(this);
  16112. settings.onComplete.call(this);
  16113. module.force.visible();
  16114. // module.repaint();
  16115. },
  16116. toggle: function() {
  16117. if( module.is.visible() ) {
  16118. module.hide();
  16119. }
  16120. else {
  16121. module.show();
  16122. }
  16123. },
  16124. stop: function() {
  16125. module.debug('Stopping current animation');
  16126. $module.triggerHandler(animationEnd);
  16127. },
  16128. stopAll: function() {
  16129. module.debug('Stopping all animation');
  16130. module.remove.queueCallback();
  16131. $module.triggerHandler(animationEnd);
  16132. },
  16133. clear: {
  16134. queue: function() {
  16135. module.debug('Clearing animation queue');
  16136. module.remove.queueCallback();
  16137. }
  16138. },
  16139. enable: function() {
  16140. module.verbose('Starting animation');
  16141. $module.removeClass(className.disabled);
  16142. },
  16143. disable: function() {
  16144. module.debug('Stopping animation');
  16145. $module.addClass(className.disabled);
  16146. },
  16147. setting: function(name, value) {
  16148. module.debug('Changing setting', name, value);
  16149. if( $.isPlainObject(name) ) {
  16150. $.extend(true, settings, name);
  16151. }
  16152. else if(value !== undefined) {
  16153. settings[name] = value;
  16154. }
  16155. else {
  16156. return settings[name];
  16157. }
  16158. },
  16159. internal: function(name, value) {
  16160. if( $.isPlainObject(name) ) {
  16161. $.extend(true, module, name);
  16162. }
  16163. else if(value !== undefined) {
  16164. module[name] = value;
  16165. }
  16166. else {
  16167. return module[name];
  16168. }
  16169. },
  16170. debug: function() {
  16171. if(settings.debug) {
  16172. if(settings.performance) {
  16173. module.performance.log(arguments);
  16174. }
  16175. else {
  16176. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16177. module.debug.apply(console, arguments);
  16178. }
  16179. }
  16180. },
  16181. verbose: function() {
  16182. if(settings.verbose && settings.debug) {
  16183. if(settings.performance) {
  16184. module.performance.log(arguments);
  16185. }
  16186. else {
  16187. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16188. module.verbose.apply(console, arguments);
  16189. }
  16190. }
  16191. },
  16192. error: function() {
  16193. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  16194. module.error.apply(console, arguments);
  16195. },
  16196. performance: {
  16197. log: function(message) {
  16198. var
  16199. currentTime,
  16200. executionTime,
  16201. previousTime
  16202. ;
  16203. if(settings.performance) {
  16204. currentTime = new Date().getTime();
  16205. previousTime = time || currentTime;
  16206. executionTime = currentTime - previousTime;
  16207. time = currentTime;
  16208. performance.push({
  16209. 'Name' : message[0],
  16210. 'Arguments' : [].slice.call(message, 1) || '',
  16211. 'Element' : element,
  16212. 'Execution Time' : executionTime
  16213. });
  16214. }
  16215. clearTimeout(module.performance.timer);
  16216. module.performance.timer = setTimeout(module.performance.display, 500);
  16217. },
  16218. display: function() {
  16219. var
  16220. title = settings.name + ':',
  16221. totalTime = 0
  16222. ;
  16223. time = false;
  16224. clearTimeout(module.performance.timer);
  16225. $.each(performance, function(index, data) {
  16226. totalTime += data['Execution Time'];
  16227. });
  16228. title += ' ' + totalTime + 'ms';
  16229. if(moduleSelector) {
  16230. title += ' \'' + moduleSelector + '\'';
  16231. }
  16232. if($allModules.length > 1) {
  16233. title += ' ' + '(' + $allModules.length + ')';
  16234. }
  16235. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  16236. console.groupCollapsed(title);
  16237. if(console.table) {
  16238. console.table(performance);
  16239. }
  16240. else {
  16241. $.each(performance, function(index, data) {
  16242. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  16243. });
  16244. }
  16245. console.groupEnd();
  16246. }
  16247. performance = [];
  16248. }
  16249. },
  16250. // modified for transition to return invoke success
  16251. invoke: function(query, passedArguments, context) {
  16252. var
  16253. object = instance,
  16254. maxDepth,
  16255. found,
  16256. response
  16257. ;
  16258. passedArguments = passedArguments || queryArguments;
  16259. context = element || context;
  16260. if(typeof query == 'string' && object !== undefined) {
  16261. query = query.split(/[\. ]/);
  16262. maxDepth = query.length - 1;
  16263. $.each(query, function(depth, value) {
  16264. var camelCaseValue = (depth != maxDepth)
  16265. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  16266. : query
  16267. ;
  16268. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  16269. object = object[camelCaseValue];
  16270. }
  16271. else if( object[camelCaseValue] !== undefined ) {
  16272. found = object[camelCaseValue];
  16273. return false;
  16274. }
  16275. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  16276. object = object[value];
  16277. }
  16278. else if( object[value] !== undefined ) {
  16279. found = object[value];
  16280. return false;
  16281. }
  16282. else {
  16283. return false;
  16284. }
  16285. });
  16286. }
  16287. if ( $.isFunction( found ) ) {
  16288. response = found.apply(context, passedArguments);
  16289. }
  16290. else if(found !== undefined) {
  16291. response = found;
  16292. }
  16293. if($.isArray(returnedValue)) {
  16294. returnedValue.push(response);
  16295. }
  16296. else if(returnedValue !== undefined) {
  16297. returnedValue = [returnedValue, response];
  16298. }
  16299. else if(response !== undefined) {
  16300. returnedValue = response;
  16301. }
  16302. return (found !== undefined)
  16303. ? found
  16304. : false
  16305. ;
  16306. }
  16307. };
  16308. module.initialize();
  16309. })
  16310. ;
  16311. return (returnedValue !== undefined)
  16312. ? returnedValue
  16313. : this
  16314. ;
  16315. };
  16316. // Records if CSS transition is available
  16317. $.fn.transition.exists = {};
  16318. $.fn.transition.settings = {
  16319. // module info
  16320. name : 'Transition',
  16321. // debug content outputted to console
  16322. debug : false,
  16323. // verbose debug output
  16324. verbose : false,
  16325. // performance data output
  16326. performance : true,
  16327. // event namespace
  16328. namespace : 'transition',
  16329. // delay between animations in group
  16330. interval : 0,
  16331. // whether group animations should be reversed
  16332. reverse : 'auto',
  16333. // animation callback event
  16334. onStart : function() {},
  16335. onComplete : function() {},
  16336. onShow : function() {},
  16337. onHide : function() {},
  16338. // whether timeout should be used to ensure callback fires in cases animationend does not
  16339. useFailSafe : true,
  16340. // delay in ms for fail safe
  16341. failSafeDelay : 100,
  16342. // whether EXACT animation can occur twice in a row
  16343. allowRepeats : false,
  16344. // Override final display type on visible
  16345. displayType : false,
  16346. // animation duration
  16347. animation : 'fade',
  16348. duration : false,
  16349. // new animations will occur after previous ones
  16350. queue : true,
  16351. metadata : {
  16352. displayType: 'display'
  16353. },
  16354. className : {
  16355. animating : 'animating',
  16356. disabled : 'disabled',
  16357. hidden : 'hidden',
  16358. inward : 'in',
  16359. loading : 'loading',
  16360. looping : 'looping',
  16361. outward : 'out',
  16362. transition : 'transition',
  16363. visible : 'visible'
  16364. },
  16365. // possible errors
  16366. error: {
  16367. noAnimation : 'There is no css animation matching the one you specified. Please make sure your css is vendor prefixed, and you have included transition css.',
  16368. repeated : 'That animation is already occurring, cancelling repeated animation',
  16369. method : 'The method you called is not defined',
  16370. support : 'This browser does not support CSS animations'
  16371. }
  16372. };
  16373. })( jQuery, window , document );
  16374. /*!
  16375. * # Semantic UI 2.0.0 - API
  16376. * http://github.com/semantic-org/semantic-ui/
  16377. *
  16378. *
  16379. * Copyright 2015 Contributors
  16380. * Released under the MIT license
  16381. * http://opensource.org/licenses/MIT
  16382. *
  16383. */
  16384. ;(function ( $, window, document, undefined ) {
  16385. "use strict";
  16386. $.api = $.fn.api = function(parameters) {
  16387. var
  16388. // use window context if none specified
  16389. $allModules = $.isFunction(this)
  16390. ? $(window)
  16391. : $(this),
  16392. moduleSelector = $allModules.selector || '',
  16393. time = new Date().getTime(),
  16394. performance = [],
  16395. query = arguments[0],
  16396. methodInvoked = (typeof query == 'string'),
  16397. queryArguments = [].slice.call(arguments, 1),
  16398. returnedValue
  16399. ;
  16400. $allModules
  16401. .each(function() {
  16402. var
  16403. settings = ( $.isPlainObject(parameters) )
  16404. ? $.extend(true, {}, $.fn.api.settings, parameters)
  16405. : $.extend({}, $.fn.api.settings),
  16406. // internal aliases
  16407. namespace = settings.namespace,
  16408. metadata = settings.metadata,
  16409. selector = settings.selector,
  16410. error = settings.error,
  16411. className = settings.className,
  16412. // define namespaces for modules
  16413. eventNamespace = '.' + namespace,
  16414. moduleNamespace = 'module-' + namespace,
  16415. // element that creates request
  16416. $module = $(this),
  16417. $form = $module.closest(selector.form),
  16418. // context used for state
  16419. $context = (settings.stateContext)
  16420. ? $(settings.stateContext)
  16421. : $module,
  16422. // request details
  16423. ajaxSettings,
  16424. requestSettings,
  16425. url,
  16426. data,
  16427. requestStartTime,
  16428. // standard module
  16429. element = this,
  16430. context = $context[0],
  16431. instance = $module.data(moduleNamespace),
  16432. module
  16433. ;
  16434. module = {
  16435. initialize: function() {
  16436. if(!methodInvoked) {
  16437. module.bind.events();
  16438. }
  16439. module.instantiate();
  16440. },
  16441. instantiate: function() {
  16442. module.verbose('Storing instance of module', module);
  16443. instance = module;
  16444. $module
  16445. .data(moduleNamespace, instance)
  16446. ;
  16447. },
  16448. destroy: function() {
  16449. module.verbose('Destroying previous module for', element);
  16450. $module
  16451. .removeData(moduleNamespace)
  16452. .off(eventNamespace)
  16453. ;
  16454. },
  16455. bind: {
  16456. events: function() {
  16457. var
  16458. triggerEvent = module.get.event()
  16459. ;
  16460. if( triggerEvent ) {
  16461. module.verbose('Attaching API events to element', triggerEvent);
  16462. $module
  16463. .on(triggerEvent + eventNamespace, module.event.trigger)
  16464. ;
  16465. }
  16466. else if(settings.on == 'now') {
  16467. module.debug('Querying API now', triggerEvent);
  16468. module.query();
  16469. }
  16470. }
  16471. },
  16472. read: {
  16473. cachedResponse: function(url) {
  16474. var
  16475. response
  16476. ;
  16477. if(window.Storage === undefined) {
  16478. module.error(error.noStorage);
  16479. return;
  16480. }
  16481. response = sessionStorage.getItem(url);
  16482. module.debug('Using cached response', url, response);
  16483. if(response !== undefined) {
  16484. try {
  16485. response = JSON.parse(response);
  16486. }
  16487. catch(e) {
  16488. // didnt store object
  16489. }
  16490. return response;
  16491. }
  16492. return false;
  16493. }
  16494. },
  16495. write: {
  16496. cachedResponse: function(url, response) {
  16497. if(response && response === '') {
  16498. module.debug('Response empty, not caching', response);
  16499. return;
  16500. }
  16501. if(window.Storage === undefined) {
  16502. module.error(error.noStorage);
  16503. return;
  16504. }
  16505. if( $.isPlainObject(response) ) {
  16506. response = JSON.stringify(response);
  16507. }
  16508. sessionStorage.setItem(url, response);
  16509. module.verbose('Storing cached response for url', url, response);
  16510. }
  16511. },
  16512. query: function() {
  16513. if(module.is.disabled()) {
  16514. module.debug('Element is disabled API request aborted');
  16515. return;
  16516. }
  16517. if(module.is.loading()) {
  16518. if(settings.interruptRequests) {
  16519. module.debug('Interrupting previous request');
  16520. module.abort();
  16521. }
  16522. else {
  16523. module.debug('Cancelling request, previous request is still pending');
  16524. return;
  16525. }
  16526. }
  16527. // pass element metadata to url (value, text)
  16528. if(settings.defaultData) {
  16529. $.extend(true, settings.urlData, module.get.defaultData());
  16530. }
  16531. // Add form content
  16532. if(settings.serializeForm) {
  16533. settings.data = module.add.formData(settings.data);
  16534. }
  16535. // call beforesend and get any settings changes
  16536. requestSettings = module.get.settings();
  16537. // check if before send cancelled request
  16538. if(requestSettings === false) {
  16539. module.cancelled = true;
  16540. module.error(error.beforeSend);
  16541. return;
  16542. }
  16543. else {
  16544. module.cancelled = false;
  16545. }
  16546. // get url
  16547. url = module.get.templatedURL();
  16548. if(!url && !module.is.mocked()) {
  16549. module.error(error.missingURL);
  16550. return;
  16551. }
  16552. // replace variables
  16553. url = module.add.urlData( url );
  16554. // missing url parameters
  16555. if( !url && !module.is.mocked()) {
  16556. return;
  16557. }
  16558. // look for jQuery ajax parameters in settings
  16559. ajaxSettings = $.extend(true, {}, settings, {
  16560. type : settings.method || settings.type,
  16561. data : data,
  16562. url : settings.base + url,
  16563. beforeSend : settings.beforeXHR,
  16564. success : function() {},
  16565. failure : function() {},
  16566. complete : function() {}
  16567. });
  16568. module.debug('Querying URL', ajaxSettings.url);
  16569. module.verbose('Using AJAX settings', ajaxSettings);
  16570. if(settings.cache === 'local' && module.read.cachedResponse(url)) {
  16571. module.debug('Response returned from local cache');
  16572. module.request = module.create.request();
  16573. module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
  16574. return;
  16575. }
  16576. if( !settings.throttle ) {
  16577. module.debug('Sending request', data, ajaxSettings.method);
  16578. module.send.request();
  16579. }
  16580. else {
  16581. if(!settings.throttleFirstRequest && !module.timer) {
  16582. module.debug('Sending request', data, ajaxSettings.method);
  16583. module.send.request();
  16584. module.timer = setTimeout(function(){}, settings.throttle);
  16585. }
  16586. else {
  16587. module.debug('Throttling request', settings.throttle);
  16588. clearTimeout(module.timer);
  16589. module.timer = setTimeout(function() {
  16590. if(module.timer) {
  16591. delete module.timer;
  16592. }
  16593. module.debug('Sending throttled request', data, ajaxSettings.method);
  16594. module.send.request();
  16595. }, settings.throttle);
  16596. }
  16597. }
  16598. },
  16599. is: {
  16600. disabled: function() {
  16601. return ($module.filter(selector.disabled).length > 0);
  16602. },
  16603. form: function() {
  16604. return $module.is('form');
  16605. },
  16606. mocked: function() {
  16607. return (settings.mockResponse || settings.mockResponseAsync);
  16608. },
  16609. input: function() {
  16610. return $module.is('input');
  16611. },
  16612. loading: function() {
  16613. return (module.request && module.request.state() == 'pending');
  16614. },
  16615. abortedRequest: function(xhr) {
  16616. if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
  16617. module.verbose('XHR request determined to be aborted');
  16618. return true;
  16619. }
  16620. else {
  16621. module.verbose('XHR request was not aborted');
  16622. return false;
  16623. }
  16624. },
  16625. validResponse: function(response) {
  16626. if( settings.dataType !== 'json' || !$.isFunction(settings.successTest) ) {
  16627. module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
  16628. return true;
  16629. }
  16630. module.debug('Checking JSON returned success', settings.successTest, response);
  16631. if( settings.successTest(response) ) {
  16632. module.debug('Response passed success test', response);
  16633. return true;
  16634. }
  16635. else {
  16636. module.debug('Response failed success test', response);
  16637. return false;
  16638. }
  16639. }
  16640. },
  16641. was: {
  16642. cancelled: function() {
  16643. return (module.cancelled || false);
  16644. },
  16645. succesful: function() {
  16646. return (module.request && module.request.state() == 'resolved');
  16647. },
  16648. failure: function() {
  16649. return (module.request && module.request.state() == 'rejected');
  16650. },
  16651. complete: function() {
  16652. return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
  16653. }
  16654. },
  16655. add: {
  16656. urlData: function(url, urlData) {
  16657. var
  16658. requiredVariables,
  16659. optionalVariables
  16660. ;
  16661. if(url) {
  16662. requiredVariables = url.match(settings.regExp.required);
  16663. optionalVariables = url.match(settings.regExp.optional);
  16664. urlData = urlData || settings.urlData;
  16665. if(requiredVariables) {
  16666. module.debug('Looking for required URL variables', requiredVariables);
  16667. $.each(requiredVariables, function(index, templatedString) {
  16668. var
  16669. // allow legacy {$var} style
  16670. variable = (templatedString.indexOf('$') !== -1)
  16671. ? templatedString.substr(2, templatedString.length - 3)
  16672. : templatedString.substr(1, templatedString.length - 2),
  16673. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  16674. ? urlData[variable]
  16675. : ($module.data(variable) !== undefined)
  16676. ? $module.data(variable)
  16677. : ($context.data(variable) !== undefined)
  16678. ? $context.data(variable)
  16679. : urlData[variable]
  16680. ;
  16681. // remove value
  16682. if(value === undefined) {
  16683. module.error(error.requiredParameter, variable, url);
  16684. url = false;
  16685. return false;
  16686. }
  16687. else {
  16688. module.verbose('Found required variable', variable, value);
  16689. url = url.replace(templatedString, value);
  16690. }
  16691. });
  16692. }
  16693. if(optionalVariables) {
  16694. module.debug('Looking for optional URL variables', requiredVariables);
  16695. $.each(optionalVariables, function(index, templatedString) {
  16696. var
  16697. // allow legacy {/$var} style
  16698. variable = (templatedString.indexOf('$') !== -1)
  16699. ? templatedString.substr(3, templatedString.length - 4)
  16700. : templatedString.substr(2, templatedString.length - 3),
  16701. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  16702. ? urlData[variable]
  16703. : ($module.data(variable) !== undefined)
  16704. ? $module.data(variable)
  16705. : ($context.data(variable) !== undefined)
  16706. ? $context.data(variable)
  16707. : urlData[variable]
  16708. ;
  16709. // optional replacement
  16710. if(value !== undefined) {
  16711. module.verbose('Optional variable Found', variable, value);
  16712. url = url.replace(templatedString, value);
  16713. }
  16714. else {
  16715. module.verbose('Optional variable not found', variable);
  16716. // remove preceding slash if set
  16717. if(url.indexOf('/' + templatedString) !== -1) {
  16718. url = url.replace('/' + templatedString, '');
  16719. }
  16720. else {
  16721. url = url.replace(templatedString, '');
  16722. }
  16723. }
  16724. });
  16725. }
  16726. }
  16727. return url;
  16728. },
  16729. formData: function(data) {
  16730. var
  16731. canSerialize = ($.fn.serializeObject !== undefined),
  16732. formData = (canSerialize)
  16733. ? $form.serializeObject()
  16734. : $form.serialize(),
  16735. hasOtherData
  16736. ;
  16737. data = data || settings.data;
  16738. hasOtherData = $.isPlainObject(data);
  16739. if(hasOtherData) {
  16740. if(canSerialize) {
  16741. module.debug('Extending existing data with form data', data, formData);
  16742. data = $.extend(true, {}, data, formData);
  16743. }
  16744. else {
  16745. module.error(error.missingSerialize);
  16746. module.debug('Cant extend data. Replacing data with form data', data, formData);
  16747. data = formData;
  16748. }
  16749. }
  16750. else {
  16751. module.debug('Adding form data', formData);
  16752. data = formData;
  16753. }
  16754. return data;
  16755. }
  16756. },
  16757. send: {
  16758. request: function() {
  16759. module.set.loading();
  16760. module.request = module.create.request();
  16761. if( module.is.mocked() ) {
  16762. module.mockedXHR = module.create.mockedXHR();
  16763. }
  16764. else {
  16765. module.xhr = module.create.xhr();
  16766. }
  16767. settings.onRequest.call(context, module.request, module.xhr);
  16768. }
  16769. },
  16770. event: {
  16771. trigger: function(event) {
  16772. module.query();
  16773. if(event.type == 'submit' || event.type == 'click') {
  16774. event.preventDefault();
  16775. }
  16776. },
  16777. xhr: {
  16778. always: function() {
  16779. // calculate if loading time was below minimum threshold
  16780. },
  16781. done: function(response, textStatus, xhr) {
  16782. var
  16783. context = this,
  16784. elapsedTime = (new Date().getTime() - requestStartTime),
  16785. timeLeft = (settings.loadingDuration - elapsedTime),
  16786. translatedResponse = ( $.isFunction(settings.onResponse) )
  16787. ? settings.onResponse.call(context, $.extend(true, {}, response))
  16788. : false
  16789. ;
  16790. timeLeft = (timeLeft > 0)
  16791. ? timeLeft
  16792. : 0
  16793. ;
  16794. if(translatedResponse) {
  16795. module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
  16796. response = translatedResponse;
  16797. }
  16798. if(timeLeft > 0) {
  16799. module.debug('Response completed early delaying state change by', timeLeft);
  16800. }
  16801. setTimeout(function() {
  16802. if( module.is.validResponse(response) ) {
  16803. module.request.resolveWith(context, [response]);
  16804. }
  16805. else {
  16806. module.request.rejectWith(context, [xhr, 'invalid']);
  16807. }
  16808. }, timeLeft);
  16809. },
  16810. fail: function(xhr, status, httpMessage) {
  16811. var
  16812. context = this,
  16813. elapsedTime = (new Date().getTime() - requestStartTime),
  16814. timeLeft = (settings.loadingDuration - elapsedTime)
  16815. ;
  16816. timeLeft = (timeLeft > 0)
  16817. ? timeLeft
  16818. : 0
  16819. ;
  16820. if(timeLeft > 0) {
  16821. module.debug('Response completed early delaying state change by', timeLeft);
  16822. }
  16823. setTimeout(function() {
  16824. if( module.is.abortedRequest(xhr) ) {
  16825. module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
  16826. }
  16827. else {
  16828. module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
  16829. }
  16830. }, timeLeft);
  16831. }
  16832. },
  16833. request: {
  16834. complete: function(response) {
  16835. module.remove.loading();
  16836. settings.onComplete.call(context, response, $module);
  16837. },
  16838. done: function(response) {
  16839. module.debug('Successful API Response', response);
  16840. if(settings.cache === 'local' && url) {
  16841. module.write.cachedResponse(url, response);
  16842. module.debug('Saving server response locally', module.cache);
  16843. }
  16844. settings.onSuccess.call(context, response, $module);
  16845. },
  16846. fail: function(xhr, status, httpMessage) {
  16847. var
  16848. // pull response from xhr if available
  16849. response = $.isPlainObject(xhr)
  16850. ? (xhr.responseText)
  16851. : false,
  16852. errorMessage = ($.isPlainObject(response) && response.error !== undefined)
  16853. ? response.error // use json error message
  16854. : (settings.error[status] !== undefined) // use server error message
  16855. ? settings.error[status]
  16856. : httpMessage
  16857. ;
  16858. if(status == 'aborted') {
  16859. module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
  16860. settings.onAbort.call(context, status, $module);
  16861. }
  16862. else if(status == 'invalid') {
  16863. module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
  16864. }
  16865. else if(status == 'error') {
  16866. if(xhr !== undefined) {
  16867. module.debug('XHR produced a server error', status, httpMessage);
  16868. // make sure we have an error to display to console
  16869. if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
  16870. module.error(error.statusMessage + httpMessage, ajaxSettings.url);
  16871. }
  16872. settings.onError.call(context, errorMessage, $module);
  16873. }
  16874. }
  16875. if(settings.errorDuration && status !== 'aborted') {
  16876. module.debug('Adding error state');
  16877. module.set.error();
  16878. setTimeout(module.remove.error, settings.errorDuration);
  16879. }
  16880. module.debug('API Request failed', errorMessage, xhr);
  16881. settings.onFailure.call(context, response, $module);
  16882. }
  16883. }
  16884. },
  16885. create: {
  16886. request: function() {
  16887. // api request promise
  16888. return $.Deferred()
  16889. .always(module.event.request.complete)
  16890. .done(module.event.request.done)
  16891. .fail(module.event.request.fail)
  16892. ;
  16893. },
  16894. mockedXHR: function () {
  16895. var
  16896. // xhr does not simulate these properties of xhr but must return them
  16897. textStatus = false,
  16898. status = false,
  16899. httpMessage = false,
  16900. asyncCallback,
  16901. response,
  16902. mockedXHR
  16903. ;
  16904. mockedXHR = $.Deferred()
  16905. .always(module.event.xhr.complete)
  16906. .done(module.event.xhr.done)
  16907. .fail(module.event.xhr.fail)
  16908. ;
  16909. if(settings.mockResponse) {
  16910. if( $.isFunction(settings.mockResponse) ) {
  16911. module.debug('Using mocked callback returning response', settings.mockResponse);
  16912. response = settings.mockResponse.call(context, settings);
  16913. }
  16914. else {
  16915. module.debug('Using specified response', settings.mockResponse);
  16916. response = settings.mockResponse;
  16917. }
  16918. // simulating response
  16919. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  16920. }
  16921. else if( $.isFunction(settings.mockResponseAsync) ) {
  16922. asyncCallback = function(response) {
  16923. module.debug('Async callback returned response', response);
  16924. if(response) {
  16925. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  16926. }
  16927. else {
  16928. mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
  16929. }
  16930. };
  16931. module.debug('Using async mocked response', settings.mockResponseAsync);
  16932. settings.mockResponseAsync.call(context, settings, asyncCallback);
  16933. }
  16934. return mockedXHR;
  16935. },
  16936. xhr: function() {
  16937. var
  16938. xhr
  16939. ;
  16940. // ajax request promise
  16941. xhr = $.ajax(ajaxSettings)
  16942. .always(module.event.xhr.always)
  16943. .done(module.event.xhr.done)
  16944. .fail(module.event.xhr.fail)
  16945. ;
  16946. module.verbose('Created server request', xhr);
  16947. return xhr;
  16948. }
  16949. },
  16950. set: {
  16951. error: function() {
  16952. module.verbose('Adding error state to element', $context);
  16953. $context.addClass(className.error);
  16954. },
  16955. loading: function() {
  16956. module.verbose('Adding loading state to element', $context);
  16957. $context.addClass(className.loading);
  16958. requestStartTime = new Date().getTime();
  16959. }
  16960. },
  16961. remove: {
  16962. error: function() {
  16963. module.verbose('Removing error state from element', $context);
  16964. $context.removeClass(className.error);
  16965. },
  16966. loading: function() {
  16967. module.verbose('Removing loading state from element', $context);
  16968. $context.removeClass(className.loading);
  16969. }
  16970. },
  16971. get: {
  16972. request: function() {
  16973. return module.request || false;
  16974. },
  16975. xhr: function() {
  16976. return module.xhr || false;
  16977. },
  16978. settings: function() {
  16979. var
  16980. runSettings
  16981. ;
  16982. runSettings = settings.beforeSend.call(context, settings);
  16983. if(runSettings) {
  16984. if(runSettings.success !== undefined) {
  16985. module.debug('Legacy success callback detected', runSettings);
  16986. module.error(error.legacyParameters, runSettings.success);
  16987. runSettings.onSuccess = runSettings.success;
  16988. }
  16989. if(runSettings.failure !== undefined) {
  16990. module.debug('Legacy failure callback detected', runSettings);
  16991. module.error(error.legacyParameters, runSettings.failure);
  16992. runSettings.onFailure = runSettings.failure;
  16993. }
  16994. if(runSettings.complete !== undefined) {
  16995. module.debug('Legacy complete callback detected', runSettings);
  16996. module.error(error.legacyParameters, runSettings.complete);
  16997. runSettings.onComplete = runSettings.complete;
  16998. }
  16999. }
  17000. if(runSettings === undefined) {
  17001. module.error(error.noReturnedValue);
  17002. }
  17003. return (runSettings !== undefined)
  17004. ? runSettings
  17005. : settings
  17006. ;
  17007. },
  17008. defaultData: function() {
  17009. var
  17010. data = {}
  17011. ;
  17012. if( !$.isWindow(element) ) {
  17013. if( module.is.input() ) {
  17014. data.value = $module.val();
  17015. }
  17016. else if( !module.is.form() ) {
  17017. }
  17018. else {
  17019. data.text = $module.text();
  17020. }
  17021. }
  17022. return data;
  17023. },
  17024. event: function() {
  17025. if( $.isWindow(element) || settings.on == 'now' ) {
  17026. module.debug('API called without element, no events attached');
  17027. return false;
  17028. }
  17029. else if(settings.on == 'auto') {
  17030. if( $module.is('input') ) {
  17031. return (element.oninput !== undefined)
  17032. ? 'input'
  17033. : (element.onpropertychange !== undefined)
  17034. ? 'propertychange'
  17035. : 'keyup'
  17036. ;
  17037. }
  17038. else if( $module.is('form') ) {
  17039. return 'submit';
  17040. }
  17041. else {
  17042. return 'click';
  17043. }
  17044. }
  17045. else {
  17046. return settings.on;
  17047. }
  17048. },
  17049. templatedURL: function(action) {
  17050. action = action || $module.data(metadata.action) || settings.action || false;
  17051. url = $module.data(metadata.url) || settings.url || false;
  17052. if(url) {
  17053. module.debug('Using specified url', url);
  17054. return url;
  17055. }
  17056. if(action) {
  17057. module.debug('Looking up url for action', action, settings.api);
  17058. if(settings.api[action] === undefined && !module.is.mocked()) {
  17059. module.error(error.missingAction, settings.action, settings.api);
  17060. return;
  17061. }
  17062. url = settings.api[action];
  17063. }
  17064. else if( module.is.form() ) {
  17065. url = $module.attr('action') || false;
  17066. module.debug('No url or action specified, defaulting to form action', url);
  17067. }
  17068. return url;
  17069. }
  17070. },
  17071. abort: function() {
  17072. var
  17073. xhr = module.get.xhr()
  17074. ;
  17075. if( xhr && xhr.state() !== 'resolved') {
  17076. module.debug('Cancelling API request');
  17077. xhr.abort();
  17078. }
  17079. },
  17080. // reset state
  17081. reset: function() {
  17082. module.remove.error();
  17083. module.remove.loading();
  17084. },
  17085. setting: function(name, value) {
  17086. module.debug('Changing setting', name, value);
  17087. if( $.isPlainObject(name) ) {
  17088. $.extend(true, settings, name);
  17089. }
  17090. else if(value !== undefined) {
  17091. settings[name] = value;
  17092. }
  17093. else {
  17094. return settings[name];
  17095. }
  17096. },
  17097. internal: function(name, value) {
  17098. if( $.isPlainObject(name) ) {
  17099. $.extend(true, module, name);
  17100. }
  17101. else if(value !== undefined) {
  17102. module[name] = value;
  17103. }
  17104. else {
  17105. return module[name];
  17106. }
  17107. },
  17108. debug: function() {
  17109. if(settings.debug) {
  17110. if(settings.performance) {
  17111. module.performance.log(arguments);
  17112. }
  17113. else {
  17114. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17115. module.debug.apply(console, arguments);
  17116. }
  17117. }
  17118. },
  17119. verbose: function() {
  17120. if(settings.verbose && settings.debug) {
  17121. if(settings.performance) {
  17122. module.performance.log(arguments);
  17123. }
  17124. else {
  17125. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17126. module.verbose.apply(console, arguments);
  17127. }
  17128. }
  17129. },
  17130. error: function() {
  17131. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  17132. module.error.apply(console, arguments);
  17133. },
  17134. performance: {
  17135. log: function(message) {
  17136. var
  17137. currentTime,
  17138. executionTime,
  17139. previousTime
  17140. ;
  17141. if(settings.performance) {
  17142. currentTime = new Date().getTime();
  17143. previousTime = time || currentTime;
  17144. executionTime = currentTime - previousTime;
  17145. time = currentTime;
  17146. performance.push({
  17147. 'Name' : message[0],
  17148. 'Arguments' : [].slice.call(message, 1) || '',
  17149. //'Element' : element,
  17150. 'Execution Time' : executionTime
  17151. });
  17152. }
  17153. clearTimeout(module.performance.timer);
  17154. module.performance.timer = setTimeout(module.performance.display, 500);
  17155. },
  17156. display: function() {
  17157. var
  17158. title = settings.name + ':',
  17159. totalTime = 0
  17160. ;
  17161. time = false;
  17162. clearTimeout(module.performance.timer);
  17163. $.each(performance, function(index, data) {
  17164. totalTime += data['Execution Time'];
  17165. });
  17166. title += ' ' + totalTime + 'ms';
  17167. if(moduleSelector) {
  17168. title += ' \'' + moduleSelector + '\'';
  17169. }
  17170. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  17171. console.groupCollapsed(title);
  17172. if(console.table) {
  17173. console.table(performance);
  17174. }
  17175. else {
  17176. $.each(performance, function(index, data) {
  17177. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  17178. });
  17179. }
  17180. console.groupEnd();
  17181. }
  17182. performance = [];
  17183. }
  17184. },
  17185. invoke: function(query, passedArguments, context) {
  17186. var
  17187. object = instance,
  17188. maxDepth,
  17189. found,
  17190. response
  17191. ;
  17192. passedArguments = passedArguments || queryArguments;
  17193. context = element || context;
  17194. if(typeof query == 'string' && object !== undefined) {
  17195. query = query.split(/[\. ]/);
  17196. maxDepth = query.length - 1;
  17197. $.each(query, function(depth, value) {
  17198. var camelCaseValue = (depth != maxDepth)
  17199. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  17200. : query
  17201. ;
  17202. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  17203. object = object[camelCaseValue];
  17204. }
  17205. else if( object[camelCaseValue] !== undefined ) {
  17206. found = object[camelCaseValue];
  17207. return false;
  17208. }
  17209. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  17210. object = object[value];
  17211. }
  17212. else if( object[value] !== undefined ) {
  17213. found = object[value];
  17214. return false;
  17215. }
  17216. else {
  17217. module.error(error.method, query);
  17218. return false;
  17219. }
  17220. });
  17221. }
  17222. if ( $.isFunction( found ) ) {
  17223. response = found.apply(context, passedArguments);
  17224. }
  17225. else if(found !== undefined) {
  17226. response = found;
  17227. }
  17228. if($.isArray(returnedValue)) {
  17229. returnedValue.push(response);
  17230. }
  17231. else if(returnedValue !== undefined) {
  17232. returnedValue = [returnedValue, response];
  17233. }
  17234. else if(response !== undefined) {
  17235. returnedValue = response;
  17236. }
  17237. return found;
  17238. }
  17239. };
  17240. if(methodInvoked) {
  17241. if(instance === undefined) {
  17242. module.initialize();
  17243. }
  17244. module.invoke(query);
  17245. }
  17246. else {
  17247. if(instance !== undefined) {
  17248. instance.invoke('destroy');
  17249. }
  17250. module.initialize();
  17251. }
  17252. })
  17253. ;
  17254. return (returnedValue !== undefined)
  17255. ? returnedValue
  17256. : this
  17257. ;
  17258. };
  17259. $.api.settings = {
  17260. name : 'API',
  17261. namespace : 'api',
  17262. debug : true,
  17263. verbose : false,
  17264. performance : true,
  17265. // object containing all templates endpoints
  17266. api : {},
  17267. // whether to cache responses
  17268. cache : true,
  17269. // whether new requests should abort previous requests
  17270. interruptRequests : true,
  17271. // event binding
  17272. on : 'auto',
  17273. // context for applying state classes
  17274. stateContext : false,
  17275. // duration for loading state
  17276. loadingDuration : 0,
  17277. // duration for error state
  17278. errorDuration : 2000,
  17279. // API action to use
  17280. action : false,
  17281. // templated URL to use
  17282. url : false,
  17283. // base URL to apply to all endpoints
  17284. base : '',
  17285. // data that will
  17286. urlData : {},
  17287. // whether to add default data to url data
  17288. defaultData : true,
  17289. // whether to serialize closest form
  17290. serializeForm : false,
  17291. // how long to wait before request should occur
  17292. throttle : 0,
  17293. // whether to throttle first request or only repeated
  17294. throttleFirstRequest : true,
  17295. // standard ajax settings
  17296. method : 'get',
  17297. data : {},
  17298. dataType : 'json',
  17299. // mock response
  17300. mockResponse : false,
  17301. mockResponseAsync : false,
  17302. // callbacks before request
  17303. beforeSend : function(settings) { return settings; },
  17304. beforeXHR : function(xhr) {},
  17305. onRequest : function(promise, xhr) {},
  17306. // after request
  17307. onResponse : false, // function(response) { },
  17308. // response was successful, if JSON passed validation
  17309. onSuccess : function(response, $module) {},
  17310. // request finished without aborting
  17311. onComplete : function(response, $module) {},
  17312. // failed JSON success test
  17313. onFailure : function(response, $module) {},
  17314. // server error
  17315. onError : function(errorMessage, $module) {},
  17316. // request aborted
  17317. onAbort : function(errorMessage, $module) {},
  17318. successTest : false,
  17319. // errors
  17320. error : {
  17321. beforeSend : 'The before send function has aborted the request',
  17322. error : 'There was an error with your request',
  17323. exitConditions : 'API Request Aborted. Exit conditions met',
  17324. JSONParse : 'JSON could not be parsed during error handling',
  17325. legacyParameters : 'You are using legacy API success callback names',
  17326. method : 'The method you called is not defined',
  17327. missingAction : 'API action used but no url was defined',
  17328. missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
  17329. missingURL : 'No URL specified for api event',
  17330. noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
  17331. noStorage : 'Caching respopnses locally requires session storage',
  17332. parseError : 'There was an error parsing your request',
  17333. requiredParameter : 'Missing a required URL parameter: ',
  17334. statusMessage : 'Server gave an error: ',
  17335. timeout : 'Your request timed out'
  17336. },
  17337. regExp : {
  17338. required : /\{\$*[A-z0-9]+\}/g,
  17339. optional : /\{\/\$*[A-z0-9]+\}/g,
  17340. },
  17341. className: {
  17342. loading : 'loading',
  17343. error : 'error'
  17344. },
  17345. selector: {
  17346. disabled : '.disabled',
  17347. form : 'form'
  17348. },
  17349. metadata: {
  17350. action : 'action',
  17351. url : 'url'
  17352. }
  17353. };
  17354. })( jQuery, window , document );
  17355. /*!
  17356. * # Semantic UI 2.0.0 - State
  17357. * http://github.com/semantic-org/semantic-ui/
  17358. *
  17359. *
  17360. * Copyright 2015 Contributors
  17361. * Released under the MIT license
  17362. * http://opensource.org/licenses/MIT
  17363. *
  17364. */
  17365. ;(function ( $, window, document, undefined ) {
  17366. "use strict";
  17367. $.fn.state = function(parameters) {
  17368. var
  17369. $allModules = $(this),
  17370. moduleSelector = $allModules.selector || '',
  17371. hasTouch = ('ontouchstart' in document.documentElement),
  17372. time = new Date().getTime(),
  17373. performance = [],
  17374. query = arguments[0],
  17375. methodInvoked = (typeof query == 'string'),
  17376. queryArguments = [].slice.call(arguments, 1),
  17377. returnedValue
  17378. ;
  17379. $allModules
  17380. .each(function() {
  17381. var
  17382. settings = ( $.isPlainObject(parameters) )
  17383. ? $.extend(true, {}, $.fn.state.settings, parameters)
  17384. : $.extend({}, $.fn.state.settings),
  17385. error = settings.error,
  17386. metadata = settings.metadata,
  17387. className = settings.className,
  17388. namespace = settings.namespace,
  17389. states = settings.states,
  17390. text = settings.text,
  17391. eventNamespace = '.' + namespace,
  17392. moduleNamespace = namespace + '-module',
  17393. $module = $(this),
  17394. element = this,
  17395. instance = $module.data(moduleNamespace),
  17396. module
  17397. ;
  17398. module = {
  17399. initialize: function() {
  17400. module.verbose('Initializing module');
  17401. // allow module to guess desired state based on element
  17402. if(settings.automatic) {
  17403. module.add.defaults();
  17404. }
  17405. // bind events with delegated events
  17406. if(settings.context && moduleSelector !== '') {
  17407. $(settings.context)
  17408. .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text)
  17409. .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text)
  17410. .on(moduleSelector, 'click' + eventNamespace, module.toggle.state)
  17411. ;
  17412. }
  17413. else {
  17414. $module
  17415. .on('mouseenter' + eventNamespace, module.change.text)
  17416. .on('mouseleave' + eventNamespace, module.reset.text)
  17417. .on('click' + eventNamespace, module.toggle.state)
  17418. ;
  17419. }
  17420. module.instantiate();
  17421. },
  17422. instantiate: function() {
  17423. module.verbose('Storing instance of module', module);
  17424. instance = module;
  17425. $module
  17426. .data(moduleNamespace, module)
  17427. ;
  17428. },
  17429. destroy: function() {
  17430. module.verbose('Destroying previous module', instance);
  17431. $module
  17432. .off(eventNamespace)
  17433. .removeData(moduleNamespace)
  17434. ;
  17435. },
  17436. refresh: function() {
  17437. module.verbose('Refreshing selector cache');
  17438. $module = $(element);
  17439. },
  17440. add: {
  17441. defaults: function() {
  17442. var
  17443. userStates = parameters && $.isPlainObject(parameters.states)
  17444. ? parameters.states
  17445. : {}
  17446. ;
  17447. $.each(settings.defaults, function(type, typeStates) {
  17448. if( module.is[type] !== undefined && module.is[type]() ) {
  17449. module.verbose('Adding default states', type, element);
  17450. $.extend(settings.states, typeStates, userStates);
  17451. }
  17452. });
  17453. }
  17454. },
  17455. is: {
  17456. active: function() {
  17457. return $module.hasClass(className.active);
  17458. },
  17459. loading: function() {
  17460. return $module.hasClass(className.loading);
  17461. },
  17462. inactive: function() {
  17463. return !( $module.hasClass(className.active) );
  17464. },
  17465. state: function(state) {
  17466. if(className[state] === undefined) {
  17467. return false;
  17468. }
  17469. return $module.hasClass( className[state] );
  17470. },
  17471. enabled: function() {
  17472. return !( $module.is(settings.filter.active) );
  17473. },
  17474. disabled: function() {
  17475. return ( $module.is(settings.filter.active) );
  17476. },
  17477. textEnabled: function() {
  17478. return !( $module.is(settings.filter.text) );
  17479. },
  17480. // definitions for automatic type detection
  17481. button: function() {
  17482. return $module.is('.button:not(a, .submit)');
  17483. },
  17484. input: function() {
  17485. return $module.is('input');
  17486. },
  17487. progress: function() {
  17488. return $module.is('.ui.progress');
  17489. }
  17490. },
  17491. allow: function(state) {
  17492. module.debug('Now allowing state', state);
  17493. states[state] = true;
  17494. },
  17495. disallow: function(state) {
  17496. module.debug('No longer allowing', state);
  17497. states[state] = false;
  17498. },
  17499. allows: function(state) {
  17500. return states[state] || false;
  17501. },
  17502. enable: function() {
  17503. $module.removeClass(className.disabled);
  17504. },
  17505. disable: function() {
  17506. $module.addClass(className.disabled);
  17507. },
  17508. setState: function(state) {
  17509. if(module.allows(state)) {
  17510. $module.addClass( className[state] );
  17511. }
  17512. },
  17513. removeState: function(state) {
  17514. if(module.allows(state)) {
  17515. $module.removeClass( className[state] );
  17516. }
  17517. },
  17518. toggle: {
  17519. state: function() {
  17520. var
  17521. apiRequest,
  17522. requestCancelled
  17523. ;
  17524. if( module.allows('active') && module.is.enabled() ) {
  17525. module.refresh();
  17526. if($.fn.api !== undefined) {
  17527. apiRequest = $module.api('get request');
  17528. requestCancelled = $module.api('was cancelled');
  17529. if( requestCancelled ) {
  17530. module.debug('API Request cancelled by beforesend');
  17531. settings.activateTest = function(){ return false; };
  17532. settings.deactivateTest = function(){ return false; };
  17533. }
  17534. else if(apiRequest) {
  17535. module.listenTo(apiRequest);
  17536. return;
  17537. }
  17538. }
  17539. module.change.state();
  17540. }
  17541. }
  17542. },
  17543. listenTo: function(apiRequest) {
  17544. module.debug('API request detected, waiting for state signal', apiRequest);
  17545. if(apiRequest) {
  17546. if(text.loading) {
  17547. module.update.text(text.loading);
  17548. }
  17549. $.when(apiRequest)
  17550. .then(function() {
  17551. if(apiRequest.state() == 'resolved') {
  17552. module.debug('API request succeeded');
  17553. settings.activateTest = function(){ return true; };
  17554. settings.deactivateTest = function(){ return true; };
  17555. }
  17556. else {
  17557. module.debug('API request failed');
  17558. settings.activateTest = function(){ return false; };
  17559. settings.deactivateTest = function(){ return false; };
  17560. }
  17561. module.change.state();
  17562. })
  17563. ;
  17564. }
  17565. },
  17566. // checks whether active/inactive state can be given
  17567. change: {
  17568. state: function() {
  17569. module.debug('Determining state change direction');
  17570. // inactive to active change
  17571. if( module.is.inactive() ) {
  17572. module.activate();
  17573. }
  17574. else {
  17575. module.deactivate();
  17576. }
  17577. if(settings.sync) {
  17578. module.sync();
  17579. }
  17580. settings.onChange.call(element);
  17581. },
  17582. text: function() {
  17583. if( module.is.textEnabled() ) {
  17584. if(module.is.disabled() ) {
  17585. module.verbose('Changing text to disabled text', text.hover);
  17586. module.update.text(text.disabled);
  17587. }
  17588. else if( module.is.active() ) {
  17589. if(text.hover) {
  17590. module.verbose('Changing text to hover text', text.hover);
  17591. module.update.text(text.hover);
  17592. }
  17593. else if(text.deactivate) {
  17594. module.verbose('Changing text to deactivating text', text.deactivate);
  17595. module.update.text(text.deactivate);
  17596. }
  17597. }
  17598. else {
  17599. if(text.hover) {
  17600. module.verbose('Changing text to hover text', text.hover);
  17601. module.update.text(text.hover);
  17602. }
  17603. else if(text.activate){
  17604. module.verbose('Changing text to activating text', text.activate);
  17605. module.update.text(text.activate);
  17606. }
  17607. }
  17608. }
  17609. }
  17610. },
  17611. activate: function() {
  17612. if( settings.activateTest.call(element) ) {
  17613. module.debug('Setting state to active');
  17614. $module
  17615. .addClass(className.active)
  17616. ;
  17617. module.update.text(text.active);
  17618. settings.onActivate.call(element);
  17619. }
  17620. },
  17621. deactivate: function() {
  17622. if( settings.deactivateTest.call(element) ) {
  17623. module.debug('Setting state to inactive');
  17624. $module
  17625. .removeClass(className.active)
  17626. ;
  17627. module.update.text(text.inactive);
  17628. settings.onDeactivate.call(element);
  17629. }
  17630. },
  17631. sync: function() {
  17632. module.verbose('Syncing other buttons to current state');
  17633. if( module.is.active() ) {
  17634. $allModules
  17635. .not($module)
  17636. .state('activate');
  17637. }
  17638. else {
  17639. $allModules
  17640. .not($module)
  17641. .state('deactivate')
  17642. ;
  17643. }
  17644. },
  17645. get: {
  17646. text: function() {
  17647. return (settings.selector.text)
  17648. ? $module.find(settings.selector.text).text()
  17649. : $module.html()
  17650. ;
  17651. },
  17652. textFor: function(state) {
  17653. return text[state] || false;
  17654. }
  17655. },
  17656. flash: {
  17657. text: function(text, duration, callback) {
  17658. var
  17659. previousText = module.get.text()
  17660. ;
  17661. module.debug('Flashing text message', text, duration);
  17662. text = text || settings.text.flash;
  17663. duration = duration || settings.flashDuration;
  17664. callback = callback || function() {};
  17665. module.update.text(text);
  17666. setTimeout(function(){
  17667. module.update.text(previousText);
  17668. callback.call(element);
  17669. }, duration);
  17670. }
  17671. },
  17672. reset: {
  17673. // on mouseout sets text to previous value
  17674. text: function() {
  17675. var
  17676. activeText = text.active || $module.data(metadata.storedText),
  17677. inactiveText = text.inactive || $module.data(metadata.storedText)
  17678. ;
  17679. if( module.is.textEnabled() ) {
  17680. if( module.is.active() && activeText) {
  17681. module.verbose('Resetting active text', activeText);
  17682. module.update.text(activeText);
  17683. }
  17684. else if(inactiveText) {
  17685. module.verbose('Resetting inactive text', activeText);
  17686. module.update.text(inactiveText);
  17687. }
  17688. }
  17689. }
  17690. },
  17691. update: {
  17692. text: function(text) {
  17693. var
  17694. currentText = module.get.text()
  17695. ;
  17696. if(text && text !== currentText) {
  17697. module.debug('Updating text', text);
  17698. if(settings.selector.text) {
  17699. $module
  17700. .data(metadata.storedText, text)
  17701. .find(settings.selector.text)
  17702. .text(text)
  17703. ;
  17704. }
  17705. else {
  17706. $module
  17707. .data(metadata.storedText, text)
  17708. .html(text)
  17709. ;
  17710. }
  17711. }
  17712. else {
  17713. module.debug('Text is already set, ignoring update', text);
  17714. }
  17715. }
  17716. },
  17717. setting: function(name, value) {
  17718. module.debug('Changing setting', name, value);
  17719. if( $.isPlainObject(name) ) {
  17720. $.extend(true, settings, name);
  17721. }
  17722. else if(value !== undefined) {
  17723. settings[name] = value;
  17724. }
  17725. else {
  17726. return settings[name];
  17727. }
  17728. },
  17729. internal: function(name, value) {
  17730. if( $.isPlainObject(name) ) {
  17731. $.extend(true, module, name);
  17732. }
  17733. else if(value !== undefined) {
  17734. module[name] = value;
  17735. }
  17736. else {
  17737. return module[name];
  17738. }
  17739. },
  17740. debug: function() {
  17741. if(settings.debug) {
  17742. if(settings.performance) {
  17743. module.performance.log(arguments);
  17744. }
  17745. else {
  17746. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17747. module.debug.apply(console, arguments);
  17748. }
  17749. }
  17750. },
  17751. verbose: function() {
  17752. if(settings.verbose && settings.debug) {
  17753. if(settings.performance) {
  17754. module.performance.log(arguments);
  17755. }
  17756. else {
  17757. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17758. module.verbose.apply(console, arguments);
  17759. }
  17760. }
  17761. },
  17762. error: function() {
  17763. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  17764. module.error.apply(console, arguments);
  17765. },
  17766. performance: {
  17767. log: function(message) {
  17768. var
  17769. currentTime,
  17770. executionTime,
  17771. previousTime
  17772. ;
  17773. if(settings.performance) {
  17774. currentTime = new Date().getTime();
  17775. previousTime = time || currentTime;
  17776. executionTime = currentTime - previousTime;
  17777. time = currentTime;
  17778. performance.push({
  17779. 'Name' : message[0],
  17780. 'Arguments' : [].slice.call(message, 1) || '',
  17781. 'Element' : element,
  17782. 'Execution Time' : executionTime
  17783. });
  17784. }
  17785. clearTimeout(module.performance.timer);
  17786. module.performance.timer = setTimeout(module.performance.display, 500);
  17787. },
  17788. display: function() {
  17789. var
  17790. title = settings.name + ':',
  17791. totalTime = 0
  17792. ;
  17793. time = false;
  17794. clearTimeout(module.performance.timer);
  17795. $.each(performance, function(index, data) {
  17796. totalTime += data['Execution Time'];
  17797. });
  17798. title += ' ' + totalTime + 'ms';
  17799. if(moduleSelector) {
  17800. title += ' \'' + moduleSelector + '\'';
  17801. }
  17802. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  17803. console.groupCollapsed(title);
  17804. if(console.table) {
  17805. console.table(performance);
  17806. }
  17807. else {
  17808. $.each(performance, function(index, data) {
  17809. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  17810. });
  17811. }
  17812. console.groupEnd();
  17813. }
  17814. performance = [];
  17815. }
  17816. },
  17817. invoke: function(query, passedArguments, context) {
  17818. var
  17819. object = instance,
  17820. maxDepth,
  17821. found,
  17822. response
  17823. ;
  17824. passedArguments = passedArguments || queryArguments;
  17825. context = element || context;
  17826. if(typeof query == 'string' && object !== undefined) {
  17827. query = query.split(/[\. ]/);
  17828. maxDepth = query.length - 1;
  17829. $.each(query, function(depth, value) {
  17830. var camelCaseValue = (depth != maxDepth)
  17831. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  17832. : query
  17833. ;
  17834. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  17835. object = object[camelCaseValue];
  17836. }
  17837. else if( object[camelCaseValue] !== undefined ) {
  17838. found = object[camelCaseValue];
  17839. return false;
  17840. }
  17841. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  17842. object = object[value];
  17843. }
  17844. else if( object[value] !== undefined ) {
  17845. found = object[value];
  17846. return false;
  17847. }
  17848. else {
  17849. module.error(error.method, query);
  17850. return false;
  17851. }
  17852. });
  17853. }
  17854. if ( $.isFunction( found ) ) {
  17855. response = found.apply(context, passedArguments);
  17856. }
  17857. else if(found !== undefined) {
  17858. response = found;
  17859. }
  17860. if($.isArray(returnedValue)) {
  17861. returnedValue.push(response);
  17862. }
  17863. else if(returnedValue !== undefined) {
  17864. returnedValue = [returnedValue, response];
  17865. }
  17866. else if(response !== undefined) {
  17867. returnedValue = response;
  17868. }
  17869. return found;
  17870. }
  17871. };
  17872. if(methodInvoked) {
  17873. if(instance === undefined) {
  17874. module.initialize();
  17875. }
  17876. module.invoke(query);
  17877. }
  17878. else {
  17879. if(instance !== undefined) {
  17880. instance.invoke('destroy');
  17881. }
  17882. module.initialize();
  17883. }
  17884. })
  17885. ;
  17886. return (returnedValue !== undefined)
  17887. ? returnedValue
  17888. : this
  17889. ;
  17890. };
  17891. $.fn.state.settings = {
  17892. // module info
  17893. name : 'State',
  17894. // debug output
  17895. debug : false,
  17896. // verbose debug output
  17897. verbose : false,
  17898. // namespace for events
  17899. namespace : 'state',
  17900. // debug data includes performance
  17901. performance : true,
  17902. // callback occurs on state change
  17903. onActivate : function() {},
  17904. onDeactivate : function() {},
  17905. onChange : function() {},
  17906. // state test functions
  17907. activateTest : function() { return true; },
  17908. deactivateTest : function() { return true; },
  17909. // whether to automatically map default states
  17910. automatic : true,
  17911. // activate / deactivate changes all elements instantiated at same time
  17912. sync : false,
  17913. // default flash text duration, used for temporarily changing text of an element
  17914. flashDuration : 1000,
  17915. // selector filter
  17916. filter : {
  17917. text : '.loading, .disabled',
  17918. active : '.disabled'
  17919. },
  17920. context : false,
  17921. // error
  17922. error: {
  17923. beforeSend : 'The before send function has cancelled state change',
  17924. method : 'The method you called is not defined.'
  17925. },
  17926. // metadata
  17927. metadata: {
  17928. promise : 'promise',
  17929. storedText : 'stored-text'
  17930. },
  17931. // change class on state
  17932. className: {
  17933. active : 'active',
  17934. disabled : 'disabled',
  17935. error : 'error',
  17936. loading : 'loading',
  17937. success : 'success',
  17938. warning : 'warning'
  17939. },
  17940. selector: {
  17941. // selector for text node
  17942. text: false
  17943. },
  17944. defaults : {
  17945. input: {
  17946. disabled : true,
  17947. loading : true,
  17948. active : true
  17949. },
  17950. button: {
  17951. disabled : true,
  17952. loading : true,
  17953. active : true,
  17954. },
  17955. progress: {
  17956. active : true,
  17957. success : true,
  17958. warning : true,
  17959. error : true
  17960. }
  17961. },
  17962. states : {
  17963. active : true,
  17964. disabled : true,
  17965. error : true,
  17966. loading : true,
  17967. success : true,
  17968. warning : true
  17969. },
  17970. text : {
  17971. disabled : false,
  17972. flash : false,
  17973. hover : false,
  17974. active : false,
  17975. inactive : false,
  17976. activate : false,
  17977. deactivate : false
  17978. }
  17979. };
  17980. })( jQuery, window , document );
  17981. /*!
  17982. * # Semantic UI 2.0.0 - Visibility
  17983. * http://github.com/semantic-org/semantic-ui/
  17984. *
  17985. *
  17986. * Copyright 2015 Contributors
  17987. * Released under the MIT license
  17988. * http://opensource.org/licenses/MIT
  17989. *
  17990. */
  17991. ;(function ( $, window, document, undefined ) {
  17992. "use strict";
  17993. $.fn.visibility = function(parameters) {
  17994. var
  17995. $allModules = $(this),
  17996. moduleSelector = $allModules.selector || '',
  17997. time = new Date().getTime(),
  17998. performance = [],
  17999. query = arguments[0],
  18000. methodInvoked = (typeof query == 'string'),
  18001. queryArguments = [].slice.call(arguments, 1),
  18002. returnedValue
  18003. ;
  18004. $allModules
  18005. .each(function() {
  18006. var
  18007. settings = ( $.isPlainObject(parameters) )
  18008. ? $.extend(true, {}, $.fn.visibility.settings, parameters)
  18009. : $.extend({}, $.fn.visibility.settings),
  18010. className = settings.className,
  18011. namespace = settings.namespace,
  18012. error = settings.error,
  18013. metadata = settings.metadata,
  18014. eventNamespace = '.' + namespace,
  18015. moduleNamespace = 'module-' + namespace,
  18016. $window = $(window),
  18017. $module = $(this),
  18018. $context = $(settings.context),
  18019. $placeholder,
  18020. selector = $module.selector || '',
  18021. instance = $module.data(moduleNamespace),
  18022. requestAnimationFrame = window.requestAnimationFrame
  18023. || window.mozRequestAnimationFrame
  18024. || window.webkitRequestAnimationFrame
  18025. || window.msRequestAnimationFrame
  18026. || function(callback) { setTimeout(callback, 0); },
  18027. element = this,
  18028. disabled = false,
  18029. observer,
  18030. module
  18031. ;
  18032. module = {
  18033. initialize: function() {
  18034. module.debug('Initializing', settings);
  18035. module.setup.cache();
  18036. if( module.should.trackChanges() ) {
  18037. if(settings.type == 'image') {
  18038. module.setup.image();
  18039. }
  18040. if(settings.type == 'fixed') {
  18041. module.setup.fixed();
  18042. }
  18043. if(settings.observeChanges) {
  18044. module.observeChanges();
  18045. }
  18046. module.bind.events();
  18047. }
  18048. module.save.position();
  18049. if( !module.is.visible() ) {
  18050. module.error(error.visible, $module);
  18051. }
  18052. if(settings.initialCheck) {
  18053. module.checkVisibility();
  18054. }
  18055. module.instantiate();
  18056. },
  18057. instantiate: function() {
  18058. module.debug('Storing instance', module);
  18059. $module
  18060. .data(moduleNamespace, module)
  18061. ;
  18062. instance = module;
  18063. },
  18064. destroy: function() {
  18065. module.verbose('Destroying previous module');
  18066. if(observer) {
  18067. observer.disconnect();
  18068. }
  18069. $window
  18070. .off('load' + eventNamespace, module.event.load)
  18071. .off('resize' + eventNamespace, module.event.resize)
  18072. ;
  18073. $context
  18074. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  18075. ;
  18076. $module
  18077. .off(eventNamespace)
  18078. .removeData(moduleNamespace)
  18079. ;
  18080. },
  18081. observeChanges: function() {
  18082. if('MutationObserver' in window) {
  18083. observer = new MutationObserver(function(mutations) {
  18084. module.verbose('DOM tree modified, updating visibility calculations');
  18085. module.timer = setTimeout(function() {
  18086. module.verbose('DOM tree modified, updating sticky menu');
  18087. module.refresh();
  18088. }, 100);
  18089. });
  18090. observer.observe(element, {
  18091. childList : true,
  18092. subtree : true
  18093. });
  18094. module.debug('Setting up mutation observer', observer);
  18095. }
  18096. },
  18097. bind: {
  18098. events: function() {
  18099. module.verbose('Binding visibility events to scroll and resize');
  18100. if(settings.refreshOnLoad) {
  18101. $window
  18102. .on('load' + eventNamespace, module.event.load)
  18103. ;
  18104. }
  18105. $window
  18106. .on('resize' + eventNamespace, module.event.resize)
  18107. ;
  18108. // pub/sub pattern
  18109. $context
  18110. .off('scroll' + eventNamespace)
  18111. .on('scroll' + eventNamespace, module.event.scroll)
  18112. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  18113. ;
  18114. }
  18115. },
  18116. event: {
  18117. resize: function() {
  18118. module.debug('Window resized');
  18119. if(settings.refreshOnResize) {
  18120. requestAnimationFrame(module.refresh);
  18121. }
  18122. },
  18123. load: function() {
  18124. module.debug('Page finished loading');
  18125. requestAnimationFrame(module.refresh);
  18126. },
  18127. // publishes scrollchange event on one scroll
  18128. scroll: function() {
  18129. if(settings.throttle) {
  18130. clearTimeout(module.timer);
  18131. module.timer = setTimeout(function() {
  18132. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  18133. }, settings.throttle);
  18134. }
  18135. else {
  18136. requestAnimationFrame(function() {
  18137. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  18138. });
  18139. }
  18140. },
  18141. // subscribes to scrollchange
  18142. scrollchange: function(event, scrollPosition) {
  18143. module.checkVisibility(scrollPosition);
  18144. },
  18145. },
  18146. precache: function(images, callback) {
  18147. if (!(images instanceof Array)) {
  18148. images = [images];
  18149. }
  18150. var
  18151. imagesLength = images.length,
  18152. loadedCounter = 0,
  18153. cache = [],
  18154. cacheImage = document.createElement('img'),
  18155. handleLoad = function() {
  18156. loadedCounter++;
  18157. if (loadedCounter >= images.length) {
  18158. if ($.isFunction(callback)) {
  18159. callback();
  18160. }
  18161. }
  18162. }
  18163. ;
  18164. while (imagesLength--) {
  18165. cacheImage = document.createElement('img');
  18166. cacheImage.onload = handleLoad;
  18167. cacheImage.onerror = handleLoad;
  18168. cacheImage.src = images[imagesLength];
  18169. cache.push(cacheImage);
  18170. }
  18171. },
  18172. enableCallbacks: function() {
  18173. module.debug('Allowing callbacks to occur');
  18174. disabled = false;
  18175. },
  18176. disableCallbacks: function() {
  18177. module.debug('Disabling all callbacks temporarily');
  18178. disabled = true;
  18179. },
  18180. should: {
  18181. trackChanges: function() {
  18182. if(methodInvoked) {
  18183. module.debug('One time query, no need to bind events');
  18184. return false;
  18185. }
  18186. module.debug('Callbacks being attached');
  18187. return true;
  18188. }
  18189. },
  18190. setup: {
  18191. cache: function() {
  18192. module.cache = {
  18193. occurred : {},
  18194. screen : {},
  18195. element : {},
  18196. };
  18197. },
  18198. image: function() {
  18199. var
  18200. src = $module.data(metadata.src)
  18201. ;
  18202. if(src) {
  18203. module.verbose('Lazy loading image', src);
  18204. settings.once = true;
  18205. settings.observeChanges = false;
  18206. // show when top visible
  18207. settings.onOnScreen = function() {
  18208. module.debug('Image on screen', element);
  18209. module.precache(src, function() {
  18210. module.set.image(src);
  18211. });
  18212. };
  18213. }
  18214. },
  18215. fixed: function() {
  18216. module.debug('Setting up fixed');
  18217. settings.once = false;
  18218. settings.observeChanges = false;
  18219. settings.initialCheck = true;
  18220. settings.refreshOnLoad = true;
  18221. if(!parameters.transition) {
  18222. settings.transition = false;
  18223. }
  18224. module.create.placeholder();
  18225. module.debug('Added placeholder', $placeholder);
  18226. settings.onTopPassed = function() {
  18227. module.debug('Element passed, adding fixed position', $module);
  18228. module.show.placeholder();
  18229. module.set.fixed();
  18230. if(settings.transition) {
  18231. if($.fn.transition !== undefined) {
  18232. $module.transition(settings.transition, settings.duration);
  18233. }
  18234. }
  18235. };
  18236. settings.onTopPassedReverse = function() {
  18237. module.debug('Element returned to position, removing fixed', $module);
  18238. module.hide.placeholder();
  18239. module.remove.fixed();
  18240. };
  18241. }
  18242. },
  18243. create: {
  18244. placeholder: function() {
  18245. module.verbose('Creating fixed position placeholder');
  18246. $placeholder = $module
  18247. .clone(false)
  18248. .css('display', 'none')
  18249. .addClass(className.placeholder)
  18250. .insertAfter($module)
  18251. ;
  18252. }
  18253. },
  18254. show: {
  18255. placeholder: function() {
  18256. module.verbose('Showing placeholder');
  18257. $placeholder
  18258. .css('display', 'block')
  18259. .css('visibility', 'hidden')
  18260. ;
  18261. }
  18262. },
  18263. hide: {
  18264. placeholder: function() {
  18265. module.verbose('Hiding placeholder');
  18266. $placeholder
  18267. .css('display', 'none')
  18268. .css('visibility', '')
  18269. ;
  18270. }
  18271. },
  18272. set: {
  18273. fixed: function() {
  18274. module.verbose('Setting element to fixed position');
  18275. $module
  18276. .addClass(className.fixed)
  18277. .css({
  18278. position : 'fixed',
  18279. top : settings.offset + 'px',
  18280. left : 'auto',
  18281. zIndex : '1'
  18282. })
  18283. ;
  18284. },
  18285. image: function(src) {
  18286. $module
  18287. .attr('src', src)
  18288. ;
  18289. if(settings.transition) {
  18290. if( $.fn.transition !== undefined ) {
  18291. $module.transition(settings.transition, settings.duration);
  18292. }
  18293. else {
  18294. $module.fadeIn(settings.duration);
  18295. }
  18296. }
  18297. else {
  18298. $module.show();
  18299. }
  18300. }
  18301. },
  18302. is: {
  18303. onScreen: function() {
  18304. var
  18305. calculations = module.get.elementCalculations()
  18306. ;
  18307. return calculations.onScreen;
  18308. },
  18309. offScreen: function() {
  18310. var
  18311. calculations = module.get.elementCalculations()
  18312. ;
  18313. return calculations.offScreen;
  18314. },
  18315. visible: function() {
  18316. if(module.cache && module.cache.element) {
  18317. return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
  18318. }
  18319. return false;
  18320. }
  18321. },
  18322. refresh: function() {
  18323. module.debug('Refreshing constants (width/height)');
  18324. if(settings.type == 'fixed') {
  18325. module.remove.fixed();
  18326. module.remove.occurred();
  18327. }
  18328. module.reset();
  18329. module.save.position();
  18330. if(settings.checkOnRefresh) {
  18331. module.checkVisibility();
  18332. }
  18333. settings.onRefresh.call(element);
  18334. },
  18335. reset: function() {
  18336. module.verbose('Reseting all cached values');
  18337. if( $.isPlainObject(module.cache) ) {
  18338. module.cache.screen = {};
  18339. module.cache.element = {};
  18340. }
  18341. },
  18342. checkVisibility: function(scroll) {
  18343. module.verbose('Checking visibility of element', module.cache.element);
  18344. if( !disabled && module.is.visible() ) {
  18345. // save scroll position
  18346. module.save.scroll(scroll);
  18347. // update calculations derived from scroll
  18348. module.save.calculations();
  18349. // percentage
  18350. module.passed();
  18351. // reverse (must be first)
  18352. module.passingReverse();
  18353. module.topVisibleReverse();
  18354. module.bottomVisibleReverse();
  18355. module.topPassedReverse();
  18356. module.bottomPassedReverse();
  18357. // one time
  18358. module.onScreen();
  18359. module.offScreen();
  18360. module.passing();
  18361. module.topVisible();
  18362. module.bottomVisible();
  18363. module.topPassed();
  18364. module.bottomPassed();
  18365. // on update callback
  18366. if(settings.onUpdate) {
  18367. settings.onUpdate.call(element, module.get.elementCalculations());
  18368. }
  18369. }
  18370. },
  18371. passed: function(amount, newCallback) {
  18372. var
  18373. calculations = module.get.elementCalculations(),
  18374. amountInPixels
  18375. ;
  18376. // assign callback
  18377. if(amount && newCallback) {
  18378. settings.onPassed[amount] = newCallback;
  18379. }
  18380. else if(amount !== undefined) {
  18381. return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
  18382. }
  18383. else if(calculations.passing) {
  18384. $.each(settings.onPassed, function(amount, callback) {
  18385. if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
  18386. module.execute(callback, amount);
  18387. }
  18388. else if(!settings.once) {
  18389. module.remove.occurred(callback);
  18390. }
  18391. });
  18392. }
  18393. },
  18394. onScreen: function(newCallback) {
  18395. var
  18396. calculations = module.get.elementCalculations(),
  18397. callback = newCallback || settings.onOnScreen,
  18398. callbackName = 'onScreen'
  18399. ;
  18400. if(newCallback) {
  18401. module.debug('Adding callback for onScreen', newCallback);
  18402. settings.onOnScreen = newCallback;
  18403. }
  18404. if(calculations.onScreen) {
  18405. module.execute(callback, callbackName);
  18406. }
  18407. else if(!settings.once) {
  18408. module.remove.occurred(callbackName);
  18409. }
  18410. if(newCallback !== undefined) {
  18411. return calculations.onOnScreen;
  18412. }
  18413. },
  18414. offScreen: function(newCallback) {
  18415. var
  18416. calculations = module.get.elementCalculations(),
  18417. callback = newCallback || settings.onOffScreen,
  18418. callbackName = 'offScreen'
  18419. ;
  18420. if(newCallback) {
  18421. module.debug('Adding callback for offScreen', newCallback);
  18422. settings.onOffScreen = newCallback;
  18423. }
  18424. if(calculations.offScreen) {
  18425. module.execute(callback, callbackName);
  18426. }
  18427. else if(!settings.once) {
  18428. module.remove.occurred(callbackName);
  18429. }
  18430. if(newCallback !== undefined) {
  18431. return calculations.onOffScreen;
  18432. }
  18433. },
  18434. passing: function(newCallback) {
  18435. var
  18436. calculations = module.get.elementCalculations(),
  18437. callback = newCallback || settings.onPassing,
  18438. callbackName = 'passing'
  18439. ;
  18440. if(newCallback) {
  18441. module.debug('Adding callback for passing', newCallback);
  18442. settings.onPassing = newCallback;
  18443. }
  18444. if(calculations.passing) {
  18445. module.execute(callback, callbackName);
  18446. }
  18447. else if(!settings.once) {
  18448. module.remove.occurred(callbackName);
  18449. }
  18450. if(newCallback !== undefined) {
  18451. return calculations.passing;
  18452. }
  18453. },
  18454. topVisible: function(newCallback) {
  18455. var
  18456. calculations = module.get.elementCalculations(),
  18457. callback = newCallback || settings.onTopVisible,
  18458. callbackName = 'topVisible'
  18459. ;
  18460. if(newCallback) {
  18461. module.debug('Adding callback for top visible', newCallback);
  18462. settings.onTopVisible = newCallback;
  18463. }
  18464. if(calculations.topVisible) {
  18465. module.execute(callback, callbackName);
  18466. }
  18467. else if(!settings.once) {
  18468. module.remove.occurred(callbackName);
  18469. }
  18470. if(newCallback === undefined) {
  18471. return calculations.topVisible;
  18472. }
  18473. },
  18474. bottomVisible: function(newCallback) {
  18475. var
  18476. calculations = module.get.elementCalculations(),
  18477. callback = newCallback || settings.onBottomVisible,
  18478. callbackName = 'bottomVisible'
  18479. ;
  18480. if(newCallback) {
  18481. module.debug('Adding callback for bottom visible', newCallback);
  18482. settings.onBottomVisible = newCallback;
  18483. }
  18484. if(calculations.bottomVisible) {
  18485. module.execute(callback, callbackName);
  18486. }
  18487. else if(!settings.once) {
  18488. module.remove.occurred(callbackName);
  18489. }
  18490. if(newCallback === undefined) {
  18491. return calculations.bottomVisible;
  18492. }
  18493. },
  18494. topPassed: function(newCallback) {
  18495. var
  18496. calculations = module.get.elementCalculations(),
  18497. callback = newCallback || settings.onTopPassed,
  18498. callbackName = 'topPassed'
  18499. ;
  18500. if(newCallback) {
  18501. module.debug('Adding callback for top passed', newCallback);
  18502. settings.onTopPassed = newCallback;
  18503. }
  18504. if(calculations.topPassed) {
  18505. module.execute(callback, callbackName);
  18506. }
  18507. else if(!settings.once) {
  18508. module.remove.occurred(callbackName);
  18509. }
  18510. if(newCallback === undefined) {
  18511. return calculations.topPassed;
  18512. }
  18513. },
  18514. bottomPassed: function(newCallback) {
  18515. var
  18516. calculations = module.get.elementCalculations(),
  18517. callback = newCallback || settings.onBottomPassed,
  18518. callbackName = 'bottomPassed'
  18519. ;
  18520. if(newCallback) {
  18521. module.debug('Adding callback for bottom passed', newCallback);
  18522. settings.onBottomPassed = newCallback;
  18523. }
  18524. if(calculations.bottomPassed) {
  18525. module.execute(callback, callbackName);
  18526. }
  18527. else if(!settings.once) {
  18528. module.remove.occurred(callbackName);
  18529. }
  18530. if(newCallback === undefined) {
  18531. return calculations.bottomPassed;
  18532. }
  18533. },
  18534. passingReverse: function(newCallback) {
  18535. var
  18536. calculations = module.get.elementCalculations(),
  18537. callback = newCallback || settings.onPassingReverse,
  18538. callbackName = 'passingReverse'
  18539. ;
  18540. if(newCallback) {
  18541. module.debug('Adding callback for passing reverse', newCallback);
  18542. settings.onPassingReverse = newCallback;
  18543. }
  18544. if(!calculations.passing) {
  18545. if(module.get.occurred('passing')) {
  18546. module.execute(callback, callbackName);
  18547. }
  18548. }
  18549. else if(!settings.once) {
  18550. module.remove.occurred(callbackName);
  18551. }
  18552. if(newCallback !== undefined) {
  18553. return !calculations.passing;
  18554. }
  18555. },
  18556. topVisibleReverse: function(newCallback) {
  18557. var
  18558. calculations = module.get.elementCalculations(),
  18559. callback = newCallback || settings.onTopVisibleReverse,
  18560. callbackName = 'topVisibleReverse'
  18561. ;
  18562. if(newCallback) {
  18563. module.debug('Adding callback for top visible reverse', newCallback);
  18564. settings.onTopVisibleReverse = newCallback;
  18565. }
  18566. if(!calculations.topVisible) {
  18567. if(module.get.occurred('topVisible')) {
  18568. module.execute(callback, callbackName);
  18569. }
  18570. }
  18571. else if(!settings.once) {
  18572. module.remove.occurred(callbackName);
  18573. }
  18574. if(newCallback === undefined) {
  18575. return !calculations.topVisible;
  18576. }
  18577. },
  18578. bottomVisibleReverse: function(newCallback) {
  18579. var
  18580. calculations = module.get.elementCalculations(),
  18581. callback = newCallback || settings.onBottomVisibleReverse,
  18582. callbackName = 'bottomVisibleReverse'
  18583. ;
  18584. if(newCallback) {
  18585. module.debug('Adding callback for bottom visible reverse', newCallback);
  18586. settings.onBottomVisibleReverse = newCallback;
  18587. }
  18588. if(!calculations.bottomVisible) {
  18589. if(module.get.occurred('bottomVisible')) {
  18590. module.execute(callback, callbackName);
  18591. }
  18592. }
  18593. else if(!settings.once) {
  18594. module.remove.occurred(callbackName);
  18595. }
  18596. if(newCallback === undefined) {
  18597. return !calculations.bottomVisible;
  18598. }
  18599. },
  18600. topPassedReverse: function(newCallback) {
  18601. var
  18602. calculations = module.get.elementCalculations(),
  18603. callback = newCallback || settings.onTopPassedReverse,
  18604. callbackName = 'topPassedReverse'
  18605. ;
  18606. if(newCallback) {
  18607. module.debug('Adding callback for top passed reverse', newCallback);
  18608. settings.onTopPassedReverse = newCallback;
  18609. }
  18610. if(!calculations.topPassed) {
  18611. if(module.get.occurred('topPassed')) {
  18612. module.execute(callback, callbackName);
  18613. }
  18614. }
  18615. else if(!settings.once) {
  18616. module.remove.occurred(callbackName);
  18617. }
  18618. if(newCallback === undefined) {
  18619. return !calculations.onTopPassed;
  18620. }
  18621. },
  18622. bottomPassedReverse: function(newCallback) {
  18623. var
  18624. calculations = module.get.elementCalculations(),
  18625. callback = newCallback || settings.onBottomPassedReverse,
  18626. callbackName = 'bottomPassedReverse'
  18627. ;
  18628. if(newCallback) {
  18629. module.debug('Adding callback for bottom passed reverse', newCallback);
  18630. settings.onBottomPassedReverse = newCallback;
  18631. }
  18632. if(!calculations.bottomPassed) {
  18633. if(module.get.occurred('bottomPassed')) {
  18634. module.execute(callback, callbackName);
  18635. }
  18636. }
  18637. else if(!settings.once) {
  18638. module.remove.occurred(callbackName);
  18639. }
  18640. if(newCallback === undefined) {
  18641. return !calculations.bottomPassed;
  18642. }
  18643. },
  18644. execute: function(callback, callbackName) {
  18645. var
  18646. calculations = module.get.elementCalculations(),
  18647. screen = module.get.screenCalculations()
  18648. ;
  18649. callback = callback || false;
  18650. if(callback) {
  18651. if(settings.continuous) {
  18652. module.debug('Callback being called continuously', callbackName, calculations);
  18653. callback.call(element, calculations, screen);
  18654. }
  18655. else if(!module.get.occurred(callbackName)) {
  18656. module.debug('Conditions met', callbackName, calculations);
  18657. callback.call(element, calculations, screen);
  18658. }
  18659. }
  18660. module.save.occurred(callbackName);
  18661. },
  18662. remove: {
  18663. fixed: function() {
  18664. module.debug('Removing fixed position');
  18665. $module
  18666. .removeClass(className.fixed)
  18667. .css({
  18668. position : '',
  18669. top : '',
  18670. left : '',
  18671. zIndex : ''
  18672. })
  18673. ;
  18674. },
  18675. occurred: function(callback) {
  18676. if(callback) {
  18677. var
  18678. occurred = module.cache.occurred
  18679. ;
  18680. if(occurred[callback] !== undefined && occurred[callback] === true) {
  18681. module.debug('Callback can now be called again', callback);
  18682. module.cache.occurred[callback] = false;
  18683. }
  18684. }
  18685. else {
  18686. module.cache.occurred = {};
  18687. }
  18688. }
  18689. },
  18690. save: {
  18691. calculations: function() {
  18692. module.verbose('Saving all calculations necessary to determine positioning');
  18693. module.save.direction();
  18694. module.save.screenCalculations();
  18695. module.save.elementCalculations();
  18696. },
  18697. occurred: function(callback) {
  18698. if(callback) {
  18699. if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
  18700. module.verbose('Saving callback occurred', callback);
  18701. module.cache.occurred[callback] = true;
  18702. }
  18703. }
  18704. },
  18705. scroll: function(scrollPosition) {
  18706. scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
  18707. module.cache.scroll = scrollPosition;
  18708. },
  18709. direction: function() {
  18710. var
  18711. scroll = module.get.scroll(),
  18712. lastScroll = module.get.lastScroll(),
  18713. direction
  18714. ;
  18715. if(scroll > lastScroll && lastScroll) {
  18716. direction = 'down';
  18717. }
  18718. else if(scroll < lastScroll && lastScroll) {
  18719. direction = 'up';
  18720. }
  18721. else {
  18722. direction = 'static';
  18723. }
  18724. module.cache.direction = direction;
  18725. return module.cache.direction;
  18726. },
  18727. elementPosition: function() {
  18728. var
  18729. element = module.cache.element,
  18730. screen = module.get.screenSize()
  18731. ;
  18732. module.verbose('Saving element position');
  18733. // (quicker than $.extend)
  18734. element.fits = (element.height < screen.height);
  18735. element.offset = $module.offset();
  18736. element.width = $module.outerWidth();
  18737. element.height = $module.outerHeight();
  18738. // store
  18739. module.cache.element = element;
  18740. return element;
  18741. },
  18742. elementCalculations: function() {
  18743. var
  18744. screen = module.get.screenCalculations(),
  18745. element = module.get.elementPosition()
  18746. ;
  18747. // offset
  18748. if(settings.includeMargin) {
  18749. element.margin = {};
  18750. element.margin.top = parseInt($module.css('margin-top'), 10);
  18751. element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
  18752. element.top = element.offset.top - element.margin.top;
  18753. element.bottom = element.offset.top + element.height + element.margin.bottom;
  18754. }
  18755. else {
  18756. element.top = element.offset.top;
  18757. element.bottom = element.offset.top + element.height;
  18758. }
  18759. // visibility
  18760. element.topVisible = (screen.bottom >= element.top);
  18761. element.topPassed = (screen.top >= element.top);
  18762. element.bottomVisible = (screen.bottom >= element.bottom);
  18763. element.bottomPassed = (screen.top >= element.bottom);
  18764. element.pixelsPassed = 0;
  18765. element.percentagePassed = 0;
  18766. // meta calculations
  18767. element.onScreen = (element.topVisible && !element.bottomPassed);
  18768. element.passing = (element.topPassed && !element.bottomPassed);
  18769. element.offScreen = (!element.onScreen);
  18770. // passing calculations
  18771. if(element.passing) {
  18772. element.pixelsPassed = (screen.top - element.top);
  18773. element.percentagePassed = (screen.top - element.top) / element.height;
  18774. }
  18775. module.cache.element = element;
  18776. module.verbose('Updated element calculations', element);
  18777. return element;
  18778. },
  18779. screenCalculations: function() {
  18780. var
  18781. scroll = module.get.scroll()
  18782. ;
  18783. module.save.direction();
  18784. module.cache.screen.top = scroll;
  18785. module.cache.screen.bottom = scroll + module.cache.screen.height;
  18786. return module.cache.screen;
  18787. },
  18788. screenSize: function() {
  18789. module.verbose('Saving window position');
  18790. module.cache.screen = {
  18791. height: $context.height()
  18792. };
  18793. },
  18794. position: function() {
  18795. module.save.screenSize();
  18796. module.save.elementPosition();
  18797. }
  18798. },
  18799. get: {
  18800. pixelsPassed: function(amount) {
  18801. var
  18802. element = module.get.elementCalculations()
  18803. ;
  18804. if(amount.search('%') > -1) {
  18805. return ( element.height * (parseInt(amount, 10) / 100) );
  18806. }
  18807. return parseInt(amount, 10);
  18808. },
  18809. occurred: function(callback) {
  18810. return (module.cache.occurred !== undefined)
  18811. ? module.cache.occurred[callback] || false
  18812. : false
  18813. ;
  18814. },
  18815. direction: function() {
  18816. if(module.cache.direction === undefined) {
  18817. module.save.direction();
  18818. }
  18819. return module.cache.direction;
  18820. },
  18821. elementPosition: function() {
  18822. if(module.cache.element === undefined) {
  18823. module.save.elementPosition();
  18824. }
  18825. return module.cache.element;
  18826. },
  18827. elementCalculations: function() {
  18828. if(module.cache.element === undefined) {
  18829. module.save.elementCalculations();
  18830. }
  18831. return module.cache.element;
  18832. },
  18833. screenCalculations: function() {
  18834. if(module.cache.screen === undefined) {
  18835. module.save.screenCalculations();
  18836. }
  18837. return module.cache.screen;
  18838. },
  18839. screenSize: function() {
  18840. if(module.cache.screen === undefined) {
  18841. module.save.screenSize();
  18842. }
  18843. return module.cache.screen;
  18844. },
  18845. scroll: function() {
  18846. if(module.cache.scroll === undefined) {
  18847. module.save.scroll();
  18848. }
  18849. return module.cache.scroll;
  18850. },
  18851. lastScroll: function() {
  18852. if(module.cache.screen === undefined) {
  18853. module.debug('First scroll event, no last scroll could be found');
  18854. return false;
  18855. }
  18856. return module.cache.screen.top;
  18857. }
  18858. },
  18859. setting: function(name, value) {
  18860. if( $.isPlainObject(name) ) {
  18861. $.extend(true, settings, name);
  18862. }
  18863. else if(value !== undefined) {
  18864. settings[name] = value;
  18865. }
  18866. else {
  18867. return settings[name];
  18868. }
  18869. },
  18870. internal: function(name, value) {
  18871. if( $.isPlainObject(name) ) {
  18872. $.extend(true, module, name);
  18873. }
  18874. else if(value !== undefined) {
  18875. module[name] = value;
  18876. }
  18877. else {
  18878. return module[name];
  18879. }
  18880. },
  18881. debug: function() {
  18882. if(settings.debug) {
  18883. if(settings.performance) {
  18884. module.performance.log(arguments);
  18885. }
  18886. else {
  18887. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18888. module.debug.apply(console, arguments);
  18889. }
  18890. }
  18891. },
  18892. verbose: function() {
  18893. if(settings.verbose && settings.debug) {
  18894. if(settings.performance) {
  18895. module.performance.log(arguments);
  18896. }
  18897. else {
  18898. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18899. module.verbose.apply(console, arguments);
  18900. }
  18901. }
  18902. },
  18903. error: function() {
  18904. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  18905. module.error.apply(console, arguments);
  18906. },
  18907. performance: {
  18908. log: function(message) {
  18909. var
  18910. currentTime,
  18911. executionTime,
  18912. previousTime
  18913. ;
  18914. if(settings.performance) {
  18915. currentTime = new Date().getTime();
  18916. previousTime = time || currentTime;
  18917. executionTime = currentTime - previousTime;
  18918. time = currentTime;
  18919. performance.push({
  18920. 'Name' : message[0],
  18921. 'Arguments' : [].slice.call(message, 1) || '',
  18922. 'Element' : element,
  18923. 'Execution Time' : executionTime
  18924. });
  18925. }
  18926. clearTimeout(module.performance.timer);
  18927. module.performance.timer = setTimeout(module.performance.display, 500);
  18928. },
  18929. display: function() {
  18930. var
  18931. title = settings.name + ':',
  18932. totalTime = 0
  18933. ;
  18934. time = false;
  18935. clearTimeout(module.performance.timer);
  18936. $.each(performance, function(index, data) {
  18937. totalTime += data['Execution Time'];
  18938. });
  18939. title += ' ' + totalTime + 'ms';
  18940. if(moduleSelector) {
  18941. title += ' \'' + moduleSelector + '\'';
  18942. }
  18943. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  18944. console.groupCollapsed(title);
  18945. if(console.table) {
  18946. console.table(performance);
  18947. }
  18948. else {
  18949. $.each(performance, function(index, data) {
  18950. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  18951. });
  18952. }
  18953. console.groupEnd();
  18954. }
  18955. performance = [];
  18956. }
  18957. },
  18958. invoke: function(query, passedArguments, context) {
  18959. var
  18960. object = instance,
  18961. maxDepth,
  18962. found,
  18963. response
  18964. ;
  18965. passedArguments = passedArguments || queryArguments;
  18966. context = element || context;
  18967. if(typeof query == 'string' && object !== undefined) {
  18968. query = query.split(/[\. ]/);
  18969. maxDepth = query.length - 1;
  18970. $.each(query, function(depth, value) {
  18971. var camelCaseValue = (depth != maxDepth)
  18972. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  18973. : query
  18974. ;
  18975. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  18976. object = object[camelCaseValue];
  18977. }
  18978. else if( object[camelCaseValue] !== undefined ) {
  18979. found = object[camelCaseValue];
  18980. return false;
  18981. }
  18982. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  18983. object = object[value];
  18984. }
  18985. else if( object[value] !== undefined ) {
  18986. found = object[value];
  18987. return false;
  18988. }
  18989. else {
  18990. module.error(error.method, query);
  18991. return false;
  18992. }
  18993. });
  18994. }
  18995. if ( $.isFunction( found ) ) {
  18996. response = found.apply(context, passedArguments);
  18997. }
  18998. else if(found !== undefined) {
  18999. response = found;
  19000. }
  19001. if($.isArray(returnedValue)) {
  19002. returnedValue.push(response);
  19003. }
  19004. else if(returnedValue !== undefined) {
  19005. returnedValue = [returnedValue, response];
  19006. }
  19007. else if(response !== undefined) {
  19008. returnedValue = response;
  19009. }
  19010. return found;
  19011. }
  19012. };
  19013. if(methodInvoked) {
  19014. if(instance === undefined) {
  19015. module.initialize();
  19016. }
  19017. instance.save.scroll();
  19018. instance.save.calculations();
  19019. module.invoke(query);
  19020. }
  19021. else {
  19022. if(instance !== undefined) {
  19023. instance.invoke('destroy');
  19024. }
  19025. module.initialize();
  19026. }
  19027. })
  19028. ;
  19029. return (returnedValue !== undefined)
  19030. ? returnedValue
  19031. : this
  19032. ;
  19033. };
  19034. $.fn.visibility.settings = {
  19035. name : 'Visibility',
  19036. namespace : 'visibility',
  19037. debug : false,
  19038. verbose : false,
  19039. performance : true,
  19040. // whether to use mutation observers to follow changes
  19041. observeChanges : true,
  19042. // whether to refresh calculations after all page images load
  19043. refreshOnLoad : true,
  19044. // callback should only occur one time
  19045. once : true,
  19046. // callback should fire continuously whe evaluates to true
  19047. continuous : false,
  19048. // offset to use with scroll top
  19049. offset : 0,
  19050. // whether to include margin in elements position
  19051. includeMargin : false,
  19052. // scroll context for visibility checks
  19053. context : window,
  19054. // check position immediately on init
  19055. initialCheck : true,
  19056. // visibility check delay in ms (defaults to animationFrame)
  19057. throttle : false,
  19058. // special visibility type (image, fixed)
  19059. type : false,
  19060. // image only animation settings
  19061. transition : 'fade in',
  19062. duration : 1000,
  19063. // array of callbacks for percentage
  19064. onPassed : {},
  19065. // should call callbacks on refresh event (resize, etc)
  19066. checkOnRefresh : true,
  19067. // standard callbacks
  19068. onOnScreen : false,
  19069. onOffScreen : false,
  19070. onPassing : false,
  19071. onTopVisible : false,
  19072. onBottomVisible : false,
  19073. onTopPassed : false,
  19074. onBottomPassed : false,
  19075. // reverse callbacks
  19076. onPassingReverse : false,
  19077. onTopVisibleReverse : false,
  19078. onBottomVisibleReverse : false,
  19079. onTopPassedReverse : false,
  19080. onBottomPassedReverse : false,
  19081. // utility callbacks
  19082. onUpdate : false, // disabled by default for performance
  19083. onRefresh : function(){},
  19084. metadata : {
  19085. src: 'src'
  19086. },
  19087. className: {
  19088. fixed : 'fixed',
  19089. placeholder : 'placeholder'
  19090. },
  19091. error : {
  19092. method : 'The method you called is not defined.',
  19093. visible : 'Element is hidden, you must call refresh after element becomes visible'
  19094. }
  19095. };
  19096. })( jQuery, window , document );