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.

21429 lines
676 KiB

  1. /*
  2. * # Semantic UI - 2.1.6
  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.1.6 - 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, normalizing 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.1.6 - 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. return;
  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. bracketedRule: function(rule) {
  671. return (rule.type && rule.type.match(settings.regExp.bracket));
  672. },
  673. valid: function() {
  674. var
  675. allValid = true
  676. ;
  677. module.verbose('Checking if form is valid');
  678. $.each(validation, function(fieldName, field) {
  679. if( !( module.validate.field(field, fieldName) ) ) {
  680. allValid = false;
  681. }
  682. });
  683. return allValid;
  684. }
  685. },
  686. removeEvents: function() {
  687. $module
  688. .off(eventNamespace)
  689. ;
  690. $field
  691. .off(eventNamespace)
  692. ;
  693. $submit
  694. .off(eventNamespace)
  695. ;
  696. $field
  697. .off(eventNamespace)
  698. ;
  699. },
  700. event: {
  701. field: {
  702. keydown: function(event) {
  703. var
  704. $field = $(this),
  705. key = event.which,
  706. keyCode = {
  707. enter : 13,
  708. escape : 27
  709. }
  710. ;
  711. if( key == keyCode.escape) {
  712. module.verbose('Escape key pressed blurring field');
  713. $field
  714. .blur()
  715. ;
  716. }
  717. if(!event.ctrlKey && key == keyCode.enter && $field.is(selector.input) && $field.not(selector.checkbox).length > 0 ) {
  718. if(!keyHeldDown) {
  719. $field
  720. .one('keyup' + eventNamespace, module.event.field.keyup)
  721. ;
  722. module.submit();
  723. module.debug('Enter pressed on input submitting form');
  724. }
  725. keyHeldDown = true;
  726. }
  727. },
  728. keyup: function() {
  729. keyHeldDown = false;
  730. },
  731. blur: function(event) {
  732. var
  733. $field = $(this),
  734. $fieldGroup = $field.closest($group),
  735. validationRules = module.get.validation($field)
  736. ;
  737. if( $fieldGroup.hasClass(className.error) ) {
  738. module.debug('Revalidating field', $field, validationRules);
  739. module.validate.form.call(module, event, true);
  740. }
  741. else if(settings.on == 'blur' || settings.on == 'change') {
  742. if(validationRules) {
  743. module.validate.field( validationRules );
  744. }
  745. }
  746. },
  747. change: function(event) {
  748. var
  749. $field = $(this),
  750. $fieldGroup = $field.closest($group)
  751. ;
  752. if(settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) ) {
  753. clearTimeout(module.timer);
  754. module.timer = setTimeout(function() {
  755. module.debug('Revalidating field', $field, module.get.validation($field));
  756. module.validate.form.call(module, event, true);
  757. }, settings.delay);
  758. }
  759. }
  760. }
  761. },
  762. get: {
  763. ancillaryValue: function(rule) {
  764. if(!rule.type || !module.is.bracketedRule(rule)) {
  765. return false;
  766. }
  767. return rule.type.match(settings.regExp.bracket)[1] + '';
  768. },
  769. ruleName: function(rule) {
  770. if( module.is.bracketedRule(rule) ) {
  771. return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
  772. }
  773. return rule.type;
  774. },
  775. changeEvent: function(type, $input) {
  776. if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
  777. return 'change';
  778. }
  779. else {
  780. return module.get.inputEvent();
  781. }
  782. },
  783. inputEvent: function() {
  784. return (document.createElement('input').oninput !== undefined)
  785. ? 'input'
  786. : (document.createElement('input').onpropertychange !== undefined)
  787. ? 'propertychange'
  788. : 'keyup'
  789. ;
  790. },
  791. prompt: function(rule, field) {
  792. var
  793. ruleName = module.get.ruleName(rule),
  794. ancillary = module.get.ancillaryValue(rule),
  795. prompt = rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
  796. requiresValue = (prompt.search('{value}') !== -1),
  797. requiresName = (prompt.search('{name}') !== -1),
  798. $label,
  799. $field,
  800. name
  801. ;
  802. if(requiresName || requiresValue) {
  803. $field = module.get.field(field.identifier);
  804. }
  805. if(requiresValue) {
  806. prompt = prompt.replace('{value}', $field.val());
  807. }
  808. if(requiresName) {
  809. $label = $field.closest(selector.group).find('label').eq(0);
  810. name = ($label.size() == 1)
  811. ? $label.text()
  812. : $field.prop('placeholder') || settings.text.unspecifiedField
  813. ;
  814. prompt = prompt.replace('{name}', name);
  815. }
  816. prompt = prompt.replace('{identifier}', field.identifier);
  817. prompt = prompt.replace('{ruleValue}', ancillary);
  818. if(!rule.prompt) {
  819. module.verbose('Using default validation prompt for type', prompt, ruleName);
  820. }
  821. return prompt;
  822. },
  823. settings: function() {
  824. if($.isPlainObject(parameters)) {
  825. var
  826. keys = Object.keys(parameters),
  827. isLegacySettings = (keys.length > 0)
  828. ? (parameters[keys[0]].identifier !== undefined && parameters[keys[0]].rules !== undefined)
  829. : false,
  830. ruleKeys
  831. ;
  832. if(isLegacySettings) {
  833. // 1.x (ducktyped)
  834. settings = $.extend(true, {}, $.fn.form.settings, legacyParameters);
  835. validation = $.extend({}, $.fn.form.settings.defaults, parameters);
  836. module.error(settings.error.oldSyntax, element);
  837. module.verbose('Extending settings from legacy parameters', validation, settings);
  838. }
  839. else {
  840. // 2.x
  841. if(parameters.fields) {
  842. ruleKeys = Object.keys(parameters.fields);
  843. if( typeof parameters.fields[ruleKeys[0]] == 'string' || $.isArray(parameters.fields[ruleKeys[0]]) ) {
  844. $.each(parameters.fields, function(name, rules) {
  845. if(typeof rules == 'string') {
  846. rules = [rules];
  847. }
  848. parameters.fields[name] = {
  849. rules: []
  850. };
  851. $.each(rules, function(index, rule) {
  852. parameters.fields[name].rules.push({ type: rule });
  853. });
  854. });
  855. }
  856. }
  857. settings = $.extend(true, {}, $.fn.form.settings, parameters);
  858. validation = $.extend({}, $.fn.form.settings.defaults, settings.fields);
  859. module.verbose('Extending settings', validation, settings);
  860. }
  861. }
  862. else {
  863. settings = $.fn.form.settings;
  864. validation = $.fn.form.settings.defaults;
  865. module.verbose('Using default form validation', validation, settings);
  866. }
  867. // shorthand
  868. namespace = settings.namespace;
  869. metadata = settings.metadata;
  870. selector = settings.selector;
  871. className = settings.className;
  872. error = settings.error;
  873. moduleNamespace = 'module-' + namespace;
  874. eventNamespace = '.' + namespace;
  875. // grab instance
  876. instance = $module.data(moduleNamespace);
  877. // refresh selector cache
  878. module.refresh();
  879. },
  880. field: function(identifier) {
  881. module.verbose('Finding field with identifier', identifier);
  882. if( $field.filter('#' + identifier).length > 0 ) {
  883. return $field.filter('#' + identifier);
  884. }
  885. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  886. return $field.filter('[name="' + identifier +'"]');
  887. }
  888. else if( $field.filter('[name="' + identifier +'[]"]').length > 0 ) {
  889. return $field.filter('[name="' + identifier +'[]"]');
  890. }
  891. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  892. return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]');
  893. }
  894. return $('<input/>');
  895. },
  896. fields: function(fields) {
  897. var
  898. $fields = $()
  899. ;
  900. $.each(fields, function(index, name) {
  901. $fields = $fields.add( module.get.field(name) );
  902. });
  903. return $fields;
  904. },
  905. validation: function($field) {
  906. var
  907. fieldValidation,
  908. identifier
  909. ;
  910. if(!validation) {
  911. return false;
  912. }
  913. $.each(validation, function(fieldName, field) {
  914. identifier = field.identifier || fieldName;
  915. if( module.get.field(identifier)[0] == $field[0] ) {
  916. field.identifier = identifier;
  917. fieldValidation = field;
  918. }
  919. });
  920. return fieldValidation || false;
  921. },
  922. value: function (field) {
  923. var
  924. fields = [],
  925. results
  926. ;
  927. fields.push(field);
  928. results = module.get.values.call(element, fields);
  929. return results[field];
  930. },
  931. values: function (fields) {
  932. var
  933. $fields = $.isArray(fields)
  934. ? module.get.fields(fields)
  935. : $field,
  936. values = {}
  937. ;
  938. $fields.each(function(index, field) {
  939. var
  940. $field = $(field),
  941. type = $field.prop('type'),
  942. name = $field.prop('name'),
  943. value = $field.val(),
  944. isCheckbox = $field.is(selector.checkbox),
  945. isRadio = $field.is(selector.radio),
  946. isMultiple = (name.indexOf('[]') !== -1),
  947. isChecked = (isCheckbox)
  948. ? $field.is(':checked')
  949. : false
  950. ;
  951. if(name) {
  952. if(isMultiple) {
  953. name = name.replace('[]', '');
  954. if(!values[name]) {
  955. values[name] = [];
  956. }
  957. if(isCheckbox) {
  958. if(isChecked) {
  959. values[name].push(value || true);
  960. }
  961. else {
  962. values[name].push(false);
  963. }
  964. }
  965. else {
  966. values[name].push(value);
  967. }
  968. }
  969. else {
  970. if(isRadio) {
  971. if(isChecked) {
  972. values[name] = value;
  973. }
  974. }
  975. else if(isCheckbox) {
  976. if(isChecked) {
  977. values[name] = value || true;
  978. }
  979. else {
  980. values[name] = false;
  981. }
  982. }
  983. else {
  984. values[name] = value;
  985. }
  986. }
  987. }
  988. });
  989. return values;
  990. }
  991. },
  992. has: {
  993. field: function(identifier) {
  994. module.verbose('Checking for existence of a field with identifier', identifier);
  995. if(typeof identifier !== 'string') {
  996. module.error(error.identifier, identifier);
  997. }
  998. if( $field.filter('#' + identifier).length > 0 ) {
  999. return true;
  1000. }
  1001. else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
  1002. return true;
  1003. }
  1004. else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').length > 0 ) {
  1005. return true;
  1006. }
  1007. return false;
  1008. }
  1009. },
  1010. add: {
  1011. prompt: function(identifier, errors) {
  1012. var
  1013. $field = module.get.field(identifier),
  1014. $fieldGroup = $field.closest($group),
  1015. $prompt = $fieldGroup.children(selector.prompt),
  1016. promptExists = ($prompt.length !== 0)
  1017. ;
  1018. errors = (typeof errors == 'string')
  1019. ? [errors]
  1020. : errors
  1021. ;
  1022. module.verbose('Adding field error state', identifier);
  1023. $fieldGroup
  1024. .addClass(className.error)
  1025. ;
  1026. if(settings.inline) {
  1027. if(!promptExists) {
  1028. $prompt = settings.templates.prompt(errors);
  1029. $prompt
  1030. .appendTo($fieldGroup)
  1031. ;
  1032. }
  1033. $prompt
  1034. .html(errors[0])
  1035. ;
  1036. if(!promptExists) {
  1037. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  1038. module.verbose('Displaying error with css transition', settings.transition);
  1039. $prompt.transition(settings.transition + ' in', settings.duration);
  1040. }
  1041. else {
  1042. module.verbose('Displaying error with fallback javascript animation');
  1043. $prompt
  1044. .fadeIn(settings.duration)
  1045. ;
  1046. }
  1047. }
  1048. else {
  1049. module.verbose('Inline errors are disabled, no inline error added', identifier);
  1050. }
  1051. }
  1052. },
  1053. errors: function(errors) {
  1054. module.debug('Adding form error messages', errors);
  1055. module.set.error();
  1056. $message
  1057. .html( settings.templates.error(errors) )
  1058. ;
  1059. }
  1060. },
  1061. remove: {
  1062. prompt: function(identifier) {
  1063. var
  1064. $field = module.get.field(identifier),
  1065. $fieldGroup = $field.closest($group),
  1066. $prompt = $fieldGroup.children(selector.prompt)
  1067. ;
  1068. $fieldGroup
  1069. .removeClass(className.error)
  1070. ;
  1071. if(settings.inline && $prompt.is(':visible')) {
  1072. module.verbose('Removing prompt for field', identifier);
  1073. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  1074. $prompt.transition(settings.transition + ' out', settings.duration, function() {
  1075. $prompt.remove();
  1076. });
  1077. }
  1078. else {
  1079. $prompt
  1080. .fadeOut(settings.duration, function(){
  1081. $prompt.remove();
  1082. })
  1083. ;
  1084. }
  1085. }
  1086. }
  1087. },
  1088. set: {
  1089. success: function() {
  1090. $module
  1091. .removeClass(className.error)
  1092. .addClass(className.success)
  1093. ;
  1094. },
  1095. defaults: function () {
  1096. $field
  1097. .each(function () {
  1098. var
  1099. $field = $(this),
  1100. isCheckbox = ($field.filter(selector.checkbox).length > 0),
  1101. value = (isCheckbox)
  1102. ? $field.is(':checked')
  1103. : $field.val()
  1104. ;
  1105. $field.data(metadata.defaultValue, value);
  1106. })
  1107. ;
  1108. },
  1109. error: function() {
  1110. $module
  1111. .removeClass(className.success)
  1112. .addClass(className.error)
  1113. ;
  1114. },
  1115. value: function (field, value) {
  1116. var
  1117. fields = {}
  1118. ;
  1119. fields[field] = value;
  1120. return module.set.values.call(element, fields);
  1121. },
  1122. values: function (fields) {
  1123. if($.isEmptyObject(fields)) {
  1124. return;
  1125. }
  1126. $.each(fields, function(key, value) {
  1127. var
  1128. $field = module.get.field(key),
  1129. $element = $field.parent(),
  1130. isMultiple = $.isArray(value),
  1131. isCheckbox = $element.is(selector.uiCheckbox),
  1132. isDropdown = $element.is(selector.uiDropdown),
  1133. isRadio = ($field.is(selector.radio) && isCheckbox),
  1134. fieldExists = ($field.length > 0),
  1135. $multipleField
  1136. ;
  1137. if(fieldExists) {
  1138. if(isMultiple && isCheckbox) {
  1139. module.verbose('Selecting multiple', value, $field);
  1140. $element.checkbox('uncheck');
  1141. $.each(value, function(index, value) {
  1142. $multipleField = $field.filter('[value="' + value + '"]');
  1143. $element = $multipleField.parent();
  1144. if($multipleField.length > 0) {
  1145. $element.checkbox('check');
  1146. }
  1147. });
  1148. }
  1149. else if(isRadio) {
  1150. module.verbose('Selecting radio value', value, $field);
  1151. $field.filter('[value="' + value + '"]')
  1152. .parent(selector.uiCheckbox)
  1153. .checkbox('check')
  1154. ;
  1155. }
  1156. else if(isCheckbox) {
  1157. module.verbose('Setting checkbox value', value, $element);
  1158. if(value === true) {
  1159. $element.checkbox('check');
  1160. }
  1161. else {
  1162. $element.checkbox('uncheck');
  1163. }
  1164. }
  1165. else if(isDropdown) {
  1166. module.verbose('Setting dropdown value', value, $element);
  1167. $element.dropdown('set selected', value);
  1168. }
  1169. else {
  1170. module.verbose('Setting field value', value, $field);
  1171. $field.val(value);
  1172. }
  1173. }
  1174. });
  1175. }
  1176. },
  1177. validate: {
  1178. form: function(event, ignoreCallbacks) {
  1179. var
  1180. values = module.get.values(),
  1181. apiRequest
  1182. ;
  1183. // input keydown event will fire submit repeatedly by browser default
  1184. if(keyHeldDown) {
  1185. return false;
  1186. }
  1187. // reset errors
  1188. formErrors = [];
  1189. if( module.is.valid() ) {
  1190. module.debug('Form has no validation errors, submitting');
  1191. module.set.success();
  1192. if(ignoreCallbacks !== true) {
  1193. return settings.onSuccess.call(element, event, values);
  1194. }
  1195. }
  1196. else {
  1197. module.debug('Form has errors');
  1198. module.set.error();
  1199. if(!settings.inline) {
  1200. module.add.errors(formErrors);
  1201. }
  1202. // prevent ajax submit
  1203. if($module.data('moduleApi') !== undefined) {
  1204. event.stopImmediatePropagation();
  1205. }
  1206. if(ignoreCallbacks !== true) {
  1207. return settings.onFailure.call(element, formErrors, values);
  1208. }
  1209. }
  1210. },
  1211. // takes a validation object and returns whether field passes validation
  1212. field: function(field, fieldName) {
  1213. var
  1214. identifier = field.identifier || fieldName,
  1215. $field = module.get.field(identifier),
  1216. fieldValid = true,
  1217. fieldErrors = []
  1218. ;
  1219. if(!field.identifier) {
  1220. module.debug('Using field name as identifier', identifier);
  1221. field.identifier = identifier;
  1222. }
  1223. if($field.prop('disabled')) {
  1224. module.debug('Field is disabled. Skipping', identifier);
  1225. fieldValid = true;
  1226. }
  1227. else if(field.optional && $.trim($field.val()) === ''){
  1228. module.debug('Field is optional and empty. Skipping', identifier);
  1229. fieldValid = true;
  1230. }
  1231. else if(field.rules !== undefined) {
  1232. $.each(field.rules, function(index, rule) {
  1233. if( module.has.field(identifier) && !( module.validate.rule(field, rule) ) ) {
  1234. module.debug('Field is invalid', identifier, rule.type);
  1235. fieldErrors.push(module.get.prompt(rule, field));
  1236. fieldValid = false;
  1237. }
  1238. });
  1239. }
  1240. if(fieldValid) {
  1241. module.remove.prompt(identifier, fieldErrors);
  1242. settings.onValid.call($field);
  1243. }
  1244. else {
  1245. formErrors = formErrors.concat(fieldErrors);
  1246. module.add.prompt(identifier, fieldErrors);
  1247. settings.onInvalid.call($field, fieldErrors);
  1248. return false;
  1249. }
  1250. return true;
  1251. },
  1252. // takes validation rule and returns whether field passes rule
  1253. rule: function(field, rule) {
  1254. var
  1255. $field = module.get.field(field.identifier),
  1256. type = rule.type,
  1257. value = $field.val(),
  1258. isValid = true,
  1259. ancillary = module.get.ancillaryValue(rule),
  1260. ruleName = module.get.ruleName(rule),
  1261. ruleFunction = settings.rules[ruleName]
  1262. ;
  1263. if( !$.isFunction(ruleFunction) ) {
  1264. module.error(error.noRule, ruleName);
  1265. return;
  1266. }
  1267. // cast to string avoiding encoding special values
  1268. value = (value === undefined || value === '' || value === null)
  1269. ? ''
  1270. : $.trim(value + '')
  1271. ;
  1272. return ruleFunction.call($field, value, ancillary);
  1273. }
  1274. },
  1275. setting: function(name, value) {
  1276. if( $.isPlainObject(name) ) {
  1277. $.extend(true, settings, name);
  1278. }
  1279. else if(value !== undefined) {
  1280. settings[name] = value;
  1281. }
  1282. else {
  1283. return settings[name];
  1284. }
  1285. },
  1286. internal: function(name, value) {
  1287. if( $.isPlainObject(name) ) {
  1288. $.extend(true, module, name);
  1289. }
  1290. else if(value !== undefined) {
  1291. module[name] = value;
  1292. }
  1293. else {
  1294. return module[name];
  1295. }
  1296. },
  1297. debug: function() {
  1298. if(settings.debug) {
  1299. if(settings.performance) {
  1300. module.performance.log(arguments);
  1301. }
  1302. else {
  1303. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1304. module.debug.apply(console, arguments);
  1305. }
  1306. }
  1307. },
  1308. verbose: function() {
  1309. if(settings.verbose && settings.debug) {
  1310. if(settings.performance) {
  1311. module.performance.log(arguments);
  1312. }
  1313. else {
  1314. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1315. module.verbose.apply(console, arguments);
  1316. }
  1317. }
  1318. },
  1319. error: function() {
  1320. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  1321. module.error.apply(console, arguments);
  1322. },
  1323. performance: {
  1324. log: function(message) {
  1325. var
  1326. currentTime,
  1327. executionTime,
  1328. previousTime
  1329. ;
  1330. if(settings.performance) {
  1331. currentTime = new Date().getTime();
  1332. previousTime = time || currentTime;
  1333. executionTime = currentTime - previousTime;
  1334. time = currentTime;
  1335. performance.push({
  1336. 'Name' : message[0],
  1337. 'Arguments' : [].slice.call(message, 1) || '',
  1338. 'Element' : element,
  1339. 'Execution Time' : executionTime
  1340. });
  1341. }
  1342. clearTimeout(module.performance.timer);
  1343. module.performance.timer = setTimeout(module.performance.display, 500);
  1344. },
  1345. display: function() {
  1346. var
  1347. title = settings.name + ':',
  1348. totalTime = 0
  1349. ;
  1350. time = false;
  1351. clearTimeout(module.performance.timer);
  1352. $.each(performance, function(index, data) {
  1353. totalTime += data['Execution Time'];
  1354. });
  1355. title += ' ' + totalTime + 'ms';
  1356. if(moduleSelector) {
  1357. title += ' \'' + moduleSelector + '\'';
  1358. }
  1359. if($allModules.length > 1) {
  1360. title += ' ' + '(' + $allModules.length + ')';
  1361. }
  1362. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  1363. console.groupCollapsed(title);
  1364. if(console.table) {
  1365. console.table(performance);
  1366. }
  1367. else {
  1368. $.each(performance, function(index, data) {
  1369. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  1370. });
  1371. }
  1372. console.groupEnd();
  1373. }
  1374. performance = [];
  1375. }
  1376. },
  1377. invoke: function(query, passedArguments, context) {
  1378. var
  1379. object = instance,
  1380. maxDepth,
  1381. found,
  1382. response
  1383. ;
  1384. passedArguments = passedArguments || queryArguments;
  1385. context = element || context;
  1386. if(typeof query == 'string' && object !== undefined) {
  1387. query = query.split(/[\. ]/);
  1388. maxDepth = query.length - 1;
  1389. $.each(query, function(depth, value) {
  1390. var camelCaseValue = (depth != maxDepth)
  1391. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  1392. : query
  1393. ;
  1394. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  1395. object = object[camelCaseValue];
  1396. }
  1397. else if( object[camelCaseValue] !== undefined ) {
  1398. found = object[camelCaseValue];
  1399. return false;
  1400. }
  1401. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  1402. object = object[value];
  1403. }
  1404. else if( object[value] !== undefined ) {
  1405. found = object[value];
  1406. return false;
  1407. }
  1408. else {
  1409. return false;
  1410. }
  1411. });
  1412. }
  1413. if( $.isFunction( found ) ) {
  1414. response = found.apply(context, passedArguments);
  1415. }
  1416. else if(found !== undefined) {
  1417. response = found;
  1418. }
  1419. if($.isArray(returnedValue)) {
  1420. returnedValue.push(response);
  1421. }
  1422. else if(returnedValue !== undefined) {
  1423. returnedValue = [returnedValue, response];
  1424. }
  1425. else if(response !== undefined) {
  1426. returnedValue = response;
  1427. }
  1428. return found;
  1429. }
  1430. };
  1431. module.initialize();
  1432. })
  1433. ;
  1434. return (returnedValue !== undefined)
  1435. ? returnedValue
  1436. : this
  1437. ;
  1438. };
  1439. $.fn.form.settings = {
  1440. name : 'Form',
  1441. namespace : 'form',
  1442. debug : false,
  1443. verbose : false,
  1444. performance : true,
  1445. fields : false,
  1446. keyboardShortcuts : true,
  1447. on : 'submit',
  1448. inline : false,
  1449. delay : 200,
  1450. revalidate : true,
  1451. transition : 'scale',
  1452. duration : 200,
  1453. onValid : function() {},
  1454. onInvalid : function() {},
  1455. onSuccess : function() { return true; },
  1456. onFailure : function() { return false; },
  1457. metadata : {
  1458. defaultValue : 'default',
  1459. validate : 'validate'
  1460. },
  1461. regExp: {
  1462. bracket : /\[(.*)\]/i,
  1463. decimal : /^\d*(\.)\d+/,
  1464. 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])?",
  1465. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  1466. flags : /^\/(.*)\/(.*)?/,
  1467. integer : /^\-?\d+$/,
  1468. number : /^\-?\d*(\.\d+)?$/,
  1469. url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
  1470. },
  1471. text: {
  1472. unspecifiedRule : 'Please enter a valid value',
  1473. unspecifiedField : 'This field'
  1474. },
  1475. prompt: {
  1476. empty : '{name} must have a value',
  1477. checked : '{name} must be checked',
  1478. email : '{name} must be a valid e-mail',
  1479. url : '{name} must be a valid url',
  1480. regExp : '{name} is not formatted correctly',
  1481. integer : '{name} must be an integer',
  1482. decimal : '{name} must be a decimal number',
  1483. number : '{name} must be set to a number',
  1484. is : '{name} must be "{ruleValue}"',
  1485. isExactly : '{name} must be exactly "{ruleValue}"',
  1486. not : '{name} cannot be set to "{ruleValue}"',
  1487. notExactly : '{name} cannot be set to exactly "{ruleValue}"',
  1488. contain : '{name} cannot contain "{ruleValue}"',
  1489. containExactly : '{name} cannot contain exactly "{ruleValue}"',
  1490. doesntContain : '{name} must contain "{ruleValue}"',
  1491. doesntContainExactly : '{name} must contain exactly "{ruleValue}"',
  1492. minLength : '{name} must be at least {ruleValue} characters',
  1493. length : '{name} must be at least {ruleValue} characters',
  1494. exactLength : '{name} must be exactly {ruleValue} characters',
  1495. maxLength : '{name} cannot be longer than {ruleValue} characters',
  1496. match : '{name} must match {ruleValue} field',
  1497. different : '{name} must have a different value than {ruleValue} field',
  1498. creditCard : '{name} must be a valid credit card number',
  1499. minCount : '{name} must have at least {ruleValue} choices',
  1500. exactCount : '{name} must have exactly {ruleValue} choices',
  1501. maxCount : '{name} must have {ruleValue} or less choices'
  1502. },
  1503. selector : {
  1504. checkbox : 'input[type="checkbox"], input[type="radio"]',
  1505. clear : '.clear',
  1506. field : 'input, textarea, select',
  1507. group : '.field',
  1508. input : 'input',
  1509. message : '.error.message',
  1510. prompt : '.prompt.label',
  1511. radio : 'input[type="radio"]',
  1512. reset : '.reset:not([type="reset"])',
  1513. submit : '.submit:not([type="submit"])',
  1514. uiCheckbox : '.ui.checkbox',
  1515. uiDropdown : '.ui.dropdown'
  1516. },
  1517. className : {
  1518. error : 'error',
  1519. label : 'ui prompt label',
  1520. pressed : 'down',
  1521. success : 'success'
  1522. },
  1523. error: {
  1524. identifier : 'You must specify a string identifier for each field',
  1525. method : 'The method you called is not defined.',
  1526. noRule : 'There is no rule matching the one you specified',
  1527. oldSyntax : 'Starting in 2.0 forms now only take a single settings object. Validation settings converted to new syntax automatically.'
  1528. },
  1529. templates: {
  1530. // template that produces error message
  1531. error: function(errors) {
  1532. var
  1533. html = '<ul class="list">'
  1534. ;
  1535. $.each(errors, function(index, value) {
  1536. html += '<li>' + value + '</li>';
  1537. });
  1538. html += '</ul>';
  1539. return $(html);
  1540. },
  1541. // template that produces label
  1542. prompt: function(errors) {
  1543. return $('<div/>')
  1544. .addClass('ui basic red pointing prompt label')
  1545. .html(errors[0])
  1546. ;
  1547. }
  1548. },
  1549. rules: {
  1550. // is not empty or blank string
  1551. empty: function(value) {
  1552. return !(value === undefined || '' === value || $.isArray(value) && value.length === 0);
  1553. },
  1554. // checkbox checked
  1555. checked: function() {
  1556. return ($(this).filter(':checked').length > 0);
  1557. },
  1558. // is most likely an email
  1559. email: function(value){
  1560. var
  1561. emailRegExp = new RegExp($.fn.form.settings.regExp.email, 'i')
  1562. ;
  1563. return emailRegExp.test(value);
  1564. },
  1565. // value is most likely url
  1566. url: function(value) {
  1567. return $.fn.form.settings.regExp.url.test(value);
  1568. },
  1569. // matches specified regExp
  1570. regExp: function(value, regExp) {
  1571. var
  1572. regExpParts = regExp.match($.fn.form.settings.regExp.flags),
  1573. flags
  1574. ;
  1575. // regular expression specified as /baz/gi (flags)
  1576. if(regExpParts) {
  1577. regExp = (regExpParts.length >= 2)
  1578. ? regExpParts[1]
  1579. : regExp
  1580. ;
  1581. flags = (regExpParts.length >= 3)
  1582. ? regExpParts[2]
  1583. : ''
  1584. ;
  1585. }
  1586. return value.match( new RegExp(regExp, flags) );
  1587. },
  1588. // is valid integer or matches range
  1589. integer: function(value, range) {
  1590. var
  1591. intRegExp = $.fn.form.settings.regExp.integer,
  1592. min,
  1593. max,
  1594. parts
  1595. ;
  1596. if( !range || ['', '..'].indexOf(range) !== -1) {
  1597. // do nothing
  1598. }
  1599. else if(range.indexOf('..') == -1) {
  1600. if(intRegExp.test(range)) {
  1601. min = max = range - 0;
  1602. }
  1603. }
  1604. else {
  1605. parts = range.split('..', 2);
  1606. if(intRegExp.test(parts[0])) {
  1607. min = parts[0] - 0;
  1608. }
  1609. if(intRegExp.test(parts[1])) {
  1610. max = parts[1] - 0;
  1611. }
  1612. }
  1613. return (
  1614. intRegExp.test(value) &&
  1615. (min === undefined || value >= min) &&
  1616. (max === undefined || value <= max)
  1617. );
  1618. },
  1619. // is valid number (with decimal)
  1620. decimal: function(value) {
  1621. return $.fn.form.settings.regExp.decimal.test(value);
  1622. },
  1623. // is valid number
  1624. number: function(value) {
  1625. return $.fn.form.settings.regExp.number.test(value);
  1626. },
  1627. // is value (case insensitive)
  1628. is: function(value, text) {
  1629. text = (typeof text == 'string')
  1630. ? text.toLowerCase()
  1631. : text
  1632. ;
  1633. value = (typeof value == 'string')
  1634. ? value.toLowerCase()
  1635. : value
  1636. ;
  1637. return (value == text);
  1638. },
  1639. // is value
  1640. isExactly: function(value, text) {
  1641. return (value == text);
  1642. },
  1643. // value is not another value (case insensitive)
  1644. not: function(value, notValue) {
  1645. value = (typeof value == 'string')
  1646. ? value.toLowerCase()
  1647. : value
  1648. ;
  1649. notValue = (typeof notValue == 'string')
  1650. ? notValue.toLowerCase()
  1651. : notValue
  1652. ;
  1653. return (value != notValue);
  1654. },
  1655. // value is not another value (case sensitive)
  1656. notExactly: function(value, notValue) {
  1657. return (value != notValue);
  1658. },
  1659. // value contains text (insensitive)
  1660. contains: function(value, text) {
  1661. // escape regex characters
  1662. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1663. return (value.search( new RegExp(text, 'i') ) !== -1);
  1664. },
  1665. // value contains text (case sensitive)
  1666. containsExactly: function(value, text) {
  1667. // escape regex characters
  1668. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1669. return (value.search( new RegExp(text) ) !== -1);
  1670. },
  1671. // value contains text (insensitive)
  1672. doesntContain: function(value, text) {
  1673. // escape regex characters
  1674. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1675. return (value.search( new RegExp(text, 'i') ) === -1);
  1676. },
  1677. // value contains text (case sensitive)
  1678. doesntContainExactly: function(value, text) {
  1679. // escape regex characters
  1680. text = text.replace($.fn.form.settings.regExp.escape, "\\$&");
  1681. return (value.search( new RegExp(text) ) === -1);
  1682. },
  1683. // is at least string length
  1684. minLength: function(value, requiredLength) {
  1685. return (value !== undefined)
  1686. ? (value.length >= requiredLength)
  1687. : false
  1688. ;
  1689. },
  1690. // see rls notes for 2.0.6 (this is a duplicate of minLength)
  1691. length: function(value, requiredLength) {
  1692. return (value !== undefined)
  1693. ? (value.length >= requiredLength)
  1694. : false
  1695. ;
  1696. },
  1697. // is exactly length
  1698. exactLength: function(value, requiredLength) {
  1699. return (value !== undefined)
  1700. ? (value.length == requiredLength)
  1701. : false
  1702. ;
  1703. },
  1704. // is less than length
  1705. maxLength: function(value, maxLength) {
  1706. return (value !== undefined)
  1707. ? (value.length <= maxLength)
  1708. : false
  1709. ;
  1710. },
  1711. // matches another field
  1712. match: function(value, identifier) {
  1713. var
  1714. $form = $(this),
  1715. matchingValue
  1716. ;
  1717. if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
  1718. matchingValue = $('[data-validate="'+ identifier +'"]').val();
  1719. }
  1720. else if($('#' + identifier).length > 0) {
  1721. matchingValue = $('#' + identifier).val();
  1722. }
  1723. else if($('[name="' + identifier +'"]').length > 0) {
  1724. matchingValue = $('[name="' + identifier + '"]').val();
  1725. }
  1726. else if( $('[name="' + identifier +'[]"]').length > 0 ) {
  1727. matchingValue = $('[name="' + identifier +'[]"]');
  1728. }
  1729. return (matchingValue !== undefined)
  1730. ? ( value.toString() == matchingValue.toString() )
  1731. : false
  1732. ;
  1733. },
  1734. // different than another field
  1735. different: function(value, identifier) {
  1736. // use either id or name of field
  1737. var
  1738. $form = $(this),
  1739. matchingValue
  1740. ;
  1741. if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
  1742. matchingValue = $('[data-validate="'+ identifier +'"]').val();
  1743. }
  1744. else if($('#' + identifier).length > 0) {
  1745. matchingValue = $('#' + identifier).val();
  1746. }
  1747. else if($('[name="' + identifier +'"]').length > 0) {
  1748. matchingValue = $('[name="' + identifier + '"]').val();
  1749. }
  1750. else if( $('[name="' + identifier +'[]"]').length > 0 ) {
  1751. matchingValue = $('[name="' + identifier +'[]"]');
  1752. }
  1753. return (matchingValue !== undefined)
  1754. ? ( value.toString() !== matchingValue.toString() )
  1755. : false
  1756. ;
  1757. },
  1758. creditCard: function(cardNumber, cardTypes) {
  1759. var
  1760. cards = {
  1761. visa: {
  1762. pattern : /^4/,
  1763. length : [16]
  1764. },
  1765. amex: {
  1766. pattern : /^3[47]/,
  1767. length : [15]
  1768. },
  1769. mastercard: {
  1770. pattern : /^5[1-5]/,
  1771. length : [16]
  1772. },
  1773. discover: {
  1774. pattern : /^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/,
  1775. length : [16]
  1776. },
  1777. unionPay: {
  1778. pattern : /^(62|88)/,
  1779. length : [16, 17, 18, 19]
  1780. },
  1781. jcb: {
  1782. pattern : /^35(2[89]|[3-8][0-9])/,
  1783. length : [16]
  1784. },
  1785. maestro: {
  1786. pattern : /^(5018|5020|5038|6304|6759|676[1-3])/,
  1787. length : [12, 13, 14, 15, 16, 17, 18, 19]
  1788. },
  1789. dinersClub: {
  1790. pattern : /^(30[0-5]|^36)/,
  1791. length : [14]
  1792. },
  1793. laser: {
  1794. pattern : /^(6304|670[69]|6771)/,
  1795. length : [16, 17, 18, 19]
  1796. },
  1797. visaElectron: {
  1798. pattern : /^(4026|417500|4508|4844|491(3|7))/,
  1799. length : [16]
  1800. }
  1801. },
  1802. valid = {},
  1803. validCard = false,
  1804. requiredTypes = (typeof cardTypes == 'string')
  1805. ? cardTypes.split(',')
  1806. : false,
  1807. unionPay,
  1808. validation
  1809. ;
  1810. if(typeof cardNumber !== 'string' || cardNumber.length === 0) {
  1811. return;
  1812. }
  1813. // verify card types
  1814. if(requiredTypes) {
  1815. $.each(requiredTypes, function(index, type){
  1816. // verify each card type
  1817. validation = cards[type];
  1818. if(validation) {
  1819. valid = {
  1820. length : ($.inArray(cardNumber.length, validation.length) !== -1),
  1821. pattern : (cardNumber.search(validation.pattern) !== -1)
  1822. };
  1823. if(valid.length && valid.pattern) {
  1824. validCard = true;
  1825. }
  1826. }
  1827. });
  1828. if(!validCard) {
  1829. return false;
  1830. }
  1831. }
  1832. // skip luhn for UnionPay
  1833. unionPay = {
  1834. number : ($.inArray(cardNumber.length, cards.unionPay.length) !== -1),
  1835. pattern : (cardNumber.search(cards.unionPay.pattern) !== -1)
  1836. };
  1837. if(unionPay.number && unionPay.pattern) {
  1838. return true;
  1839. }
  1840. // verify luhn, adapted from <https://gist.github.com/2134376>
  1841. var
  1842. length = cardNumber.length,
  1843. multiple = 0,
  1844. producedValue = [
  1845. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
  1846. [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
  1847. ],
  1848. sum = 0
  1849. ;
  1850. while (length--) {
  1851. sum += producedValue[multiple][parseInt(cardNumber.charAt(length), 10)];
  1852. multiple ^= 1;
  1853. }
  1854. return (sum % 10 === 0 && sum > 0);
  1855. },
  1856. minCount: function(value, minCount) {
  1857. if(minCount == 0) {
  1858. return true;
  1859. }
  1860. if(minCount == 1) {
  1861. return (value !== '');
  1862. }
  1863. return (value.split(',').length >= minCount);
  1864. },
  1865. exactCount: function(value, exactCount) {
  1866. if(exactCount == 0) {
  1867. return (value === '');
  1868. }
  1869. if(exactCount == 1) {
  1870. return (value !== '' && value.search(',') === -1);
  1871. }
  1872. return (value.split(',').length == exactCount);
  1873. },
  1874. maxCount: function(value, maxCount) {
  1875. if(maxCount == 0) {
  1876. return false;
  1877. }
  1878. if(maxCount == 1) {
  1879. return (value.search(',') === -1);
  1880. }
  1881. return (value.split(',').length <= maxCount);
  1882. }
  1883. }
  1884. };
  1885. })( jQuery, window, document );
  1886. /*!
  1887. * # Semantic UI 2.1.6 - Accordion
  1888. * http://github.com/semantic-org/semantic-ui/
  1889. *
  1890. *
  1891. * Copyright 2015 Contributors
  1892. * Released under the MIT license
  1893. * http://opensource.org/licenses/MIT
  1894. *
  1895. */
  1896. ;(function ($, window, document, undefined) {
  1897. "use strict";
  1898. $.fn.accordion = function(parameters) {
  1899. var
  1900. $allModules = $(this),
  1901. time = new Date().getTime(),
  1902. performance = [],
  1903. query = arguments[0],
  1904. methodInvoked = (typeof query == 'string'),
  1905. queryArguments = [].slice.call(arguments, 1),
  1906. requestAnimationFrame = window.requestAnimationFrame
  1907. || window.mozRequestAnimationFrame
  1908. || window.webkitRequestAnimationFrame
  1909. || window.msRequestAnimationFrame
  1910. || function(callback) { setTimeout(callback, 0); },
  1911. returnedValue
  1912. ;
  1913. $allModules
  1914. .each(function() {
  1915. var
  1916. settings = ( $.isPlainObject(parameters) )
  1917. ? $.extend(true, {}, $.fn.accordion.settings, parameters)
  1918. : $.extend({}, $.fn.accordion.settings),
  1919. className = settings.className,
  1920. namespace = settings.namespace,
  1921. selector = settings.selector,
  1922. error = settings.error,
  1923. eventNamespace = '.' + namespace,
  1924. moduleNamespace = 'module-' + namespace,
  1925. moduleSelector = $allModules.selector || '',
  1926. $module = $(this),
  1927. $title = $module.find(selector.title),
  1928. $content = $module.find(selector.content),
  1929. element = this,
  1930. instance = $module.data(moduleNamespace),
  1931. observer,
  1932. module
  1933. ;
  1934. module = {
  1935. initialize: function() {
  1936. module.debug('Initializing', $module);
  1937. module.bind.events();
  1938. if(settings.observeChanges) {
  1939. module.observeChanges();
  1940. }
  1941. module.instantiate();
  1942. },
  1943. instantiate: function() {
  1944. instance = module;
  1945. $module
  1946. .data(moduleNamespace, module)
  1947. ;
  1948. },
  1949. destroy: function() {
  1950. module.debug('Destroying previous instance', $module);
  1951. $module
  1952. .off(eventNamespace)
  1953. .removeData(moduleNamespace)
  1954. ;
  1955. },
  1956. refresh: function() {
  1957. $title = $module.find(selector.title);
  1958. $content = $module.find(selector.content);
  1959. },
  1960. observeChanges: function() {
  1961. if('MutationObserver' in window) {
  1962. observer = new MutationObserver(function(mutations) {
  1963. module.debug('DOM tree modified, updating selector cache');
  1964. module.refresh();
  1965. });
  1966. observer.observe(element, {
  1967. childList : true,
  1968. subtree : true
  1969. });
  1970. module.debug('Setting up mutation observer', observer);
  1971. }
  1972. },
  1973. bind: {
  1974. events: function() {
  1975. module.debug('Binding delegated events');
  1976. $module
  1977. .on(settings.on + eventNamespace, selector.trigger, module.event.click)
  1978. ;
  1979. }
  1980. },
  1981. event: {
  1982. click: function() {
  1983. module.toggle.call(this);
  1984. }
  1985. },
  1986. toggle: function(query) {
  1987. var
  1988. $activeTitle = (query !== undefined)
  1989. ? (typeof query === 'number')
  1990. ? $title.eq(query)
  1991. : $(query).closest(selector.title)
  1992. : $(this).closest(selector.title),
  1993. $activeContent = $activeTitle.next($content),
  1994. isAnimating = $activeContent.hasClass(className.animating),
  1995. isActive = $activeContent.hasClass(className.active),
  1996. isOpen = (isActive && !isAnimating),
  1997. isOpening = (!isActive && isAnimating)
  1998. ;
  1999. module.debug('Toggling visibility of content', $activeTitle);
  2000. if(isOpen || isOpening) {
  2001. if(settings.collapsible) {
  2002. module.close.call($activeTitle);
  2003. }
  2004. else {
  2005. module.debug('Cannot close accordion content collapsing is disabled');
  2006. }
  2007. }
  2008. else {
  2009. module.open.call($activeTitle);
  2010. }
  2011. },
  2012. open: function(query) {
  2013. var
  2014. $activeTitle = (query !== undefined)
  2015. ? (typeof query === 'number')
  2016. ? $title.eq(query)
  2017. : $(query).closest(selector.title)
  2018. : $(this).closest(selector.title),
  2019. $activeContent = $activeTitle.next($content),
  2020. isAnimating = $activeContent.hasClass(className.animating),
  2021. isActive = $activeContent.hasClass(className.active),
  2022. isOpen = (isActive || isAnimating)
  2023. ;
  2024. if(isOpen) {
  2025. module.debug('Accordion already open, skipping', $activeContent);
  2026. return;
  2027. }
  2028. module.debug('Opening accordion content', $activeTitle);
  2029. settings.onOpening.call($activeContent);
  2030. if(settings.exclusive) {
  2031. module.closeOthers.call($activeTitle);
  2032. }
  2033. $activeTitle
  2034. .addClass(className.active)
  2035. ;
  2036. $activeContent
  2037. .stop(true, true)
  2038. .addClass(className.animating)
  2039. ;
  2040. if(settings.animateChildren) {
  2041. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2042. $activeContent
  2043. .children()
  2044. .transition({
  2045. animation : 'fade in',
  2046. queue : false,
  2047. useFailSafe : true,
  2048. debug : settings.debug,
  2049. verbose : settings.verbose,
  2050. duration : settings.duration
  2051. })
  2052. ;
  2053. }
  2054. else {
  2055. $activeContent
  2056. .children()
  2057. .stop(true, true)
  2058. .animate({
  2059. opacity: 1
  2060. }, settings.duration, module.resetOpacity)
  2061. ;
  2062. }
  2063. }
  2064. $activeContent
  2065. .slideDown(settings.duration, settings.easing, function() {
  2066. $activeContent
  2067. .removeClass(className.animating)
  2068. .addClass(className.active)
  2069. ;
  2070. module.reset.display.call(this);
  2071. settings.onOpen.call(this);
  2072. settings.onChange.call(this);
  2073. })
  2074. ;
  2075. },
  2076. close: function(query) {
  2077. var
  2078. $activeTitle = (query !== undefined)
  2079. ? (typeof query === 'number')
  2080. ? $title.eq(query)
  2081. : $(query).closest(selector.title)
  2082. : $(this).closest(selector.title),
  2083. $activeContent = $activeTitle.next($content),
  2084. isAnimating = $activeContent.hasClass(className.animating),
  2085. isActive = $activeContent.hasClass(className.active),
  2086. isOpening = (!isActive && isAnimating),
  2087. isClosing = (isActive && isAnimating)
  2088. ;
  2089. if((isActive || isOpening) && !isClosing) {
  2090. module.debug('Closing accordion content', $activeContent);
  2091. settings.onClosing.call($activeContent);
  2092. $activeTitle
  2093. .removeClass(className.active)
  2094. ;
  2095. $activeContent
  2096. .stop(true, true)
  2097. .addClass(className.animating)
  2098. ;
  2099. if(settings.animateChildren) {
  2100. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2101. $activeContent
  2102. .children()
  2103. .transition({
  2104. animation : 'fade out',
  2105. queue : false,
  2106. useFailSafe : true,
  2107. debug : settings.debug,
  2108. verbose : settings.verbose,
  2109. duration : settings.duration
  2110. })
  2111. ;
  2112. }
  2113. else {
  2114. $activeContent
  2115. .children()
  2116. .stop(true, true)
  2117. .animate({
  2118. opacity: 0
  2119. }, settings.duration, module.resetOpacity)
  2120. ;
  2121. }
  2122. }
  2123. $activeContent
  2124. .slideUp(settings.duration, settings.easing, function() {
  2125. $activeContent
  2126. .removeClass(className.animating)
  2127. .removeClass(className.active)
  2128. ;
  2129. module.reset.display.call(this);
  2130. settings.onClose.call(this);
  2131. settings.onChange.call(this);
  2132. })
  2133. ;
  2134. }
  2135. },
  2136. closeOthers: function(index) {
  2137. var
  2138. $activeTitle = (index !== undefined)
  2139. ? $title.eq(index)
  2140. : $(this).closest(selector.title),
  2141. $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
  2142. $activeAccordion = $activeTitle.closest(selector.accordion),
  2143. activeSelector = selector.title + '.' + className.active + ':visible',
  2144. activeContent = selector.content + '.' + className.active + ':visible',
  2145. $openTitles,
  2146. $nestedTitles,
  2147. $openContents
  2148. ;
  2149. if(settings.closeNested) {
  2150. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2151. $openContents = $openTitles.next($content);
  2152. }
  2153. else {
  2154. $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
  2155. $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
  2156. $openTitles = $openTitles.not($nestedTitles);
  2157. $openContents = $openTitles.next($content);
  2158. }
  2159. if( ($openTitles.length > 0) ) {
  2160. module.debug('Exclusive enabled, closing other content', $openTitles);
  2161. $openTitles
  2162. .removeClass(className.active)
  2163. ;
  2164. $openContents
  2165. .removeClass(className.animating)
  2166. .stop(true, true)
  2167. ;
  2168. if(settings.animateChildren) {
  2169. if($.fn.transition !== undefined && $module.transition('is supported')) {
  2170. $openContents
  2171. .children()
  2172. .transition({
  2173. animation : 'fade out',
  2174. useFailSafe : true,
  2175. debug : settings.debug,
  2176. verbose : settings.verbose,
  2177. duration : settings.duration
  2178. })
  2179. ;
  2180. }
  2181. else {
  2182. $openContents
  2183. .children()
  2184. .stop(true, true)
  2185. .animate({
  2186. opacity: 0
  2187. }, settings.duration, module.resetOpacity)
  2188. ;
  2189. }
  2190. }
  2191. $openContents
  2192. .slideUp(settings.duration , settings.easing, function() {
  2193. $(this).removeClass(className.active);
  2194. module.reset.display.call(this);
  2195. })
  2196. ;
  2197. }
  2198. },
  2199. reset: {
  2200. display: function() {
  2201. module.verbose('Removing inline display from element', this);
  2202. $(this).css('display', '');
  2203. if( $(this).attr('style') === '') {
  2204. $(this)
  2205. .attr('style', '')
  2206. .removeAttr('style')
  2207. ;
  2208. }
  2209. },
  2210. opacity: function() {
  2211. module.verbose('Removing inline opacity from element', this);
  2212. $(this).css('opacity', '');
  2213. if( $(this).attr('style') === '') {
  2214. $(this)
  2215. .attr('style', '')
  2216. .removeAttr('style')
  2217. ;
  2218. }
  2219. },
  2220. },
  2221. setting: function(name, value) {
  2222. module.debug('Changing setting', name, value);
  2223. if( $.isPlainObject(name) ) {
  2224. $.extend(true, settings, name);
  2225. }
  2226. else if(value !== undefined) {
  2227. settings[name] = value;
  2228. }
  2229. else {
  2230. return settings[name];
  2231. }
  2232. },
  2233. internal: function(name, value) {
  2234. module.debug('Changing internal', name, value);
  2235. if(value !== undefined) {
  2236. if( $.isPlainObject(name) ) {
  2237. $.extend(true, module, name);
  2238. }
  2239. else {
  2240. module[name] = value;
  2241. }
  2242. }
  2243. else {
  2244. return module[name];
  2245. }
  2246. },
  2247. debug: function() {
  2248. if(settings.debug) {
  2249. if(settings.performance) {
  2250. module.performance.log(arguments);
  2251. }
  2252. else {
  2253. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2254. module.debug.apply(console, arguments);
  2255. }
  2256. }
  2257. },
  2258. verbose: function() {
  2259. if(settings.verbose && settings.debug) {
  2260. if(settings.performance) {
  2261. module.performance.log(arguments);
  2262. }
  2263. else {
  2264. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  2265. module.verbose.apply(console, arguments);
  2266. }
  2267. }
  2268. },
  2269. error: function() {
  2270. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  2271. module.error.apply(console, arguments);
  2272. },
  2273. performance: {
  2274. log: function(message) {
  2275. var
  2276. currentTime,
  2277. executionTime,
  2278. previousTime
  2279. ;
  2280. if(settings.performance) {
  2281. currentTime = new Date().getTime();
  2282. previousTime = time || currentTime;
  2283. executionTime = currentTime - previousTime;
  2284. time = currentTime;
  2285. performance.push({
  2286. 'Name' : message[0],
  2287. 'Arguments' : [].slice.call(message, 1) || '',
  2288. 'Element' : element,
  2289. 'Execution Time' : executionTime
  2290. });
  2291. }
  2292. clearTimeout(module.performance.timer);
  2293. module.performance.timer = setTimeout(module.performance.display, 500);
  2294. },
  2295. display: function() {
  2296. var
  2297. title = settings.name + ':',
  2298. totalTime = 0
  2299. ;
  2300. time = false;
  2301. clearTimeout(module.performance.timer);
  2302. $.each(performance, function(index, data) {
  2303. totalTime += data['Execution Time'];
  2304. });
  2305. title += ' ' + totalTime + 'ms';
  2306. if(moduleSelector) {
  2307. title += ' \'' + moduleSelector + '\'';
  2308. }
  2309. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  2310. console.groupCollapsed(title);
  2311. if(console.table) {
  2312. console.table(performance);
  2313. }
  2314. else {
  2315. $.each(performance, function(index, data) {
  2316. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  2317. });
  2318. }
  2319. console.groupEnd();
  2320. }
  2321. performance = [];
  2322. }
  2323. },
  2324. invoke: function(query, passedArguments, context) {
  2325. var
  2326. object = instance,
  2327. maxDepth,
  2328. found,
  2329. response
  2330. ;
  2331. passedArguments = passedArguments || queryArguments;
  2332. context = element || context;
  2333. if(typeof query == 'string' && object !== undefined) {
  2334. query = query.split(/[\. ]/);
  2335. maxDepth = query.length - 1;
  2336. $.each(query, function(depth, value) {
  2337. var camelCaseValue = (depth != maxDepth)
  2338. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  2339. : query
  2340. ;
  2341. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  2342. object = object[camelCaseValue];
  2343. }
  2344. else if( object[camelCaseValue] !== undefined ) {
  2345. found = object[camelCaseValue];
  2346. return false;
  2347. }
  2348. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  2349. object = object[value];
  2350. }
  2351. else if( object[value] !== undefined ) {
  2352. found = object[value];
  2353. return false;
  2354. }
  2355. else {
  2356. module.error(error.method, query);
  2357. return false;
  2358. }
  2359. });
  2360. }
  2361. if ( $.isFunction( found ) ) {
  2362. response = found.apply(context, passedArguments);
  2363. }
  2364. else if(found !== undefined) {
  2365. response = found;
  2366. }
  2367. if($.isArray(returnedValue)) {
  2368. returnedValue.push(response);
  2369. }
  2370. else if(returnedValue !== undefined) {
  2371. returnedValue = [returnedValue, response];
  2372. }
  2373. else if(response !== undefined) {
  2374. returnedValue = response;
  2375. }
  2376. return found;
  2377. }
  2378. };
  2379. if(methodInvoked) {
  2380. if(instance === undefined) {
  2381. module.initialize();
  2382. }
  2383. module.invoke(query);
  2384. }
  2385. else {
  2386. if(instance !== undefined) {
  2387. instance.invoke('destroy');
  2388. }
  2389. module.initialize();
  2390. }
  2391. })
  2392. ;
  2393. return (returnedValue !== undefined)
  2394. ? returnedValue
  2395. : this
  2396. ;
  2397. };
  2398. $.fn.accordion.settings = {
  2399. name : 'Accordion',
  2400. namespace : 'accordion',
  2401. debug : false,
  2402. verbose : false,
  2403. performance : true,
  2404. on : 'click', // event on title that opens accordion
  2405. observeChanges : true, // whether accordion should automatically refresh on DOM insertion
  2406. exclusive : true, // whether a single accordion content panel should be open at once
  2407. collapsible : true, // whether accordion content can be closed
  2408. closeNested : false, // whether nested content should be closed when a panel is closed
  2409. animateChildren : true, // whether children opacity should be animated
  2410. duration : 350, // duration of animation
  2411. easing : 'easeOutQuad', // easing equation for animation
  2412. onOpening : function(){}, // callback before open animation
  2413. onOpen : function(){}, // callback after open animation
  2414. onClosing : function(){}, // callback before closing animation
  2415. onClose : function(){}, // callback after closing animation
  2416. onChange : function(){}, // callback after closing or opening animation
  2417. error: {
  2418. method : 'The method you called is not defined'
  2419. },
  2420. className : {
  2421. active : 'active',
  2422. animating : 'animating'
  2423. },
  2424. selector : {
  2425. accordion : '.accordion',
  2426. title : '.title',
  2427. trigger : '.title',
  2428. content : '.content'
  2429. }
  2430. };
  2431. // Adds easing
  2432. $.extend( $.easing, {
  2433. easeOutQuad: function (x, t, b, c, d) {
  2434. return -c *(t/=d)*(t-2) + b;
  2435. }
  2436. });
  2437. })( jQuery, window, document );
  2438. /*!
  2439. * # Semantic UI 2.1.6 - Checkbox
  2440. * http://github.com/semantic-org/semantic-ui/
  2441. *
  2442. *
  2443. * Copyright 2015 Contributors
  2444. * Released under the MIT license
  2445. * http://opensource.org/licenses/MIT
  2446. *
  2447. */
  2448. ;(function ( $, window, document, undefined ) {
  2449. "use strict";
  2450. $.fn.checkbox = function(parameters) {
  2451. var
  2452. $allModules = $(this),
  2453. moduleSelector = $allModules.selector || '',
  2454. time = new Date().getTime(),
  2455. performance = [],
  2456. query = arguments[0],
  2457. methodInvoked = (typeof query == 'string'),
  2458. queryArguments = [].slice.call(arguments, 1),
  2459. returnedValue
  2460. ;
  2461. $allModules
  2462. .each(function() {
  2463. var
  2464. settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
  2465. className = settings.className,
  2466. namespace = settings.namespace,
  2467. selector = settings.selector,
  2468. error = settings.error,
  2469. eventNamespace = '.' + namespace,
  2470. moduleNamespace = 'module-' + namespace,
  2471. $module = $(this),
  2472. $label = $(this).children(selector.label),
  2473. $input = $(this).children(selector.input),
  2474. input = $input[0],
  2475. initialLoad = false,
  2476. shortcutPressed = false,
  2477. instance = $module.data(moduleNamespace),
  2478. observer,
  2479. element = this,
  2480. module
  2481. ;
  2482. module = {
  2483. initialize: function() {
  2484. module.verbose('Initializing checkbox', settings);
  2485. module.create.label();
  2486. module.bind.events();
  2487. module.set.tabbable();
  2488. module.hide.input();
  2489. module.observeChanges();
  2490. module.instantiate();
  2491. module.setup();
  2492. },
  2493. instantiate: function() {
  2494. module.verbose('Storing instance of module', module);
  2495. instance = module;
  2496. $module
  2497. .data(moduleNamespace, module)
  2498. ;
  2499. },
  2500. destroy: function() {
  2501. module.verbose('Destroying module');
  2502. module.unbind.events();
  2503. module.show.input();
  2504. $module.removeData(moduleNamespace);
  2505. },
  2506. fix: {
  2507. reference: function() {
  2508. if( $module.is(selector.input) ) {
  2509. module.debug('Behavior called on <input> adjusting invoked element');
  2510. $module = $module.closest(selector.checkbox);
  2511. module.refresh();
  2512. }
  2513. }
  2514. },
  2515. setup: function() {
  2516. module.set.initialLoad();
  2517. if( module.is.indeterminate() ) {
  2518. module.debug('Initial value is indeterminate');
  2519. module.indeterminate();
  2520. }
  2521. else if( module.is.checked() ) {
  2522. module.debug('Initial value is checked');
  2523. module.check();
  2524. }
  2525. else {
  2526. module.debug('Initial value is unchecked');
  2527. module.uncheck();
  2528. }
  2529. module.remove.initialLoad();
  2530. },
  2531. refresh: function() {
  2532. $label = $module.children(selector.label);
  2533. $input = $module.children(selector.input);
  2534. input = $input[0];
  2535. },
  2536. hide: {
  2537. input: function() {
  2538. module.verbose('Modfying <input> z-index to be unselectable');
  2539. $input.addClass(className.hidden);
  2540. }
  2541. },
  2542. show: {
  2543. input: function() {
  2544. module.verbose('Modfying <input> z-index to be selectable');
  2545. $input.removeClass(className.hidden);
  2546. }
  2547. },
  2548. observeChanges: function() {
  2549. if('MutationObserver' in window) {
  2550. observer = new MutationObserver(function(mutations) {
  2551. module.debug('DOM tree modified, updating selector cache');
  2552. module.refresh();
  2553. });
  2554. observer.observe(element, {
  2555. childList : true,
  2556. subtree : true
  2557. });
  2558. module.debug('Setting up mutation observer', observer);
  2559. }
  2560. },
  2561. attachEvents: function(selector, event) {
  2562. var
  2563. $element = $(selector)
  2564. ;
  2565. event = $.isFunction(module[event])
  2566. ? module[event]
  2567. : module.toggle
  2568. ;
  2569. if($element.length > 0) {
  2570. module.debug('Attaching checkbox events to element', selector, event);
  2571. $element
  2572. .on('click' + eventNamespace, event)
  2573. ;
  2574. }
  2575. else {
  2576. module.error(error.notFound);
  2577. }
  2578. },
  2579. event: {
  2580. click: function(event) {
  2581. var
  2582. $target = $(event.target)
  2583. ;
  2584. if( $target.is(selector.input) ) {
  2585. module.verbose('Using default check action on initialized checkbox');
  2586. return;
  2587. }
  2588. if( $target.is(selector.link) ) {
  2589. module.debug('Clicking link inside checkbox, skipping toggle');
  2590. return;
  2591. }
  2592. module.toggle();
  2593. $input.focus();
  2594. event.preventDefault();
  2595. },
  2596. keydown: function(event) {
  2597. var
  2598. key = event.which,
  2599. keyCode = {
  2600. enter : 13,
  2601. space : 32,
  2602. escape : 27
  2603. }
  2604. ;
  2605. if(key == keyCode.escape) {
  2606. module.verbose('Escape key pressed blurring field');
  2607. $input.blur();
  2608. shortcutPressed = true;
  2609. }
  2610. else if(!event.ctrlKey && ( key == keyCode.space || key == keyCode.enter) ) {
  2611. module.verbose('Enter/space key pressed, toggling checkbox');
  2612. module.toggle();
  2613. shortcutPressed = true;
  2614. }
  2615. else {
  2616. shortcutPressed = false;
  2617. }
  2618. },
  2619. keyup: function(event) {
  2620. if(shortcutPressed) {
  2621. event.preventDefault();
  2622. }
  2623. }
  2624. },
  2625. check: function() {
  2626. if( !module.should.allowCheck() ) {
  2627. return;
  2628. }
  2629. module.debug('Checking checkbox', $input);
  2630. module.set.checked();
  2631. if( !module.should.ignoreCallbacks() ) {
  2632. settings.onChecked.call(input);
  2633. settings.onChange.call(input);
  2634. }
  2635. },
  2636. uncheck: function() {
  2637. if( !module.should.allowUncheck() ) {
  2638. return;
  2639. }
  2640. module.debug('Unchecking checkbox');
  2641. module.set.unchecked();
  2642. if( !module.should.ignoreCallbacks() ) {
  2643. settings.onUnchecked.call(input);
  2644. settings.onChange.call(input);
  2645. }
  2646. },
  2647. indeterminate: function() {
  2648. if( module.should.allowIndeterminate() ) {
  2649. module.debug('Checkbox is already indeterminate');
  2650. return;
  2651. }
  2652. module.debug('Making checkbox indeterminate');
  2653. module.set.indeterminate();
  2654. if( !module.should.ignoreCallbacks() ) {
  2655. settings.onIndeterminate.call(input);
  2656. settings.onChange.call(input);
  2657. }
  2658. },
  2659. determinate: function() {
  2660. if( module.should.allowDeterminate() ) {
  2661. module.debug('Checkbox is already determinate');
  2662. return;
  2663. }
  2664. module.debug('Making checkbox determinate');
  2665. module.set.determinate();
  2666. if( !module.should.ignoreCallbacks() ) {
  2667. settings.onDeterminate.call(input);
  2668. settings.onChange.call(input);
  2669. }
  2670. },
  2671. enable: function() {
  2672. if( module.is.enabled() ) {
  2673. module.debug('Checkbox is already enabled');
  2674. return;
  2675. }
  2676. module.debug('Enabling checkbox');
  2677. module.set.enabled();
  2678. settings.onEnable.call(input);
  2679. },
  2680. disable: function() {
  2681. if( module.is.disabled() ) {
  2682. module.debug('Checkbox is already disabled');
  2683. return;
  2684. }
  2685. module.debug('Disabling checkbox');
  2686. module.set.disabled();
  2687. settings.onDisable.call(input);
  2688. },
  2689. get: {
  2690. radios: function() {
  2691. var
  2692. name = module.get.name()
  2693. ;
  2694. return $('input[name="' + name + '"]').closest(selector.checkbox);
  2695. },
  2696. otherRadios: function() {
  2697. return module.get.radios().not($module);
  2698. },
  2699. name: function() {
  2700. return $input.attr('name');
  2701. }
  2702. },
  2703. is: {
  2704. initialLoad: function() {
  2705. return initialLoad;
  2706. },
  2707. radio: function() {
  2708. return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
  2709. },
  2710. indeterminate: function() {
  2711. return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
  2712. },
  2713. checked: function() {
  2714. return $input.prop('checked') !== undefined && $input.prop('checked');
  2715. },
  2716. disabled: function() {
  2717. return $input.prop('disabled') !== undefined && $input.prop('disabled');
  2718. },
  2719. enabled: function() {
  2720. return !module.is.disabled();
  2721. },
  2722. determinate: function() {
  2723. return !module.is.indeterminate();
  2724. },
  2725. unchecked: function() {
  2726. return !module.is.checked();
  2727. }
  2728. },
  2729. should: {
  2730. allowCheck: function() {
  2731. if(module.is.determinate() && module.is.checked() && !module.should.forceCallbacks() ) {
  2732. module.debug('Should not allow check, checkbox is already checked');
  2733. return false;
  2734. }
  2735. if(settings.beforeChecked.apply(input) === false) {
  2736. module.debug('Should not allow check, beforeChecked cancelled');
  2737. return false;
  2738. }
  2739. return true;
  2740. },
  2741. allowUncheck: function() {
  2742. if(module.is.determinate() && module.is.unchecked() && !module.should.forceCallbacks() ) {
  2743. module.debug('Should not allow uncheck, checkbox is already unchecked');
  2744. return false;
  2745. }
  2746. if(settings.beforeUnchecked.apply(input) === false) {
  2747. module.debug('Should not allow uncheck, beforeUnchecked cancelled');
  2748. return false;
  2749. }
  2750. return true;
  2751. },
  2752. allowIndeterminate: function() {
  2753. if(module.is.indeterminate() && !module.should.forceCallbacks() ) {
  2754. module.debug('Should not allow indeterminate, checkbox is already indeterminate');
  2755. return false;
  2756. }
  2757. if(settings.beforeIndeterminate.apply(input) === false) {
  2758. module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
  2759. return false;
  2760. }
  2761. return true;
  2762. },
  2763. allowDeterminate: function() {
  2764. if(module.is.determinate() && !module.should.forceCallbacks() ) {
  2765. module.debug('Should not allow determinate, checkbox is already determinate');
  2766. return false;
  2767. }
  2768. if(settings.beforeDeterminate.apply(input) === false) {
  2769. module.debug('Should not allow determinate, beforeDeterminate cancelled');
  2770. return false;
  2771. }
  2772. return true;
  2773. },
  2774. forceCallbacks: function() {
  2775. return (module.is.initialLoad() && settings.fireOnInit);
  2776. },
  2777. ignoreCallbacks: function() {
  2778. return (initialLoad && !settings.fireOnInit);
  2779. }
  2780. },
  2781. can: {
  2782. change: function() {
  2783. return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
  2784. },
  2785. uncheck: function() {
  2786. return (typeof settings.uncheckable === 'boolean')
  2787. ? settings.uncheckable
  2788. : !module.is.radio()
  2789. ;
  2790. }
  2791. },
  2792. set: {
  2793. initialLoad: function() {
  2794. initialLoad = true;
  2795. },
  2796. checked: function() {
  2797. module.verbose('Setting class to checked');
  2798. $module
  2799. .removeClass(className.indeterminate)
  2800. .addClass(className.checked)
  2801. ;
  2802. if( module.is.radio() ) {
  2803. module.uncheckOthers();
  2804. }
  2805. if(!module.is.indeterminate() && module.is.checked()) {
  2806. module.debug('Input is already checked, skipping input property change');
  2807. return;
  2808. }
  2809. module.verbose('Setting state to checked', input);
  2810. $input
  2811. .prop('indeterminate', false)
  2812. .prop('checked', true)
  2813. ;
  2814. module.trigger.change();
  2815. },
  2816. unchecked: function() {
  2817. module.verbose('Removing checked class');
  2818. $module
  2819. .removeClass(className.indeterminate)
  2820. .removeClass(className.checked)
  2821. ;
  2822. if(!module.is.indeterminate() && module.is.unchecked() ) {
  2823. module.debug('Input is already unchecked');
  2824. return;
  2825. }
  2826. module.debug('Setting state to unchecked');
  2827. $input
  2828. .prop('indeterminate', false)
  2829. .prop('checked', false)
  2830. ;
  2831. module.trigger.change();
  2832. },
  2833. indeterminate: function() {
  2834. module.verbose('Setting class to indeterminate');
  2835. $module
  2836. .addClass(className.indeterminate)
  2837. ;
  2838. if( module.is.indeterminate() ) {
  2839. module.debug('Input is already indeterminate, skipping input property change');
  2840. return;
  2841. }
  2842. module.debug('Setting state to indeterminate');
  2843. $input
  2844. .prop('indeterminate', true)
  2845. ;
  2846. module.trigger.change();
  2847. },
  2848. determinate: function() {
  2849. module.verbose('Removing indeterminate class');
  2850. $module
  2851. .removeClass(className.indeterminate)
  2852. ;
  2853. if( module.is.determinate() ) {
  2854. module.debug('Input is already determinate, skipping input property change');
  2855. return;
  2856. }
  2857. module.debug('Setting state to determinate');
  2858. $input
  2859. .prop('indeterminate', false)
  2860. ;
  2861. },
  2862. disabled: function() {
  2863. module.verbose('Setting class to disabled');
  2864. $module
  2865. .addClass(className.disabled)
  2866. ;
  2867. if( module.is.disabled() ) {
  2868. module.debug('Input is already disabled, skipping input property change');
  2869. return;
  2870. }
  2871. module.debug('Setting state to disabled');
  2872. $input
  2873. .prop('disabled', 'disabled')
  2874. ;
  2875. module.trigger.change();
  2876. },
  2877. enabled: function() {
  2878. module.verbose('Removing disabled class');
  2879. $module.removeClass(className.disabled);
  2880. if( module.is.enabled() ) {
  2881. module.debug('Input is already enabled, skipping input property change');
  2882. return;
  2883. }
  2884. module.debug('Setting state to enabled');
  2885. $input
  2886. .prop('disabled', false)
  2887. ;
  2888. module.trigger.change();
  2889. },
  2890. tabbable: function() {
  2891. module.verbose('Adding tabindex to checkbox');
  2892. if( $input.attr('tabindex') === undefined) {
  2893. $input.attr('tabindex', 0);
  2894. }
  2895. }
  2896. },
  2897. remove: {
  2898. initialLoad: function() {
  2899. initialLoad = false;
  2900. }
  2901. },
  2902. trigger: {
  2903. change: function() {
  2904. var
  2905. events = document.createEvent('HTMLEvents'),
  2906. inputElement = $input[0]
  2907. ;
  2908. if(inputElement) {
  2909. module.verbose('Triggering native change event');
  2910. events.initEvent('change', true, false);
  2911. inputElement.dispatchEvent(events);
  2912. }
  2913. }
  2914. },
  2915. create: {
  2916. label: function() {
  2917. if($input.prevAll(selector.label).length > 0) {
  2918. $input.prev(selector.label).detach().insertAfter($input);
  2919. module.debug('Moving existing label', $label);
  2920. }
  2921. else if( !module.has.label() ) {
  2922. $label = $('<label>').insertAfter($input);
  2923. module.debug('Creating label', $label);
  2924. }
  2925. }
  2926. },
  2927. has: {
  2928. label: function() {
  2929. return ($label.length > 0);
  2930. }
  2931. },
  2932. bind: {
  2933. events: function() {
  2934. module.verbose('Attaching checkbox events');
  2935. $module
  2936. .on('click' + eventNamespace, module.event.click)
  2937. .on('keydown' + eventNamespace, selector.input, module.event.keydown)
  2938. .on('keyup' + eventNamespace, selector.input, module.event.keyup)
  2939. ;
  2940. }
  2941. },
  2942. unbind: {
  2943. events: function() {
  2944. module.debug('Removing events');
  2945. $module
  2946. .off(eventNamespace)
  2947. ;
  2948. }
  2949. },
  2950. uncheckOthers: function() {
  2951. var
  2952. $radios = module.get.otherRadios()
  2953. ;
  2954. module.debug('Unchecking other radios', $radios);
  2955. $radios.removeClass(className.checked);
  2956. },
  2957. toggle: function() {
  2958. if( !module.can.change() ) {
  2959. if(!module.is.radio()) {
  2960. module.debug('Checkbox is read-only or disabled, ignoring toggle');
  2961. }
  2962. return;
  2963. }
  2964. if( module.is.indeterminate() || module.is.unchecked() ) {
  2965. module.debug('Currently unchecked');
  2966. module.check();
  2967. }
  2968. else if( module.is.checked() && module.can.uncheck() ) {
  2969. module.debug('Currently checked');
  2970. module.uncheck();
  2971. }
  2972. },
  2973. setting: function(name, value) {
  2974. module.debug('Changing setting', name, value);
  2975. if( $.isPlainObject(name) ) {
  2976. $.extend(true, settings, name);
  2977. }
  2978. else if(value !== undefined) {
  2979. settings[name] = value;
  2980. }
  2981. else {
  2982. return settings[name];
  2983. }
  2984. },
  2985. internal: function(name, value) {
  2986. if( $.isPlainObject(name) ) {
  2987. $.extend(true, module, name);
  2988. }
  2989. else if(value !== undefined) {
  2990. module[name] = value;
  2991. }
  2992. else {
  2993. return module[name];
  2994. }
  2995. },
  2996. debug: function() {
  2997. if(settings.debug) {
  2998. if(settings.performance) {
  2999. module.performance.log(arguments);
  3000. }
  3001. else {
  3002. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3003. module.debug.apply(console, arguments);
  3004. }
  3005. }
  3006. },
  3007. verbose: function() {
  3008. if(settings.verbose && settings.debug) {
  3009. if(settings.performance) {
  3010. module.performance.log(arguments);
  3011. }
  3012. else {
  3013. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3014. module.verbose.apply(console, arguments);
  3015. }
  3016. }
  3017. },
  3018. error: function() {
  3019. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3020. module.error.apply(console, arguments);
  3021. },
  3022. performance: {
  3023. log: function(message) {
  3024. var
  3025. currentTime,
  3026. executionTime,
  3027. previousTime
  3028. ;
  3029. if(settings.performance) {
  3030. currentTime = new Date().getTime();
  3031. previousTime = time || currentTime;
  3032. executionTime = currentTime - previousTime;
  3033. time = currentTime;
  3034. performance.push({
  3035. 'Name' : message[0],
  3036. 'Arguments' : [].slice.call(message, 1) || '',
  3037. 'Element' : element,
  3038. 'Execution Time' : executionTime
  3039. });
  3040. }
  3041. clearTimeout(module.performance.timer);
  3042. module.performance.timer = setTimeout(module.performance.display, 500);
  3043. },
  3044. display: function() {
  3045. var
  3046. title = settings.name + ':',
  3047. totalTime = 0
  3048. ;
  3049. time = false;
  3050. clearTimeout(module.performance.timer);
  3051. $.each(performance, function(index, data) {
  3052. totalTime += data['Execution Time'];
  3053. });
  3054. title += ' ' + totalTime + 'ms';
  3055. if(moduleSelector) {
  3056. title += ' \'' + moduleSelector + '\'';
  3057. }
  3058. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3059. console.groupCollapsed(title);
  3060. if(console.table) {
  3061. console.table(performance);
  3062. }
  3063. else {
  3064. $.each(performance, function(index, data) {
  3065. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  3066. });
  3067. }
  3068. console.groupEnd();
  3069. }
  3070. performance = [];
  3071. }
  3072. },
  3073. invoke: function(query, passedArguments, context) {
  3074. var
  3075. object = instance,
  3076. maxDepth,
  3077. found,
  3078. response
  3079. ;
  3080. passedArguments = passedArguments || queryArguments;
  3081. context = element || context;
  3082. if(typeof query == 'string' && object !== undefined) {
  3083. query = query.split(/[\. ]/);
  3084. maxDepth = query.length - 1;
  3085. $.each(query, function(depth, value) {
  3086. var camelCaseValue = (depth != maxDepth)
  3087. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3088. : query
  3089. ;
  3090. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  3091. object = object[camelCaseValue];
  3092. }
  3093. else if( object[camelCaseValue] !== undefined ) {
  3094. found = object[camelCaseValue];
  3095. return false;
  3096. }
  3097. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  3098. object = object[value];
  3099. }
  3100. else if( object[value] !== undefined ) {
  3101. found = object[value];
  3102. return false;
  3103. }
  3104. else {
  3105. module.error(error.method, query);
  3106. return false;
  3107. }
  3108. });
  3109. }
  3110. if ( $.isFunction( found ) ) {
  3111. response = found.apply(context, passedArguments);
  3112. }
  3113. else if(found !== undefined) {
  3114. response = found;
  3115. }
  3116. if($.isArray(returnedValue)) {
  3117. returnedValue.push(response);
  3118. }
  3119. else if(returnedValue !== undefined) {
  3120. returnedValue = [returnedValue, response];
  3121. }
  3122. else if(response !== undefined) {
  3123. returnedValue = response;
  3124. }
  3125. return found;
  3126. }
  3127. };
  3128. if(methodInvoked) {
  3129. if(instance === undefined) {
  3130. module.initialize();
  3131. }
  3132. module.invoke(query);
  3133. }
  3134. else {
  3135. if(instance !== undefined) {
  3136. instance.invoke('destroy');
  3137. }
  3138. module.initialize();
  3139. }
  3140. })
  3141. ;
  3142. return (returnedValue !== undefined)
  3143. ? returnedValue
  3144. : this
  3145. ;
  3146. };
  3147. $.fn.checkbox.settings = {
  3148. name : 'Checkbox',
  3149. namespace : 'checkbox',
  3150. debug : false,
  3151. verbose : true,
  3152. performance : true,
  3153. // delegated event context
  3154. uncheckable : 'auto',
  3155. fireOnInit : false,
  3156. onChange : function(){},
  3157. beforeChecked : function(){},
  3158. beforeUnchecked : function(){},
  3159. beforeDeterminate : function(){},
  3160. beforeIndeterminate : function(){},
  3161. onChecked : function(){},
  3162. onUnchecked : function(){},
  3163. onDeterminate : function() {},
  3164. onIndeterminate : function() {},
  3165. onEnabled : function(){},
  3166. onDisabled : function(){},
  3167. className : {
  3168. checked : 'checked',
  3169. indeterminate : 'indeterminate',
  3170. disabled : 'disabled',
  3171. hidden : 'hidden',
  3172. radio : 'radio',
  3173. readOnly : 'read-only'
  3174. },
  3175. error : {
  3176. method : 'The method you called is not defined'
  3177. },
  3178. selector : {
  3179. checkbox : '.ui.checkbox',
  3180. label : 'label, .box',
  3181. input : 'input[type="checkbox"], input[type="radio"]',
  3182. link : 'a[href]'
  3183. }
  3184. };
  3185. })( jQuery, window, document );
  3186. /*!
  3187. * # Semantic UI 2.1.6 - Dimmer
  3188. * http://github.com/semantic-org/semantic-ui/
  3189. *
  3190. *
  3191. * Copyright 2015 Contributors
  3192. * Released under the MIT license
  3193. * http://opensource.org/licenses/MIT
  3194. *
  3195. */
  3196. ;(function ( $, window, document, undefined ) {
  3197. "use strict";
  3198. $.fn.dimmer = function(parameters) {
  3199. var
  3200. $allModules = $(this),
  3201. time = new Date().getTime(),
  3202. performance = [],
  3203. query = arguments[0],
  3204. methodInvoked = (typeof query == 'string'),
  3205. queryArguments = [].slice.call(arguments, 1),
  3206. returnedValue
  3207. ;
  3208. $allModules
  3209. .each(function() {
  3210. var
  3211. settings = ( $.isPlainObject(parameters) )
  3212. ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
  3213. : $.extend({}, $.fn.dimmer.settings),
  3214. selector = settings.selector,
  3215. namespace = settings.namespace,
  3216. className = settings.className,
  3217. error = settings.error,
  3218. eventNamespace = '.' + namespace,
  3219. moduleNamespace = 'module-' + namespace,
  3220. moduleSelector = $allModules.selector || '',
  3221. clickEvent = ('ontouchstart' in document.documentElement)
  3222. ? 'touchstart'
  3223. : 'click',
  3224. $module = $(this),
  3225. $dimmer,
  3226. $dimmable,
  3227. element = this,
  3228. instance = $module.data(moduleNamespace),
  3229. module
  3230. ;
  3231. module = {
  3232. preinitialize: function() {
  3233. if( module.is.dimmer() ) {
  3234. $dimmable = $module.parent();
  3235. $dimmer = $module;
  3236. }
  3237. else {
  3238. $dimmable = $module;
  3239. if( module.has.dimmer() ) {
  3240. if(settings.dimmerName) {
  3241. $dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
  3242. }
  3243. else {
  3244. $dimmer = $dimmable.find(selector.dimmer);
  3245. }
  3246. }
  3247. else {
  3248. $dimmer = module.create();
  3249. }
  3250. }
  3251. },
  3252. initialize: function() {
  3253. module.debug('Initializing dimmer', settings);
  3254. module.bind.events();
  3255. module.set.dimmable();
  3256. module.instantiate();
  3257. },
  3258. instantiate: function() {
  3259. module.verbose('Storing instance of module', module);
  3260. instance = module;
  3261. $module
  3262. .data(moduleNamespace, instance)
  3263. ;
  3264. },
  3265. destroy: function() {
  3266. module.verbose('Destroying previous module', $dimmer);
  3267. module.unbind.events();
  3268. module.remove.variation();
  3269. $dimmable
  3270. .off(eventNamespace)
  3271. ;
  3272. },
  3273. bind: {
  3274. events: function() {
  3275. if(settings.on == 'hover') {
  3276. $dimmable
  3277. .on('mouseenter' + eventNamespace, module.show)
  3278. .on('mouseleave' + eventNamespace, module.hide)
  3279. ;
  3280. }
  3281. else if(settings.on == 'click') {
  3282. $dimmable
  3283. .on(clickEvent + eventNamespace, module.toggle)
  3284. ;
  3285. }
  3286. if( module.is.page() ) {
  3287. module.debug('Setting as a page dimmer', $dimmable);
  3288. module.set.pageDimmer();
  3289. }
  3290. if( module.is.closable() ) {
  3291. module.verbose('Adding dimmer close event', $dimmer);
  3292. $dimmable
  3293. .on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
  3294. ;
  3295. }
  3296. }
  3297. },
  3298. unbind: {
  3299. events: function() {
  3300. $module
  3301. .removeData(moduleNamespace)
  3302. ;
  3303. }
  3304. },
  3305. event: {
  3306. click: function(event) {
  3307. module.verbose('Determining if event occured on dimmer', event);
  3308. if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
  3309. module.hide();
  3310. event.stopImmediatePropagation();
  3311. }
  3312. }
  3313. },
  3314. addContent: function(element) {
  3315. var
  3316. $content = $(element)
  3317. ;
  3318. module.debug('Add content to dimmer', $content);
  3319. if($content.parent()[0] !== $dimmer[0]) {
  3320. $content.detach().appendTo($dimmer);
  3321. }
  3322. },
  3323. create: function() {
  3324. var
  3325. $element = $( settings.template.dimmer() )
  3326. ;
  3327. if(settings.variation) {
  3328. module.debug('Creating dimmer with variation', settings.variation);
  3329. $element.addClass(settings.variation);
  3330. }
  3331. if(settings.dimmerName) {
  3332. module.debug('Creating named dimmer', settings.dimmerName);
  3333. $element.addClass(settings.dimmerName);
  3334. }
  3335. $element
  3336. .appendTo($dimmable)
  3337. ;
  3338. return $element;
  3339. },
  3340. show: function(callback) {
  3341. callback = $.isFunction(callback)
  3342. ? callback
  3343. : function(){}
  3344. ;
  3345. module.debug('Showing dimmer', $dimmer, settings);
  3346. if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
  3347. module.animate.show(callback);
  3348. settings.onShow.call(element);
  3349. settings.onChange.call(element);
  3350. }
  3351. else {
  3352. module.debug('Dimmer is already shown or disabled');
  3353. }
  3354. },
  3355. hide: function(callback) {
  3356. callback = $.isFunction(callback)
  3357. ? callback
  3358. : function(){}
  3359. ;
  3360. if( module.is.dimmed() || module.is.animating() ) {
  3361. module.debug('Hiding dimmer', $dimmer);
  3362. module.animate.hide(callback);
  3363. settings.onHide.call(element);
  3364. settings.onChange.call(element);
  3365. }
  3366. else {
  3367. module.debug('Dimmer is not visible');
  3368. }
  3369. },
  3370. toggle: function() {
  3371. module.verbose('Toggling dimmer visibility', $dimmer);
  3372. if( !module.is.dimmed() ) {
  3373. module.show();
  3374. }
  3375. else {
  3376. module.hide();
  3377. }
  3378. },
  3379. animate: {
  3380. show: function(callback) {
  3381. callback = $.isFunction(callback)
  3382. ? callback
  3383. : function(){}
  3384. ;
  3385. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3386. if(settings.opacity !== 'auto') {
  3387. module.set.opacity();
  3388. }
  3389. $dimmer
  3390. .transition({
  3391. animation : settings.transition + ' in',
  3392. queue : false,
  3393. duration : module.get.duration(),
  3394. useFailSafe : true,
  3395. onStart : function() {
  3396. module.set.dimmed();
  3397. },
  3398. onComplete : function() {
  3399. module.set.active();
  3400. callback();
  3401. }
  3402. })
  3403. ;
  3404. }
  3405. else {
  3406. module.verbose('Showing dimmer animation with javascript');
  3407. module.set.dimmed();
  3408. if(settings.opacity == 'auto') {
  3409. settings.opacity = 0.8;
  3410. }
  3411. $dimmer
  3412. .stop()
  3413. .css({
  3414. opacity : 0,
  3415. width : '100%',
  3416. height : '100%'
  3417. })
  3418. .fadeTo(module.get.duration(), settings.opacity, function() {
  3419. $dimmer.removeAttr('style');
  3420. module.set.active();
  3421. callback();
  3422. })
  3423. ;
  3424. }
  3425. },
  3426. hide: function(callback) {
  3427. callback = $.isFunction(callback)
  3428. ? callback
  3429. : function(){}
  3430. ;
  3431. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  3432. module.verbose('Hiding dimmer with css');
  3433. $dimmer
  3434. .transition({
  3435. animation : settings.transition + ' out',
  3436. queue : false,
  3437. duration : module.get.duration(),
  3438. useFailSafe : true,
  3439. onStart : function() {
  3440. module.remove.dimmed();
  3441. },
  3442. onComplete : function() {
  3443. module.remove.active();
  3444. callback();
  3445. }
  3446. })
  3447. ;
  3448. }
  3449. else {
  3450. module.verbose('Hiding dimmer with javascript');
  3451. module.remove.dimmed();
  3452. $dimmer
  3453. .stop()
  3454. .fadeOut(module.get.duration(), function() {
  3455. module.remove.active();
  3456. $dimmer.removeAttr('style');
  3457. callback();
  3458. })
  3459. ;
  3460. }
  3461. }
  3462. },
  3463. get: {
  3464. dimmer: function() {
  3465. return $dimmer;
  3466. },
  3467. duration: function() {
  3468. if(typeof settings.duration == 'object') {
  3469. if( module.is.active() ) {
  3470. return settings.duration.hide;
  3471. }
  3472. else {
  3473. return settings.duration.show;
  3474. }
  3475. }
  3476. return settings.duration;
  3477. }
  3478. },
  3479. has: {
  3480. dimmer: function() {
  3481. if(settings.dimmerName) {
  3482. return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
  3483. }
  3484. else {
  3485. return ( $module.find(selector.dimmer).length > 0 );
  3486. }
  3487. }
  3488. },
  3489. is: {
  3490. active: function() {
  3491. return $dimmer.hasClass(className.active);
  3492. },
  3493. animating: function() {
  3494. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
  3495. },
  3496. closable: function() {
  3497. if(settings.closable == 'auto') {
  3498. if(settings.on == 'hover') {
  3499. return false;
  3500. }
  3501. return true;
  3502. }
  3503. return settings.closable;
  3504. },
  3505. dimmer: function() {
  3506. return $module.hasClass(className.dimmer);
  3507. },
  3508. dimmable: function() {
  3509. return $module.hasClass(className.dimmable);
  3510. },
  3511. dimmed: function() {
  3512. return $dimmable.hasClass(className.dimmed);
  3513. },
  3514. disabled: function() {
  3515. return $dimmable.hasClass(className.disabled);
  3516. },
  3517. enabled: function() {
  3518. return !module.is.disabled();
  3519. },
  3520. page: function () {
  3521. return $dimmable.is('body');
  3522. },
  3523. pageDimmer: function() {
  3524. return $dimmer.hasClass(className.pageDimmer);
  3525. }
  3526. },
  3527. can: {
  3528. show: function() {
  3529. return !$dimmer.hasClass(className.disabled);
  3530. }
  3531. },
  3532. set: {
  3533. opacity: function(opacity) {
  3534. var
  3535. color = $dimmer.css('background-color'),
  3536. colorArray = color.split(','),
  3537. isRGBA = (colorArray && colorArray.length == 4)
  3538. ;
  3539. opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
  3540. if(isRGBA) {
  3541. colorArray[3] = opacity + ')';
  3542. color = colorArray.join(',');
  3543. }
  3544. else {
  3545. color = 'rgba(0, 0, 0, ' + opacity + ')';
  3546. }
  3547. module.debug('Setting opacity to', opacity);
  3548. $dimmer.css('background-color', color);
  3549. },
  3550. active: function() {
  3551. $dimmer.addClass(className.active);
  3552. },
  3553. dimmable: function() {
  3554. $dimmable.addClass(className.dimmable);
  3555. },
  3556. dimmed: function() {
  3557. $dimmable.addClass(className.dimmed);
  3558. },
  3559. pageDimmer: function() {
  3560. $dimmer.addClass(className.pageDimmer);
  3561. },
  3562. disabled: function() {
  3563. $dimmer.addClass(className.disabled);
  3564. },
  3565. variation: function(variation) {
  3566. variation = variation || settings.variation;
  3567. if(variation) {
  3568. $dimmer.addClass(variation);
  3569. }
  3570. }
  3571. },
  3572. remove: {
  3573. active: function() {
  3574. $dimmer
  3575. .removeClass(className.active)
  3576. ;
  3577. },
  3578. dimmed: function() {
  3579. $dimmable.removeClass(className.dimmed);
  3580. },
  3581. disabled: function() {
  3582. $dimmer.removeClass(className.disabled);
  3583. },
  3584. variation: function(variation) {
  3585. variation = variation || settings.variation;
  3586. if(variation) {
  3587. $dimmer.removeClass(variation);
  3588. }
  3589. }
  3590. },
  3591. setting: function(name, value) {
  3592. module.debug('Changing setting', name, value);
  3593. if( $.isPlainObject(name) ) {
  3594. $.extend(true, settings, name);
  3595. }
  3596. else if(value !== undefined) {
  3597. settings[name] = value;
  3598. }
  3599. else {
  3600. return settings[name];
  3601. }
  3602. },
  3603. internal: function(name, value) {
  3604. if( $.isPlainObject(name) ) {
  3605. $.extend(true, module, name);
  3606. }
  3607. else if(value !== undefined) {
  3608. module[name] = value;
  3609. }
  3610. else {
  3611. return module[name];
  3612. }
  3613. },
  3614. debug: function() {
  3615. if(settings.debug) {
  3616. if(settings.performance) {
  3617. module.performance.log(arguments);
  3618. }
  3619. else {
  3620. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3621. module.debug.apply(console, arguments);
  3622. }
  3623. }
  3624. },
  3625. verbose: function() {
  3626. if(settings.verbose && settings.debug) {
  3627. if(settings.performance) {
  3628. module.performance.log(arguments);
  3629. }
  3630. else {
  3631. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  3632. module.verbose.apply(console, arguments);
  3633. }
  3634. }
  3635. },
  3636. error: function() {
  3637. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  3638. module.error.apply(console, arguments);
  3639. },
  3640. performance: {
  3641. log: function(message) {
  3642. var
  3643. currentTime,
  3644. executionTime,
  3645. previousTime
  3646. ;
  3647. if(settings.performance) {
  3648. currentTime = new Date().getTime();
  3649. previousTime = time || currentTime;
  3650. executionTime = currentTime - previousTime;
  3651. time = currentTime;
  3652. performance.push({
  3653. 'Name' : message[0],
  3654. 'Arguments' : [].slice.call(message, 1) || '',
  3655. 'Element' : element,
  3656. 'Execution Time' : executionTime
  3657. });
  3658. }
  3659. clearTimeout(module.performance.timer);
  3660. module.performance.timer = setTimeout(module.performance.display, 500);
  3661. },
  3662. display: function() {
  3663. var
  3664. title = settings.name + ':',
  3665. totalTime = 0
  3666. ;
  3667. time = false;
  3668. clearTimeout(module.performance.timer);
  3669. $.each(performance, function(index, data) {
  3670. totalTime += data['Execution Time'];
  3671. });
  3672. title += ' ' + totalTime + 'ms';
  3673. if(moduleSelector) {
  3674. title += ' \'' + moduleSelector + '\'';
  3675. }
  3676. if($allModules.length > 1) {
  3677. title += ' ' + '(' + $allModules.length + ')';
  3678. }
  3679. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  3680. console.groupCollapsed(title);
  3681. if(console.table) {
  3682. console.table(performance);
  3683. }
  3684. else {
  3685. $.each(performance, function(index, data) {
  3686. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  3687. });
  3688. }
  3689. console.groupEnd();
  3690. }
  3691. performance = [];
  3692. }
  3693. },
  3694. invoke: function(query, passedArguments, context) {
  3695. var
  3696. object = instance,
  3697. maxDepth,
  3698. found,
  3699. response
  3700. ;
  3701. passedArguments = passedArguments || queryArguments;
  3702. context = element || context;
  3703. if(typeof query == 'string' && object !== undefined) {
  3704. query = query.split(/[\. ]/);
  3705. maxDepth = query.length - 1;
  3706. $.each(query, function(depth, value) {
  3707. var camelCaseValue = (depth != maxDepth)
  3708. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  3709. : query
  3710. ;
  3711. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  3712. object = object[camelCaseValue];
  3713. }
  3714. else if( object[camelCaseValue] !== undefined ) {
  3715. found = object[camelCaseValue];
  3716. return false;
  3717. }
  3718. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  3719. object = object[value];
  3720. }
  3721. else if( object[value] !== undefined ) {
  3722. found = object[value];
  3723. return false;
  3724. }
  3725. else {
  3726. module.error(error.method, query);
  3727. return false;
  3728. }
  3729. });
  3730. }
  3731. if ( $.isFunction( found ) ) {
  3732. response = found.apply(context, passedArguments);
  3733. }
  3734. else if(found !== undefined) {
  3735. response = found;
  3736. }
  3737. if($.isArray(returnedValue)) {
  3738. returnedValue.push(response);
  3739. }
  3740. else if(returnedValue !== undefined) {
  3741. returnedValue = [returnedValue, response];
  3742. }
  3743. else if(response !== undefined) {
  3744. returnedValue = response;
  3745. }
  3746. return found;
  3747. }
  3748. };
  3749. module.preinitialize();
  3750. if(methodInvoked) {
  3751. if(instance === undefined) {
  3752. module.initialize();
  3753. }
  3754. module.invoke(query);
  3755. }
  3756. else {
  3757. if(instance !== undefined) {
  3758. instance.invoke('destroy');
  3759. }
  3760. module.initialize();
  3761. }
  3762. })
  3763. ;
  3764. return (returnedValue !== undefined)
  3765. ? returnedValue
  3766. : this
  3767. ;
  3768. };
  3769. $.fn.dimmer.settings = {
  3770. name : 'Dimmer',
  3771. namespace : 'dimmer',
  3772. debug : false,
  3773. verbose : false,
  3774. performance : true,
  3775. // name to distinguish between multiple dimmers in context
  3776. dimmerName : false,
  3777. // whether to add a variation type
  3778. variation : false,
  3779. // whether to bind close events
  3780. closable : 'auto',
  3781. // whether to use css animations
  3782. useCSS : true,
  3783. // css animation to use
  3784. transition : 'fade',
  3785. // event to bind to
  3786. on : false,
  3787. // overriding opacity value
  3788. opacity : 'auto',
  3789. // transition durations
  3790. duration : {
  3791. show : 500,
  3792. hide : 500
  3793. },
  3794. onChange : function(){},
  3795. onShow : function(){},
  3796. onHide : function(){},
  3797. error : {
  3798. method : 'The method you called is not defined.'
  3799. },
  3800. className : {
  3801. active : 'active',
  3802. animating : 'animating',
  3803. dimmable : 'dimmable',
  3804. dimmed : 'dimmed',
  3805. dimmer : 'dimmer',
  3806. disabled : 'disabled',
  3807. hide : 'hide',
  3808. pageDimmer : 'page',
  3809. show : 'show'
  3810. },
  3811. selector: {
  3812. dimmer : '> .ui.dimmer',
  3813. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  3814. },
  3815. template: {
  3816. dimmer: function() {
  3817. return $('<div />').attr('class', 'ui dimmer');
  3818. }
  3819. }
  3820. };
  3821. })( jQuery, window, document );
  3822. /*!
  3823. * # Semantic UI 2.1.6 - Dropdown
  3824. * http://github.com/semantic-org/semantic-ui/
  3825. *
  3826. *
  3827. * Copyright 2015 Contributors
  3828. * Released under the MIT license
  3829. * http://opensource.org/licenses/MIT
  3830. *
  3831. */
  3832. ;(function ( $, window, document, undefined ) {
  3833. "use strict";
  3834. $.fn.dropdown = function(parameters) {
  3835. var
  3836. $allModules = $(this),
  3837. $document = $(document),
  3838. moduleSelector = $allModules.selector || '',
  3839. hasTouch = ('ontouchstart' in document.documentElement),
  3840. time = new Date().getTime(),
  3841. performance = [],
  3842. query = arguments[0],
  3843. methodInvoked = (typeof query == 'string'),
  3844. queryArguments = [].slice.call(arguments, 1),
  3845. returnedValue
  3846. ;
  3847. $allModules
  3848. .each(function(elementIndex) {
  3849. var
  3850. settings = ( $.isPlainObject(parameters) )
  3851. ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
  3852. : $.extend({}, $.fn.dropdown.settings),
  3853. className = settings.className,
  3854. message = settings.message,
  3855. fields = settings.fields,
  3856. keys = settings.keys,
  3857. metadata = settings.metadata,
  3858. namespace = settings.namespace,
  3859. regExp = settings.regExp,
  3860. selector = settings.selector,
  3861. error = settings.error,
  3862. templates = settings.templates,
  3863. eventNamespace = '.' + namespace,
  3864. moduleNamespace = 'module-' + namespace,
  3865. $module = $(this),
  3866. $context = $(settings.context),
  3867. $text = $module.find(selector.text),
  3868. $search = $module.find(selector.search),
  3869. $input = $module.find(selector.input),
  3870. $icon = $module.find(selector.icon),
  3871. $combo = ($module.prev().find(selector.text).length > 0)
  3872. ? $module.prev().find(selector.text)
  3873. : $module.prev(),
  3874. $menu = $module.children(selector.menu),
  3875. $item = $menu.find(selector.item),
  3876. activated = false,
  3877. itemActivated = false,
  3878. internalChange = false,
  3879. element = this,
  3880. instance = $module.data(moduleNamespace),
  3881. initialLoad,
  3882. pageLostFocus,
  3883. elementNamespace,
  3884. id,
  3885. selectObserver,
  3886. menuObserver,
  3887. module
  3888. ;
  3889. module = {
  3890. initialize: function() {
  3891. module.debug('Initializing dropdown', settings);
  3892. if( module.is.alreadySetup() ) {
  3893. module.setup.reference();
  3894. }
  3895. else {
  3896. module.setup.layout();
  3897. module.refreshData();
  3898. module.save.defaults();
  3899. module.restore.selected();
  3900. module.create.id();
  3901. module.bind.events();
  3902. module.observeChanges();
  3903. module.instantiate();
  3904. }
  3905. },
  3906. instantiate: function() {
  3907. module.verbose('Storing instance of dropdown', module);
  3908. instance = module;
  3909. $module
  3910. .data(moduleNamespace, module)
  3911. ;
  3912. },
  3913. destroy: function() {
  3914. module.verbose('Destroying previous dropdown', $module);
  3915. module.remove.tabbable();
  3916. $module
  3917. .off(eventNamespace)
  3918. .removeData(moduleNamespace)
  3919. ;
  3920. $menu
  3921. .off(eventNamespace)
  3922. ;
  3923. $document
  3924. .off(elementNamespace)
  3925. ;
  3926. if(selectObserver) {
  3927. selectObserver.disconnect();
  3928. }
  3929. if(menuObserver) {
  3930. menuObserver.disconnect();
  3931. }
  3932. },
  3933. observeChanges: function() {
  3934. if('MutationObserver' in window) {
  3935. selectObserver = new MutationObserver(function(mutations) {
  3936. module.debug('<select> modified, recreating menu');
  3937. module.setup.select();
  3938. });
  3939. menuObserver = new MutationObserver(function(mutations) {
  3940. module.debug('Menu modified, updating selector cache');
  3941. module.refresh();
  3942. });
  3943. if(module.has.input()) {
  3944. selectObserver.observe($input[0], {
  3945. childList : true,
  3946. subtree : true
  3947. });
  3948. }
  3949. if(module.has.menu()) {
  3950. menuObserver.observe($menu[0], {
  3951. childList : true,
  3952. subtree : true
  3953. });
  3954. }
  3955. module.debug('Setting up mutation observer', selectObserver, menuObserver);
  3956. }
  3957. },
  3958. create: {
  3959. id: function() {
  3960. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  3961. elementNamespace = '.' + id;
  3962. module.verbose('Creating unique id for element', id);
  3963. },
  3964. userChoice: function(values) {
  3965. var
  3966. $userChoices,
  3967. $userChoice,
  3968. isUserValue,
  3969. html
  3970. ;
  3971. values = values || module.get.userValues();
  3972. if(!values) {
  3973. return false;
  3974. }
  3975. values = $.isArray(values)
  3976. ? values
  3977. : [values]
  3978. ;
  3979. $.each(values, function(index, value) {
  3980. if(module.get.item(value) === false) {
  3981. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  3982. $userChoice = $('<div />')
  3983. .html(html)
  3984. .attr('data-' + metadata.value, value)
  3985. .attr('data-' + metadata.text, value)
  3986. .addClass(className.addition)
  3987. .addClass(className.item)
  3988. ;
  3989. $userChoices = ($userChoices === undefined)
  3990. ? $userChoice
  3991. : $userChoices.add($userChoice)
  3992. ;
  3993. module.verbose('Creating user choices for value', value, $userChoice);
  3994. }
  3995. });
  3996. return $userChoices;
  3997. },
  3998. userLabels: function(value) {
  3999. var
  4000. userValues = module.get.userValues()
  4001. ;
  4002. if(userValues) {
  4003. module.debug('Adding user labels', userValues);
  4004. $.each(userValues, function(index, value) {
  4005. module.verbose('Adding custom user value');
  4006. module.add.label(value, value);
  4007. });
  4008. }
  4009. },
  4010. menu: function() {
  4011. $menu = $('<div />')
  4012. .addClass(className.menu)
  4013. .appendTo($module)
  4014. ;
  4015. }
  4016. },
  4017. search: function(query) {
  4018. query = (query !== undefined)
  4019. ? query
  4020. : module.get.query()
  4021. ;
  4022. module.verbose('Searching for query', query);
  4023. module.filter(query);
  4024. },
  4025. select: {
  4026. firstUnfiltered: function() {
  4027. module.verbose('Selecting first non-filtered element');
  4028. module.remove.selectedItem();
  4029. $item
  4030. .not(selector.unselectable)
  4031. .eq(0)
  4032. .addClass(className.selected)
  4033. ;
  4034. },
  4035. nextAvailable: function($selected) {
  4036. $selected = $selected.eq(0);
  4037. var
  4038. $nextAvailable = $selected.nextAll(selector.item).not(selector.unselectable).eq(0),
  4039. $prevAvailable = $selected.prevAll(selector.item).not(selector.unselectable).eq(0),
  4040. hasNext = ($nextAvailable.length > 0)
  4041. ;
  4042. if(hasNext) {
  4043. module.verbose('Moving selection to', $nextAvailable);
  4044. $nextAvailable.addClass(className.selected);
  4045. }
  4046. else {
  4047. module.verbose('Moving selection to', $prevAvailable);
  4048. $prevAvailable.addClass(className.selected);
  4049. }
  4050. }
  4051. },
  4052. setup: {
  4053. api: function() {
  4054. var
  4055. apiSettings = {
  4056. debug : settings.debug,
  4057. on : false
  4058. }
  4059. ;
  4060. module.verbose('First request, initializing API');
  4061. $module
  4062. .api(apiSettings)
  4063. ;
  4064. },
  4065. layout: function() {
  4066. if( $module.is('select') ) {
  4067. module.setup.select();
  4068. module.setup.returnedObject();
  4069. }
  4070. if( !module.has.menu() ) {
  4071. module.create.menu();
  4072. }
  4073. if( module.is.search() && !module.has.search() ) {
  4074. module.verbose('Adding search input');
  4075. $search = $('<input />')
  4076. .addClass(className.search)
  4077. .prop('autocomplete', 'off')
  4078. .insertBefore($text)
  4079. ;
  4080. }
  4081. if(settings.allowTab) {
  4082. module.set.tabbable();
  4083. }
  4084. },
  4085. select: function() {
  4086. var
  4087. selectValues = module.get.selectValues()
  4088. ;
  4089. module.debug('Dropdown initialized on a select', selectValues);
  4090. if( $module.is('select') ) {
  4091. $input = $module;
  4092. }
  4093. // see if select is placed correctly already
  4094. if($input.parent(selector.dropdown).length > 0) {
  4095. module.debug('UI dropdown already exists. Creating dropdown menu only');
  4096. $module = $input.closest(selector.dropdown);
  4097. if( !module.has.menu() ) {
  4098. module.create.menu();
  4099. }
  4100. $menu = $module.children(selector.menu);
  4101. module.setup.menu(selectValues);
  4102. }
  4103. else {
  4104. module.debug('Creating entire dropdown from select');
  4105. $module = $('<div />')
  4106. .attr('class', $input.attr('class') )
  4107. .addClass(className.selection)
  4108. .addClass(className.dropdown)
  4109. .html( templates.dropdown(selectValues) )
  4110. .insertBefore($input)
  4111. ;
  4112. if($input.hasClass(className.multiple) && $input.prop('multiple') === false) {
  4113. module.error(error.missingMultiple);
  4114. $input.prop('multiple', true);
  4115. }
  4116. if($input.is('[multiple]')) {
  4117. module.set.multiple();
  4118. }
  4119. if ($input.prop('disabled')) {
  4120. module.debug('Disabling dropdown')
  4121. $module.addClass(className.disabled)
  4122. }
  4123. $input
  4124. .removeAttr('class')
  4125. .detach()
  4126. .prependTo($module)
  4127. ;
  4128. }
  4129. module.refresh();
  4130. },
  4131. menu: function(values) {
  4132. $menu.html( templates.menu(values, fields));
  4133. $item = $menu.find(selector.item);
  4134. },
  4135. reference: function() {
  4136. module.debug('Dropdown behavior was called on select, replacing with closest dropdown');
  4137. // replace module reference
  4138. $module = $module.parent(selector.dropdown);
  4139. module.refresh();
  4140. module.setup.returnedObject();
  4141. // invoke method in context of current instance
  4142. if(methodInvoked) {
  4143. instance = module;
  4144. module.invoke(query);
  4145. }
  4146. },
  4147. returnedObject: function() {
  4148. var
  4149. $firstModules = $allModules.slice(0, elementIndex),
  4150. $lastModules = $allModules.slice(elementIndex + 1)
  4151. ;
  4152. // adjust all modules to use correct reference
  4153. $allModules = $firstModules.add($module).add($lastModules);
  4154. }
  4155. },
  4156. refresh: function() {
  4157. module.refreshSelectors();
  4158. module.refreshData();
  4159. },
  4160. refreshSelectors: function() {
  4161. module.verbose('Refreshing selector cache');
  4162. $text = $module.find(selector.text);
  4163. $search = $module.find(selector.search);
  4164. $input = $module.find(selector.input);
  4165. $icon = $module.find(selector.icon);
  4166. $combo = ($module.prev().find(selector.text).length > 0)
  4167. ? $module.prev().find(selector.text)
  4168. : $module.prev()
  4169. ;
  4170. $menu = $module.children(selector.menu);
  4171. $item = $menu.find(selector.item);
  4172. },
  4173. refreshData: function() {
  4174. module.verbose('Refreshing cached metadata');
  4175. $item
  4176. .removeData(metadata.text)
  4177. .removeData(metadata.value)
  4178. ;
  4179. $module
  4180. .removeData(metadata.defaultText)
  4181. .removeData(metadata.defaultValue)
  4182. .removeData(metadata.placeholderText)
  4183. ;
  4184. },
  4185. toggle: function() {
  4186. module.verbose('Toggling menu visibility');
  4187. if( !module.is.active() ) {
  4188. module.show();
  4189. }
  4190. else {
  4191. module.hide();
  4192. }
  4193. },
  4194. show: function(callback) {
  4195. callback = $.isFunction(callback)
  4196. ? callback
  4197. : function(){}
  4198. ;
  4199. if( module.can.show() && !module.is.active() ) {
  4200. module.debug('Showing dropdown');
  4201. if(module.is.multiple() && !module.has.search() && module.is.allFiltered()) {
  4202. return true;
  4203. }
  4204. if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
  4205. module.remove.message();
  4206. }
  4207. if(settings.onShow.call(element) !== false) {
  4208. module.animate.show(function() {
  4209. if( module.can.click() ) {
  4210. module.bind.intent();
  4211. }
  4212. module.set.visible();
  4213. callback.call(element);
  4214. });
  4215. }
  4216. }
  4217. },
  4218. hide: function(callback) {
  4219. callback = $.isFunction(callback)
  4220. ? callback
  4221. : function(){}
  4222. ;
  4223. if( module.is.active() ) {
  4224. module.debug('Hiding dropdown');
  4225. if(settings.onHide.call(element) !== false) {
  4226. module.animate.hide(function() {
  4227. module.remove.visible();
  4228. callback.call(element);
  4229. });
  4230. }
  4231. }
  4232. },
  4233. hideOthers: function() {
  4234. module.verbose('Finding other dropdowns to hide');
  4235. $allModules
  4236. .not($module)
  4237. .has(selector.menu + '.' + className.visible)
  4238. .dropdown('hide')
  4239. ;
  4240. },
  4241. hideMenu: function() {
  4242. module.verbose('Hiding menu instantaneously');
  4243. module.remove.active();
  4244. module.remove.visible();
  4245. $menu.transition('hide');
  4246. },
  4247. hideSubMenus: function() {
  4248. var
  4249. $subMenus = $menu.children(selector.item).find(selector.menu)
  4250. ;
  4251. module.verbose('Hiding sub menus', $subMenus);
  4252. $subMenus.transition('hide');
  4253. },
  4254. bind: {
  4255. events: function() {
  4256. if(hasTouch) {
  4257. module.bind.touchEvents();
  4258. }
  4259. module.bind.keyboardEvents();
  4260. module.bind.inputEvents();
  4261. module.bind.mouseEvents();
  4262. },
  4263. touchEvents: function() {
  4264. module.debug('Touch device detected binding additional touch events');
  4265. if( module.is.searchSelection() ) {
  4266. // do nothing special yet
  4267. }
  4268. else if( module.is.single() ) {
  4269. $module
  4270. .on('touchstart' + eventNamespace, module.event.test.toggle)
  4271. ;
  4272. }
  4273. $menu
  4274. .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
  4275. ;
  4276. },
  4277. keyboardEvents: function() {
  4278. module.verbose('Binding keyboard events');
  4279. $module
  4280. .on('keydown' + eventNamespace, module.event.keydown)
  4281. ;
  4282. if( module.has.search() ) {
  4283. $module
  4284. .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
  4285. ;
  4286. }
  4287. if( module.is.multiple() ) {
  4288. $document
  4289. .on('keydown' + elementNamespace, module.event.document.keydown)
  4290. ;
  4291. }
  4292. },
  4293. inputEvents: function() {
  4294. module.verbose('Binding input change events');
  4295. $module
  4296. .on('change' + eventNamespace, selector.input, module.event.change)
  4297. ;
  4298. },
  4299. mouseEvents: function() {
  4300. module.verbose('Binding mouse events');
  4301. if(module.is.multiple()) {
  4302. $module
  4303. .on('click' + eventNamespace, selector.label, module.event.label.click)
  4304. .on('click' + eventNamespace, selector.remove, module.event.remove.click)
  4305. ;
  4306. }
  4307. if( module.is.searchSelection() ) {
  4308. $module
  4309. .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
  4310. .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
  4311. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  4312. .on('click' + eventNamespace, selector.search, module.show)
  4313. .on('focus' + eventNamespace, selector.search, module.event.search.focus)
  4314. .on('blur' + eventNamespace, selector.search, module.event.search.blur)
  4315. .on('click' + eventNamespace, selector.text, module.event.text.focus)
  4316. ;
  4317. if(module.is.multiple()) {
  4318. $module
  4319. .on('click' + eventNamespace, module.event.click)
  4320. ;
  4321. }
  4322. }
  4323. else {
  4324. if(settings.on == 'click') {
  4325. $module
  4326. .on('click' + eventNamespace, selector.icon, module.event.icon.click)
  4327. .on('click' + eventNamespace, module.event.test.toggle)
  4328. ;
  4329. }
  4330. else if(settings.on == 'hover') {
  4331. $module
  4332. .on('mouseenter' + eventNamespace, module.delay.show)
  4333. .on('mouseleave' + eventNamespace, module.delay.hide)
  4334. ;
  4335. }
  4336. else {
  4337. $module
  4338. .on(settings.on + eventNamespace, module.toggle)
  4339. ;
  4340. }
  4341. $module
  4342. .on('mousedown' + eventNamespace, module.event.mousedown)
  4343. .on('mouseup' + eventNamespace, module.event.mouseup)
  4344. .on('focus' + eventNamespace, module.event.focus)
  4345. .on('blur' + eventNamespace, module.event.blur)
  4346. ;
  4347. }
  4348. $menu
  4349. .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
  4350. .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
  4351. .on('click' + eventNamespace, selector.item, module.event.item.click)
  4352. ;
  4353. },
  4354. intent: function() {
  4355. module.verbose('Binding hide intent event to document');
  4356. if(hasTouch) {
  4357. $document
  4358. .on('touchstart' + elementNamespace, module.event.test.touch)
  4359. .on('touchmove' + elementNamespace, module.event.test.touch)
  4360. ;
  4361. }
  4362. $document
  4363. .on('click' + elementNamespace, module.event.test.hide)
  4364. ;
  4365. }
  4366. },
  4367. unbind: {
  4368. intent: function() {
  4369. module.verbose('Removing hide intent event from document');
  4370. if(hasTouch) {
  4371. $document
  4372. .off('touchstart' + elementNamespace)
  4373. .off('touchmove' + elementNamespace)
  4374. ;
  4375. }
  4376. $document
  4377. .off('click' + elementNamespace)
  4378. ;
  4379. }
  4380. },
  4381. filter: function(query) {
  4382. var
  4383. searchTerm = (query !== undefined)
  4384. ? query
  4385. : module.get.query(),
  4386. afterFiltered = function() {
  4387. if(module.is.multiple()) {
  4388. module.filterActive();
  4389. }
  4390. module.select.firstUnfiltered();
  4391. if( module.has.allResultsFiltered() ) {
  4392. if( settings.onNoResults.call(element, searchTerm) ) {
  4393. if(!settings.allowAdditions) {
  4394. module.verbose('All items filtered, showing message', searchTerm);
  4395. module.add.message(message.noResults);
  4396. }
  4397. }
  4398. else {
  4399. module.verbose('All items filtered, hiding dropdown', searchTerm);
  4400. module.hideMenu();
  4401. }
  4402. }
  4403. else {
  4404. module.remove.message();
  4405. }
  4406. if(settings.allowAdditions) {
  4407. module.add.userSuggestion(query);
  4408. }
  4409. if(module.is.searchSelection() && module.can.show() && module.is.focusedOnSearch() ) {
  4410. module.show();
  4411. }
  4412. }
  4413. ;
  4414. if(settings.useLabels && module.has.maxSelections()) {
  4415. return;
  4416. }
  4417. if(settings.apiSettings) {
  4418. if( module.can.useAPI() ) {
  4419. module.queryRemote(searchTerm, function() {
  4420. afterFiltered();
  4421. });
  4422. }
  4423. else {
  4424. module.error(error.noAPI);
  4425. }
  4426. }
  4427. else {
  4428. module.filterItems(searchTerm);
  4429. afterFiltered();
  4430. }
  4431. },
  4432. queryRemote: function(query, callback) {
  4433. var
  4434. apiSettings = {
  4435. errorDuration : false,
  4436. throttle : settings.throttle,
  4437. urlData : {
  4438. query: query
  4439. },
  4440. onError: function() {
  4441. module.add.message(message.serverError);
  4442. callback();
  4443. },
  4444. onFailure: function() {
  4445. module.add.message(message.serverError);
  4446. callback();
  4447. },
  4448. onSuccess : function(response) {
  4449. module.remove.message();
  4450. module.setup.menu({
  4451. values: response[fields.remoteValues]
  4452. });
  4453. callback();
  4454. }
  4455. }
  4456. ;
  4457. if( !$module.api('get request') ) {
  4458. module.setup.api();
  4459. }
  4460. apiSettings = $.extend(true, {}, apiSettings, settings.apiSettings);
  4461. $module
  4462. .api('setting', apiSettings)
  4463. .api('query')
  4464. ;
  4465. },
  4466. filterItems: function(query) {
  4467. var
  4468. searchTerm = (query !== undefined)
  4469. ? query
  4470. : module.get.query(),
  4471. results = null,
  4472. escapedTerm = module.escape.regExp(searchTerm),
  4473. beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm')
  4474. ;
  4475. // avoid loop if we're matching nothing
  4476. if( module.has.query() ) {
  4477. results = [];
  4478. module.verbose('Searching for matching values', searchTerm);
  4479. $item
  4480. .each(function(){
  4481. var
  4482. $choice = $(this),
  4483. text,
  4484. value
  4485. ;
  4486. if(settings.match == 'both' || settings.match == 'text') {
  4487. text = String(module.get.choiceText($choice, false));
  4488. if(text.search(beginsWithRegExp) !== -1) {
  4489. results.push(this);
  4490. return true;
  4491. }
  4492. else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, text)) {
  4493. results.push(this);
  4494. return true;
  4495. }
  4496. }
  4497. if(settings.match == 'both' || settings.match == 'value') {
  4498. value = String(module.get.choiceValue($choice, text));
  4499. if(value.search(beginsWithRegExp) !== -1) {
  4500. results.push(this);
  4501. return true;
  4502. }
  4503. else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, value)) {
  4504. results.push(this);
  4505. return true;
  4506. }
  4507. }
  4508. })
  4509. ;
  4510. }
  4511. module.debug('Showing only matched items', searchTerm);
  4512. module.remove.filteredItem();
  4513. if(results) {
  4514. $item
  4515. .not(results)
  4516. .addClass(className.filtered)
  4517. ;
  4518. }
  4519. },
  4520. fuzzySearch: function(query, term) {
  4521. var
  4522. termLength = term.length,
  4523. queryLength = query.length
  4524. ;
  4525. query = query.toLowerCase();
  4526. term = term.toLowerCase();
  4527. if(queryLength > termLength) {
  4528. return false;
  4529. }
  4530. if(queryLength === termLength) {
  4531. return (query === term);
  4532. }
  4533. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  4534. var
  4535. queryCharacter = query.charCodeAt(characterIndex)
  4536. ;
  4537. while(nextCharacterIndex < termLength) {
  4538. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  4539. continue search;
  4540. }
  4541. }
  4542. return false;
  4543. }
  4544. return true;
  4545. },
  4546. filterActive: function() {
  4547. if(settings.useLabels) {
  4548. $item.filter('.' + className.active)
  4549. .addClass(className.filtered)
  4550. ;
  4551. }
  4552. },
  4553. focusSearch: function() {
  4554. if( module.is.search() && !module.is.focusedOnSearch() ) {
  4555. $search[0].focus();
  4556. }
  4557. },
  4558. forceSelection: function() {
  4559. var
  4560. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  4561. $activeItem = $item.not(className.filtered).filter('.' + className.active).eq(0),
  4562. $selectedItem = ($currentlySelected.length > 0)
  4563. ? $currentlySelected
  4564. : $activeItem,
  4565. hasSelected = ($selectedItem.size() > 0)
  4566. ;
  4567. if( module.has.query() ) {
  4568. if(hasSelected) {
  4569. module.debug('Forcing partial selection to selected item', $selectedItem);
  4570. module.event.item.click.call($selectedItem);
  4571. return;
  4572. }
  4573. else {
  4574. module.remove.searchTerm();
  4575. }
  4576. }
  4577. module.hide();
  4578. },
  4579. event: {
  4580. change: function() {
  4581. if(!internalChange) {
  4582. module.debug('Input changed, updating selection');
  4583. module.set.selected();
  4584. }
  4585. },
  4586. focus: function() {
  4587. if(settings.showOnFocus && !activated && module.is.hidden() && !pageLostFocus) {
  4588. module.show();
  4589. }
  4590. },
  4591. click: function(event) {
  4592. var
  4593. $target = $(event.target)
  4594. ;
  4595. // focus search
  4596. if($target.is($module) && !module.is.focusedOnSearch()) {
  4597. module.focusSearch();
  4598. }
  4599. },
  4600. blur: function(event) {
  4601. pageLostFocus = (document.activeElement === this);
  4602. if(!activated && !pageLostFocus) {
  4603. module.remove.activeLabel();
  4604. module.hide();
  4605. }
  4606. },
  4607. // prevents focus callback from occurring on mousedown
  4608. mousedown: function() {
  4609. activated = true;
  4610. },
  4611. mouseup: function() {
  4612. activated = false;
  4613. },
  4614. search: {
  4615. focus: function() {
  4616. activated = true;
  4617. if(module.is.multiple()) {
  4618. module.remove.activeLabel();
  4619. }
  4620. if(settings.showOnFocus) {
  4621. module.search();
  4622. module.show();
  4623. }
  4624. },
  4625. blur: function(event) {
  4626. pageLostFocus = (document.activeElement === this);
  4627. if(!itemActivated && !pageLostFocus) {
  4628. if(module.is.multiple()) {
  4629. module.remove.activeLabel();
  4630. module.hide();
  4631. }
  4632. else if(settings.forceSelection) {
  4633. module.forceSelection();
  4634. }
  4635. else {
  4636. module.hide();
  4637. }
  4638. }
  4639. else if(pageLostFocus) {
  4640. if(settings.forceSelection) {
  4641. module.forceSelection();
  4642. }
  4643. }
  4644. }
  4645. },
  4646. icon: {
  4647. click: function(event) {
  4648. module.toggle();
  4649. event.stopPropagation();
  4650. }
  4651. },
  4652. text: {
  4653. focus: function(event) {
  4654. activated = true;
  4655. module.focusSearch();
  4656. }
  4657. },
  4658. input: function(event) {
  4659. if(module.is.multiple() || module.is.searchSelection()) {
  4660. module.set.filtered();
  4661. }
  4662. clearTimeout(module.timer);
  4663. module.timer = setTimeout(module.search, settings.delay.search);
  4664. },
  4665. label: {
  4666. click: function(event) {
  4667. var
  4668. $label = $(this),
  4669. $labels = $module.find(selector.label),
  4670. $activeLabels = $labels.filter('.' + className.active),
  4671. $nextActive = $label.nextAll('.' + className.active),
  4672. $prevActive = $label.prevAll('.' + className.active),
  4673. $range = ($nextActive.length > 0)
  4674. ? $label.nextUntil($nextActive).add($activeLabels).add($label)
  4675. : $label.prevUntil($prevActive).add($activeLabels).add($label)
  4676. ;
  4677. if(event.shiftKey) {
  4678. $activeLabels.removeClass(className.active);
  4679. $range.addClass(className.active);
  4680. }
  4681. else if(event.ctrlKey) {
  4682. $label.toggleClass(className.active);
  4683. }
  4684. else {
  4685. $activeLabels.removeClass(className.active);
  4686. $label.addClass(className.active);
  4687. }
  4688. settings.onLabelSelect.apply(this, $labels.filter('.' + className.active));
  4689. }
  4690. },
  4691. remove: {
  4692. click: function() {
  4693. var
  4694. $label = $(this).parent()
  4695. ;
  4696. if( $label.hasClass(className.active) ) {
  4697. // remove all selected labels
  4698. module.remove.activeLabels();
  4699. }
  4700. else {
  4701. // remove this label only
  4702. module.remove.activeLabels( $label );
  4703. }
  4704. }
  4705. },
  4706. test: {
  4707. toggle: function(event) {
  4708. var
  4709. toggleBehavior = (module.is.multiple())
  4710. ? module.show
  4711. : module.toggle
  4712. ;
  4713. if( module.determine.eventOnElement(event, toggleBehavior) ) {
  4714. event.preventDefault();
  4715. }
  4716. },
  4717. touch: function(event) {
  4718. module.determine.eventOnElement(event, function() {
  4719. if(event.type == 'touchstart') {
  4720. module.timer = setTimeout(function() {
  4721. module.hide();
  4722. }, settings.delay.touch);
  4723. }
  4724. else if(event.type == 'touchmove') {
  4725. clearTimeout(module.timer);
  4726. }
  4727. });
  4728. event.stopPropagation();
  4729. },
  4730. hide: function(event) {
  4731. module.determine.eventInModule(event, module.hide);
  4732. }
  4733. },
  4734. menu: {
  4735. mousedown: function() {
  4736. itemActivated = true;
  4737. },
  4738. mouseup: function() {
  4739. itemActivated = false;
  4740. }
  4741. },
  4742. item: {
  4743. mouseenter: function(event) {
  4744. var
  4745. $subMenu = $(this).children(selector.menu),
  4746. $otherMenus = $(this).siblings(selector.item).children(selector.menu)
  4747. ;
  4748. if( $subMenu.length > 0 ) {
  4749. clearTimeout(module.itemTimer);
  4750. module.itemTimer = setTimeout(function() {
  4751. module.verbose('Showing sub-menu', $subMenu);
  4752. $.each($otherMenus, function() {
  4753. module.animate.hide(false, $(this));
  4754. });
  4755. module.animate.show(false, $subMenu);
  4756. }, settings.delay.show);
  4757. event.preventDefault();
  4758. }
  4759. },
  4760. mouseleave: function(event) {
  4761. var
  4762. $subMenu = $(this).children(selector.menu)
  4763. ;
  4764. if($subMenu.length > 0) {
  4765. clearTimeout(module.itemTimer);
  4766. module.itemTimer = setTimeout(function() {
  4767. module.verbose('Hiding sub-menu', $subMenu);
  4768. module.animate.hide(false, $subMenu);
  4769. }, settings.delay.hide);
  4770. }
  4771. },
  4772. touchend: function() {
  4773. },
  4774. click: function (event) {
  4775. var
  4776. $choice = $(this),
  4777. $target = (event)
  4778. ? $(event.target)
  4779. : $(''),
  4780. $subMenu = $choice.find(selector.menu),
  4781. text = module.get.choiceText($choice),
  4782. value = module.get.choiceValue($choice, text),
  4783. hasSubMenu = ($subMenu.length > 0),
  4784. isBubbledEvent = ($subMenu.find($target).length > 0)
  4785. ;
  4786. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  4787. if(!settings.useLabels) {
  4788. module.remove.filteredItem();
  4789. module.remove.searchTerm();
  4790. module.set.scrollPosition($choice);
  4791. }
  4792. module.determine.selectAction.call(this, text, value);
  4793. }
  4794. }
  4795. },
  4796. document: {
  4797. // label selection should occur even when element has no focus
  4798. keydown: function(event) {
  4799. var
  4800. pressedKey = event.which,
  4801. isShortcutKey = module.is.inObject(pressedKey, keys)
  4802. ;
  4803. if(isShortcutKey) {
  4804. var
  4805. $label = $module.find(selector.label),
  4806. $activeLabel = $label.filter('.' + className.active),
  4807. activeValue = $activeLabel.data(metadata.value),
  4808. labelIndex = $label.index($activeLabel),
  4809. labelCount = $label.length,
  4810. hasActiveLabel = ($activeLabel.length > 0),
  4811. hasMultipleActive = ($activeLabel.length > 1),
  4812. isFirstLabel = (labelIndex === 0),
  4813. isLastLabel = (labelIndex + 1 == labelCount),
  4814. isSearch = module.is.searchSelection(),
  4815. isFocusedOnSearch = module.is.focusedOnSearch(),
  4816. isFocused = module.is.focused(),
  4817. caretAtStart = (isFocusedOnSearch && module.get.caretPosition() === 0),
  4818. $nextLabel
  4819. ;
  4820. if(isSearch && !hasActiveLabel && !isFocusedOnSearch) {
  4821. return;
  4822. }
  4823. if(pressedKey == keys.leftArrow) {
  4824. // activate previous label
  4825. if((isFocused || caretAtStart) && !hasActiveLabel) {
  4826. module.verbose('Selecting previous label');
  4827. $label.last().addClass(className.active);
  4828. }
  4829. else if(hasActiveLabel) {
  4830. if(!event.shiftKey) {
  4831. module.verbose('Selecting previous label');
  4832. $label.removeClass(className.active);
  4833. }
  4834. else {
  4835. module.verbose('Adding previous label to selection');
  4836. }
  4837. if(isFirstLabel && !hasMultipleActive) {
  4838. $activeLabel.addClass(className.active);
  4839. }
  4840. else {
  4841. $activeLabel.prev(selector.siblingLabel)
  4842. .addClass(className.active)
  4843. .end()
  4844. ;
  4845. }
  4846. event.preventDefault();
  4847. }
  4848. }
  4849. else if(pressedKey == keys.rightArrow) {
  4850. // activate first label
  4851. if(isFocused && !hasActiveLabel) {
  4852. $label.first().addClass(className.active);
  4853. }
  4854. // activate next label
  4855. if(hasActiveLabel) {
  4856. if(!event.shiftKey) {
  4857. module.verbose('Selecting next label');
  4858. $label.removeClass(className.active);
  4859. }
  4860. else {
  4861. module.verbose('Adding next label to selection');
  4862. }
  4863. if(isLastLabel) {
  4864. if(isSearch) {
  4865. if(!isFocusedOnSearch) {
  4866. module.focusSearch();
  4867. }
  4868. else {
  4869. $label.removeClass(className.active);
  4870. }
  4871. }
  4872. else if(hasMultipleActive) {
  4873. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  4874. }
  4875. else {
  4876. $activeLabel.addClass(className.active);
  4877. }
  4878. }
  4879. else {
  4880. $activeLabel.next(selector.siblingLabel).addClass(className.active);
  4881. }
  4882. event.preventDefault();
  4883. }
  4884. }
  4885. else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
  4886. if(hasActiveLabel) {
  4887. module.verbose('Removing active labels');
  4888. if(isLastLabel) {
  4889. if(isSearch && !isFocusedOnSearch) {
  4890. module.focusSearch();
  4891. }
  4892. }
  4893. $activeLabel.last().next(selector.siblingLabel).addClass(className.active);
  4894. module.remove.activeLabels($activeLabel);
  4895. event.preventDefault();
  4896. }
  4897. else if(caretAtStart && !hasActiveLabel && pressedKey == keys.backspace) {
  4898. module.verbose('Removing last label on input backspace');
  4899. $activeLabel = $label.last().addClass(className.active);
  4900. module.remove.activeLabels($activeLabel);
  4901. }
  4902. }
  4903. else {
  4904. $activeLabel.removeClass(className.active);
  4905. }
  4906. }
  4907. }
  4908. },
  4909. keydown: function(event) {
  4910. var
  4911. pressedKey = event.which,
  4912. isShortcutKey = module.is.inObject(pressedKey, keys)
  4913. ;
  4914. if(isShortcutKey) {
  4915. var
  4916. $currentlySelected = $item.not(selector.unselectable).filter('.' + className.selected).eq(0),
  4917. $activeItem = $menu.children('.' + className.active).eq(0),
  4918. $selectedItem = ($currentlySelected.length > 0)
  4919. ? $currentlySelected
  4920. : $activeItem,
  4921. $visibleItems = ($selectedItem.length > 0)
  4922. ? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf()
  4923. : $menu.children(':not(.' + className.filtered +')'),
  4924. $subMenu = $selectedItem.children(selector.menu),
  4925. $parentMenu = $selectedItem.closest(selector.menu),
  4926. inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
  4927. hasSubMenu = ($subMenu.length> 0),
  4928. hasSelectedItem = ($selectedItem.length > 0),
  4929. selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
  4930. delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
  4931. $nextItem,
  4932. isSubMenuItem,
  4933. newIndex
  4934. ;
  4935. // visible menu keyboard shortcuts
  4936. if( module.is.visible() ) {
  4937. // enter (select or open sub-menu)
  4938. if(pressedKey == keys.enter || delimiterPressed) {
  4939. if(pressedKey == keys.enter && hasSelectedItem && hasSubMenu && !settings.allowCategorySelection) {
  4940. module.verbose('Pressed enter on unselectable category, opening sub menu');
  4941. pressedKey = keys.rightArrow;
  4942. }
  4943. else if(selectedIsSelectable) {
  4944. module.verbose('Selecting item from keyboard shortcut', $selectedItem);
  4945. module.event.item.click.call($selectedItem, event);
  4946. if(module.is.searchSelection()) {
  4947. module.remove.searchTerm();
  4948. }
  4949. }
  4950. event.preventDefault();
  4951. }
  4952. // left arrow (hide sub-menu)
  4953. if(pressedKey == keys.leftArrow) {
  4954. isSubMenuItem = ($parentMenu[0] !== $menu[0]);
  4955. if(isSubMenuItem) {
  4956. module.verbose('Left key pressed, closing sub-menu');
  4957. module.animate.hide(false, $parentMenu);
  4958. $selectedItem
  4959. .removeClass(className.selected)
  4960. ;
  4961. $parentMenu
  4962. .closest(selector.item)
  4963. .addClass(className.selected)
  4964. ;
  4965. event.preventDefault();
  4966. }
  4967. }
  4968. // right arrow (show sub-menu)
  4969. if(pressedKey == keys.rightArrow) {
  4970. if(hasSubMenu) {
  4971. module.verbose('Right key pressed, opening sub-menu');
  4972. module.animate.show(false, $subMenu);
  4973. $selectedItem
  4974. .removeClass(className.selected)
  4975. ;
  4976. $subMenu
  4977. .find(selector.item).eq(0)
  4978. .addClass(className.selected)
  4979. ;
  4980. event.preventDefault();
  4981. }
  4982. }
  4983. // up arrow (traverse menu up)
  4984. if(pressedKey == keys.upArrow) {
  4985. $nextItem = (hasSelectedItem && inVisibleMenu)
  4986. ? $selectedItem.prevAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  4987. : $item.eq(0)
  4988. ;
  4989. if($visibleItems.index( $nextItem ) < 0) {
  4990. module.verbose('Up key pressed but reached top of current menu');
  4991. event.preventDefault();
  4992. return;
  4993. }
  4994. else {
  4995. module.verbose('Up key pressed, changing active item');
  4996. $selectedItem
  4997. .removeClass(className.selected)
  4998. ;
  4999. $nextItem
  5000. .addClass(className.selected)
  5001. ;
  5002. module.set.scrollPosition($nextItem);
  5003. }
  5004. event.preventDefault();
  5005. }
  5006. // down arrow (traverse menu down)
  5007. if(pressedKey == keys.downArrow) {
  5008. $nextItem = (hasSelectedItem && inVisibleMenu)
  5009. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(' + selector.unselectable + ')').eq(0)
  5010. : $item.eq(0)
  5011. ;
  5012. if($nextItem.length === 0) {
  5013. module.verbose('Down key pressed but reached bottom of current menu');
  5014. event.preventDefault();
  5015. return;
  5016. }
  5017. else {
  5018. module.verbose('Down key pressed, changing active item');
  5019. $item
  5020. .removeClass(className.selected)
  5021. ;
  5022. $nextItem
  5023. .addClass(className.selected)
  5024. ;
  5025. module.set.scrollPosition($nextItem);
  5026. }
  5027. event.preventDefault();
  5028. }
  5029. // page down (show next page)
  5030. if(pressedKey == keys.pageUp) {
  5031. module.scrollPage('up');
  5032. event.preventDefault();
  5033. }
  5034. if(pressedKey == keys.pageDown) {
  5035. module.scrollPage('down');
  5036. event.preventDefault();
  5037. }
  5038. // escape (close menu)
  5039. if(pressedKey == keys.escape) {
  5040. module.verbose('Escape key pressed, closing dropdown');
  5041. module.hide();
  5042. }
  5043. }
  5044. else {
  5045. // delimiter key
  5046. if(delimiterPressed) {
  5047. event.preventDefault();
  5048. }
  5049. // down arrow (open menu)
  5050. if(pressedKey == keys.downArrow) {
  5051. module.verbose('Down key pressed, showing dropdown');
  5052. module.show();
  5053. event.preventDefault();
  5054. }
  5055. }
  5056. }
  5057. else {
  5058. if( module.is.selection() && !module.is.search() ) {
  5059. module.set.selectedLetter( String.fromCharCode(pressedKey) );
  5060. }
  5061. }
  5062. }
  5063. },
  5064. trigger: {
  5065. change: function() {
  5066. var
  5067. events = document.createEvent('HTMLEvents'),
  5068. inputElement = $input[0]
  5069. ;
  5070. if(inputElement) {
  5071. module.verbose('Triggering native change event');
  5072. events.initEvent('change', true, false);
  5073. inputElement.dispatchEvent(events);
  5074. }
  5075. }
  5076. },
  5077. determine: {
  5078. selectAction: function(text, value) {
  5079. module.verbose('Determining action', settings.action);
  5080. if( $.isFunction( module.action[settings.action] ) ) {
  5081. module.verbose('Triggering preset action', settings.action, text, value);
  5082. module.action[ settings.action ].call(this, text, value);
  5083. }
  5084. else if( $.isFunction(settings.action) ) {
  5085. module.verbose('Triggering user action', settings.action, text, value);
  5086. settings.action.call(this, text, value);
  5087. }
  5088. else {
  5089. module.error(error.action, settings.action);
  5090. }
  5091. },
  5092. eventInModule: function(event, callback) {
  5093. var
  5094. $target = $(event.target),
  5095. inDocument = ($target.closest(document.documentElement).length > 0),
  5096. inModule = ($target.closest($module).length > 0)
  5097. ;
  5098. callback = $.isFunction(callback)
  5099. ? callback
  5100. : function(){}
  5101. ;
  5102. if(inDocument && !inModule) {
  5103. module.verbose('Triggering event', callback);
  5104. callback();
  5105. return true;
  5106. }
  5107. else {
  5108. module.verbose('Event occurred in dropdown, canceling callback');
  5109. return false;
  5110. }
  5111. },
  5112. eventOnElement: function(event, callback) {
  5113. var
  5114. $target = $(event.target),
  5115. $label = $target.closest(selector.siblingLabel),
  5116. notOnLabel = ($module.find($label).length === 0),
  5117. notInMenu = ($target.closest($menu).length === 0)
  5118. ;
  5119. callback = $.isFunction(callback)
  5120. ? callback
  5121. : function(){}
  5122. ;
  5123. if(notOnLabel && notInMenu) {
  5124. module.verbose('Triggering event', callback);
  5125. callback();
  5126. return true;
  5127. }
  5128. else {
  5129. module.verbose('Event occurred in dropdown menu, canceling callback');
  5130. return false;
  5131. }
  5132. }
  5133. },
  5134. action: {
  5135. nothing: function() {},
  5136. activate: function(text, value) {
  5137. value = (value !== undefined)
  5138. ? value
  5139. : text
  5140. ;
  5141. if( module.can.activate( $(this) ) ) {
  5142. module.set.selected(value, $(this));
  5143. if(module.is.multiple() && !module.is.allFiltered()) {
  5144. return;
  5145. }
  5146. else {
  5147. module.hideAndClear();
  5148. }
  5149. }
  5150. },
  5151. select: function(text, value) {
  5152. // mimics action.activate but does not select text
  5153. module.action.activate.call(this);
  5154. },
  5155. combo: function(text, value) {
  5156. value = (value !== undefined)
  5157. ? value
  5158. : text
  5159. ;
  5160. module.set.selected(value, $(this));
  5161. module.hideAndClear();
  5162. },
  5163. hide: function(text, value) {
  5164. module.set.value(value);
  5165. module.hideAndClear();
  5166. }
  5167. },
  5168. get: {
  5169. id: function() {
  5170. return id;
  5171. },
  5172. defaultText: function() {
  5173. return $module.data(metadata.defaultText);
  5174. },
  5175. defaultValue: function() {
  5176. return $module.data(metadata.defaultValue);
  5177. },
  5178. placeholderText: function() {
  5179. return $module.data(metadata.placeholderText) || '';
  5180. },
  5181. text: function() {
  5182. return $text.text();
  5183. },
  5184. query: function() {
  5185. return $.trim($search.val());
  5186. },
  5187. searchWidth: function(characterCount) {
  5188. return (characterCount * settings.glyphWidth) + 'em';
  5189. },
  5190. selectionCount: function() {
  5191. var
  5192. values = module.get.values(),
  5193. count
  5194. ;
  5195. count = ( module.is.multiple() )
  5196. ? $.isArray(values)
  5197. ? values.length
  5198. : 0
  5199. : (module.get.value() !== '')
  5200. ? 1
  5201. : 0
  5202. ;
  5203. return count;
  5204. },
  5205. transition: function($subMenu) {
  5206. return (settings.transition == 'auto')
  5207. ? module.is.upward($subMenu)
  5208. ? 'slide up'
  5209. : 'slide down'
  5210. : settings.transition
  5211. ;
  5212. },
  5213. userValues: function() {
  5214. var
  5215. values = module.get.values()
  5216. ;
  5217. if(!values) {
  5218. return false;
  5219. }
  5220. values = $.isArray(values)
  5221. ? values
  5222. : [values]
  5223. ;
  5224. return $.grep(values, function(value) {
  5225. return (module.get.item(value) === false);
  5226. });
  5227. },
  5228. uniqueArray: function(array) {
  5229. return $.grep(array, function (value, index) {
  5230. return $.inArray(value, array) === index;
  5231. });
  5232. },
  5233. caretPosition: function() {
  5234. var
  5235. input = $search.get(0),
  5236. range,
  5237. rangeLength
  5238. ;
  5239. if('selectionStart' in input) {
  5240. return input.selectionStart;
  5241. }
  5242. else if (document.selection) {
  5243. input.focus();
  5244. range = document.selection.createRange();
  5245. rangeLength = range.text.length;
  5246. range.moveStart('character', -input.value.length);
  5247. return range.text.length - rangeLength;
  5248. }
  5249. },
  5250. value: function() {
  5251. var
  5252. value = ($input.length > 0)
  5253. ? $input.val()
  5254. : $module.data(metadata.value)
  5255. ;
  5256. // prevents placeholder element from being selected when multiple
  5257. if($.isArray(value) && value.length === 1 && value[0] === '') {
  5258. return '';
  5259. }
  5260. return value;
  5261. },
  5262. values: function() {
  5263. var
  5264. value = module.get.value()
  5265. ;
  5266. if(value === '') {
  5267. return '';
  5268. }
  5269. return ( !module.has.selectInput() && module.is.multiple() )
  5270. ? (typeof value == 'string') // delimited string
  5271. ? value.split(settings.delimiter)
  5272. : ''
  5273. : value
  5274. ;
  5275. },
  5276. remoteValues: function() {
  5277. var
  5278. values = module.get.values(),
  5279. remoteValues = false
  5280. ;
  5281. if(values) {
  5282. if(typeof values == 'string') {
  5283. values = [values];
  5284. }
  5285. remoteValues = {};
  5286. $.each(values, function(index, value) {
  5287. var
  5288. name = module.read.remoteData(value)
  5289. ;
  5290. module.verbose('Restoring value from session data', name, value);
  5291. remoteValues[value] = (name)
  5292. ? name
  5293. : value
  5294. ;
  5295. });
  5296. }
  5297. return remoteValues;
  5298. },
  5299. choiceText: function($choice, preserveHTML) {
  5300. preserveHTML = (preserveHTML !== undefined)
  5301. ? preserveHTML
  5302. : settings.preserveHTML
  5303. ;
  5304. if($choice) {
  5305. if($choice.find(selector.menu).length > 0) {
  5306. module.verbose('Retreiving text of element with sub-menu');
  5307. $choice = $choice.clone();
  5308. $choice.find(selector.menu).remove();
  5309. $choice.find(selector.menuIcon).remove();
  5310. }
  5311. return ($choice.data(metadata.text) !== undefined)
  5312. ? $choice.data(metadata.text)
  5313. : (preserveHTML)
  5314. ? $.trim($choice.html())
  5315. : $.trim($choice.text())
  5316. ;
  5317. }
  5318. },
  5319. choiceValue: function($choice, choiceText) {
  5320. choiceText = choiceText || module.get.choiceText($choice);
  5321. if(!$choice) {
  5322. return false;
  5323. }
  5324. return ($choice.data(metadata.value) !== undefined)
  5325. ? String( $choice.data(metadata.value) )
  5326. : (typeof choiceText === 'string')
  5327. ? $.trim(choiceText.toLowerCase())
  5328. : String(choiceText)
  5329. ;
  5330. },
  5331. inputEvent: function() {
  5332. var
  5333. input = $search[0]
  5334. ;
  5335. if(input) {
  5336. return (input.oninput !== undefined)
  5337. ? 'input'
  5338. : (input.onpropertychange !== undefined)
  5339. ? 'propertychange'
  5340. : 'keyup'
  5341. ;
  5342. }
  5343. return false;
  5344. },
  5345. selectValues: function() {
  5346. var
  5347. select = {}
  5348. ;
  5349. select.values = [];
  5350. $module
  5351. .find('option')
  5352. .each(function() {
  5353. var
  5354. $option = $(this),
  5355. name = $option.html(),
  5356. disabled = $option.attr('disabled'),
  5357. value = ( $option.attr('value') !== undefined )
  5358. ? $option.attr('value')
  5359. : name
  5360. ;
  5361. if(settings.placeholder === 'auto' && value === '') {
  5362. select.placeholder = name;
  5363. }
  5364. else {
  5365. select.values.push({
  5366. name : name,
  5367. value : value,
  5368. disabled : disabled
  5369. });
  5370. }
  5371. })
  5372. ;
  5373. if(settings.placeholder && settings.placeholder !== 'auto') {
  5374. module.debug('Setting placeholder value to', settings.placeholder);
  5375. select.placeholder = settings.placeholder;
  5376. }
  5377. if(settings.sortSelect) {
  5378. select.values.sort(function(a, b) {
  5379. return (a.name > b.name)
  5380. ? 1
  5381. : -1
  5382. ;
  5383. });
  5384. module.debug('Retrieved and sorted values from select', select);
  5385. }
  5386. else {
  5387. module.debug('Retreived values from select', select);
  5388. }
  5389. return select;
  5390. },
  5391. activeItem: function() {
  5392. return $item.filter('.' + className.active);
  5393. },
  5394. selectedItem: function() {
  5395. var
  5396. $selectedItem = $item.not(selector.unselectable).filter('.' + className.selected)
  5397. ;
  5398. return ($selectedItem.length > 0)
  5399. ? $selectedItem
  5400. : $item.eq(0)
  5401. ;
  5402. },
  5403. itemWithAdditions: function(value) {
  5404. var
  5405. $items = module.get.item(value),
  5406. $userItems = module.create.userChoice(value),
  5407. hasUserItems = ($userItems && $userItems.length > 0)
  5408. ;
  5409. if(hasUserItems) {
  5410. $items = ($items.length > 0)
  5411. ? $items.add($userItems)
  5412. : $userItems
  5413. ;
  5414. }
  5415. return $items;
  5416. },
  5417. item: function(value, strict) {
  5418. var
  5419. $selectedItem = false,
  5420. shouldSearch,
  5421. isMultiple
  5422. ;
  5423. value = (value !== undefined)
  5424. ? value
  5425. : ( module.get.values() !== undefined)
  5426. ? module.get.values()
  5427. : module.get.text()
  5428. ;
  5429. shouldSearch = (isMultiple)
  5430. ? (value.length > 0)
  5431. : (value !== undefined && value !== null)
  5432. ;
  5433. isMultiple = (module.is.multiple() && $.isArray(value));
  5434. strict = (value === '' || value === 0)
  5435. ? true
  5436. : strict || false
  5437. ;
  5438. if(shouldSearch) {
  5439. $item
  5440. .each(function() {
  5441. var
  5442. $choice = $(this),
  5443. optionText = module.get.choiceText($choice),
  5444. optionValue = module.get.choiceValue($choice, optionText)
  5445. ;
  5446. // safe early exit
  5447. if(optionValue === null || optionValue === undefined) {
  5448. return;
  5449. }
  5450. if(isMultiple) {
  5451. if($.inArray( String(optionValue), value) !== -1 || $.inArray(optionText, value) !== -1) {
  5452. $selectedItem = ($selectedItem)
  5453. ? $selectedItem.add($choice)
  5454. : $choice
  5455. ;
  5456. }
  5457. }
  5458. else if(strict) {
  5459. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  5460. if( optionValue === value || optionText === value) {
  5461. $selectedItem = $choice;
  5462. return true;
  5463. }
  5464. }
  5465. else {
  5466. if( String(optionValue) == String(value) || optionText == value) {
  5467. module.verbose('Found select item by value', optionValue, value);
  5468. $selectedItem = $choice;
  5469. return true;
  5470. }
  5471. }
  5472. })
  5473. ;
  5474. }
  5475. return $selectedItem;
  5476. }
  5477. },
  5478. check: {
  5479. maxSelections: function(selectionCount) {
  5480. if(settings.maxSelections) {
  5481. selectionCount = (selectionCount !== undefined)
  5482. ? selectionCount
  5483. : module.get.selectionCount()
  5484. ;
  5485. if(selectionCount >= settings.maxSelections) {
  5486. module.debug('Maximum selection count reached');
  5487. if(settings.useLabels) {
  5488. $item.addClass(className.filtered);
  5489. module.add.message(message.maxSelections);
  5490. }
  5491. return true;
  5492. }
  5493. else {
  5494. module.verbose('No longer at maximum selection count');
  5495. module.remove.message();
  5496. module.remove.filteredItem();
  5497. if(module.is.searchSelection()) {
  5498. module.filterItems();
  5499. }
  5500. return false;
  5501. }
  5502. }
  5503. return true;
  5504. }
  5505. },
  5506. restore: {
  5507. defaults: function() {
  5508. module.clear();
  5509. module.restore.defaultText();
  5510. module.restore.defaultValue();
  5511. },
  5512. defaultText: function() {
  5513. var
  5514. defaultText = module.get.defaultText(),
  5515. placeholderText = module.get.placeholderText
  5516. ;
  5517. if(defaultText === placeholderText) {
  5518. module.debug('Restoring default placeholder text', defaultText);
  5519. module.set.placeholderText(defaultText);
  5520. }
  5521. else {
  5522. module.debug('Restoring default text', defaultText);
  5523. module.set.text(defaultText);
  5524. }
  5525. },
  5526. defaultValue: function() {
  5527. var
  5528. defaultValue = module.get.defaultValue()
  5529. ;
  5530. if(defaultValue !== undefined) {
  5531. module.debug('Restoring default value', defaultValue);
  5532. if(defaultValue !== '') {
  5533. module.set.value(defaultValue);
  5534. module.set.selected();
  5535. }
  5536. else {
  5537. module.remove.activeItem();
  5538. module.remove.selectedItem();
  5539. }
  5540. }
  5541. },
  5542. labels: function() {
  5543. if(settings.allowAdditions) {
  5544. if(!settings.useLabels) {
  5545. module.error(error.labels);
  5546. settings.useLabels = true;
  5547. }
  5548. module.debug('Restoring selected values');
  5549. module.create.userLabels();
  5550. }
  5551. module.check.maxSelections();
  5552. },
  5553. selected: function() {
  5554. module.restore.values();
  5555. if(module.is.multiple()) {
  5556. module.debug('Restoring previously selected values and labels');
  5557. module.restore.labels();
  5558. }
  5559. else {
  5560. module.debug('Restoring previously selected values');
  5561. }
  5562. },
  5563. values: function() {
  5564. // prevents callbacks from occuring on initial load
  5565. module.set.initialLoad();
  5566. if(settings.apiSettings) {
  5567. if(settings.saveRemoteData) {
  5568. module.restore.remoteValues();
  5569. }
  5570. else {
  5571. module.clearValue();
  5572. }
  5573. }
  5574. else {
  5575. module.set.selected();
  5576. }
  5577. module.remove.initialLoad();
  5578. },
  5579. remoteValues: function() {
  5580. var
  5581. values = module.get.remoteValues()
  5582. ;
  5583. module.debug('Recreating selected from session data', values);
  5584. if(values) {
  5585. if( module.is.single() ) {
  5586. $.each(values, function(value, name) {
  5587. module.set.text(name);
  5588. });
  5589. }
  5590. else {
  5591. $.each(values, function(value, name) {
  5592. module.add.label(value, name);
  5593. });
  5594. }
  5595. }
  5596. }
  5597. },
  5598. read: {
  5599. remoteData: function(value) {
  5600. var
  5601. name
  5602. ;
  5603. if(window.Storage === undefined) {
  5604. module.error(error.noStorage);
  5605. return;
  5606. }
  5607. name = sessionStorage.getItem(value);
  5608. return (name !== undefined)
  5609. ? name
  5610. : false
  5611. ;
  5612. }
  5613. },
  5614. save: {
  5615. defaults: function() {
  5616. module.save.defaultText();
  5617. module.save.placeholderText();
  5618. module.save.defaultValue();
  5619. },
  5620. defaultValue: function() {
  5621. var
  5622. value = module.get.value()
  5623. ;
  5624. module.verbose('Saving default value as', value);
  5625. $module.data(metadata.defaultValue, value);
  5626. },
  5627. defaultText: function() {
  5628. var
  5629. text = module.get.text()
  5630. ;
  5631. module.verbose('Saving default text as', text);
  5632. $module.data(metadata.defaultText, text);
  5633. },
  5634. placeholderText: function() {
  5635. var
  5636. text
  5637. ;
  5638. if(settings.placeholder !== false && $text.hasClass(className.placeholder)) {
  5639. text = module.get.text();
  5640. module.verbose('Saving placeholder text as', text);
  5641. $module.data(metadata.placeholderText, text);
  5642. }
  5643. },
  5644. remoteData: function(name, value) {
  5645. if(window.Storage === undefined) {
  5646. module.error(error.noStorage);
  5647. return;
  5648. }
  5649. module.verbose('Saving remote data to session storage', value, name);
  5650. sessionStorage.setItem(value, name);
  5651. }
  5652. },
  5653. clear: function() {
  5654. if(module.is.multiple()) {
  5655. module.remove.labels();
  5656. }
  5657. else {
  5658. module.remove.activeItem();
  5659. module.remove.selectedItem();
  5660. }
  5661. module.set.placeholderText();
  5662. module.clearValue();
  5663. },
  5664. clearValue: function() {
  5665. module.set.value('');
  5666. },
  5667. scrollPage: function(direction, $selectedItem) {
  5668. var
  5669. $currentItem = $selectedItem || module.get.selectedItem(),
  5670. $menu = $currentItem.closest(selector.menu),
  5671. menuHeight = $menu.outerHeight(),
  5672. currentScroll = $menu.scrollTop(),
  5673. itemHeight = $item.eq(0).outerHeight(),
  5674. itemsPerPage = Math.floor(menuHeight / itemHeight),
  5675. maxScroll = $menu.prop('scrollHeight'),
  5676. newScroll = (direction == 'up')
  5677. ? currentScroll - (itemHeight * itemsPerPage)
  5678. : currentScroll + (itemHeight * itemsPerPage),
  5679. $selectableItem = $item.not(selector.unselectable),
  5680. isWithinRange,
  5681. $nextSelectedItem,
  5682. elementIndex
  5683. ;
  5684. elementIndex = (direction == 'up')
  5685. ? $selectableItem.index($currentItem) - itemsPerPage
  5686. : $selectableItem.index($currentItem) + itemsPerPage
  5687. ;
  5688. isWithinRange = (direction == 'up')
  5689. ? (elementIndex >= 0)
  5690. : (elementIndex < $selectableItem.length)
  5691. ;
  5692. $nextSelectedItem = (isWithinRange)
  5693. ? $selectableItem.eq(elementIndex)
  5694. : (direction == 'up')
  5695. ? $selectableItem.first()
  5696. : $selectableItem.last()
  5697. ;
  5698. if($nextSelectedItem.length > 0) {
  5699. module.debug('Scrolling page', direction, $nextSelectedItem);
  5700. $currentItem
  5701. .removeClass(className.selected)
  5702. ;
  5703. $nextSelectedItem
  5704. .addClass(className.selected)
  5705. ;
  5706. $menu
  5707. .scrollTop(newScroll)
  5708. ;
  5709. }
  5710. },
  5711. set: {
  5712. filtered: function() {
  5713. var
  5714. isMultiple = module.is.multiple(),
  5715. isSearch = module.is.searchSelection(),
  5716. isSearchMultiple = (isMultiple && isSearch),
  5717. searchValue = (isSearch)
  5718. ? module.get.query()
  5719. : '',
  5720. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
  5721. searchWidth = module.get.searchWidth(searchValue.length),
  5722. valueIsSet = searchValue !== ''
  5723. ;
  5724. if(isMultiple && hasSearchValue) {
  5725. module.verbose('Adjusting input width', searchWidth, settings.glyphWidth);
  5726. $search.css('width', searchWidth);
  5727. }
  5728. if(hasSearchValue || (isSearchMultiple && valueIsSet)) {
  5729. module.verbose('Hiding placeholder text');
  5730. $text.addClass(className.filtered);
  5731. }
  5732. else if(!isMultiple || (isSearchMultiple && !valueIsSet)) {
  5733. module.verbose('Showing placeholder text');
  5734. $text.removeClass(className.filtered);
  5735. }
  5736. },
  5737. loading: function() {
  5738. $module.addClass(className.loading);
  5739. },
  5740. placeholderText: function(text) {
  5741. text = text || module.get.placeholderText();
  5742. module.debug('Setting placeholder text', text);
  5743. module.set.text(text);
  5744. $text.addClass(className.placeholder);
  5745. },
  5746. tabbable: function() {
  5747. if( module.has.search() ) {
  5748. module.debug('Added tabindex to searchable dropdown');
  5749. $search
  5750. .val('')
  5751. .attr('tabindex', 0)
  5752. ;
  5753. $menu
  5754. .attr('tabindex', -1)
  5755. ;
  5756. }
  5757. else {
  5758. module.debug('Added tabindex to dropdown');
  5759. if( $module.attr('tabindex') === undefined) {
  5760. $module
  5761. .attr('tabindex', 0)
  5762. ;
  5763. $menu
  5764. .attr('tabindex', -1)
  5765. ;
  5766. }
  5767. }
  5768. },
  5769. initialLoad: function() {
  5770. module.verbose('Setting initial load');
  5771. initialLoad = true;
  5772. },
  5773. activeItem: function($item) {
  5774. if( settings.allowAdditions && $item.filter(selector.addition).length > 0 ) {
  5775. $item.addClass(className.filtered);
  5776. }
  5777. else {
  5778. $item.addClass(className.active);
  5779. }
  5780. },
  5781. scrollPosition: function($item, forceScroll) {
  5782. var
  5783. edgeTolerance = 5,
  5784. $menu,
  5785. hasActive,
  5786. offset,
  5787. itemHeight,
  5788. itemOffset,
  5789. menuOffset,
  5790. menuScroll,
  5791. menuHeight,
  5792. abovePage,
  5793. belowPage
  5794. ;
  5795. $item = $item || module.get.selectedItem();
  5796. $menu = $item.closest(selector.menu);
  5797. hasActive = ($item && $item.length > 0);
  5798. forceScroll = (forceScroll !== undefined)
  5799. ? forceScroll
  5800. : false
  5801. ;
  5802. if($item && $menu.length > 0 && hasActive) {
  5803. itemOffset = $item.position().top;
  5804. $menu.addClass(className.loading);
  5805. menuScroll = $menu.scrollTop();
  5806. menuOffset = $menu.offset().top;
  5807. itemOffset = $item.offset().top;
  5808. offset = menuScroll - menuOffset + itemOffset;
  5809. if(!forceScroll) {
  5810. menuHeight = $menu.height();
  5811. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  5812. abovePage = ((offset - edgeTolerance) < menuScroll);
  5813. }
  5814. module.debug('Scrolling to active item', offset);
  5815. if(forceScroll || abovePage || belowPage) {
  5816. $menu.scrollTop(offset);
  5817. }
  5818. $menu.removeClass(className.loading);
  5819. }
  5820. },
  5821. text: function(text) {
  5822. if(settings.action !== 'select') {
  5823. if(settings.action == 'combo') {
  5824. module.debug('Changing combo button text', text, $combo);
  5825. if(settings.preserveHTML) {
  5826. $combo.html(text);
  5827. }
  5828. else {
  5829. $combo.text(text);
  5830. }
  5831. }
  5832. else {
  5833. if(text !== module.get.placeholderText()) {
  5834. $text.removeClass(className.placeholder);
  5835. }
  5836. module.debug('Changing text', text, $text);
  5837. $text
  5838. .removeClass(className.filtered)
  5839. ;
  5840. if(settings.preserveHTML) {
  5841. $text.html(text);
  5842. }
  5843. else {
  5844. $text.text(text);
  5845. }
  5846. }
  5847. }
  5848. },
  5849. selectedLetter: function(letter) {
  5850. var
  5851. $selectedItem = $item.filter('.' + className.selected),
  5852. alreadySelectedLetter = $selectedItem.length > 0 && module.has.firstLetter($selectedItem, letter),
  5853. $nextValue = false,
  5854. $nextItem
  5855. ;
  5856. // check next of same letter
  5857. if(alreadySelectedLetter) {
  5858. $nextItem = $selectedItem.nextAll($item).eq(0);
  5859. if( module.has.firstLetter($nextItem, letter) ) {
  5860. $nextValue = $nextItem;
  5861. }
  5862. }
  5863. // check all values
  5864. if(!$nextValue) {
  5865. $item
  5866. .each(function(){
  5867. if(module.has.firstLetter($(this), letter)) {
  5868. $nextValue = $(this);
  5869. return false;
  5870. }
  5871. })
  5872. ;
  5873. }
  5874. // set next value
  5875. if($nextValue) {
  5876. module.verbose('Scrolling to next value with letter', letter);
  5877. module.set.scrollPosition($nextValue);
  5878. $selectedItem.removeClass(className.selected);
  5879. $nextValue.addClass(className.selected);
  5880. }
  5881. },
  5882. direction: function($menu) {
  5883. if(settings.direction == 'auto') {
  5884. if(module.is.onScreen($menu)) {
  5885. module.remove.upward($menu);
  5886. }
  5887. else {
  5888. module.set.upward($menu);
  5889. }
  5890. }
  5891. else if(settings.direction == 'upward') {
  5892. module.set.upward($menu);
  5893. }
  5894. },
  5895. upward: function($menu) {
  5896. var $element = $menu || $module;
  5897. $element.addClass(className.upward);
  5898. },
  5899. value: function(value, text, $selected) {
  5900. var
  5901. hasInput = ($input.length > 0),
  5902. isAddition = !module.has.value(value),
  5903. currentValue = module.get.values(),
  5904. stringValue = (value !== undefined)
  5905. ? String(value)
  5906. : value,
  5907. newValue
  5908. ;
  5909. if(hasInput) {
  5910. if(stringValue == currentValue) {
  5911. module.verbose('Skipping value update already same value', value, currentValue);
  5912. if(!module.is.initialLoad()) {
  5913. return;
  5914. }
  5915. }
  5916. if( module.is.single() && module.has.selectInput() && module.can.extendSelect() ) {
  5917. module.debug('Adding user option', value);
  5918. module.add.optionValue(value);
  5919. }
  5920. module.debug('Updating input value', value, currentValue);
  5921. internalChange = true;
  5922. $input
  5923. .val(value)
  5924. ;
  5925. if(settings.fireOnInit === false && module.is.initialLoad()) {
  5926. module.debug('Input native change event ignored on initial load');
  5927. }
  5928. else {
  5929. module.trigger.change();
  5930. }
  5931. internalChange = false;
  5932. }
  5933. else {
  5934. module.verbose('Storing value in metadata', value, $input);
  5935. if(value !== currentValue) {
  5936. $module.data(metadata.value, stringValue);
  5937. }
  5938. }
  5939. if(settings.fireOnInit === false && module.is.initialLoad()) {
  5940. module.verbose('No callback on initial load', settings.onChange);
  5941. }
  5942. else {
  5943. settings.onChange.call(element, value, text, $selected);
  5944. }
  5945. },
  5946. active: function() {
  5947. $module
  5948. .addClass(className.active)
  5949. ;
  5950. },
  5951. multiple: function() {
  5952. $module.addClass(className.multiple);
  5953. },
  5954. visible: function() {
  5955. $module.addClass(className.visible);
  5956. },
  5957. exactly: function(value, $selectedItem) {
  5958. module.debug('Setting selected to exact values');
  5959. module.clear();
  5960. module.set.selected(value, $selectedItem);
  5961. },
  5962. selected: function(value, $selectedItem) {
  5963. var
  5964. isMultiple = module.is.multiple(),
  5965. $userSelectedItem
  5966. ;
  5967. $selectedItem = (settings.allowAdditions)
  5968. ? $selectedItem || module.get.itemWithAdditions(value)
  5969. : $selectedItem || module.get.item(value)
  5970. ;
  5971. if(!$selectedItem) {
  5972. return;
  5973. }
  5974. module.debug('Setting selected menu item to', $selectedItem);
  5975. if(module.is.single()) {
  5976. module.remove.activeItem();
  5977. module.remove.selectedItem();
  5978. }
  5979. else if(settings.useLabels) {
  5980. module.remove.selectedItem();
  5981. }
  5982. // select each item
  5983. $selectedItem
  5984. .each(function() {
  5985. var
  5986. $selected = $(this),
  5987. selectedText = module.get.choiceText($selected),
  5988. selectedValue = module.get.choiceValue($selected, selectedText),
  5989. isFiltered = $selected.hasClass(className.filtered),
  5990. isActive = $selected.hasClass(className.active),
  5991. isUserValue = $selected.hasClass(className.addition),
  5992. shouldAnimate = (isMultiple && $selectedItem.length == 1)
  5993. ;
  5994. if(isMultiple) {
  5995. if(!isActive || isUserValue) {
  5996. if(settings.apiSettings && settings.saveRemoteData) {
  5997. module.save.remoteData(selectedText, selectedValue);
  5998. }
  5999. if(settings.useLabels) {
  6000. module.add.value(selectedValue, selectedText, $selected);
  6001. module.add.label(selectedValue, selectedText, shouldAnimate);
  6002. module.set.activeItem($selected);
  6003. module.filterActive();
  6004. module.select.nextAvailable($selectedItem);
  6005. }
  6006. else {
  6007. module.add.value(selectedValue, selectedText, $selected);
  6008. module.set.text(module.add.variables(message.count));
  6009. module.set.activeItem($selected);
  6010. }
  6011. }
  6012. else if(!isFiltered) {
  6013. module.debug('Selected active value, removing label');
  6014. module.remove.selected(selectedValue);
  6015. }
  6016. }
  6017. else {
  6018. if(settings.apiSettings && settings.saveRemoteData) {
  6019. module.save.remoteData(selectedText, selectedValue);
  6020. }
  6021. module.set.text(selectedText);
  6022. module.set.value(selectedValue, selectedText, $selected);
  6023. $selected
  6024. .addClass(className.active)
  6025. .addClass(className.selected)
  6026. ;
  6027. }
  6028. })
  6029. ;
  6030. }
  6031. },
  6032. add: {
  6033. label: function(value, text, shouldAnimate) {
  6034. var
  6035. $next = module.is.searchSelection()
  6036. ? $search
  6037. : $text,
  6038. $label
  6039. ;
  6040. $label = $('<a />')
  6041. .addClass(className.label)
  6042. .attr('data-value', value)
  6043. .html(templates.label(value, text))
  6044. ;
  6045. $label = settings.onLabelCreate.call($label, value, text);
  6046. if(module.has.label(value)) {
  6047. module.debug('Label already exists, skipping', value);
  6048. return;
  6049. }
  6050. if(settings.label.variation) {
  6051. $label.addClass(settings.label.variation);
  6052. }
  6053. if(shouldAnimate === true) {
  6054. module.debug('Animating in label', $label);
  6055. $label
  6056. .addClass(className.hidden)
  6057. .insertBefore($next)
  6058. .transition(settings.label.transition, settings.label.duration)
  6059. ;
  6060. }
  6061. else {
  6062. module.debug('Adding selection label', $label);
  6063. $label
  6064. .insertBefore($next)
  6065. ;
  6066. }
  6067. },
  6068. message: function(message) {
  6069. var
  6070. $message = $menu.children(selector.message),
  6071. html = settings.templates.message(module.add.variables(message))
  6072. ;
  6073. if($message.length > 0) {
  6074. $message
  6075. .html(html)
  6076. ;
  6077. }
  6078. else {
  6079. $message = $('<div/>')
  6080. .html(html)
  6081. .addClass(className.message)
  6082. .appendTo($menu)
  6083. ;
  6084. }
  6085. },
  6086. optionValue: function(value) {
  6087. var
  6088. $option = $input.find('option[value="' + value + '"]'),
  6089. hasOption = ($option.length > 0)
  6090. ;
  6091. if(hasOption) {
  6092. return;
  6093. }
  6094. // temporarily disconnect observer
  6095. if(selectObserver) {
  6096. selectObserver.disconnect();
  6097. module.verbose('Temporarily disconnecting mutation observer', value);
  6098. }
  6099. if( module.is.single() ) {
  6100. module.verbose('Removing previous user addition');
  6101. $input.find('option.' + className.addition).remove();
  6102. }
  6103. $('<option/>')
  6104. .prop('value', value)
  6105. .addClass(className.addition)
  6106. .html(value)
  6107. .appendTo($input)
  6108. ;
  6109. module.verbose('Adding user addition as an <option>', value);
  6110. if(selectObserver) {
  6111. selectObserver.observe($input[0], {
  6112. childList : true,
  6113. subtree : true
  6114. });
  6115. }
  6116. },
  6117. userSuggestion: function(value) {
  6118. var
  6119. $addition = $menu.children(selector.addition),
  6120. $existingItem = module.get.item(value),
  6121. alreadyHasValue = $existingItem && $existingItem.not(selector.addition).length,
  6122. hasUserSuggestion = $addition.length > 0,
  6123. html
  6124. ;
  6125. if(settings.useLabels && module.has.maxSelections()) {
  6126. return;
  6127. }
  6128. if(value === '' || alreadyHasValue) {
  6129. $addition.remove();
  6130. return;
  6131. }
  6132. $item
  6133. .removeClass(className.selected)
  6134. ;
  6135. if(hasUserSuggestion) {
  6136. html = settings.templates.addition( module.add.variables(message.addResult, value) );
  6137. $addition
  6138. .html(html)
  6139. .attr('data-' + metadata.value, value)
  6140. .attr('data-' + metadata.text, value)
  6141. .removeClass(className.filtered)
  6142. .addClass(className.selected)
  6143. ;
  6144. module.verbose('Replacing user suggestion with new value', $addition);
  6145. }
  6146. else {
  6147. $addition = module.create.userChoice(value);
  6148. $addition
  6149. .prependTo($menu)
  6150. .addClass(className.selected)
  6151. ;
  6152. module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
  6153. }
  6154. },
  6155. variables: function(message, term) {
  6156. var
  6157. hasCount = (message.search('{count}') !== -1),
  6158. hasMaxCount = (message.search('{maxCount}') !== -1),
  6159. hasTerm = (message.search('{term}') !== -1),
  6160. values,
  6161. count,
  6162. query
  6163. ;
  6164. module.verbose('Adding templated variables to message', message);
  6165. if(hasCount) {
  6166. count = module.get.selectionCount();
  6167. message = message.replace('{count}', count);
  6168. }
  6169. if(hasMaxCount) {
  6170. count = module.get.selectionCount();
  6171. message = message.replace('{maxCount}', settings.maxSelections);
  6172. }
  6173. if(hasTerm) {
  6174. query = term || module.get.query();
  6175. message = message.replace('{term}', query);
  6176. }
  6177. return message;
  6178. },
  6179. value: function(addedValue, addedText, $selectedItem) {
  6180. var
  6181. currentValue = module.get.values(),
  6182. newValue
  6183. ;
  6184. if(addedValue === '') {
  6185. module.debug('Cannot select blank values from multiselect');
  6186. return;
  6187. }
  6188. // extend current array
  6189. if($.isArray(currentValue)) {
  6190. newValue = currentValue.concat([addedValue]);
  6191. newValue = module.get.uniqueArray(newValue);
  6192. }
  6193. else {
  6194. newValue = [addedValue];
  6195. }
  6196. // add values
  6197. if( module.has.selectInput() ) {
  6198. if(module.can.extendSelect()) {
  6199. module.debug('Adding value to select', addedValue, newValue, $input);
  6200. module.add.optionValue(addedValue);
  6201. }
  6202. }
  6203. else {
  6204. newValue = newValue.join(settings.delimiter);
  6205. module.debug('Setting hidden input to delimited value', newValue, $input);
  6206. }
  6207. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6208. module.verbose('Skipping onadd callback on initial load', settings.onAdd);
  6209. }
  6210. else {
  6211. settings.onAdd.call(element, addedValue, addedText, $selectedItem);
  6212. }
  6213. module.set.value(newValue, addedValue, addedText, $selectedItem);
  6214. module.check.maxSelections();
  6215. }
  6216. },
  6217. remove: {
  6218. active: function() {
  6219. $module.removeClass(className.active);
  6220. },
  6221. activeLabel: function() {
  6222. $module.find(selector.label).removeClass(className.active);
  6223. },
  6224. loading: function() {
  6225. $module.removeClass(className.loading);
  6226. },
  6227. initialLoad: function() {
  6228. initialLoad = false;
  6229. },
  6230. upward: function($menu) {
  6231. var $element = $menu || $module;
  6232. $element.removeClass(className.upward);
  6233. },
  6234. visible: function() {
  6235. $module.removeClass(className.visible);
  6236. },
  6237. activeItem: function() {
  6238. $item.removeClass(className.active);
  6239. },
  6240. filteredItem: function() {
  6241. if(settings.useLabels && module.has.maxSelections() ) {
  6242. return;
  6243. }
  6244. if(settings.useLabels && module.is.multiple()) {
  6245. $item.not('.' + className.active).removeClass(className.filtered);
  6246. }
  6247. else {
  6248. $item.removeClass(className.filtered);
  6249. }
  6250. },
  6251. optionValue: function(value) {
  6252. var
  6253. $option = $input.find('option[value="' + value + '"]'),
  6254. hasOption = ($option.length > 0)
  6255. ;
  6256. if(!hasOption || !$option.hasClass(className.addition)) {
  6257. return;
  6258. }
  6259. // temporarily disconnect observer
  6260. if(selectObserver) {
  6261. selectObserver.disconnect();
  6262. module.verbose('Temporarily disconnecting mutation observer', value);
  6263. }
  6264. $option.remove();
  6265. module.verbose('Removing user addition as an <option>', value);
  6266. if(selectObserver) {
  6267. selectObserver.observe($input[0], {
  6268. childList : true,
  6269. subtree : true
  6270. });
  6271. }
  6272. },
  6273. message: function() {
  6274. $menu.children(selector.message).remove();
  6275. },
  6276. searchTerm: function() {
  6277. module.verbose('Cleared search term');
  6278. $search.val('');
  6279. module.set.filtered();
  6280. },
  6281. selected: function(value, $selectedItem) {
  6282. $selectedItem = (settings.allowAdditions)
  6283. ? $selectedItem || module.get.itemWithAdditions(value)
  6284. : $selectedItem || module.get.item(value)
  6285. ;
  6286. if(!$selectedItem) {
  6287. return false;
  6288. }
  6289. $selectedItem
  6290. .each(function() {
  6291. var
  6292. $selected = $(this),
  6293. selectedText = module.get.choiceText($selected),
  6294. selectedValue = module.get.choiceValue($selected, selectedText)
  6295. ;
  6296. if(module.is.multiple()) {
  6297. if(settings.useLabels) {
  6298. module.remove.value(selectedValue, selectedText, $selected);
  6299. module.remove.label(selectedValue);
  6300. }
  6301. else {
  6302. module.remove.value(selectedValue, selectedText, $selected);
  6303. if(module.get.selectionCount() === 0) {
  6304. module.set.placeholderText();
  6305. }
  6306. else {
  6307. module.set.text(module.add.variables(message.count));
  6308. }
  6309. }
  6310. }
  6311. else {
  6312. module.remove.value(selectedValue, selectedText, $selected);
  6313. }
  6314. $selected
  6315. .removeClass(className.filtered)
  6316. .removeClass(className.active)
  6317. ;
  6318. if(settings.useLabels) {
  6319. $selected.removeClass(className.selected);
  6320. }
  6321. })
  6322. ;
  6323. },
  6324. selectedItem: function() {
  6325. $item.removeClass(className.selected);
  6326. },
  6327. value: function(removedValue, removedText, $removedItem) {
  6328. var
  6329. values = module.get.values(),
  6330. newValue
  6331. ;
  6332. if( module.has.selectInput() ) {
  6333. module.verbose('Input is <select> removing selected option', removedValue);
  6334. newValue = module.remove.arrayValue(removedValue, values);
  6335. module.remove.optionValue(removedValue);
  6336. }
  6337. else {
  6338. module.verbose('Removing from delimited values', removedValue);
  6339. newValue = module.remove.arrayValue(removedValue, values);
  6340. newValue = newValue.join(settings.delimiter);
  6341. }
  6342. if(settings.fireOnInit === false && module.is.initialLoad()) {
  6343. module.verbose('No callback on initial load', settings.onRemove);
  6344. }
  6345. else {
  6346. settings.onRemove.call(element, removedValue, removedText, $removedItem);
  6347. }
  6348. module.set.value(newValue, removedText, $removedItem);
  6349. module.check.maxSelections();
  6350. },
  6351. arrayValue: function(removedValue, values) {
  6352. if( !$.isArray(values) ) {
  6353. values = [values];
  6354. }
  6355. values = $.grep(values, function(value){
  6356. return (removedValue != value);
  6357. });
  6358. module.verbose('Removed value from delimited string', removedValue, values);
  6359. return values;
  6360. },
  6361. label: function(value, shouldAnimate) {
  6362. var
  6363. $labels = $module.find(selector.label),
  6364. $removedLabel = $labels.filter('[data-value="' + value +'"]')
  6365. ;
  6366. module.verbose('Removing label', $removedLabel);
  6367. $removedLabel.remove();
  6368. },
  6369. activeLabels: function($activeLabels) {
  6370. $activeLabels = $activeLabels || $module.find(selector.label).filter('.' + className.active);
  6371. module.verbose('Removing active label selections', $activeLabels);
  6372. module.remove.labels($activeLabels);
  6373. },
  6374. labels: function($labels) {
  6375. $labels = $labels || $module.find(selector.label);
  6376. module.verbose('Removing labels', $labels);
  6377. $labels
  6378. .each(function(){
  6379. var
  6380. $label = $(this),
  6381. value = $label.data(metadata.value),
  6382. stringValue = (value !== undefined)
  6383. ? String(value)
  6384. : value,
  6385. isUserValue = module.is.userValue(stringValue)
  6386. ;
  6387. if(settings.onLabelRemove.call($label, value) === false) {
  6388. module.debug('Label remove callback cancelled removal');
  6389. return;
  6390. }
  6391. if(isUserValue) {
  6392. module.remove.value(stringValue);
  6393. module.remove.label(stringValue);
  6394. }
  6395. else {
  6396. // selected will also remove label
  6397. module.remove.selected(stringValue);
  6398. }
  6399. })
  6400. ;
  6401. },
  6402. tabbable: function() {
  6403. if( module.has.search() ) {
  6404. module.debug('Searchable dropdown initialized');
  6405. $search
  6406. .removeAttr('tabindex')
  6407. ;
  6408. $menu
  6409. .removeAttr('tabindex')
  6410. ;
  6411. }
  6412. else {
  6413. module.debug('Simple selection dropdown initialized');
  6414. $module
  6415. .removeAttr('tabindex')
  6416. ;
  6417. $menu
  6418. .removeAttr('tabindex')
  6419. ;
  6420. }
  6421. }
  6422. },
  6423. has: {
  6424. search: function() {
  6425. return ($search.length > 0);
  6426. },
  6427. selectInput: function() {
  6428. return ( $input.is('select') );
  6429. },
  6430. firstLetter: function($item, letter) {
  6431. var
  6432. text,
  6433. firstLetter
  6434. ;
  6435. if(!$item || $item.length === 0 || typeof letter !== 'string') {
  6436. return false;
  6437. }
  6438. text = module.get.choiceText($item, false);
  6439. letter = letter.toLowerCase();
  6440. firstLetter = String(text).charAt(0).toLowerCase();
  6441. return (letter == firstLetter);
  6442. },
  6443. input: function() {
  6444. return ($input.length > 0);
  6445. },
  6446. items: function() {
  6447. return ($item.length > 0);
  6448. },
  6449. menu: function() {
  6450. return ($menu.length > 0);
  6451. },
  6452. message: function() {
  6453. return ($menu.children(selector.message).length !== 0);
  6454. },
  6455. label: function(value) {
  6456. var
  6457. $labels = $module.find(selector.label)
  6458. ;
  6459. return ($labels.filter('[data-value="' + value +'"]').length > 0);
  6460. },
  6461. maxSelections: function() {
  6462. return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
  6463. },
  6464. allResultsFiltered: function() {
  6465. return ($item.filter(selector.unselectable).length === $item.length);
  6466. },
  6467. query: function() {
  6468. return (module.get.query() !== '');
  6469. },
  6470. value: function(value) {
  6471. var
  6472. values = module.get.values(),
  6473. hasValue = $.isArray(values)
  6474. ? values && ($.inArray(value, values) !== -1)
  6475. : (values == value)
  6476. ;
  6477. return (hasValue)
  6478. ? true
  6479. : false
  6480. ;
  6481. }
  6482. },
  6483. is: {
  6484. active: function() {
  6485. return $module.hasClass(className.active);
  6486. },
  6487. alreadySetup: function() {
  6488. return ($module.is('select') && $module.parent(selector.dropdown).length > 0 && $module.prev().length === 0);
  6489. },
  6490. animating: function($subMenu) {
  6491. return ($subMenu)
  6492. ? $subMenu.transition && $subMenu.transition('is animating')
  6493. : $menu.transition && $menu.transition('is animating')
  6494. ;
  6495. },
  6496. disabled: function() {
  6497. return $module.hasClass(className.disabled);
  6498. },
  6499. focused: function() {
  6500. return (document.activeElement === $module[0]);
  6501. },
  6502. focusedOnSearch: function() {
  6503. return (document.activeElement === $search[0]);
  6504. },
  6505. allFiltered: function() {
  6506. return( (module.is.multiple() || module.has.search()) && !module.has.message() && module.has.allResultsFiltered() );
  6507. },
  6508. hidden: function($subMenu) {
  6509. return !module.is.visible($subMenu);
  6510. },
  6511. initialLoad: function() {
  6512. return initialLoad;
  6513. },
  6514. onScreen: function($subMenu) {
  6515. var
  6516. $currentMenu = $subMenu || $menu,
  6517. canOpenDownward = true,
  6518. onScreen = {},
  6519. calculations
  6520. ;
  6521. $currentMenu.addClass(className.loading);
  6522. calculations = {
  6523. context: {
  6524. scrollTop : $context.scrollTop(),
  6525. height : $context.outerHeight()
  6526. },
  6527. menu : {
  6528. offset: $currentMenu.offset(),
  6529. height: $currentMenu.outerHeight()
  6530. }
  6531. };
  6532. onScreen = {
  6533. above : (calculations.context.scrollTop) <= calculations.menu.offset.top - calculations.menu.height,
  6534. below : (calculations.context.scrollTop + calculations.context.height) >= calculations.menu.offset.top + calculations.menu.height
  6535. };
  6536. if(onScreen.below) {
  6537. module.verbose('Dropdown can fit in context downward', onScreen);
  6538. canOpenDownward = true;
  6539. }
  6540. else if(!onScreen.below && !onScreen.above) {
  6541. module.verbose('Dropdown cannot fit in either direction, favoring downward', onScreen);
  6542. canOpenDownward = true;
  6543. }
  6544. else {
  6545. module.verbose('Dropdown cannot fit below, opening upward', onScreen);
  6546. canOpenDownward = false;
  6547. }
  6548. $currentMenu.removeClass(className.loading);
  6549. return canOpenDownward;
  6550. },
  6551. inObject: function(needle, object) {
  6552. var
  6553. found = false
  6554. ;
  6555. $.each(object, function(index, property) {
  6556. if(property == needle) {
  6557. found = true;
  6558. return true;
  6559. }
  6560. });
  6561. return found;
  6562. },
  6563. multiple: function() {
  6564. return $module.hasClass(className.multiple);
  6565. },
  6566. single: function() {
  6567. return !module.is.multiple();
  6568. },
  6569. selectMutation: function(mutations) {
  6570. var
  6571. selectChanged = false
  6572. ;
  6573. $.each(mutations, function(index, mutation) {
  6574. if(mutation.target && $(mutation.target).is('select')) {
  6575. selectChanged = true;
  6576. return true;
  6577. }
  6578. });
  6579. return selectChanged;
  6580. },
  6581. search: function() {
  6582. return $module.hasClass(className.search);
  6583. },
  6584. searchSelection: function() {
  6585. return ( module.has.search() && $search.parent(selector.dropdown).length === 1 );
  6586. },
  6587. selection: function() {
  6588. return $module.hasClass(className.selection);
  6589. },
  6590. userValue: function(value) {
  6591. return ($.inArray(value, module.get.userValues()) !== -1);
  6592. },
  6593. upward: function($menu) {
  6594. var $element = $menu || $module;
  6595. return $element.hasClass(className.upward);
  6596. },
  6597. visible: function($subMenu) {
  6598. return ($subMenu)
  6599. ? $subMenu.hasClass(className.visible)
  6600. : $menu.hasClass(className.visible)
  6601. ;
  6602. }
  6603. },
  6604. can: {
  6605. activate: function($item) {
  6606. if(settings.useLabels) {
  6607. return true;
  6608. }
  6609. if(!module.has.maxSelections()) {
  6610. return true;
  6611. }
  6612. if(module.has.maxSelections() && $item.hasClass(className.active)) {
  6613. return true;
  6614. }
  6615. return false;
  6616. },
  6617. click: function() {
  6618. return (hasTouch || settings.on == 'click');
  6619. },
  6620. extendSelect: function() {
  6621. return settings.allowAdditions || settings.apiSettings;
  6622. },
  6623. show: function() {
  6624. return !module.is.disabled() && (module.has.items() || module.has.message());
  6625. },
  6626. useAPI: function() {
  6627. return $.fn.api !== undefined;
  6628. }
  6629. },
  6630. animate: {
  6631. show: function(callback, $subMenu) {
  6632. var
  6633. $currentMenu = $subMenu || $menu,
  6634. start = ($subMenu)
  6635. ? function() {}
  6636. : function() {
  6637. module.hideSubMenus();
  6638. module.hideOthers();
  6639. module.set.active();
  6640. },
  6641. transition
  6642. ;
  6643. callback = $.isFunction(callback)
  6644. ? callback
  6645. : function(){}
  6646. ;
  6647. module.verbose('Doing menu show animation', $currentMenu);
  6648. module.set.direction($subMenu);
  6649. transition = module.get.transition($subMenu);
  6650. if( module.is.selection() ) {
  6651. module.set.scrollPosition(module.get.selectedItem(), true);
  6652. }
  6653. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  6654. if(transition == 'none') {
  6655. start();
  6656. $currentMenu.transition('show');
  6657. callback.call(element);
  6658. }
  6659. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  6660. $currentMenu
  6661. .transition({
  6662. animation : transition + ' in',
  6663. debug : settings.debug,
  6664. verbose : settings.verbose,
  6665. duration : settings.duration,
  6666. queue : true,
  6667. onStart : start,
  6668. onComplete : function() {
  6669. callback.call(element);
  6670. }
  6671. })
  6672. ;
  6673. }
  6674. else {
  6675. module.error(error.noTransition, transition);
  6676. }
  6677. }
  6678. },
  6679. hide: function(callback, $subMenu) {
  6680. var
  6681. $currentMenu = $subMenu || $menu,
  6682. duration = ($subMenu)
  6683. ? (settings.duration * 0.9)
  6684. : settings.duration,
  6685. start = ($subMenu)
  6686. ? function() {}
  6687. : function() {
  6688. if( module.can.click() ) {
  6689. module.unbind.intent();
  6690. }
  6691. module.remove.active();
  6692. },
  6693. transition = module.get.transition($subMenu)
  6694. ;
  6695. callback = $.isFunction(callback)
  6696. ? callback
  6697. : function(){}
  6698. ;
  6699. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  6700. module.verbose('Doing menu hide animation', $currentMenu);
  6701. if(transition == 'none') {
  6702. start();
  6703. $currentMenu.transition('hide');
  6704. callback.call(element);
  6705. }
  6706. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  6707. $currentMenu
  6708. .transition({
  6709. animation : transition + ' out',
  6710. duration : settings.duration,
  6711. debug : settings.debug,
  6712. verbose : settings.verbose,
  6713. queue : true,
  6714. onStart : start,
  6715. onComplete : function() {
  6716. if(settings.direction == 'auto') {
  6717. module.remove.upward($subMenu);
  6718. }
  6719. callback.call(element);
  6720. }
  6721. })
  6722. ;
  6723. }
  6724. else {
  6725. module.error(error.transition);
  6726. }
  6727. }
  6728. }
  6729. },
  6730. hideAndClear: function() {
  6731. module.remove.searchTerm();
  6732. if( module.has.maxSelections() ) {
  6733. return;
  6734. }
  6735. if(module.has.search()) {
  6736. module.hide(function() {
  6737. module.remove.filteredItem();
  6738. });
  6739. }
  6740. else {
  6741. module.hide();
  6742. }
  6743. },
  6744. delay: {
  6745. show: function() {
  6746. module.verbose('Delaying show event to ensure user intent');
  6747. clearTimeout(module.timer);
  6748. module.timer = setTimeout(module.show, settings.delay.show);
  6749. },
  6750. hide: function() {
  6751. module.verbose('Delaying hide event to ensure user intent');
  6752. clearTimeout(module.timer);
  6753. module.timer = setTimeout(module.hide, settings.delay.hide);
  6754. }
  6755. },
  6756. escape: {
  6757. regExp: function(text) {
  6758. text = String(text);
  6759. return text.replace(regExp.escape, '\\$&');
  6760. }
  6761. },
  6762. setting: function(name, value) {
  6763. module.debug('Changing setting', name, value);
  6764. if( $.isPlainObject(name) ) {
  6765. $.extend(true, settings, name);
  6766. }
  6767. else if(value !== undefined) {
  6768. settings[name] = value;
  6769. }
  6770. else {
  6771. return settings[name];
  6772. }
  6773. },
  6774. internal: function(name, value) {
  6775. if( $.isPlainObject(name) ) {
  6776. $.extend(true, module, name);
  6777. }
  6778. else if(value !== undefined) {
  6779. module[name] = value;
  6780. }
  6781. else {
  6782. return module[name];
  6783. }
  6784. },
  6785. debug: function() {
  6786. if(settings.debug) {
  6787. if(settings.performance) {
  6788. module.performance.log(arguments);
  6789. }
  6790. else {
  6791. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  6792. module.debug.apply(console, arguments);
  6793. }
  6794. }
  6795. },
  6796. verbose: function() {
  6797. if(settings.verbose && settings.debug) {
  6798. if(settings.performance) {
  6799. module.performance.log(arguments);
  6800. }
  6801. else {
  6802. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  6803. module.verbose.apply(console, arguments);
  6804. }
  6805. }
  6806. },
  6807. error: function() {
  6808. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  6809. module.error.apply(console, arguments);
  6810. },
  6811. performance: {
  6812. log: function(message) {
  6813. var
  6814. currentTime,
  6815. executionTime,
  6816. previousTime
  6817. ;
  6818. if(settings.performance) {
  6819. currentTime = new Date().getTime();
  6820. previousTime = time || currentTime;
  6821. executionTime = currentTime - previousTime;
  6822. time = currentTime;
  6823. performance.push({
  6824. 'Name' : message[0],
  6825. 'Arguments' : [].slice.call(message, 1) || '',
  6826. 'Element' : element,
  6827. 'Execution Time' : executionTime
  6828. });
  6829. }
  6830. clearTimeout(module.performance.timer);
  6831. module.performance.timer = setTimeout(module.performance.display, 500);
  6832. },
  6833. display: function() {
  6834. var
  6835. title = settings.name + ':',
  6836. totalTime = 0
  6837. ;
  6838. time = false;
  6839. clearTimeout(module.performance.timer);
  6840. $.each(performance, function(index, data) {
  6841. totalTime += data['Execution Time'];
  6842. });
  6843. title += ' ' + totalTime + 'ms';
  6844. if(moduleSelector) {
  6845. title += ' \'' + moduleSelector + '\'';
  6846. }
  6847. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  6848. console.groupCollapsed(title);
  6849. if(console.table) {
  6850. console.table(performance);
  6851. }
  6852. else {
  6853. $.each(performance, function(index, data) {
  6854. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  6855. });
  6856. }
  6857. console.groupEnd();
  6858. }
  6859. performance = [];
  6860. }
  6861. },
  6862. invoke: function(query, passedArguments, context) {
  6863. var
  6864. object = instance,
  6865. maxDepth,
  6866. found,
  6867. response
  6868. ;
  6869. passedArguments = passedArguments || queryArguments;
  6870. context = element || context;
  6871. if(typeof query == 'string' && object !== undefined) {
  6872. query = query.split(/[\. ]/);
  6873. maxDepth = query.length - 1;
  6874. $.each(query, function(depth, value) {
  6875. var camelCaseValue = (depth != maxDepth)
  6876. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  6877. : query
  6878. ;
  6879. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  6880. object = object[camelCaseValue];
  6881. }
  6882. else if( object[camelCaseValue] !== undefined ) {
  6883. found = object[camelCaseValue];
  6884. return false;
  6885. }
  6886. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  6887. object = object[value];
  6888. }
  6889. else if( object[value] !== undefined ) {
  6890. found = object[value];
  6891. return false;
  6892. }
  6893. else {
  6894. module.error(error.method, query);
  6895. return false;
  6896. }
  6897. });
  6898. }
  6899. if ( $.isFunction( found ) ) {
  6900. response = found.apply(context, passedArguments);
  6901. }
  6902. else if(found !== undefined) {
  6903. response = found;
  6904. }
  6905. if($.isArray(returnedValue)) {
  6906. returnedValue.push(response);
  6907. }
  6908. else if(returnedValue !== undefined) {
  6909. returnedValue = [returnedValue, response];
  6910. }
  6911. else if(response !== undefined) {
  6912. returnedValue = response;
  6913. }
  6914. return found;
  6915. }
  6916. };
  6917. if(methodInvoked) {
  6918. if(instance === undefined) {
  6919. module.initialize();
  6920. }
  6921. module.invoke(query);
  6922. }
  6923. else {
  6924. if(instance !== undefined) {
  6925. instance.invoke('destroy');
  6926. }
  6927. module.initialize();
  6928. }
  6929. })
  6930. ;
  6931. return (returnedValue !== undefined)
  6932. ? returnedValue
  6933. : $allModules
  6934. ;
  6935. };
  6936. $.fn.dropdown.settings = {
  6937. debug : false,
  6938. verbose : false,
  6939. performance : true,
  6940. on : 'click', // what event should show menu action on item selection
  6941. action : 'activate', // action on item selection (nothing, activate, select, combo, hide, function(){})
  6942. apiSettings : false,
  6943. saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
  6944. throttle : 200, // How long to wait after last user input to search remotely
  6945. context : window, // Context to use when determining if on screen
  6946. direction : 'auto', // Whether dropdown should always open in one direction
  6947. keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
  6948. match : 'both', // what to match against with search selection (both, text, or label)
  6949. fullTextSearch : false, // search anywhere in value
  6950. placeholder : 'auto', // whether to convert blank <select> values to placeholder text
  6951. preserveHTML : true, // preserve html when selecting value
  6952. sortSelect : false, // sort selection on init
  6953. forceSelection : true, // force a choice on blur with search selection
  6954. allowAdditions : false, // whether multiple select should allow user added values
  6955. maxSelections : false, // When set to a number limits the number of selections to this count
  6956. useLabels : true, // whether multiple select should filter currently active selections from choices
  6957. delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
  6958. showOnFocus : true, // show menu on focus
  6959. allowTab : true, // add tabindex to element
  6960. allowCategorySelection : false, // allow elements with sub-menus to be selected
  6961. fireOnInit : false, // Whether callbacks should fire when initializing dropdown values
  6962. transition : 'auto', // auto transition will slide down or up based on direction
  6963. duration : 200, // duration of transition
  6964. glyphWidth : 1.0714, // widest glyph width in em (W is 1.0714 em) used to calculate multiselect input width
  6965. // label settings on multi-select
  6966. label: {
  6967. transition : 'scale',
  6968. duration : 200,
  6969. variation : false
  6970. },
  6971. // delay before event
  6972. delay : {
  6973. hide : 300,
  6974. show : 200,
  6975. search : 20,
  6976. touch : 50
  6977. },
  6978. /* Callbacks */
  6979. onChange : function(value, text, $selected){},
  6980. onAdd : function(value, text, $selected){},
  6981. onRemove : function(value, text, $selected){},
  6982. onLabelSelect : function($selectedLabels){},
  6983. onLabelCreate : function(value, text) { return $(this); },
  6984. onLabelRemove : function(value) { return true; },
  6985. onNoResults : function(searchTerm) { return true; },
  6986. onShow : function(){},
  6987. onHide : function(){},
  6988. /* Component */
  6989. name : 'Dropdown',
  6990. namespace : 'dropdown',
  6991. message: {
  6992. addResult : 'Add <b>{term}</b>',
  6993. count : '{count} selected',
  6994. maxSelections : 'Max {maxCount} selections',
  6995. noResults : 'No results found.',
  6996. serverError : 'There was an error contacting the server'
  6997. },
  6998. error : {
  6999. action : 'You called a dropdown action that was not defined',
  7000. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  7001. labels : 'Allowing user additions currently requires the use of labels.',
  7002. missingMultiple : '<select> requires multiple property to be set to correctly preserve multiple values',
  7003. method : 'The method you called is not defined.',
  7004. noAPI : 'The API module is required to load resources remotely',
  7005. noStorage : 'Saving remote data requires session storage',
  7006. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>'
  7007. },
  7008. regExp : {
  7009. escape : /[-[\]{}()*+?.,\\^$|#\s]/g,
  7010. },
  7011. metadata : {
  7012. defaultText : 'defaultText',
  7013. defaultValue : 'defaultValue',
  7014. placeholderText : 'placeholder',
  7015. text : 'text',
  7016. value : 'value'
  7017. },
  7018. // property names for remote query
  7019. fields: {
  7020. remoteValues : 'results', // grouping for api results
  7021. values : 'values', // grouping for all dropdown values
  7022. name : 'name', // displayed dropdown text
  7023. value : 'value' // actual dropdown value
  7024. },
  7025. keys : {
  7026. backspace : 8,
  7027. delimiter : 188, // comma
  7028. deleteKey : 46,
  7029. enter : 13,
  7030. escape : 27,
  7031. pageUp : 33,
  7032. pageDown : 34,
  7033. leftArrow : 37,
  7034. upArrow : 38,
  7035. rightArrow : 39,
  7036. downArrow : 40
  7037. },
  7038. selector : {
  7039. addition : '.addition',
  7040. dropdown : '.ui.dropdown',
  7041. icon : '> .dropdown.icon',
  7042. input : '> input[type="hidden"], > select',
  7043. item : '.item',
  7044. label : '> .label',
  7045. remove : '> .label > .delete.icon',
  7046. siblingLabel : '.label',
  7047. menu : '.menu',
  7048. message : '.message',
  7049. menuIcon : '.dropdown.icon',
  7050. search : 'input.search, .menu > .search > input',
  7051. text : '> .text:not(.icon)',
  7052. unselectable : '.disabled, .filtered'
  7053. },
  7054. className : {
  7055. active : 'active',
  7056. addition : 'addition',
  7057. animating : 'animating',
  7058. disabled : 'disabled',
  7059. dropdown : 'ui dropdown',
  7060. filtered : 'filtered',
  7061. hidden : 'hidden transition',
  7062. item : 'item',
  7063. label : 'ui label',
  7064. loading : 'loading',
  7065. menu : 'menu',
  7066. message : 'message',
  7067. multiple : 'multiple',
  7068. placeholder : 'default',
  7069. search : 'search',
  7070. selected : 'selected',
  7071. selection : 'selection',
  7072. upward : 'upward',
  7073. visible : 'visible'
  7074. }
  7075. };
  7076. /* Templates */
  7077. $.fn.dropdown.settings.templates = {
  7078. // generates dropdown from select values
  7079. dropdown: function(select) {
  7080. var
  7081. placeholder = select.placeholder || false,
  7082. values = select.values || {},
  7083. html = ''
  7084. ;
  7085. html += '<i class="dropdown icon"></i>';
  7086. if(select.placeholder) {
  7087. html += '<div class="default text">' + placeholder + '</div>';
  7088. }
  7089. else {
  7090. html += '<div class="text"></div>';
  7091. }
  7092. html += '<div class="menu">';
  7093. $.each(select.values, function(index, option) {
  7094. html += (option.disabled)
  7095. ? '<div class="disabled item" data-value="' + option.value + '">' + option.name + '</div>'
  7096. : '<div class="item" data-value="' + option.value + '">' + option.name + '</div>'
  7097. ;
  7098. });
  7099. html += '</div>';
  7100. return html;
  7101. },
  7102. // generates just menu from select
  7103. menu: function(response, fields) {
  7104. var
  7105. values = response[fields.values] || {},
  7106. html = ''
  7107. ;
  7108. $.each(values, function(index, option) {
  7109. html += '<div class="item" data-value="' + option[fields.value] + '">' + option[fields.name] + '</div>';
  7110. });
  7111. return html;
  7112. },
  7113. // generates label for multiselect
  7114. label: function(value, text) {
  7115. return text + '<i class="delete icon"></i>';
  7116. },
  7117. // generates messages like "No results"
  7118. message: function(message) {
  7119. return message;
  7120. },
  7121. // generates user addition to selection menu
  7122. addition: function(choice) {
  7123. return choice;
  7124. }
  7125. };
  7126. })( jQuery, window, document );
  7127. /*!
  7128. * # Semantic UI 2.1.6 - Video
  7129. * http://github.com/semantic-org/semantic-ui/
  7130. *
  7131. *
  7132. * Copyright 2015 Contributors
  7133. * Released under the MIT license
  7134. * http://opensource.org/licenses/MIT
  7135. *
  7136. */
  7137. ;(function ($, window, document, undefined) {
  7138. "use strict";
  7139. $.fn.embed = function(parameters) {
  7140. var
  7141. $allModules = $(this),
  7142. moduleSelector = $allModules.selector || '',
  7143. time = new Date().getTime(),
  7144. performance = [],
  7145. query = arguments[0],
  7146. methodInvoked = (typeof query == 'string'),
  7147. queryArguments = [].slice.call(arguments, 1),
  7148. returnedValue
  7149. ;
  7150. $allModules
  7151. .each(function() {
  7152. var
  7153. settings = ( $.isPlainObject(parameters) )
  7154. ? $.extend(true, {}, $.fn.embed.settings, parameters)
  7155. : $.extend({}, $.fn.embed.settings),
  7156. selector = settings.selector,
  7157. className = settings.className,
  7158. sources = settings.sources,
  7159. error = settings.error,
  7160. metadata = settings.metadata,
  7161. namespace = settings.namespace,
  7162. templates = settings.templates,
  7163. eventNamespace = '.' + namespace,
  7164. moduleNamespace = 'module-' + namespace,
  7165. $window = $(window),
  7166. $module = $(this),
  7167. $placeholder = $module.find(selector.placeholder),
  7168. $icon = $module.find(selector.icon),
  7169. $embed = $module.find(selector.embed),
  7170. element = this,
  7171. instance = $module.data(moduleNamespace),
  7172. module
  7173. ;
  7174. module = {
  7175. initialize: function() {
  7176. module.debug('Initializing embed');
  7177. module.determine.autoplay();
  7178. module.create();
  7179. module.bind.events();
  7180. module.instantiate();
  7181. },
  7182. instantiate: function() {
  7183. module.verbose('Storing instance of module', module);
  7184. instance = module;
  7185. $module
  7186. .data(moduleNamespace, module)
  7187. ;
  7188. },
  7189. destroy: function() {
  7190. module.verbose('Destroying previous instance of embed');
  7191. module.reset();
  7192. $module
  7193. .removeData(moduleNamespace)
  7194. .off(eventNamespace)
  7195. ;
  7196. },
  7197. refresh: function() {
  7198. module.verbose('Refreshing selector cache');
  7199. $placeholder = $module.find(selector.placeholder);
  7200. $icon = $module.find(selector.icon);
  7201. $embed = $module.find(selector.embed);
  7202. },
  7203. bind: {
  7204. events: function() {
  7205. if( module.has.placeholder() ) {
  7206. module.debug('Adding placeholder events');
  7207. $module
  7208. .on('click' + eventNamespace, selector.placeholder, module.createAndShow)
  7209. .on('click' + eventNamespace, selector.icon, module.createAndShow)
  7210. ;
  7211. }
  7212. }
  7213. },
  7214. create: function() {
  7215. var
  7216. placeholder = module.get.placeholder()
  7217. ;
  7218. if(placeholder) {
  7219. module.createPlaceholder();
  7220. }
  7221. else {
  7222. module.createAndShow();
  7223. }
  7224. },
  7225. createPlaceholder: function(placeholder) {
  7226. var
  7227. icon = module.get.icon(),
  7228. url = module.get.url(),
  7229. embed = module.generate.embed(url)
  7230. ;
  7231. placeholder = placeholder || module.get.placeholder();
  7232. $module.html( templates.placeholder(placeholder, icon) );
  7233. module.debug('Creating placeholder for embed', placeholder, icon);
  7234. },
  7235. createEmbed: function(url) {
  7236. module.refresh();
  7237. url = url || module.get.url();
  7238. $embed = $('<div/>')
  7239. .addClass(className.embed)
  7240. .html( module.generate.embed(url) )
  7241. .appendTo($module)
  7242. ;
  7243. settings.onCreate.call(element, url);
  7244. module.debug('Creating embed object', $embed);
  7245. },
  7246. createAndShow: function() {
  7247. module.createEmbed();
  7248. module.show();
  7249. },
  7250. // sets new embed
  7251. change: function(source, id, url) {
  7252. module.debug('Changing video to ', source, id, url);
  7253. $module
  7254. .data(metadata.source, source)
  7255. .data(metadata.id, id)
  7256. .data(metadata.url, url)
  7257. ;
  7258. module.create();
  7259. },
  7260. // clears embed
  7261. reset: function() {
  7262. module.debug('Clearing embed and showing placeholder');
  7263. module.remove.active();
  7264. module.remove.embed();
  7265. module.showPlaceholder();
  7266. settings.onReset.call(element);
  7267. },
  7268. // shows current embed
  7269. show: function() {
  7270. module.debug('Showing embed');
  7271. module.set.active();
  7272. settings.onDisplay.call(element);
  7273. },
  7274. hide: function() {
  7275. module.debug('Hiding embed');
  7276. module.showPlaceholder();
  7277. },
  7278. showPlaceholder: function() {
  7279. module.debug('Showing placeholder image');
  7280. module.remove.active();
  7281. settings.onPlaceholderDisplay.call(element);
  7282. },
  7283. get: {
  7284. id: function() {
  7285. return settings.id || $module.data(metadata.id);
  7286. },
  7287. placeholder: function() {
  7288. return settings.placeholder || $module.data(metadata.placeholder);
  7289. },
  7290. icon: function() {
  7291. return (settings.icon)
  7292. ? settings.icon
  7293. : ($module.data(metadata.icon) !== undefined)
  7294. ? $module.data(metadata.icon)
  7295. : module.determine.icon()
  7296. ;
  7297. },
  7298. source: function(url) {
  7299. return (settings.source)
  7300. ? settings.source
  7301. : ($module.data(metadata.source) !== undefined)
  7302. ? $module.data(metadata.source)
  7303. : module.determine.source()
  7304. ;
  7305. },
  7306. type: function() {
  7307. var source = module.get.source();
  7308. return (sources[source] !== undefined)
  7309. ? sources[source].type
  7310. : false
  7311. ;
  7312. },
  7313. url: function() {
  7314. return (settings.url)
  7315. ? settings.url
  7316. : ($module.data(metadata.url) !== undefined)
  7317. ? $module.data(metadata.url)
  7318. : module.determine.url()
  7319. ;
  7320. }
  7321. },
  7322. determine: {
  7323. autoplay: function() {
  7324. if(module.should.autoplay()) {
  7325. settings.autoplay = true;
  7326. }
  7327. },
  7328. source: function(url) {
  7329. var
  7330. matchedSource = false
  7331. ;
  7332. url = url || module.get.url();
  7333. if(url) {
  7334. $.each(sources, function(name, source) {
  7335. if(url.search(source.domain) !== -1) {
  7336. matchedSource = name;
  7337. return false;
  7338. }
  7339. });
  7340. }
  7341. return matchedSource;
  7342. },
  7343. icon: function() {
  7344. var
  7345. source = module.get.source()
  7346. ;
  7347. return (sources[source] !== undefined)
  7348. ? sources[source].icon
  7349. : false
  7350. ;
  7351. },
  7352. url: function() {
  7353. var
  7354. id = settings.id || $module.data(metadata.id),
  7355. source = settings.source || $module.data(metadata.source),
  7356. url
  7357. ;
  7358. url = (sources[source] !== undefined)
  7359. ? sources[source].url.replace('{id}', id)
  7360. : false
  7361. ;
  7362. if(url) {
  7363. $module.data(metadata.url, url);
  7364. }
  7365. return url;
  7366. }
  7367. },
  7368. set: {
  7369. active: function() {
  7370. $module.addClass(className.active);
  7371. }
  7372. },
  7373. remove: {
  7374. active: function() {
  7375. $module.removeClass(className.active);
  7376. },
  7377. embed: function() {
  7378. $embed.empty();
  7379. }
  7380. },
  7381. encode: {
  7382. parameters: function(parameters) {
  7383. var
  7384. urlString = [],
  7385. index
  7386. ;
  7387. for (index in parameters) {
  7388. urlString.push( encodeURIComponent(index) + '=' + encodeURIComponent( parameters[index] ) );
  7389. }
  7390. return urlString.join('&amp;');
  7391. }
  7392. },
  7393. generate: {
  7394. embed: function(url) {
  7395. module.debug('Generating embed html');
  7396. var
  7397. source = module.get.source(),
  7398. html,
  7399. parameters
  7400. ;
  7401. url = module.get.url(url);
  7402. if(url) {
  7403. parameters = module.generate.parameters(source);
  7404. html = templates.iframe(url, parameters);
  7405. }
  7406. else {
  7407. module.error(error.noURL, $module);
  7408. }
  7409. return html;
  7410. },
  7411. parameters: function(source, extraParameters) {
  7412. var
  7413. parameters = (sources[source] && sources[source].parameters !== undefined)
  7414. ? sources[source].parameters(settings)
  7415. : {}
  7416. ;
  7417. extraParameters = extraParameters || settings.parameters;
  7418. if(extraParameters) {
  7419. parameters = $.extend({}, parameters, extraParameters);
  7420. }
  7421. parameters = settings.onEmbed(parameters);
  7422. return module.encode.parameters(parameters);
  7423. }
  7424. },
  7425. has: {
  7426. placeholder: function() {
  7427. return settings.placeholder || $module.data(metadata.placeholder);
  7428. }
  7429. },
  7430. should: {
  7431. autoplay: function() {
  7432. return (settings.autoplay === 'auto')
  7433. ? (settings.placeholder || $module.data(metadata.placeholder) !== undefined)
  7434. : settings.autoplay
  7435. ;
  7436. }
  7437. },
  7438. is: {
  7439. video: function() {
  7440. return module.get.type() == 'video';
  7441. }
  7442. },
  7443. setting: function(name, value) {
  7444. module.debug('Changing setting', name, value);
  7445. if( $.isPlainObject(name) ) {
  7446. $.extend(true, settings, name);
  7447. }
  7448. else if(value !== undefined) {
  7449. settings[name] = value;
  7450. }
  7451. else {
  7452. return settings[name];
  7453. }
  7454. },
  7455. internal: function(name, value) {
  7456. if( $.isPlainObject(name) ) {
  7457. $.extend(true, module, name);
  7458. }
  7459. else if(value !== undefined) {
  7460. module[name] = value;
  7461. }
  7462. else {
  7463. return module[name];
  7464. }
  7465. },
  7466. debug: function() {
  7467. if(settings.debug) {
  7468. if(settings.performance) {
  7469. module.performance.log(arguments);
  7470. }
  7471. else {
  7472. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7473. module.debug.apply(console, arguments);
  7474. }
  7475. }
  7476. },
  7477. verbose: function() {
  7478. if(settings.verbose && settings.debug) {
  7479. if(settings.performance) {
  7480. module.performance.log(arguments);
  7481. }
  7482. else {
  7483. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  7484. module.verbose.apply(console, arguments);
  7485. }
  7486. }
  7487. },
  7488. error: function() {
  7489. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  7490. module.error.apply(console, arguments);
  7491. },
  7492. performance: {
  7493. log: function(message) {
  7494. var
  7495. currentTime,
  7496. executionTime,
  7497. previousTime
  7498. ;
  7499. if(settings.performance) {
  7500. currentTime = new Date().getTime();
  7501. previousTime = time || currentTime;
  7502. executionTime = currentTime - previousTime;
  7503. time = currentTime;
  7504. performance.push({
  7505. 'Name' : message[0],
  7506. 'Arguments' : [].slice.call(message, 1) || '',
  7507. 'Element' : element,
  7508. 'Execution Time' : executionTime
  7509. });
  7510. }
  7511. clearTimeout(module.performance.timer);
  7512. module.performance.timer = setTimeout(module.performance.display, 500);
  7513. },
  7514. display: function() {
  7515. var
  7516. title = settings.name + ':',
  7517. totalTime = 0
  7518. ;
  7519. time = false;
  7520. clearTimeout(module.performance.timer);
  7521. $.each(performance, function(index, data) {
  7522. totalTime += data['Execution Time'];
  7523. });
  7524. title += ' ' + totalTime + 'ms';
  7525. if(moduleSelector) {
  7526. title += ' \'' + moduleSelector + '\'';
  7527. }
  7528. if($allModules.length > 1) {
  7529. title += ' ' + '(' + $allModules.length + ')';
  7530. }
  7531. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  7532. console.groupCollapsed(title);
  7533. if(console.table) {
  7534. console.table(performance);
  7535. }
  7536. else {
  7537. $.each(performance, function(index, data) {
  7538. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  7539. });
  7540. }
  7541. console.groupEnd();
  7542. }
  7543. performance = [];
  7544. }
  7545. },
  7546. invoke: function(query, passedArguments, context) {
  7547. var
  7548. object = instance,
  7549. maxDepth,
  7550. found,
  7551. response
  7552. ;
  7553. passedArguments = passedArguments || queryArguments;
  7554. context = element || context;
  7555. if(typeof query == 'string' && object !== undefined) {
  7556. query = query.split(/[\. ]/);
  7557. maxDepth = query.length - 1;
  7558. $.each(query, function(depth, value) {
  7559. var camelCaseValue = (depth != maxDepth)
  7560. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  7561. : query
  7562. ;
  7563. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  7564. object = object[camelCaseValue];
  7565. }
  7566. else if( object[camelCaseValue] !== undefined ) {
  7567. found = object[camelCaseValue];
  7568. return false;
  7569. }
  7570. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  7571. object = object[value];
  7572. }
  7573. else if( object[value] !== undefined ) {
  7574. found = object[value];
  7575. return false;
  7576. }
  7577. else {
  7578. module.error(error.method, query);
  7579. return false;
  7580. }
  7581. });
  7582. }
  7583. if ( $.isFunction( found ) ) {
  7584. response = found.apply(context, passedArguments);
  7585. }
  7586. else if(found !== undefined) {
  7587. response = found;
  7588. }
  7589. if($.isArray(returnedValue)) {
  7590. returnedValue.push(response);
  7591. }
  7592. else if(returnedValue !== undefined) {
  7593. returnedValue = [returnedValue, response];
  7594. }
  7595. else if(response !== undefined) {
  7596. returnedValue = response;
  7597. }
  7598. return found;
  7599. }
  7600. };
  7601. if(methodInvoked) {
  7602. if(instance === undefined) {
  7603. module.initialize();
  7604. }
  7605. module.invoke(query);
  7606. }
  7607. else {
  7608. if(instance !== undefined) {
  7609. instance.invoke('destroy');
  7610. }
  7611. module.initialize();
  7612. }
  7613. })
  7614. ;
  7615. return (returnedValue !== undefined)
  7616. ? returnedValue
  7617. : this
  7618. ;
  7619. };
  7620. $.fn.embed.settings = {
  7621. name : 'Embed',
  7622. namespace : 'embed',
  7623. debug : false,
  7624. verbose : false,
  7625. performance : true,
  7626. icon : false,
  7627. source : false,
  7628. url : false,
  7629. id : false,
  7630. // standard video settings
  7631. autoplay : 'auto',
  7632. color : '#444444',
  7633. hd : true,
  7634. brandedUI : false,
  7635. // additional parameters to include with the embed
  7636. parameters: false,
  7637. onDisplay : function() {},
  7638. onPlaceholderDisplay : function() {},
  7639. onReset : function() {},
  7640. onCreate : function(url) {},
  7641. onEmbed : function(parameters) {
  7642. return parameters;
  7643. },
  7644. metadata : {
  7645. id : 'id',
  7646. icon : 'icon',
  7647. placeholder : 'placeholder',
  7648. source : 'source',
  7649. url : 'url'
  7650. },
  7651. error : {
  7652. noURL : 'No URL specified',
  7653. method : 'The method you called is not defined'
  7654. },
  7655. className : {
  7656. active : 'active',
  7657. embed : 'embed'
  7658. },
  7659. selector : {
  7660. embed : '.embed',
  7661. placeholder : '.placeholder',
  7662. icon : '.icon'
  7663. },
  7664. sources: {
  7665. youtube: {
  7666. name : 'youtube',
  7667. type : 'video',
  7668. icon : 'video play',
  7669. domain : 'youtube.com',
  7670. url : '//www.youtube.com/embed/{id}',
  7671. parameters: function(settings) {
  7672. return {
  7673. autohide : !settings.brandedUI,
  7674. autoplay : settings.autoplay,
  7675. color : settings.colors || undefined,
  7676. hq : settings.hd,
  7677. jsapi : settings.api,
  7678. modestbranding : !settings.brandedUI
  7679. };
  7680. }
  7681. },
  7682. vimeo: {
  7683. name : 'vimeo',
  7684. type : 'video',
  7685. icon : 'video play',
  7686. domain : 'vimeo.com',
  7687. url : '//player.vimeo.com/video/{id}',
  7688. parameters: function(settings) {
  7689. return {
  7690. api : settings.api,
  7691. autoplay : settings.autoplay,
  7692. byline : settings.brandedUI,
  7693. color : settings.colors || undefined,
  7694. portrait : settings.brandedUI,
  7695. title : settings.brandedUI
  7696. };
  7697. }
  7698. }
  7699. },
  7700. templates: {
  7701. iframe : function(url, parameters) {
  7702. return ''
  7703. + '<iframe src="' + url + '?' + parameters + '"'
  7704. + ' width="100%" height="100%"'
  7705. + ' frameborder="0" scrolling="no" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'
  7706. ;
  7707. },
  7708. placeholder : function(image, icon) {
  7709. var
  7710. html = ''
  7711. ;
  7712. if(icon) {
  7713. html += '<i class="' + icon + ' icon"></i>';
  7714. }
  7715. if(image) {
  7716. html += '<img class="placeholder" src="' + image + '">';
  7717. }
  7718. return html;
  7719. }
  7720. },
  7721. // NOT YET IMPLEMENTED
  7722. api : true,
  7723. onPause : function() {},
  7724. onPlay : function() {},
  7725. onStop : function() {}
  7726. };
  7727. })( jQuery, window, document );
  7728. /*!
  7729. * # Semantic UI 2.1.6 - Modal
  7730. * http://github.com/semantic-org/semantic-ui/
  7731. *
  7732. *
  7733. * Copyright 2015 Contributors
  7734. * Released under the MIT license
  7735. * http://opensource.org/licenses/MIT
  7736. *
  7737. */
  7738. ;(function ( $, window, document, undefined ) {
  7739. "use strict";
  7740. $.fn.modal = function(parameters) {
  7741. var
  7742. $allModules = $(this),
  7743. $window = $(window),
  7744. $document = $(document),
  7745. $body = $('body'),
  7746. moduleSelector = $allModules.selector || '',
  7747. time = new Date().getTime(),
  7748. performance = [],
  7749. query = arguments[0],
  7750. methodInvoked = (typeof query == 'string'),
  7751. queryArguments = [].slice.call(arguments, 1),
  7752. requestAnimationFrame = window.requestAnimationFrame
  7753. || window.mozRequestAnimationFrame
  7754. || window.webkitRequestAnimationFrame
  7755. || window.msRequestAnimationFrame
  7756. || function(callback) { setTimeout(callback, 0); },
  7757. returnedValue
  7758. ;
  7759. $allModules
  7760. .each(function() {
  7761. var
  7762. settings = ( $.isPlainObject(parameters) )
  7763. ? $.extend(true, {}, $.fn.modal.settings, parameters)
  7764. : $.extend({}, $.fn.modal.settings),
  7765. selector = settings.selector,
  7766. className = settings.className,
  7767. namespace = settings.namespace,
  7768. error = settings.error,
  7769. eventNamespace = '.' + namespace,
  7770. moduleNamespace = 'module-' + namespace,
  7771. $module = $(this),
  7772. $context = $(settings.context),
  7773. $close = $module.find(selector.close),
  7774. $allModals,
  7775. $otherModals,
  7776. $focusedElement,
  7777. $dimmable,
  7778. $dimmer,
  7779. element = this,
  7780. instance = $module.data(moduleNamespace),
  7781. elementNamespace,
  7782. id,
  7783. observer,
  7784. module
  7785. ;
  7786. module = {
  7787. initialize: function() {
  7788. module.verbose('Initializing dimmer', $context);
  7789. module.create.id();
  7790. module.create.dimmer();
  7791. module.refreshModals();
  7792. module.bind.events();
  7793. if(settings.observeChanges) {
  7794. module.observeChanges();
  7795. }
  7796. module.instantiate();
  7797. },
  7798. instantiate: function() {
  7799. module.verbose('Storing instance of modal');
  7800. instance = module;
  7801. $module
  7802. .data(moduleNamespace, instance)
  7803. ;
  7804. },
  7805. create: {
  7806. dimmer: function() {
  7807. var
  7808. defaultSettings = {
  7809. debug : settings.debug,
  7810. dimmerName : 'modals',
  7811. duration : {
  7812. show : settings.duration,
  7813. hide : settings.duration
  7814. }
  7815. },
  7816. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  7817. ;
  7818. if(settings.inverted) {
  7819. dimmerSettings.variation = (dimmerSettings.variation !== undefined)
  7820. ? dimmerSettings.variation + ' inverted'
  7821. : 'inverted'
  7822. ;
  7823. }
  7824. if($.fn.dimmer === undefined) {
  7825. module.error(error.dimmer);
  7826. return;
  7827. }
  7828. module.debug('Creating dimmer with settings', dimmerSettings);
  7829. $dimmable = $context.dimmer(dimmerSettings);
  7830. if(settings.detachable) {
  7831. module.verbose('Modal is detachable, moving content into dimmer');
  7832. $dimmable.dimmer('add content', $module);
  7833. }
  7834. else {
  7835. module.set.undetached();
  7836. }
  7837. if(settings.blurring) {
  7838. $dimmable.addClass(className.blurring);
  7839. }
  7840. $dimmer = $dimmable.dimmer('get dimmer');
  7841. },
  7842. id: function() {
  7843. id = (Math.random().toString(16) + '000000000').substr(2,8);
  7844. elementNamespace = '.' + id;
  7845. module.verbose('Creating unique id for element', id);
  7846. }
  7847. },
  7848. destroy: function() {
  7849. module.verbose('Destroying previous modal');
  7850. $module
  7851. .removeData(moduleNamespace)
  7852. .off(eventNamespace)
  7853. ;
  7854. $window.off(elementNamespace);
  7855. $close.off(eventNamespace);
  7856. $context.dimmer('destroy');
  7857. },
  7858. observeChanges: function() {
  7859. if('MutationObserver' in window) {
  7860. observer = new MutationObserver(function(mutations) {
  7861. module.debug('DOM tree modified, refreshing');
  7862. module.refresh();
  7863. });
  7864. observer.observe(element, {
  7865. childList : true,
  7866. subtree : true
  7867. });
  7868. module.debug('Setting up mutation observer', observer);
  7869. }
  7870. },
  7871. refresh: function() {
  7872. module.remove.scrolling();
  7873. module.cacheSizes();
  7874. module.set.screenHeight();
  7875. module.set.type();
  7876. module.set.position();
  7877. },
  7878. refreshModals: function() {
  7879. $otherModals = $module.siblings(selector.modal);
  7880. $allModals = $otherModals.add($module);
  7881. },
  7882. attachEvents: function(selector, event) {
  7883. var
  7884. $toggle = $(selector)
  7885. ;
  7886. event = $.isFunction(module[event])
  7887. ? module[event]
  7888. : module.toggle
  7889. ;
  7890. if($toggle.length > 0) {
  7891. module.debug('Attaching modal events to element', selector, event);
  7892. $toggle
  7893. .off(eventNamespace)
  7894. .on('click' + eventNamespace, event)
  7895. ;
  7896. }
  7897. else {
  7898. module.error(error.notFound, selector);
  7899. }
  7900. },
  7901. bind: {
  7902. events: function() {
  7903. module.verbose('Attaching events');
  7904. $module
  7905. .on('click' + eventNamespace, selector.close, module.event.close)
  7906. .on('click' + eventNamespace, selector.approve, module.event.approve)
  7907. .on('click' + eventNamespace, selector.deny, module.event.deny)
  7908. ;
  7909. $window
  7910. .on('resize' + elementNamespace, module.event.resize)
  7911. ;
  7912. }
  7913. },
  7914. get: {
  7915. id: function() {
  7916. return (Math.random().toString(16) + '000000000').substr(2,8);
  7917. }
  7918. },
  7919. event: {
  7920. approve: function() {
  7921. if(settings.onApprove.call(element, $(this)) === false) {
  7922. module.verbose('Approve callback returned false cancelling hide');
  7923. return;
  7924. }
  7925. module.hide();
  7926. },
  7927. deny: function() {
  7928. if(settings.onDeny.call(element, $(this)) === false) {
  7929. module.verbose('Deny callback returned false cancelling hide');
  7930. return;
  7931. }
  7932. module.hide();
  7933. },
  7934. close: function() {
  7935. module.hide();
  7936. },
  7937. click: function(event) {
  7938. var
  7939. $target = $(event.target),
  7940. isInModal = ($target.closest(selector.modal).length > 0),
  7941. isInDOM = $.contains(document.documentElement, event.target)
  7942. ;
  7943. if(!isInModal && isInDOM) {
  7944. module.debug('Dimmer clicked, hiding all modals');
  7945. if( module.is.active() ) {
  7946. module.remove.clickaway();
  7947. if(settings.allowMultiple) {
  7948. module.hide();
  7949. }
  7950. else {
  7951. module.hideAll();
  7952. }
  7953. }
  7954. }
  7955. },
  7956. debounce: function(method, delay) {
  7957. clearTimeout(module.timer);
  7958. module.timer = setTimeout(method, delay);
  7959. },
  7960. keyboard: function(event) {
  7961. var
  7962. keyCode = event.which,
  7963. escapeKey = 27
  7964. ;
  7965. if(keyCode == escapeKey) {
  7966. if(settings.closable) {
  7967. module.debug('Escape key pressed hiding modal');
  7968. module.hide();
  7969. }
  7970. else {
  7971. module.debug('Escape key pressed, but closable is set to false');
  7972. }
  7973. event.preventDefault();
  7974. }
  7975. },
  7976. resize: function() {
  7977. if( $dimmable.dimmer('is active') ) {
  7978. requestAnimationFrame(module.refresh);
  7979. }
  7980. }
  7981. },
  7982. toggle: function() {
  7983. if( module.is.active() || module.is.animating() ) {
  7984. module.hide();
  7985. }
  7986. else {
  7987. module.show();
  7988. }
  7989. },
  7990. show: function(callback) {
  7991. callback = $.isFunction(callback)
  7992. ? callback
  7993. : function(){}
  7994. ;
  7995. module.refreshModals();
  7996. module.showModal(callback);
  7997. },
  7998. hide: function(callback) {
  7999. callback = $.isFunction(callback)
  8000. ? callback
  8001. : function(){}
  8002. ;
  8003. module.refreshModals();
  8004. module.hideModal(callback);
  8005. },
  8006. showModal: function(callback) {
  8007. callback = $.isFunction(callback)
  8008. ? callback
  8009. : function(){}
  8010. ;
  8011. if( module.is.animating() || !module.is.active() ) {
  8012. module.showDimmer();
  8013. module.cacheSizes();
  8014. module.set.position();
  8015. module.set.screenHeight();
  8016. module.set.type();
  8017. module.set.clickaway();
  8018. if( !settings.allowMultiple && module.others.active() ) {
  8019. module.hideOthers(module.showModal);
  8020. }
  8021. else {
  8022. settings.onShow.call(element);
  8023. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8024. module.debug('Showing modal with css animations');
  8025. $module
  8026. .transition({
  8027. debug : settings.debug,
  8028. animation : settings.transition + ' in',
  8029. queue : settings.queue,
  8030. duration : settings.duration,
  8031. useFailSafe : true,
  8032. onComplete : function() {
  8033. settings.onVisible.apply(element);
  8034. module.add.keyboardShortcuts();
  8035. module.save.focus();
  8036. module.set.active();
  8037. if(settings.autofocus) {
  8038. module.set.autofocus();
  8039. }
  8040. callback();
  8041. }
  8042. })
  8043. ;
  8044. }
  8045. else {
  8046. module.error(error.noTransition);
  8047. }
  8048. }
  8049. }
  8050. else {
  8051. module.debug('Modal is already visible');
  8052. }
  8053. },
  8054. hideModal: function(callback, keepDimmed) {
  8055. callback = $.isFunction(callback)
  8056. ? callback
  8057. : function(){}
  8058. ;
  8059. module.debug('Hiding modal');
  8060. if(settings.onHide.call(element, $(this)) === false) {
  8061. module.verbose('Hide callback returned false cancelling hide');
  8062. return;
  8063. }
  8064. if( module.is.animating() || module.is.active() ) {
  8065. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  8066. module.remove.active();
  8067. $module
  8068. .transition({
  8069. debug : settings.debug,
  8070. animation : settings.transition + ' out',
  8071. queue : settings.queue,
  8072. duration : settings.duration,
  8073. useFailSafe : true,
  8074. onStart : function() {
  8075. if(!module.others.active() && !keepDimmed) {
  8076. module.hideDimmer();
  8077. }
  8078. module.remove.keyboardShortcuts();
  8079. },
  8080. onComplete : function() {
  8081. settings.onHidden.call(element);
  8082. module.restore.focus();
  8083. callback();
  8084. }
  8085. })
  8086. ;
  8087. }
  8088. else {
  8089. module.error(error.noTransition);
  8090. }
  8091. }
  8092. },
  8093. showDimmer: function() {
  8094. if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
  8095. module.debug('Showing dimmer');
  8096. $dimmable.dimmer('show');
  8097. }
  8098. else {
  8099. module.debug('Dimmer already visible');
  8100. }
  8101. },
  8102. hideDimmer: function() {
  8103. if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
  8104. $dimmable.dimmer('hide', function() {
  8105. module.remove.clickaway();
  8106. module.remove.screenHeight();
  8107. });
  8108. }
  8109. else {
  8110. module.debug('Dimmer is not visible cannot hide');
  8111. return;
  8112. }
  8113. },
  8114. hideAll: function(callback) {
  8115. var
  8116. $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
  8117. ;
  8118. callback = $.isFunction(callback)
  8119. ? callback
  8120. : function(){}
  8121. ;
  8122. if( $visibleModals.length > 0 ) {
  8123. module.debug('Hiding all visible modals');
  8124. module.hideDimmer();
  8125. $visibleModals
  8126. .modal('hide modal', callback)
  8127. ;
  8128. }
  8129. },
  8130. hideOthers: function(callback) {
  8131. var
  8132. $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
  8133. ;
  8134. callback = $.isFunction(callback)
  8135. ? callback
  8136. : function(){}
  8137. ;
  8138. if( $visibleModals.length > 0 ) {
  8139. module.debug('Hiding other modals', $otherModals);
  8140. $visibleModals
  8141. .modal('hide modal', callback, true)
  8142. ;
  8143. }
  8144. },
  8145. others: {
  8146. active: function() {
  8147. return ($otherModals.filter('.' + className.active).length > 0);
  8148. },
  8149. animating: function() {
  8150. return ($otherModals.filter('.' + className.animating).length > 0);
  8151. }
  8152. },
  8153. add: {
  8154. keyboardShortcuts: function() {
  8155. module.verbose('Adding keyboard shortcuts');
  8156. $document
  8157. .on('keyup' + eventNamespace, module.event.keyboard)
  8158. ;
  8159. }
  8160. },
  8161. save: {
  8162. focus: function() {
  8163. $focusedElement = $(document.activeElement).blur();
  8164. }
  8165. },
  8166. restore: {
  8167. focus: function() {
  8168. if($focusedElement && $focusedElement.length > 0) {
  8169. $focusedElement.focus();
  8170. }
  8171. }
  8172. },
  8173. remove: {
  8174. active: function() {
  8175. $module.removeClass(className.active);
  8176. },
  8177. clickaway: function() {
  8178. if(settings.closable) {
  8179. $dimmer
  8180. .off('click' + elementNamespace)
  8181. ;
  8182. }
  8183. },
  8184. bodyStyle: function() {
  8185. if($body.attr('style') === '') {
  8186. module.verbose('Removing style attribute');
  8187. $body.removeAttr('style');
  8188. }
  8189. },
  8190. screenHeight: function() {
  8191. module.debug('Removing page height');
  8192. $body
  8193. .css('height', '')
  8194. ;
  8195. },
  8196. keyboardShortcuts: function() {
  8197. module.verbose('Removing keyboard shortcuts');
  8198. $document
  8199. .off('keyup' + eventNamespace)
  8200. ;
  8201. },
  8202. scrolling: function() {
  8203. $dimmable.removeClass(className.scrolling);
  8204. $module.removeClass(className.scrolling);
  8205. }
  8206. },
  8207. cacheSizes: function() {
  8208. var
  8209. modalHeight = $module.outerHeight()
  8210. ;
  8211. if(module.cache === undefined || modalHeight !== 0) {
  8212. module.cache = {
  8213. pageHeight : $(document).outerHeight(),
  8214. height : modalHeight + settings.offset,
  8215. contextHeight : (settings.context == 'body')
  8216. ? $(window).height()
  8217. : $dimmable.height()
  8218. };
  8219. }
  8220. module.debug('Caching modal and container sizes', module.cache);
  8221. },
  8222. can: {
  8223. fit: function() {
  8224. return ( ( module.cache.height + (settings.padding * 2) ) < module.cache.contextHeight);
  8225. }
  8226. },
  8227. is: {
  8228. active: function() {
  8229. return $module.hasClass(className.active);
  8230. },
  8231. animating: function() {
  8232. return $module.transition('is supported')
  8233. ? $module.transition('is animating')
  8234. : $module.is(':visible')
  8235. ;
  8236. },
  8237. scrolling: function() {
  8238. return $dimmable.hasClass(className.scrolling);
  8239. },
  8240. modernBrowser: function() {
  8241. // appName for IE11 reports 'Netscape' can no longer use
  8242. return !(window.ActiveXObject || "ActiveXObject" in window);
  8243. }
  8244. },
  8245. set: {
  8246. autofocus: function() {
  8247. var
  8248. $inputs = $module.find(':input').filter(':visible'),
  8249. $autofocus = $inputs.filter('[autofocus]'),
  8250. $input = ($autofocus.length > 0)
  8251. ? $autofocus.first()
  8252. : $inputs.first()
  8253. ;
  8254. if($input.length > 0) {
  8255. $input.focus();
  8256. }
  8257. },
  8258. clickaway: function() {
  8259. if(settings.closable) {
  8260. $dimmer
  8261. .on('click' + elementNamespace, module.event.click)
  8262. ;
  8263. }
  8264. },
  8265. screenHeight: function() {
  8266. if( module.can.fit() ) {
  8267. $body.css('height', '');
  8268. }
  8269. else {
  8270. module.debug('Modal is taller than page content, resizing page height');
  8271. $body
  8272. .css('height', module.cache.height + (settings.padding * 2) )
  8273. ;
  8274. }
  8275. },
  8276. active: function() {
  8277. $module.addClass(className.active);
  8278. },
  8279. scrolling: function() {
  8280. $dimmable.addClass(className.scrolling);
  8281. $module.addClass(className.scrolling);
  8282. },
  8283. type: function() {
  8284. if(module.can.fit()) {
  8285. module.verbose('Modal fits on screen');
  8286. if(!module.others.active() && !module.others.animating()) {
  8287. module.remove.scrolling();
  8288. }
  8289. }
  8290. else {
  8291. module.verbose('Modal cannot fit on screen setting to scrolling');
  8292. module.set.scrolling();
  8293. }
  8294. },
  8295. position: function() {
  8296. module.verbose('Centering modal on page', module.cache);
  8297. if(module.can.fit()) {
  8298. $module
  8299. .css({
  8300. top: '',
  8301. marginTop: -(module.cache.height / 2)
  8302. })
  8303. ;
  8304. }
  8305. else {
  8306. $module
  8307. .css({
  8308. marginTop : '',
  8309. top : $document.scrollTop()
  8310. })
  8311. ;
  8312. }
  8313. },
  8314. undetached: function() {
  8315. $dimmable.addClass(className.undetached);
  8316. }
  8317. },
  8318. setting: function(name, value) {
  8319. module.debug('Changing setting', name, value);
  8320. if( $.isPlainObject(name) ) {
  8321. $.extend(true, settings, name);
  8322. }
  8323. else if(value !== undefined) {
  8324. settings[name] = value;
  8325. }
  8326. else {
  8327. return settings[name];
  8328. }
  8329. },
  8330. internal: function(name, value) {
  8331. if( $.isPlainObject(name) ) {
  8332. $.extend(true, module, name);
  8333. }
  8334. else if(value !== undefined) {
  8335. module[name] = value;
  8336. }
  8337. else {
  8338. return module[name];
  8339. }
  8340. },
  8341. debug: function() {
  8342. if(settings.debug) {
  8343. if(settings.performance) {
  8344. module.performance.log(arguments);
  8345. }
  8346. else {
  8347. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8348. module.debug.apply(console, arguments);
  8349. }
  8350. }
  8351. },
  8352. verbose: function() {
  8353. if(settings.verbose && settings.debug) {
  8354. if(settings.performance) {
  8355. module.performance.log(arguments);
  8356. }
  8357. else {
  8358. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8359. module.verbose.apply(console, arguments);
  8360. }
  8361. }
  8362. },
  8363. error: function() {
  8364. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  8365. module.error.apply(console, arguments);
  8366. },
  8367. performance: {
  8368. log: function(message) {
  8369. var
  8370. currentTime,
  8371. executionTime,
  8372. previousTime
  8373. ;
  8374. if(settings.performance) {
  8375. currentTime = new Date().getTime();
  8376. previousTime = time || currentTime;
  8377. executionTime = currentTime - previousTime;
  8378. time = currentTime;
  8379. performance.push({
  8380. 'Name' : message[0],
  8381. 'Arguments' : [].slice.call(message, 1) || '',
  8382. 'Element' : element,
  8383. 'Execution Time' : executionTime
  8384. });
  8385. }
  8386. clearTimeout(module.performance.timer);
  8387. module.performance.timer = setTimeout(module.performance.display, 500);
  8388. },
  8389. display: function() {
  8390. var
  8391. title = settings.name + ':',
  8392. totalTime = 0
  8393. ;
  8394. time = false;
  8395. clearTimeout(module.performance.timer);
  8396. $.each(performance, function(index, data) {
  8397. totalTime += data['Execution Time'];
  8398. });
  8399. title += ' ' + totalTime + 'ms';
  8400. if(moduleSelector) {
  8401. title += ' \'' + moduleSelector + '\'';
  8402. }
  8403. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  8404. console.groupCollapsed(title);
  8405. if(console.table) {
  8406. console.table(performance);
  8407. }
  8408. else {
  8409. $.each(performance, function(index, data) {
  8410. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  8411. });
  8412. }
  8413. console.groupEnd();
  8414. }
  8415. performance = [];
  8416. }
  8417. },
  8418. invoke: function(query, passedArguments, context) {
  8419. var
  8420. object = instance,
  8421. maxDepth,
  8422. found,
  8423. response
  8424. ;
  8425. passedArguments = passedArguments || queryArguments;
  8426. context = element || context;
  8427. if(typeof query == 'string' && object !== undefined) {
  8428. query = query.split(/[\. ]/);
  8429. maxDepth = query.length - 1;
  8430. $.each(query, function(depth, value) {
  8431. var camelCaseValue = (depth != maxDepth)
  8432. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  8433. : query
  8434. ;
  8435. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  8436. object = object[camelCaseValue];
  8437. }
  8438. else if( object[camelCaseValue] !== undefined ) {
  8439. found = object[camelCaseValue];
  8440. return false;
  8441. }
  8442. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  8443. object = object[value];
  8444. }
  8445. else if( object[value] !== undefined ) {
  8446. found = object[value];
  8447. return false;
  8448. }
  8449. else {
  8450. return false;
  8451. }
  8452. });
  8453. }
  8454. if ( $.isFunction( found ) ) {
  8455. response = found.apply(context, passedArguments);
  8456. }
  8457. else if(found !== undefined) {
  8458. response = found;
  8459. }
  8460. if($.isArray(returnedValue)) {
  8461. returnedValue.push(response);
  8462. }
  8463. else if(returnedValue !== undefined) {
  8464. returnedValue = [returnedValue, response];
  8465. }
  8466. else if(response !== undefined) {
  8467. returnedValue = response;
  8468. }
  8469. return found;
  8470. }
  8471. };
  8472. if(methodInvoked) {
  8473. if(instance === undefined) {
  8474. module.initialize();
  8475. }
  8476. module.invoke(query);
  8477. }
  8478. else {
  8479. if(instance !== undefined) {
  8480. instance.invoke('destroy');
  8481. }
  8482. module.initialize();
  8483. }
  8484. })
  8485. ;
  8486. return (returnedValue !== undefined)
  8487. ? returnedValue
  8488. : this
  8489. ;
  8490. };
  8491. $.fn.modal.settings = {
  8492. name : 'Modal',
  8493. namespace : 'modal',
  8494. debug : false,
  8495. verbose : false,
  8496. performance : true,
  8497. observeChanges : false,
  8498. allowMultiple : false,
  8499. detachable : true,
  8500. closable : true,
  8501. autofocus : true,
  8502. inverted : false,
  8503. blurring : false,
  8504. dimmerSettings : {
  8505. closable : false,
  8506. useCSS : true
  8507. },
  8508. context : 'body',
  8509. queue : false,
  8510. duration : 500,
  8511. offset : 0,
  8512. transition : 'scale',
  8513. // padding with edge of page
  8514. padding : 50,
  8515. // called before show animation
  8516. onShow : function(){},
  8517. // called after show animation
  8518. onVisible : function(){},
  8519. // called before hide animation
  8520. onHide : function(){ return true; },
  8521. // called after hide animation
  8522. onHidden : function(){},
  8523. // called after approve selector match
  8524. onApprove : function(){ return true; },
  8525. // called after deny selector match
  8526. onDeny : function(){ return true; },
  8527. selector : {
  8528. close : '> .close',
  8529. approve : '.actions .positive, .actions .approve, .actions .ok',
  8530. deny : '.actions .negative, .actions .deny, .actions .cancel',
  8531. modal : '.ui.modal'
  8532. },
  8533. error : {
  8534. dimmer : 'UI Dimmer, a required component is not included in this page',
  8535. method : 'The method you called is not defined.',
  8536. notFound : 'The element you specified could not be found'
  8537. },
  8538. className : {
  8539. active : 'active',
  8540. animating : 'animating',
  8541. blurring : 'blurring',
  8542. scrolling : 'scrolling',
  8543. undetached : 'undetached'
  8544. }
  8545. };
  8546. })( jQuery, window, document );
  8547. /*!
  8548. * # Semantic UI 2.1.6 - Nag
  8549. * http://github.com/semantic-org/semantic-ui/
  8550. *
  8551. *
  8552. * Copyright 2015 Contributors
  8553. * Released under the MIT license
  8554. * http://opensource.org/licenses/MIT
  8555. *
  8556. */
  8557. ;(function ($, window, document, undefined) {
  8558. "use strict";
  8559. $.fn.nag = function(parameters) {
  8560. var
  8561. $allModules = $(this),
  8562. moduleSelector = $allModules.selector || '',
  8563. time = new Date().getTime(),
  8564. performance = [],
  8565. query = arguments[0],
  8566. methodInvoked = (typeof query == 'string'),
  8567. queryArguments = [].slice.call(arguments, 1),
  8568. returnedValue
  8569. ;
  8570. $allModules
  8571. .each(function() {
  8572. var
  8573. settings = ( $.isPlainObject(parameters) )
  8574. ? $.extend(true, {}, $.fn.nag.settings, parameters)
  8575. : $.extend({}, $.fn.nag.settings),
  8576. className = settings.className,
  8577. selector = settings.selector,
  8578. error = settings.error,
  8579. namespace = settings.namespace,
  8580. eventNamespace = '.' + namespace,
  8581. moduleNamespace = namespace + '-module',
  8582. $module = $(this),
  8583. $close = $module.find(selector.close),
  8584. $context = (settings.context)
  8585. ? $(settings.context)
  8586. : $('body'),
  8587. element = this,
  8588. instance = $module.data(moduleNamespace),
  8589. moduleOffset,
  8590. moduleHeight,
  8591. contextWidth,
  8592. contextHeight,
  8593. contextOffset,
  8594. yOffset,
  8595. yPosition,
  8596. timer,
  8597. module,
  8598. requestAnimationFrame = window.requestAnimationFrame
  8599. || window.mozRequestAnimationFrame
  8600. || window.webkitRequestAnimationFrame
  8601. || window.msRequestAnimationFrame
  8602. || function(callback) { setTimeout(callback, 0); }
  8603. ;
  8604. module = {
  8605. initialize: function() {
  8606. module.verbose('Initializing element');
  8607. $module
  8608. .on('click' + eventNamespace, selector.close, module.dismiss)
  8609. .data(moduleNamespace, module)
  8610. ;
  8611. if(settings.detachable && $module.parent()[0] !== $context[0]) {
  8612. $module
  8613. .detach()
  8614. .prependTo($context)
  8615. ;
  8616. }
  8617. if(settings.displayTime > 0) {
  8618. setTimeout(module.hide, settings.displayTime);
  8619. }
  8620. module.show();
  8621. },
  8622. destroy: function() {
  8623. module.verbose('Destroying instance');
  8624. $module
  8625. .removeData(moduleNamespace)
  8626. .off(eventNamespace)
  8627. ;
  8628. },
  8629. show: function() {
  8630. if( module.should.show() && !$module.is(':visible') ) {
  8631. module.debug('Showing nag', settings.animation.show);
  8632. if(settings.animation.show == 'fade') {
  8633. $module
  8634. .fadeIn(settings.duration, settings.easing)
  8635. ;
  8636. }
  8637. else {
  8638. $module
  8639. .slideDown(settings.duration, settings.easing)
  8640. ;
  8641. }
  8642. }
  8643. },
  8644. hide: function() {
  8645. module.debug('Showing nag', settings.animation.hide);
  8646. if(settings.animation.show == 'fade') {
  8647. $module
  8648. .fadeIn(settings.duration, settings.easing)
  8649. ;
  8650. }
  8651. else {
  8652. $module
  8653. .slideUp(settings.duration, settings.easing)
  8654. ;
  8655. }
  8656. },
  8657. onHide: function() {
  8658. module.debug('Removing nag', settings.animation.hide);
  8659. $module.remove();
  8660. if (settings.onHide) {
  8661. settings.onHide();
  8662. }
  8663. },
  8664. dismiss: function(event) {
  8665. if(settings.storageMethod) {
  8666. module.storage.set(settings.key, settings.value);
  8667. }
  8668. module.hide();
  8669. event.stopImmediatePropagation();
  8670. event.preventDefault();
  8671. },
  8672. should: {
  8673. show: function() {
  8674. if(settings.persist) {
  8675. module.debug('Persistent nag is set, can show nag');
  8676. return true;
  8677. }
  8678. if( module.storage.get(settings.key) != settings.value.toString() ) {
  8679. module.debug('Stored value is not set, can show nag', module.storage.get(settings.key));
  8680. return true;
  8681. }
  8682. module.debug('Stored value is set, cannot show nag', module.storage.get(settings.key));
  8683. return false;
  8684. }
  8685. },
  8686. get: {
  8687. storageOptions: function() {
  8688. var
  8689. options = {}
  8690. ;
  8691. if(settings.expires) {
  8692. options.expires = settings.expires;
  8693. }
  8694. if(settings.domain) {
  8695. options.domain = settings.domain;
  8696. }
  8697. if(settings.path) {
  8698. options.path = settings.path;
  8699. }
  8700. return options;
  8701. }
  8702. },
  8703. clear: function() {
  8704. module.storage.remove(settings.key);
  8705. },
  8706. storage: {
  8707. set: function(key, value) {
  8708. var
  8709. options = module.get.storageOptions()
  8710. ;
  8711. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  8712. window.localStorage.setItem(key, value);
  8713. module.debug('Value stored using local storage', key, value);
  8714. }
  8715. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  8716. window.sessionStorage.setItem(key, value);
  8717. module.debug('Value stored using session storage', key, value);
  8718. }
  8719. else if($.cookie !== undefined) {
  8720. $.cookie(key, value, options);
  8721. module.debug('Value stored using cookie', key, value, options);
  8722. }
  8723. else {
  8724. module.error(error.noCookieStorage);
  8725. return;
  8726. }
  8727. },
  8728. get: function(key, value) {
  8729. var
  8730. storedValue
  8731. ;
  8732. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  8733. storedValue = window.localStorage.getItem(key);
  8734. }
  8735. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  8736. storedValue = window.sessionStorage.getItem(key);
  8737. }
  8738. // get by cookie
  8739. else if($.cookie !== undefined) {
  8740. storedValue = $.cookie(key);
  8741. }
  8742. else {
  8743. module.error(error.noCookieStorage);
  8744. }
  8745. if(storedValue == 'undefined' || storedValue == 'null' || storedValue === undefined || storedValue === null) {
  8746. storedValue = undefined;
  8747. }
  8748. return storedValue;
  8749. },
  8750. remove: function(key) {
  8751. var
  8752. options = module.get.storageOptions()
  8753. ;
  8754. if(settings.storageMethod == 'localstorage' && window.localStorage !== undefined) {
  8755. window.localStorage.removeItem(key);
  8756. }
  8757. else if(settings.storageMethod == 'sessionstorage' && window.sessionStorage !== undefined) {
  8758. window.sessionStorage.removeItem(key);
  8759. }
  8760. // store by cookie
  8761. else if($.cookie !== undefined) {
  8762. $.removeCookie(key, options);
  8763. }
  8764. else {
  8765. module.error(error.noStorage);
  8766. }
  8767. }
  8768. },
  8769. setting: function(name, value) {
  8770. module.debug('Changing setting', name, value);
  8771. if( $.isPlainObject(name) ) {
  8772. $.extend(true, settings, name);
  8773. }
  8774. else if(value !== undefined) {
  8775. settings[name] = value;
  8776. }
  8777. else {
  8778. return settings[name];
  8779. }
  8780. },
  8781. internal: function(name, value) {
  8782. if( $.isPlainObject(name) ) {
  8783. $.extend(true, module, name);
  8784. }
  8785. else if(value !== undefined) {
  8786. module[name] = value;
  8787. }
  8788. else {
  8789. return module[name];
  8790. }
  8791. },
  8792. debug: function() {
  8793. if(settings.debug) {
  8794. if(settings.performance) {
  8795. module.performance.log(arguments);
  8796. }
  8797. else {
  8798. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8799. module.debug.apply(console, arguments);
  8800. }
  8801. }
  8802. },
  8803. verbose: function() {
  8804. if(settings.verbose && settings.debug) {
  8805. if(settings.performance) {
  8806. module.performance.log(arguments);
  8807. }
  8808. else {
  8809. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  8810. module.verbose.apply(console, arguments);
  8811. }
  8812. }
  8813. },
  8814. error: function() {
  8815. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  8816. module.error.apply(console, arguments);
  8817. },
  8818. performance: {
  8819. log: function(message) {
  8820. var
  8821. currentTime,
  8822. executionTime,
  8823. previousTime
  8824. ;
  8825. if(settings.performance) {
  8826. currentTime = new Date().getTime();
  8827. previousTime = time || currentTime;
  8828. executionTime = currentTime - previousTime;
  8829. time = currentTime;
  8830. performance.push({
  8831. 'Name' : message[0],
  8832. 'Arguments' : [].slice.call(message, 1) || '',
  8833. 'Element' : element,
  8834. 'Execution Time' : executionTime
  8835. });
  8836. }
  8837. clearTimeout(module.performance.timer);
  8838. module.performance.timer = setTimeout(module.performance.display, 500);
  8839. },
  8840. display: function() {
  8841. var
  8842. title = settings.name + ':',
  8843. totalTime = 0
  8844. ;
  8845. time = false;
  8846. clearTimeout(module.performance.timer);
  8847. $.each(performance, function(index, data) {
  8848. totalTime += data['Execution Time'];
  8849. });
  8850. title += ' ' + totalTime + 'ms';
  8851. if(moduleSelector) {
  8852. title += ' \'' + moduleSelector + '\'';
  8853. }
  8854. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  8855. console.groupCollapsed(title);
  8856. if(console.table) {
  8857. console.table(performance);
  8858. }
  8859. else {
  8860. $.each(performance, function(index, data) {
  8861. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  8862. });
  8863. }
  8864. console.groupEnd();
  8865. }
  8866. performance = [];
  8867. }
  8868. },
  8869. invoke: function(query, passedArguments, context) {
  8870. var
  8871. object = instance,
  8872. maxDepth,
  8873. found,
  8874. response
  8875. ;
  8876. passedArguments = passedArguments || queryArguments;
  8877. context = element || context;
  8878. if(typeof query == 'string' && object !== undefined) {
  8879. query = query.split(/[\. ]/);
  8880. maxDepth = query.length - 1;
  8881. $.each(query, function(depth, value) {
  8882. var camelCaseValue = (depth != maxDepth)
  8883. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  8884. : query
  8885. ;
  8886. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  8887. object = object[camelCaseValue];
  8888. }
  8889. else if( object[camelCaseValue] !== undefined ) {
  8890. found = object[camelCaseValue];
  8891. return false;
  8892. }
  8893. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  8894. object = object[value];
  8895. }
  8896. else if( object[value] !== undefined ) {
  8897. found = object[value];
  8898. return false;
  8899. }
  8900. else {
  8901. module.error(error.method, query);
  8902. return false;
  8903. }
  8904. });
  8905. }
  8906. if ( $.isFunction( found ) ) {
  8907. response = found.apply(context, passedArguments);
  8908. }
  8909. else if(found !== undefined) {
  8910. response = found;
  8911. }
  8912. if($.isArray(returnedValue)) {
  8913. returnedValue.push(response);
  8914. }
  8915. else if(returnedValue !== undefined) {
  8916. returnedValue = [returnedValue, response];
  8917. }
  8918. else if(response !== undefined) {
  8919. returnedValue = response;
  8920. }
  8921. return found;
  8922. }
  8923. };
  8924. if(methodInvoked) {
  8925. if(instance === undefined) {
  8926. module.initialize();
  8927. }
  8928. module.invoke(query);
  8929. }
  8930. else {
  8931. if(instance !== undefined) {
  8932. instance.invoke('destroy');
  8933. }
  8934. module.initialize();
  8935. }
  8936. })
  8937. ;
  8938. return (returnedValue !== undefined)
  8939. ? returnedValue
  8940. : this
  8941. ;
  8942. };
  8943. $.fn.nag.settings = {
  8944. name : 'Nag',
  8945. debug : false,
  8946. verbose : false,
  8947. performance : true,
  8948. namespace : 'Nag',
  8949. // allows cookie to be overriden
  8950. persist : false,
  8951. // set to zero to require manually dismissal, otherwise hides on its own
  8952. displayTime : 0,
  8953. animation : {
  8954. show : 'slide',
  8955. hide : 'slide'
  8956. },
  8957. context : false,
  8958. detachable : false,
  8959. expires : 30,
  8960. domain : false,
  8961. path : '/',
  8962. // type of storage to use
  8963. storageMethod : 'cookie',
  8964. // value to store in dismissed localstorage/cookie
  8965. key : 'nag',
  8966. value : 'dismiss',
  8967. error: {
  8968. noCookieStorage : '$.cookie is not included. A storage solution is required.',
  8969. noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
  8970. method : 'The method you called is not defined.'
  8971. },
  8972. className : {
  8973. bottom : 'bottom',
  8974. fixed : 'fixed'
  8975. },
  8976. selector : {
  8977. close : '.close.icon'
  8978. },
  8979. speed : 500,
  8980. easing : 'easeOutQuad',
  8981. onHide: function() {}
  8982. };
  8983. })( jQuery, window, document );
  8984. /*!
  8985. * # Semantic UI 2.1.6 - Popup
  8986. * http://github.com/semantic-org/semantic-ui/
  8987. *
  8988. *
  8989. * Copyright 2015 Contributors
  8990. * Released under the MIT license
  8991. * http://opensource.org/licenses/MIT
  8992. *
  8993. */
  8994. ;(function ($, window, document, undefined) {
  8995. "use strict";
  8996. $.fn.popup = function(parameters) {
  8997. var
  8998. $allModules = $(this),
  8999. $document = $(document),
  9000. $window = $(window),
  9001. $body = $('body'),
  9002. moduleSelector = $allModules.selector || '',
  9003. hasTouch = (true),
  9004. time = new Date().getTime(),
  9005. performance = [],
  9006. query = arguments[0],
  9007. methodInvoked = (typeof query == 'string'),
  9008. queryArguments = [].slice.call(arguments, 1),
  9009. returnedValue
  9010. ;
  9011. $allModules
  9012. .each(function() {
  9013. var
  9014. settings = ( $.isPlainObject(parameters) )
  9015. ? $.extend(true, {}, $.fn.popup.settings, parameters)
  9016. : $.extend({}, $.fn.popup.settings),
  9017. selector = settings.selector,
  9018. className = settings.className,
  9019. error = settings.error,
  9020. metadata = settings.metadata,
  9021. namespace = settings.namespace,
  9022. eventNamespace = '.' + settings.namespace,
  9023. moduleNamespace = 'module-' + namespace,
  9024. $module = $(this),
  9025. $context = $(settings.context),
  9026. $target = (settings.target)
  9027. ? $(settings.target)
  9028. : $module,
  9029. $popup,
  9030. $offsetParent,
  9031. searchDepth = 0,
  9032. triedPositions = false,
  9033. openedWithTouch = false,
  9034. element = this,
  9035. instance = $module.data(moduleNamespace),
  9036. elementNamespace,
  9037. id,
  9038. module
  9039. ;
  9040. module = {
  9041. // binds events
  9042. initialize: function() {
  9043. module.debug('Initializing', $module);
  9044. module.createID();
  9045. module.bind.events();
  9046. if( !module.exists() && settings.preserve) {
  9047. module.create();
  9048. }
  9049. module.instantiate();
  9050. },
  9051. instantiate: function() {
  9052. module.verbose('Storing instance', module);
  9053. instance = module;
  9054. $module
  9055. .data(moduleNamespace, instance)
  9056. ;
  9057. },
  9058. refresh: function() {
  9059. if(settings.popup) {
  9060. $popup = $(settings.popup).eq(0);
  9061. }
  9062. else {
  9063. if(settings.inline) {
  9064. $popup = $target.nextAll(selector.popup).eq(0);
  9065. settings.popup = $popup;
  9066. }
  9067. }
  9068. if(settings.popup) {
  9069. $popup.addClass(className.loading);
  9070. $offsetParent = module.get.offsetParent();
  9071. $popup.removeClass(className.loading);
  9072. if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) {
  9073. module.debug('Moving popup to the same offset parent as activating element');
  9074. $popup
  9075. .detach()
  9076. .appendTo($offsetParent)
  9077. ;
  9078. }
  9079. }
  9080. else {
  9081. $offsetParent = (settings.inline)
  9082. ? module.get.offsetParent($target)
  9083. : module.has.popup()
  9084. ? module.get.offsetParent($popup)
  9085. : $body
  9086. ;
  9087. }
  9088. if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) {
  9089. module.debug('Setting page as offset parent');
  9090. $offsetParent = $body;
  9091. }
  9092. if( module.get.variation() ) {
  9093. module.set.variation();
  9094. }
  9095. },
  9096. reposition: function() {
  9097. module.refresh();
  9098. module.set.position();
  9099. },
  9100. destroy: function() {
  9101. module.debug('Destroying previous module');
  9102. // remove element only if was created dynamically
  9103. if($popup && !settings.preserve) {
  9104. module.removePopup();
  9105. }
  9106. // clear all timeouts
  9107. clearTimeout(module.hideTimer);
  9108. clearTimeout(module.showTimer);
  9109. // remove events
  9110. $window.off(elementNamespace);
  9111. $module
  9112. .off(eventNamespace)
  9113. .removeData(moduleNamespace)
  9114. ;
  9115. },
  9116. event: {
  9117. start: function(event) {
  9118. var
  9119. delay = ($.isPlainObject(settings.delay))
  9120. ? settings.delay.show
  9121. : settings.delay
  9122. ;
  9123. clearTimeout(module.hideTimer);
  9124. if(!openedWithTouch) {
  9125. module.showTimer = setTimeout(module.show, delay);
  9126. }
  9127. },
  9128. end: function() {
  9129. var
  9130. delay = ($.isPlainObject(settings.delay))
  9131. ? settings.delay.hide
  9132. : settings.delay
  9133. ;
  9134. clearTimeout(module.showTimer);
  9135. module.hideTimer = setTimeout(module.hide, delay);
  9136. },
  9137. touchstart: function(event) {
  9138. openedWithTouch = true;
  9139. module.show();
  9140. },
  9141. resize: function() {
  9142. if( module.is.visible() ) {
  9143. module.set.position();
  9144. }
  9145. },
  9146. hideGracefully: function(event) {
  9147. // don't close on clicks inside popup
  9148. if(event && $(event.target).closest(selector.popup).length === 0) {
  9149. module.debug('Click occurred outside popup hiding popup');
  9150. module.hide();
  9151. }
  9152. else {
  9153. module.debug('Click was inside popup, keeping popup open');
  9154. }
  9155. }
  9156. },
  9157. // generates popup html from metadata
  9158. create: function() {
  9159. var
  9160. html = module.get.html(),
  9161. title = module.get.title(),
  9162. content = module.get.content()
  9163. ;
  9164. if(html || content || title) {
  9165. module.debug('Creating pop-up html');
  9166. if(!html) {
  9167. html = settings.templates.popup({
  9168. title : title,
  9169. content : content
  9170. });
  9171. }
  9172. $popup = $('<div/>')
  9173. .addClass(className.popup)
  9174. .data(metadata.activator, $module)
  9175. .html(html)
  9176. ;
  9177. if(settings.inline) {
  9178. module.verbose('Inserting popup element inline', $popup);
  9179. $popup
  9180. .insertAfter($module)
  9181. ;
  9182. }
  9183. else {
  9184. module.verbose('Appending popup element to body', $popup);
  9185. $popup
  9186. .appendTo( $context )
  9187. ;
  9188. }
  9189. module.refresh();
  9190. module.set.variation();
  9191. if(settings.hoverable) {
  9192. module.bind.popup();
  9193. }
  9194. settings.onCreate.call($popup, element);
  9195. }
  9196. else if($target.next(selector.popup).length !== 0) {
  9197. module.verbose('Pre-existing popup found');
  9198. settings.inline = true;
  9199. settings.popups = $target.next(selector.popup).data(metadata.activator, $module);
  9200. module.refresh();
  9201. if(settings.hoverable) {
  9202. module.bind.popup();
  9203. }
  9204. }
  9205. else if(settings.popup) {
  9206. $(settings.popup).data(metadata.activator, $module);
  9207. module.verbose('Used popup specified in settings');
  9208. module.refresh();
  9209. if(settings.hoverable) {
  9210. module.bind.popup();
  9211. }
  9212. }
  9213. else {
  9214. module.debug('No content specified skipping display', element);
  9215. }
  9216. },
  9217. createID: function() {
  9218. id = (Math.random().toString(16) + '000000000').substr(2,8);
  9219. elementNamespace = '.' + id;
  9220. module.verbose('Creating unique id for element', id);
  9221. },
  9222. // determines popup state
  9223. toggle: function() {
  9224. module.debug('Toggling pop-up');
  9225. if( module.is.hidden() ) {
  9226. module.debug('Popup is hidden, showing pop-up');
  9227. module.unbind.close();
  9228. module.show();
  9229. }
  9230. else {
  9231. module.debug('Popup is visible, hiding pop-up');
  9232. module.hide();
  9233. }
  9234. },
  9235. show: function(callback) {
  9236. callback = callback || function(){};
  9237. module.debug('Showing pop-up', settings.transition);
  9238. if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
  9239. if( !module.exists() ) {
  9240. module.create();
  9241. }
  9242. if(settings.onShow.call($popup, element) === false) {
  9243. module.debug('onShow callback returned false, cancelling popup animation');
  9244. return;
  9245. }
  9246. else if(!settings.preserve && !settings.popup) {
  9247. module.refresh();
  9248. }
  9249. if( $popup && module.set.position() ) {
  9250. module.save.conditions();
  9251. if(settings.exclusive) {
  9252. module.hideAll();
  9253. }
  9254. module.animate.show(callback);
  9255. }
  9256. }
  9257. },
  9258. hide: function(callback) {
  9259. callback = callback || function(){};
  9260. if( module.is.visible() || module.is.animating() ) {
  9261. if(settings.onHide.call($popup, element) === false) {
  9262. module.debug('onHide callback returned false, cancelling popup animation');
  9263. return;
  9264. }
  9265. module.remove.visible();
  9266. module.unbind.close();
  9267. module.restore.conditions();
  9268. module.animate.hide(callback);
  9269. }
  9270. },
  9271. hideAll: function() {
  9272. $(selector.popup)
  9273. .filter('.' + className.visible)
  9274. .each(function() {
  9275. $(this)
  9276. .data(metadata.activator)
  9277. .popup('hide')
  9278. ;
  9279. })
  9280. ;
  9281. },
  9282. exists: function() {
  9283. if(!$popup) {
  9284. return false;
  9285. }
  9286. if(settings.inline || settings.popup) {
  9287. return ( module.has.popup() );
  9288. }
  9289. else {
  9290. return ( $popup.closest($context).length >= 1 )
  9291. ? true
  9292. : false
  9293. ;
  9294. }
  9295. },
  9296. removePopup: function() {
  9297. if( module.has.popup() && !settings.popup) {
  9298. module.debug('Removing popup', $popup);
  9299. $popup.remove();
  9300. $popup = undefined;
  9301. settings.onRemove.call($popup, element);
  9302. }
  9303. },
  9304. save: {
  9305. conditions: function() {
  9306. module.cache = {
  9307. title: $module.attr('title')
  9308. };
  9309. if (module.cache.title) {
  9310. $module.removeAttr('title');
  9311. }
  9312. module.verbose('Saving original attributes', module.cache.title);
  9313. }
  9314. },
  9315. restore: {
  9316. conditions: function() {
  9317. if(module.cache && module.cache.title) {
  9318. $module.attr('title', module.cache.title);
  9319. module.verbose('Restoring original attributes', module.cache.title);
  9320. }
  9321. return true;
  9322. }
  9323. },
  9324. animate: {
  9325. show: function(callback) {
  9326. callback = $.isFunction(callback) ? callback : function(){};
  9327. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  9328. module.set.visible();
  9329. $popup
  9330. .transition({
  9331. animation : settings.transition + ' in',
  9332. queue : false,
  9333. debug : settings.debug,
  9334. verbose : settings.verbose,
  9335. duration : settings.duration,
  9336. onComplete : function() {
  9337. module.bind.close();
  9338. callback.call($popup, element);
  9339. settings.onVisible.call($popup, element);
  9340. }
  9341. })
  9342. ;
  9343. }
  9344. else {
  9345. module.error(error.noTransition);
  9346. }
  9347. },
  9348. hide: function(callback) {
  9349. callback = $.isFunction(callback) ? callback : function(){};
  9350. module.debug('Hiding pop-up');
  9351. if(settings.onHide.call($popup, element) === false) {
  9352. module.debug('onHide callback returned false, cancelling popup animation');
  9353. return;
  9354. }
  9355. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  9356. $popup
  9357. .transition({
  9358. animation : settings.transition + ' out',
  9359. queue : false,
  9360. duration : settings.duration,
  9361. debug : settings.debug,
  9362. verbose : settings.verbose,
  9363. onComplete : function() {
  9364. module.reset();
  9365. callback.call($popup, element);
  9366. settings.onHidden.call($popup, element);
  9367. }
  9368. })
  9369. ;
  9370. }
  9371. else {
  9372. module.error(error.noTransition);
  9373. }
  9374. }
  9375. },
  9376. change: {
  9377. content: function(html) {
  9378. $popup.html(html);
  9379. }
  9380. },
  9381. get: {
  9382. html: function() {
  9383. $module.removeData(metadata.html);
  9384. return $module.data(metadata.html) || settings.html;
  9385. },
  9386. title: function() {
  9387. $module.removeData(metadata.title);
  9388. return $module.data(metadata.title) || settings.title;
  9389. },
  9390. content: function() {
  9391. $module.removeData(metadata.content);
  9392. return $module.data(metadata.content) || $module.attr('title') || settings.content;
  9393. },
  9394. variation: function() {
  9395. $module.removeData(metadata.variation);
  9396. return $module.data(metadata.variation) || settings.variation;
  9397. },
  9398. popup: function() {
  9399. return $popup;
  9400. },
  9401. popupOffset: function() {
  9402. return $popup.offset();
  9403. },
  9404. calculations: function() {
  9405. var
  9406. targetElement = $target[0],
  9407. targetPosition = (settings.inline || (settings.popup && settings.movePopup))
  9408. ? $target.position()
  9409. : $target.offset(),
  9410. calculations = {},
  9411. screen
  9412. ;
  9413. calculations = {
  9414. // element which is launching popup
  9415. target : {
  9416. element : $target[0],
  9417. width : $target.outerWidth(),
  9418. height : $target.outerHeight(),
  9419. top : targetPosition.top,
  9420. left : targetPosition.left,
  9421. margin : {}
  9422. },
  9423. // popup itself
  9424. popup : {
  9425. width : $popup.outerWidth(),
  9426. height : $popup.outerHeight()
  9427. },
  9428. // offset container (or 3d context)
  9429. parent : {
  9430. width : $offsetParent.outerWidth(),
  9431. height : $offsetParent.outerHeight()
  9432. },
  9433. // screen boundaries
  9434. screen : {
  9435. scroll: {
  9436. top : $window.scrollTop(),
  9437. left : $window.scrollLeft()
  9438. },
  9439. width : $window.width(),
  9440. height : $window.height()
  9441. }
  9442. };
  9443. // add in container calcs if fluid
  9444. if( settings.setFluidWidth && module.is.fluid() ) {
  9445. calculations.container = {
  9446. width: $popup.parent().outerWidth()
  9447. };
  9448. calculations.popup.width = calculations.container.width;
  9449. }
  9450. // add in margins if inline
  9451. calculations.target.margin.top = (settings.inline)
  9452. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
  9453. : 0
  9454. ;
  9455. calculations.target.margin.left = (settings.inline)
  9456. ? module.is.rtl()
  9457. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10)
  9458. : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left') , 10)
  9459. : 0
  9460. ;
  9461. // calculate screen boundaries
  9462. screen = calculations.screen;
  9463. calculations.boundary = {
  9464. top : screen.scroll.top,
  9465. bottom : screen.scroll.top + screen.height,
  9466. left : screen.scroll.left,
  9467. right : screen.scroll.left + screen.width
  9468. };
  9469. return calculations;
  9470. },
  9471. id: function() {
  9472. return id;
  9473. },
  9474. startEvent: function() {
  9475. if(settings.on == 'hover') {
  9476. return 'mouseenter';
  9477. }
  9478. else if(settings.on == 'focus') {
  9479. return 'focus';
  9480. }
  9481. return false;
  9482. },
  9483. scrollEvent: function() {
  9484. return 'scroll';
  9485. },
  9486. endEvent: function() {
  9487. if(settings.on == 'hover') {
  9488. return 'mouseleave';
  9489. }
  9490. else if(settings.on == 'focus') {
  9491. return 'blur';
  9492. }
  9493. return false;
  9494. },
  9495. distanceFromBoundary: function(offset, calculations) {
  9496. var
  9497. distanceFromBoundary = {},
  9498. popup,
  9499. boundary
  9500. ;
  9501. offset = offset || module.get.offset();
  9502. calculations = calculations || module.get.calculations();
  9503. // shorthand
  9504. popup = calculations.popup;
  9505. boundary = calculations.boundary;
  9506. if(offset) {
  9507. distanceFromBoundary = {
  9508. top : (offset.top - boundary.top),
  9509. left : (offset.left - boundary.left),
  9510. right : (boundary.right - (offset.left + popup.width) ),
  9511. bottom : (boundary.bottom - (offset.top + popup.height) )
  9512. };
  9513. module.verbose('Distance from boundaries determined', offset, distanceFromBoundary);
  9514. }
  9515. return distanceFromBoundary;
  9516. },
  9517. offsetParent: function($target) {
  9518. var
  9519. element = ($target !== undefined)
  9520. ? $target[0]
  9521. : $module[0],
  9522. parentNode = element.parentNode,
  9523. $node = $(parentNode)
  9524. ;
  9525. if(parentNode) {
  9526. var
  9527. is2D = ($node.css('transform') === 'none'),
  9528. isStatic = ($node.css('position') === 'static'),
  9529. isHTML = $node.is('html')
  9530. ;
  9531. while(parentNode && !isHTML && isStatic && is2D) {
  9532. parentNode = parentNode.parentNode;
  9533. $node = $(parentNode);
  9534. is2D = ($node.css('transform') === 'none');
  9535. isStatic = ($node.css('position') === 'static');
  9536. isHTML = $node.is('html');
  9537. }
  9538. }
  9539. return ($node && $node.length > 0)
  9540. ? $node
  9541. : $()
  9542. ;
  9543. },
  9544. positions: function() {
  9545. return {
  9546. 'top left' : false,
  9547. 'top center' : false,
  9548. 'top right' : false,
  9549. 'bottom left' : false,
  9550. 'bottom center' : false,
  9551. 'bottom right' : false,
  9552. 'left center' : false,
  9553. 'right center' : false
  9554. };
  9555. },
  9556. nextPosition: function(position) {
  9557. var
  9558. positions = position.split(' '),
  9559. verticalPosition = positions[0],
  9560. horizontalPosition = positions[1],
  9561. opposite = {
  9562. top : 'bottom',
  9563. bottom : 'top',
  9564. left : 'right',
  9565. right : 'left'
  9566. },
  9567. adjacent = {
  9568. left : 'center',
  9569. center : 'right',
  9570. right : 'left'
  9571. },
  9572. backup = {
  9573. 'top left' : 'top center',
  9574. 'top center' : 'top right',
  9575. 'top right' : 'right center',
  9576. 'right center' : 'bottom right',
  9577. 'bottom right' : 'bottom center',
  9578. 'bottom center' : 'bottom left',
  9579. 'bottom left' : 'left center',
  9580. 'left center' : 'top left'
  9581. },
  9582. adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'),
  9583. oppositeTried = false,
  9584. adjacentTried = false,
  9585. nextPosition = false
  9586. ;
  9587. if(!triedPositions) {
  9588. module.verbose('All available positions available');
  9589. triedPositions = module.get.positions();
  9590. }
  9591. module.debug('Recording last position tried', position);
  9592. triedPositions[position] = true;
  9593. if(settings.prefer === 'opposite') {
  9594. nextPosition = [opposite[verticalPosition], horizontalPosition];
  9595. nextPosition = nextPosition.join(' ');
  9596. oppositeTried = (triedPositions[nextPosition] === true);
  9597. module.debug('Trying opposite strategy', nextPosition);
  9598. }
  9599. if((settings.prefer === 'adjacent') && adjacentsAvailable ) {
  9600. nextPosition = [verticalPosition, adjacent[horizontalPosition]];
  9601. nextPosition = nextPosition.join(' ');
  9602. adjacentTried = (triedPositions[nextPosition] === true);
  9603. module.debug('Trying adjacent strategy', nextPosition);
  9604. }
  9605. if(adjacentTried || oppositeTried) {
  9606. module.debug('Using backup position', nextPosition);
  9607. nextPosition = backup[position];
  9608. }
  9609. return nextPosition;
  9610. }
  9611. },
  9612. set: {
  9613. position: function(position, calculations) {
  9614. // exit conditions
  9615. if($target.length === 0 || $popup.length === 0) {
  9616. module.error(error.notFound);
  9617. return;
  9618. }
  9619. var
  9620. offset,
  9621. distanceAway,
  9622. target,
  9623. popup,
  9624. parent,
  9625. positioning,
  9626. popupOffset,
  9627. distanceFromBoundary
  9628. ;
  9629. calculations = calculations || module.get.calculations();
  9630. position = position || $module.data(metadata.position) || settings.position;
  9631. offset = $module.data(metadata.offset) || settings.offset;
  9632. distanceAway = settings.distanceAway;
  9633. // shorthand
  9634. target = calculations.target;
  9635. popup = calculations.popup;
  9636. parent = calculations.parent;
  9637. if(target.width === 0 && target.height === 0 && !(target.element instanceof SVGGraphicsElement)) {
  9638. module.debug('Popup target is hidden, no action taken');
  9639. return false;
  9640. }
  9641. if(settings.inline) {
  9642. module.debug('Adding margin to calculation', target.margin);
  9643. if(position == 'left center' || position == 'right center') {
  9644. offset += target.margin.top;
  9645. distanceAway += -target.margin.left;
  9646. }
  9647. else if (position == 'top left' || position == 'top center' || position == 'top right') {
  9648. offset += target.margin.left;
  9649. distanceAway -= target.margin.top;
  9650. }
  9651. else {
  9652. offset += target.margin.left;
  9653. distanceAway += target.margin.top;
  9654. }
  9655. }
  9656. module.debug('Determining popup position from calculations', position, calculations);
  9657. if (module.is.rtl()) {
  9658. position = position.replace(/left|right/g, function (match) {
  9659. return (match == 'left')
  9660. ? 'right'
  9661. : 'left'
  9662. ;
  9663. });
  9664. module.debug('RTL: Popup position updated', position);
  9665. }
  9666. // if last attempt use specified last resort position
  9667. if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') {
  9668. position = settings.lastResort;
  9669. }
  9670. switch (position) {
  9671. case 'top left':
  9672. positioning = {
  9673. top : 'auto',
  9674. bottom : parent.height - target.top + distanceAway,
  9675. left : target.left + offset,
  9676. right : 'auto'
  9677. };
  9678. break;
  9679. case 'top center':
  9680. positioning = {
  9681. bottom : parent.height - target.top + distanceAway,
  9682. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  9683. top : 'auto',
  9684. right : 'auto'
  9685. };
  9686. break;
  9687. case 'top right':
  9688. positioning = {
  9689. bottom : parent.height - target.top + distanceAway,
  9690. right : parent.width - target.left - target.width - offset,
  9691. top : 'auto',
  9692. left : 'auto'
  9693. };
  9694. break;
  9695. case 'left center':
  9696. positioning = {
  9697. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  9698. right : parent.width - target.left + distanceAway,
  9699. left : 'auto',
  9700. bottom : 'auto'
  9701. };
  9702. break;
  9703. case 'right center':
  9704. positioning = {
  9705. top : target.top + (target.height / 2) - (popup.height / 2) + offset,
  9706. left : target.left + target.width + distanceAway,
  9707. bottom : 'auto',
  9708. right : 'auto'
  9709. };
  9710. break;
  9711. case 'bottom left':
  9712. positioning = {
  9713. top : target.top + target.height + distanceAway,
  9714. left : target.left + offset,
  9715. bottom : 'auto',
  9716. right : 'auto'
  9717. };
  9718. break;
  9719. case 'bottom center':
  9720. positioning = {
  9721. top : target.top + target.height + distanceAway,
  9722. left : target.left + (target.width / 2) - (popup.width / 2) + offset,
  9723. bottom : 'auto',
  9724. right : 'auto'
  9725. };
  9726. break;
  9727. case 'bottom right':
  9728. positioning = {
  9729. top : target.top + target.height + distanceAway,
  9730. right : parent.width - target.left - target.width - offset,
  9731. left : 'auto',
  9732. bottom : 'auto'
  9733. };
  9734. break;
  9735. }
  9736. if(positioning === undefined) {
  9737. module.error(error.invalidPosition, position);
  9738. }
  9739. module.debug('Calculated popup positioning values', positioning);
  9740. // tentatively place on stage
  9741. $popup
  9742. .css(positioning)
  9743. .removeClass(className.position)
  9744. .addClass(position)
  9745. .addClass(className.loading)
  9746. ;
  9747. popupOffset = module.get.popupOffset();
  9748. // see if any boundaries are surpassed with this tentative position
  9749. distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations);
  9750. if( module.is.offstage(distanceFromBoundary, position) ) {
  9751. module.debug('Position is outside viewport', position);
  9752. if(searchDepth < settings.maxSearchDepth) {
  9753. searchDepth++;
  9754. position = module.get.nextPosition(position);
  9755. module.debug('Trying new position', position);
  9756. return ($popup)
  9757. ? module.set.position(position, calculations)
  9758. : false
  9759. ;
  9760. }
  9761. else {
  9762. if(settings.lastResort) {
  9763. module.debug('No position found, showing with last position');
  9764. }
  9765. else {
  9766. module.debug('Popup could not find a position to display', $popup);
  9767. module.error(error.cannotPlace, element);
  9768. module.remove.attempts();
  9769. module.remove.loading();
  9770. module.reset();
  9771. return false;
  9772. }
  9773. }
  9774. }
  9775. module.debug('Position is on stage', position);
  9776. module.remove.attempts();
  9777. module.remove.loading();
  9778. if( settings.setFluidWidth && module.is.fluid() ) {
  9779. module.set.fluidWidth(calculations);
  9780. }
  9781. return true;
  9782. },
  9783. fluidWidth: function(calculations) {
  9784. calculations = calculations || module.get.calculations();
  9785. module.debug('Automatically setting element width to parent width', calculations.parent.width);
  9786. $popup.css('width', calculations.container.width);
  9787. },
  9788. variation: function(variation) {
  9789. variation = variation || module.get.variation();
  9790. if(variation && module.has.popup() ) {
  9791. module.verbose('Adding variation to popup', variation);
  9792. $popup.addClass(variation);
  9793. }
  9794. },
  9795. visible: function() {
  9796. $module.addClass(className.visible);
  9797. }
  9798. },
  9799. remove: {
  9800. loading: function() {
  9801. $popup.removeClass(className.loading);
  9802. },
  9803. variation: function(variation) {
  9804. variation = variation || module.get.variation();
  9805. if(variation) {
  9806. module.verbose('Removing variation', variation);
  9807. $popup.removeClass(variation);
  9808. }
  9809. },
  9810. visible: function() {
  9811. $module.removeClass(className.visible);
  9812. },
  9813. attempts: function() {
  9814. module.verbose('Resetting all searched positions');
  9815. searchDepth = 0;
  9816. triedPositions = false;
  9817. }
  9818. },
  9819. bind: {
  9820. events: function() {
  9821. module.debug('Binding popup events to module');
  9822. if(settings.on == 'click') {
  9823. $module
  9824. .on('click' + eventNamespace, module.toggle)
  9825. ;
  9826. }
  9827. if(settings.on == 'hover' && hasTouch) {
  9828. $module
  9829. .on('touchstart' + eventNamespace, module.event.touchstart)
  9830. ;
  9831. }
  9832. if( module.get.startEvent() ) {
  9833. $module
  9834. .on(module.get.startEvent() + eventNamespace, module.event.start)
  9835. .on(module.get.endEvent() + eventNamespace, module.event.end)
  9836. ;
  9837. }
  9838. if(settings.target) {
  9839. module.debug('Target set to element', $target);
  9840. }
  9841. $window.on('resize' + elementNamespace, module.event.resize);
  9842. },
  9843. popup: function() {
  9844. module.verbose('Allowing hover events on popup to prevent closing');
  9845. if( $popup && module.has.popup() ) {
  9846. $popup
  9847. .on('mouseenter' + eventNamespace, module.event.start)
  9848. .on('mouseleave' + eventNamespace, module.event.end)
  9849. ;
  9850. }
  9851. },
  9852. close: function() {
  9853. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  9854. $document
  9855. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  9856. ;
  9857. $context
  9858. .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully)
  9859. ;
  9860. }
  9861. if(settings.on == 'hover' && openedWithTouch) {
  9862. module.verbose('Binding popup close event to document');
  9863. $document
  9864. .on('touchstart' + elementNamespace, function(event) {
  9865. module.verbose('Touched away from popup');
  9866. module.event.hideGracefully.call(element, event);
  9867. })
  9868. ;
  9869. }
  9870. if(settings.on == 'click' && settings.closable) {
  9871. module.verbose('Binding popup close event to document');
  9872. $document
  9873. .on('click' + elementNamespace, function(event) {
  9874. module.verbose('Clicked away from popup');
  9875. module.event.hideGracefully.call(element, event);
  9876. })
  9877. ;
  9878. }
  9879. }
  9880. },
  9881. unbind: {
  9882. close: function() {
  9883. if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
  9884. $document
  9885. .off('scroll' + elementNamespace, module.hide)
  9886. ;
  9887. $context
  9888. .off('scroll' + elementNamespace, module.hide)
  9889. ;
  9890. }
  9891. if(settings.on == 'hover' && openedWithTouch) {
  9892. $document
  9893. .off('touchstart' + elementNamespace)
  9894. ;
  9895. openedWithTouch = false;
  9896. }
  9897. if(settings.on == 'click' && settings.closable) {
  9898. module.verbose('Removing close event from document');
  9899. $document
  9900. .off('click' + elementNamespace)
  9901. ;
  9902. }
  9903. }
  9904. },
  9905. has: {
  9906. popup: function() {
  9907. return ($popup && $popup.length > 0);
  9908. }
  9909. },
  9910. is: {
  9911. offstage: function(distanceFromBoundary, position) {
  9912. var
  9913. offstage = []
  9914. ;
  9915. // return boundaries that have been surpassed
  9916. $.each(distanceFromBoundary, function(direction, distance) {
  9917. if(distance < -settings.jitter) {
  9918. module.debug('Position exceeds allowable distance from edge', direction, distance, position);
  9919. offstage.push(direction);
  9920. }
  9921. });
  9922. if(offstage.length > 0) {
  9923. return true;
  9924. }
  9925. else {
  9926. return false;
  9927. }
  9928. },
  9929. active: function() {
  9930. return $module.hasClass(className.active);
  9931. },
  9932. animating: function() {
  9933. return ( $popup && $popup.hasClass(className.animating) );
  9934. },
  9935. fluid: function() {
  9936. return ( $popup && $popup.hasClass(className.fluid));
  9937. },
  9938. visible: function() {
  9939. return $popup && $popup.hasClass(className.visible);
  9940. },
  9941. dropdown: function() {
  9942. return $module.hasClass(className.dropdown);
  9943. },
  9944. hidden: function() {
  9945. return !module.is.visible();
  9946. },
  9947. rtl: function () {
  9948. return $module.css('direction') == 'rtl';
  9949. }
  9950. },
  9951. reset: function() {
  9952. module.remove.visible();
  9953. if(settings.preserve) {
  9954. if($.fn.transition !== undefined) {
  9955. $popup
  9956. .transition('remove transition')
  9957. ;
  9958. }
  9959. }
  9960. else {
  9961. module.removePopup();
  9962. }
  9963. },
  9964. setting: function(name, value) {
  9965. if( $.isPlainObject(name) ) {
  9966. $.extend(true, settings, name);
  9967. }
  9968. else if(value !== undefined) {
  9969. settings[name] = value;
  9970. }
  9971. else {
  9972. return settings[name];
  9973. }
  9974. },
  9975. internal: function(name, value) {
  9976. if( $.isPlainObject(name) ) {
  9977. $.extend(true, module, name);
  9978. }
  9979. else if(value !== undefined) {
  9980. module[name] = value;
  9981. }
  9982. else {
  9983. return module[name];
  9984. }
  9985. },
  9986. debug: function() {
  9987. if(settings.debug) {
  9988. if(settings.performance) {
  9989. module.performance.log(arguments);
  9990. }
  9991. else {
  9992. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  9993. module.debug.apply(console, arguments);
  9994. }
  9995. }
  9996. },
  9997. verbose: function() {
  9998. if(settings.verbose && settings.debug) {
  9999. if(settings.performance) {
  10000. module.performance.log(arguments);
  10001. }
  10002. else {
  10003. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10004. module.verbose.apply(console, arguments);
  10005. }
  10006. }
  10007. },
  10008. error: function() {
  10009. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  10010. module.error.apply(console, arguments);
  10011. },
  10012. performance: {
  10013. log: function(message) {
  10014. var
  10015. currentTime,
  10016. executionTime,
  10017. previousTime
  10018. ;
  10019. if(settings.performance) {
  10020. currentTime = new Date().getTime();
  10021. previousTime = time || currentTime;
  10022. executionTime = currentTime - previousTime;
  10023. time = currentTime;
  10024. performance.push({
  10025. 'Name' : message[0],
  10026. 'Arguments' : [].slice.call(message, 1) || '',
  10027. 'Element' : element,
  10028. 'Execution Time' : executionTime
  10029. });
  10030. }
  10031. clearTimeout(module.performance.timer);
  10032. module.performance.timer = setTimeout(module.performance.display, 500);
  10033. },
  10034. display: function() {
  10035. var
  10036. title = settings.name + ':',
  10037. totalTime = 0
  10038. ;
  10039. time = false;
  10040. clearTimeout(module.performance.timer);
  10041. $.each(performance, function(index, data) {
  10042. totalTime += data['Execution Time'];
  10043. });
  10044. title += ' ' + totalTime + 'ms';
  10045. if(moduleSelector) {
  10046. title += ' \'' + moduleSelector + '\'';
  10047. }
  10048. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  10049. console.groupCollapsed(title);
  10050. if(console.table) {
  10051. console.table(performance);
  10052. }
  10053. else {
  10054. $.each(performance, function(index, data) {
  10055. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  10056. });
  10057. }
  10058. console.groupEnd();
  10059. }
  10060. performance = [];
  10061. }
  10062. },
  10063. invoke: function(query, passedArguments, context) {
  10064. var
  10065. object = instance,
  10066. maxDepth,
  10067. found,
  10068. response
  10069. ;
  10070. passedArguments = passedArguments || queryArguments;
  10071. context = element || context;
  10072. if(typeof query == 'string' && object !== undefined) {
  10073. query = query.split(/[\. ]/);
  10074. maxDepth = query.length - 1;
  10075. $.each(query, function(depth, value) {
  10076. var camelCaseValue = (depth != maxDepth)
  10077. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  10078. : query
  10079. ;
  10080. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  10081. object = object[camelCaseValue];
  10082. }
  10083. else if( object[camelCaseValue] !== undefined ) {
  10084. found = object[camelCaseValue];
  10085. return false;
  10086. }
  10087. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  10088. object = object[value];
  10089. }
  10090. else if( object[value] !== undefined ) {
  10091. found = object[value];
  10092. return false;
  10093. }
  10094. else {
  10095. return false;
  10096. }
  10097. });
  10098. }
  10099. if ( $.isFunction( found ) ) {
  10100. response = found.apply(context, passedArguments);
  10101. }
  10102. else if(found !== undefined) {
  10103. response = found;
  10104. }
  10105. if($.isArray(returnedValue)) {
  10106. returnedValue.push(response);
  10107. }
  10108. else if(returnedValue !== undefined) {
  10109. returnedValue = [returnedValue, response];
  10110. }
  10111. else if(response !== undefined) {
  10112. returnedValue = response;
  10113. }
  10114. return found;
  10115. }
  10116. };
  10117. if(methodInvoked) {
  10118. if(instance === undefined) {
  10119. module.initialize();
  10120. }
  10121. module.invoke(query);
  10122. }
  10123. else {
  10124. if(instance !== undefined) {
  10125. instance.invoke('destroy');
  10126. }
  10127. module.initialize();
  10128. }
  10129. })
  10130. ;
  10131. return (returnedValue !== undefined)
  10132. ? returnedValue
  10133. : this
  10134. ;
  10135. };
  10136. $.fn.popup.settings = {
  10137. name : 'Popup',
  10138. // module settings
  10139. debug : false,
  10140. verbose : false,
  10141. performance : true,
  10142. namespace : 'popup',
  10143. // callback only when element added to dom
  10144. onCreate : function(){},
  10145. // callback before element removed from dom
  10146. onRemove : function(){},
  10147. // callback before show animation
  10148. onShow : function(){},
  10149. // callback after show animation
  10150. onVisible : function(){},
  10151. // callback before hide animation
  10152. onHide : function(){},
  10153. // callback after hide animation
  10154. onHidden : function(){},
  10155. // when to show popup
  10156. on : 'hover',
  10157. // whether to add touchstart events when using hover
  10158. addTouchEvents : true,
  10159. // default position relative to element
  10160. position : 'top left',
  10161. // name of variation to use
  10162. variation : '',
  10163. // whether popup should be moved to context
  10164. movePopup : true,
  10165. // element which popup should be relative to
  10166. target : false,
  10167. // jq selector or element that should be used as popup
  10168. popup : false,
  10169. // popup should remain inline next to activator
  10170. inline : false,
  10171. // popup should be removed from page on hide
  10172. preserve : false,
  10173. // popup should not close when being hovered on
  10174. hoverable : false,
  10175. // explicitly set content
  10176. content : false,
  10177. // explicitly set html
  10178. html : false,
  10179. // explicitly set title
  10180. title : false,
  10181. // whether automatically close on clickaway when on click
  10182. closable : true,
  10183. // automatically hide on scroll
  10184. hideOnScroll : 'auto',
  10185. // hide other popups on show
  10186. exclusive : false,
  10187. // context to attach popups
  10188. context : 'body',
  10189. // position to prefer when calculating new position
  10190. prefer : 'opposite',
  10191. // specify position to appear even if it doesn't fit
  10192. lastResort : false,
  10193. // delay used to prevent accidental refiring of animations due to user error
  10194. delay : {
  10195. show : 50,
  10196. hide : 70
  10197. },
  10198. // whether fluid variation should assign width explicitly
  10199. setFluidWidth : true,
  10200. // transition settings
  10201. duration : 200,
  10202. transition : 'scale',
  10203. // distance away from activating element in px
  10204. distanceAway : 0,
  10205. // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding)
  10206. jitter : 2,
  10207. // offset on aligning axis from calculated position
  10208. offset : 0,
  10209. // maximum times to look for a position before failing (9 positions total)
  10210. maxSearchDepth : 15,
  10211. error: {
  10212. invalidPosition : 'The position you specified is not a valid position',
  10213. cannotPlace : 'Popup does not fit within the boundaries of the viewport',
  10214. method : 'The method you called is not defined.',
  10215. noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>',
  10216. notFound : 'The target or popup you specified does not exist on the page'
  10217. },
  10218. metadata: {
  10219. activator : 'activator',
  10220. content : 'content',
  10221. html : 'html',
  10222. offset : 'offset',
  10223. position : 'position',
  10224. title : 'title',
  10225. variation : 'variation'
  10226. },
  10227. className : {
  10228. active : 'active',
  10229. animating : 'animating',
  10230. dropdown : 'dropdown',
  10231. fluid : 'fluid',
  10232. loading : 'loading',
  10233. popup : 'ui popup',
  10234. position : 'top left center bottom right',
  10235. visible : 'visible'
  10236. },
  10237. selector : {
  10238. popup : '.ui.popup'
  10239. },
  10240. templates: {
  10241. escape: function(string) {
  10242. var
  10243. badChars = /[&<>"'`]/g,
  10244. shouldEscape = /[&<>"'`]/,
  10245. escape = {
  10246. "&": "&amp;",
  10247. "<": "&lt;",
  10248. ">": "&gt;",
  10249. '"': "&quot;",
  10250. "'": "&#x27;",
  10251. "`": "&#x60;"
  10252. },
  10253. escapedChar = function(chr) {
  10254. return escape[chr];
  10255. }
  10256. ;
  10257. if(shouldEscape.test(string)) {
  10258. return string.replace(badChars, escapedChar);
  10259. }
  10260. return string;
  10261. },
  10262. popup: function(text) {
  10263. var
  10264. html = '',
  10265. escape = $.fn.popup.settings.templates.escape
  10266. ;
  10267. if(typeof text !== undefined) {
  10268. if(typeof text.title !== undefined && text.title) {
  10269. text.title = escape(text.title);
  10270. html += '<div class="header">' + text.title + '</div>';
  10271. }
  10272. if(typeof text.content !== undefined && text.content) {
  10273. text.content = escape(text.content);
  10274. html += '<div class="content">' + text.content + '</div>';
  10275. }
  10276. }
  10277. return html;
  10278. }
  10279. }
  10280. };
  10281. })( jQuery, window, document );
  10282. /*!
  10283. * # Semantic UI 2.1.6 - Progress
  10284. * http://github.com/semantic-org/semantic-ui/
  10285. *
  10286. *
  10287. * Copyright 2015 Contributors
  10288. * Released under the MIT license
  10289. * http://opensource.org/licenses/MIT
  10290. *
  10291. */
  10292. ;(function ( $, window, document, undefined ) {
  10293. "use strict";
  10294. $.fn.progress = function(parameters) {
  10295. var
  10296. $allModules = $(this),
  10297. moduleSelector = $allModules.selector || '',
  10298. time = new Date().getTime(),
  10299. performance = [],
  10300. query = arguments[0],
  10301. methodInvoked = (typeof query == 'string'),
  10302. queryArguments = [].slice.call(arguments, 1),
  10303. returnedValue
  10304. ;
  10305. $allModules
  10306. .each(function() {
  10307. var
  10308. settings = ( $.isPlainObject(parameters) )
  10309. ? $.extend(true, {}, $.fn.progress.settings, parameters)
  10310. : $.extend({}, $.fn.progress.settings),
  10311. className = settings.className,
  10312. metadata = settings.metadata,
  10313. namespace = settings.namespace,
  10314. selector = settings.selector,
  10315. error = settings.error,
  10316. eventNamespace = '.' + namespace,
  10317. moduleNamespace = 'module-' + namespace,
  10318. $module = $(this),
  10319. $bar = $(this).find(selector.bar),
  10320. $progress = $(this).find(selector.progress),
  10321. $label = $(this).find(selector.label),
  10322. element = this,
  10323. instance = $module.data(moduleNamespace),
  10324. animating = false,
  10325. transitionEnd,
  10326. module
  10327. ;
  10328. module = {
  10329. initialize: function() {
  10330. module.debug('Initializing progress bar', settings);
  10331. module.set.duration();
  10332. module.set.transitionEvent();
  10333. module.read.metadata();
  10334. module.read.settings();
  10335. module.instantiate();
  10336. },
  10337. instantiate: function() {
  10338. module.verbose('Storing instance of progress', module);
  10339. instance = module;
  10340. $module
  10341. .data(moduleNamespace, module)
  10342. ;
  10343. },
  10344. destroy: function() {
  10345. module.verbose('Destroying previous progress for', $module);
  10346. clearInterval(instance.interval);
  10347. module.remove.state();
  10348. $module.removeData(moduleNamespace);
  10349. instance = undefined;
  10350. },
  10351. reset: function() {
  10352. module.set.percent(0);
  10353. module.set.value(0);
  10354. },
  10355. complete: function() {
  10356. if(module.percent === undefined || module.percent < 100) {
  10357. module.set.percent(100);
  10358. }
  10359. },
  10360. read: {
  10361. metadata: function() {
  10362. var
  10363. data = {
  10364. percent : $module.data(metadata.percent),
  10365. total : $module.data(metadata.total),
  10366. value : $module.data(metadata.value)
  10367. }
  10368. ;
  10369. if(data.percent) {
  10370. module.debug('Current percent value set from metadata', data.percent);
  10371. module.set.percent(data.percent);
  10372. }
  10373. if(data.total) {
  10374. module.debug('Total value set from metadata', data.total);
  10375. module.set.total(data.total);
  10376. }
  10377. if(data.value) {
  10378. module.debug('Current value set from metadata', data.value);
  10379. module.set.value(data.value);
  10380. module.set.progress(data.value);
  10381. }
  10382. },
  10383. settings: function() {
  10384. if(settings.total !== false) {
  10385. module.debug('Current total set in settings', settings.total);
  10386. module.set.total(settings.total);
  10387. }
  10388. if(settings.value !== false) {
  10389. module.debug('Current value set in settings', settings.value);
  10390. module.set.value(settings.value);
  10391. module.set.progress(module.value);
  10392. }
  10393. if(settings.percent !== false) {
  10394. module.debug('Current percent set in settings', settings.percent);
  10395. module.set.percent(settings.percent);
  10396. }
  10397. }
  10398. },
  10399. increment: function(incrementValue) {
  10400. var
  10401. maxValue,
  10402. startValue,
  10403. newValue
  10404. ;
  10405. if( module.has.total() ) {
  10406. startValue = module.get.value();
  10407. incrementValue = incrementValue || 1;
  10408. newValue = startValue + incrementValue;
  10409. maxValue = module.get.total();
  10410. module.debug('Incrementing value', startValue, newValue, maxValue);
  10411. if(newValue > maxValue ) {
  10412. module.debug('Value cannot increment above total', maxValue);
  10413. newValue = maxValue;
  10414. }
  10415. }
  10416. else {
  10417. startValue = module.get.percent();
  10418. incrementValue = incrementValue || module.get.randomValue();
  10419. newValue = startValue + incrementValue;
  10420. maxValue = 100;
  10421. module.debug('Incrementing percentage by', startValue, newValue);
  10422. if(newValue > maxValue ) {
  10423. module.debug('Value cannot increment above 100 percent');
  10424. newValue = maxValue;
  10425. }
  10426. }
  10427. module.set.progress(newValue);
  10428. },
  10429. decrement: function(decrementValue) {
  10430. var
  10431. total = module.get.total(),
  10432. startValue,
  10433. newValue
  10434. ;
  10435. if(total) {
  10436. startValue = module.get.value();
  10437. decrementValue = decrementValue || 1;
  10438. newValue = startValue - decrementValue;
  10439. module.debug('Decrementing value by', decrementValue, startValue);
  10440. }
  10441. else {
  10442. startValue = module.get.percent();
  10443. decrementValue = decrementValue || module.get.randomValue();
  10444. newValue = startValue - decrementValue;
  10445. module.debug('Decrementing percentage by', decrementValue, startValue);
  10446. }
  10447. if(newValue < 0) {
  10448. module.debug('Value cannot decrement below 0');
  10449. newValue = 0;
  10450. }
  10451. module.set.progress(newValue);
  10452. },
  10453. has: {
  10454. total: function() {
  10455. return (module.get.total() !== false);
  10456. }
  10457. },
  10458. get: {
  10459. text: function(templateText) {
  10460. var
  10461. value = module.value || 0,
  10462. total = module.total || 0,
  10463. percent = (animating)
  10464. ? module.get.displayPercent()
  10465. : module.percent || 0,
  10466. left = (module.total > 0)
  10467. ? (total - value)
  10468. : (100 - percent)
  10469. ;
  10470. templateText = templateText || '';
  10471. templateText = templateText
  10472. .replace('{value}', value)
  10473. .replace('{total}', total)
  10474. .replace('{left}', left)
  10475. .replace('{percent}', percent)
  10476. ;
  10477. module.debug('Adding variables to progress bar text', templateText);
  10478. return templateText;
  10479. },
  10480. randomValue: function() {
  10481. module.debug('Generating random increment percentage');
  10482. return Math.floor((Math.random() * settings.random.max) + settings.random.min);
  10483. },
  10484. numericValue: function(value) {
  10485. return (typeof value === 'string')
  10486. ? (value.replace(/[^\d.]/g, '') !== '')
  10487. ? +(value.replace(/[^\d.]/g, ''))
  10488. : false
  10489. : value
  10490. ;
  10491. },
  10492. transitionEnd: function() {
  10493. var
  10494. element = document.createElement('element'),
  10495. transitions = {
  10496. 'transition' :'transitionend',
  10497. 'OTransition' :'oTransitionEnd',
  10498. 'MozTransition' :'transitionend',
  10499. 'WebkitTransition' :'webkitTransitionEnd'
  10500. },
  10501. transition
  10502. ;
  10503. for(transition in transitions){
  10504. if( element.style[transition] !== undefined ){
  10505. return transitions[transition];
  10506. }
  10507. }
  10508. },
  10509. // gets current displayed percentage (if animating values this is the intermediary value)
  10510. displayPercent: function() {
  10511. var
  10512. barWidth = $bar.width(),
  10513. totalWidth = $module.width(),
  10514. minDisplay = parseInt($bar.css('min-width'), 10),
  10515. displayPercent = (barWidth > minDisplay)
  10516. ? (barWidth / totalWidth * 100)
  10517. : module.percent
  10518. ;
  10519. return (settings.precision > 0)
  10520. ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
  10521. : Math.round(displayPercent)
  10522. ;
  10523. },
  10524. percent: function() {
  10525. return module.percent || 0;
  10526. },
  10527. value: function() {
  10528. return module.value || 0;
  10529. },
  10530. total: function() {
  10531. return module.total || false;
  10532. }
  10533. },
  10534. is: {
  10535. success: function() {
  10536. return $module.hasClass(className.success);
  10537. },
  10538. warning: function() {
  10539. return $module.hasClass(className.warning);
  10540. },
  10541. error: function() {
  10542. return $module.hasClass(className.error);
  10543. },
  10544. active: function() {
  10545. return $module.hasClass(className.active);
  10546. },
  10547. visible: function() {
  10548. return $module.is(':visible');
  10549. }
  10550. },
  10551. remove: {
  10552. state: function() {
  10553. module.verbose('Removing stored state');
  10554. delete module.total;
  10555. delete module.percent;
  10556. delete module.value;
  10557. },
  10558. active: function() {
  10559. module.verbose('Removing active state');
  10560. $module.removeClass(className.active);
  10561. },
  10562. success: function() {
  10563. module.verbose('Removing success state');
  10564. $module.removeClass(className.success);
  10565. },
  10566. warning: function() {
  10567. module.verbose('Removing warning state');
  10568. $module.removeClass(className.warning);
  10569. },
  10570. error: function() {
  10571. module.verbose('Removing error state');
  10572. $module.removeClass(className.error);
  10573. }
  10574. },
  10575. set: {
  10576. barWidth: function(value) {
  10577. if(value > 100) {
  10578. module.error(error.tooHigh, value);
  10579. }
  10580. else if (value < 0) {
  10581. module.error(error.tooLow, value);
  10582. }
  10583. else {
  10584. $bar
  10585. .css('width', value + '%')
  10586. ;
  10587. $module
  10588. .attr('data-percent', parseInt(value, 10))
  10589. ;
  10590. }
  10591. },
  10592. duration: function(duration) {
  10593. duration = duration || settings.duration;
  10594. duration = (typeof duration == 'number')
  10595. ? duration + 'ms'
  10596. : duration
  10597. ;
  10598. module.verbose('Setting progress bar transition duration', duration);
  10599. $bar
  10600. .css({
  10601. 'transition-duration': duration
  10602. })
  10603. ;
  10604. },
  10605. percent: function(percent) {
  10606. percent = (typeof percent == 'string')
  10607. ? +(percent.replace('%', ''))
  10608. : percent
  10609. ;
  10610. // round display percentage
  10611. percent = (settings.precision > 0)
  10612. ? Math.round(percent * (10 * settings.precision)) / (10 * settings.precision)
  10613. : Math.round(percent)
  10614. ;
  10615. module.percent = percent;
  10616. if( !module.has.total() ) {
  10617. module.value = (settings.precision > 0)
  10618. ? Math.round( (percent / 100) * module.total * (10 * settings.precision)) / (10 * settings.precision)
  10619. : Math.round( (percent / 100) * module.total * 10) / 10
  10620. ;
  10621. if(settings.limitValues) {
  10622. module.value = (module.value > 100)
  10623. ? 100
  10624. : (module.value < 0)
  10625. ? 0
  10626. : module.value
  10627. ;
  10628. }
  10629. }
  10630. module.set.barWidth(percent);
  10631. module.set.labelInterval();
  10632. module.set.labels();
  10633. settings.onChange.call(element, percent, module.value, module.total);
  10634. },
  10635. labelInterval: function() {
  10636. var
  10637. animationCallback = function() {
  10638. module.verbose('Bar finished animating, removing continuous label updates');
  10639. clearInterval(module.interval);
  10640. animating = false;
  10641. module.set.labels();
  10642. }
  10643. ;
  10644. clearInterval(module.interval);
  10645. $bar.one(transitionEnd + eventNamespace, animationCallback);
  10646. module.timer = setTimeout(animationCallback, settings.duration + 100);
  10647. animating = true;
  10648. module.interval = setInterval(module.set.labels, settings.framerate);
  10649. },
  10650. labels: function() {
  10651. module.verbose('Setting both bar progress and outer label text');
  10652. module.set.barLabel();
  10653. module.set.state();
  10654. },
  10655. label: function(text) {
  10656. text = text || '';
  10657. if(text) {
  10658. text = module.get.text(text);
  10659. module.debug('Setting label to text', text);
  10660. $label.text(text);
  10661. }
  10662. },
  10663. state: function(percent) {
  10664. percent = (percent !== undefined)
  10665. ? percent
  10666. : module.percent
  10667. ;
  10668. if(percent === 100) {
  10669. if(settings.autoSuccess && !(module.is.warning() || module.is.error())) {
  10670. module.set.success();
  10671. module.debug('Automatically triggering success at 100%');
  10672. }
  10673. else {
  10674. module.verbose('Reached 100% removing active state');
  10675. module.remove.active();
  10676. }
  10677. }
  10678. else if(percent > 0) {
  10679. module.verbose('Adjusting active progress bar label', percent);
  10680. module.set.active();
  10681. }
  10682. else {
  10683. module.remove.active();
  10684. module.set.label(settings.text.active);
  10685. }
  10686. },
  10687. barLabel: function(text) {
  10688. if(text !== undefined) {
  10689. $progress.text( module.get.text(text) );
  10690. }
  10691. else if(settings.label == 'ratio' && module.total) {
  10692. module.debug('Adding ratio to bar label');
  10693. $progress.text( module.get.text(settings.text.ratio) );
  10694. }
  10695. else if(settings.label == 'percent') {
  10696. module.debug('Adding percentage to bar label');
  10697. $progress.text( module.get.text(settings.text.percent) );
  10698. }
  10699. },
  10700. active: function(text) {
  10701. text = text || settings.text.active;
  10702. module.debug('Setting active state');
  10703. if(settings.showActivity && !module.is.active() ) {
  10704. $module.addClass(className.active);
  10705. }
  10706. module.remove.warning();
  10707. module.remove.error();
  10708. module.remove.success();
  10709. if(text) {
  10710. module.set.label(text);
  10711. }
  10712. settings.onActive.call(element, module.value, module.total);
  10713. },
  10714. success : function(text) {
  10715. text = text || settings.text.success;
  10716. module.debug('Setting success state');
  10717. $module.addClass(className.success);
  10718. module.remove.active();
  10719. module.remove.warning();
  10720. module.remove.error();
  10721. module.complete();
  10722. if(text) {
  10723. module.set.label(text);
  10724. }
  10725. settings.onSuccess.call(element, module.total);
  10726. },
  10727. warning : function(text) {
  10728. text = text || settings.text.warning;
  10729. module.debug('Setting warning state');
  10730. $module.addClass(className.warning);
  10731. module.remove.active();
  10732. module.remove.success();
  10733. module.remove.error();
  10734. module.complete();
  10735. if(text) {
  10736. module.set.label(text);
  10737. }
  10738. settings.onWarning.call(element, module.value, module.total);
  10739. },
  10740. error : function(text) {
  10741. text = text || settings.text.error;
  10742. module.debug('Setting error state');
  10743. $module.addClass(className.error);
  10744. module.remove.active();
  10745. module.remove.success();
  10746. module.remove.warning();
  10747. module.complete();
  10748. if(text) {
  10749. module.set.label(text);
  10750. }
  10751. settings.onError.call(element, module.value, module.total);
  10752. },
  10753. transitionEvent: function() {
  10754. transitionEnd = module.get.transitionEnd();
  10755. },
  10756. total: function(totalValue) {
  10757. module.total = totalValue;
  10758. },
  10759. value: function(value) {
  10760. module.value = value;
  10761. },
  10762. progress: function(value) {
  10763. var
  10764. numericValue = module.get.numericValue(value),
  10765. percentComplete
  10766. ;
  10767. if(numericValue === false) {
  10768. module.error(error.nonNumeric, value);
  10769. }
  10770. if( module.has.total() ) {
  10771. module.set.value(numericValue);
  10772. percentComplete = (numericValue / module.total) * 100;
  10773. module.debug('Calculating percent complete from total', percentComplete);
  10774. module.set.percent( percentComplete );
  10775. }
  10776. else {
  10777. percentComplete = numericValue;
  10778. module.debug('Setting value to exact percentage value', percentComplete);
  10779. module.set.percent( percentComplete );
  10780. }
  10781. }
  10782. },
  10783. setting: function(name, value) {
  10784. module.debug('Changing setting', name, value);
  10785. if( $.isPlainObject(name) ) {
  10786. $.extend(true, settings, name);
  10787. }
  10788. else if(value !== undefined) {
  10789. settings[name] = value;
  10790. }
  10791. else {
  10792. return settings[name];
  10793. }
  10794. },
  10795. internal: function(name, value) {
  10796. if( $.isPlainObject(name) ) {
  10797. $.extend(true, module, name);
  10798. }
  10799. else if(value !== undefined) {
  10800. module[name] = value;
  10801. }
  10802. else {
  10803. return module[name];
  10804. }
  10805. },
  10806. debug: function() {
  10807. if(settings.debug) {
  10808. if(settings.performance) {
  10809. module.performance.log(arguments);
  10810. }
  10811. else {
  10812. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10813. module.debug.apply(console, arguments);
  10814. }
  10815. }
  10816. },
  10817. verbose: function() {
  10818. if(settings.verbose && settings.debug) {
  10819. if(settings.performance) {
  10820. module.performance.log(arguments);
  10821. }
  10822. else {
  10823. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  10824. module.verbose.apply(console, arguments);
  10825. }
  10826. }
  10827. },
  10828. error: function() {
  10829. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  10830. module.error.apply(console, arguments);
  10831. },
  10832. performance: {
  10833. log: function(message) {
  10834. var
  10835. currentTime,
  10836. executionTime,
  10837. previousTime
  10838. ;
  10839. if(settings.performance) {
  10840. currentTime = new Date().getTime();
  10841. previousTime = time || currentTime;
  10842. executionTime = currentTime - previousTime;
  10843. time = currentTime;
  10844. performance.push({
  10845. 'Name' : message[0],
  10846. 'Arguments' : [].slice.call(message, 1) || '',
  10847. 'Element' : element,
  10848. 'Execution Time' : executionTime
  10849. });
  10850. }
  10851. clearTimeout(module.performance.timer);
  10852. module.performance.timer = setTimeout(module.performance.display, 500);
  10853. },
  10854. display: function() {
  10855. var
  10856. title = settings.name + ':',
  10857. totalTime = 0
  10858. ;
  10859. time = false;
  10860. clearTimeout(module.performance.timer);
  10861. $.each(performance, function(index, data) {
  10862. totalTime += data['Execution Time'];
  10863. });
  10864. title += ' ' + totalTime + 'ms';
  10865. if(moduleSelector) {
  10866. title += ' \'' + moduleSelector + '\'';
  10867. }
  10868. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  10869. console.groupCollapsed(title);
  10870. if(console.table) {
  10871. console.table(performance);
  10872. }
  10873. else {
  10874. $.each(performance, function(index, data) {
  10875. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  10876. });
  10877. }
  10878. console.groupEnd();
  10879. }
  10880. performance = [];
  10881. }
  10882. },
  10883. invoke: function(query, passedArguments, context) {
  10884. var
  10885. object = instance,
  10886. maxDepth,
  10887. found,
  10888. response
  10889. ;
  10890. passedArguments = passedArguments || queryArguments;
  10891. context = element || context;
  10892. if(typeof query == 'string' && object !== undefined) {
  10893. query = query.split(/[\. ]/);
  10894. maxDepth = query.length - 1;
  10895. $.each(query, function(depth, value) {
  10896. var camelCaseValue = (depth != maxDepth)
  10897. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  10898. : query
  10899. ;
  10900. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  10901. object = object[camelCaseValue];
  10902. }
  10903. else if( object[camelCaseValue] !== undefined ) {
  10904. found = object[camelCaseValue];
  10905. return false;
  10906. }
  10907. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  10908. object = object[value];
  10909. }
  10910. else if( object[value] !== undefined ) {
  10911. found = object[value];
  10912. return false;
  10913. }
  10914. else {
  10915. module.error(error.method, query);
  10916. return false;
  10917. }
  10918. });
  10919. }
  10920. if ( $.isFunction( found ) ) {
  10921. response = found.apply(context, passedArguments);
  10922. }
  10923. else if(found !== undefined) {
  10924. response = found;
  10925. }
  10926. if($.isArray(returnedValue)) {
  10927. returnedValue.push(response);
  10928. }
  10929. else if(returnedValue !== undefined) {
  10930. returnedValue = [returnedValue, response];
  10931. }
  10932. else if(response !== undefined) {
  10933. returnedValue = response;
  10934. }
  10935. return found;
  10936. }
  10937. };
  10938. if(methodInvoked) {
  10939. if(instance === undefined) {
  10940. module.initialize();
  10941. }
  10942. module.invoke(query);
  10943. }
  10944. else {
  10945. if(instance !== undefined) {
  10946. instance.invoke('destroy');
  10947. }
  10948. module.initialize();
  10949. }
  10950. })
  10951. ;
  10952. return (returnedValue !== undefined)
  10953. ? returnedValue
  10954. : this
  10955. ;
  10956. };
  10957. $.fn.progress.settings = {
  10958. name : 'Progress',
  10959. namespace : 'progress',
  10960. debug : false,
  10961. verbose : false,
  10962. performance : true,
  10963. random : {
  10964. min : 2,
  10965. max : 5
  10966. },
  10967. duration : 300,
  10968. autoSuccess : true,
  10969. showActivity : true,
  10970. limitValues : true,
  10971. label : 'percent',
  10972. precision : 0,
  10973. framerate : (1000 / 30), /// 30 fps
  10974. percent : false,
  10975. total : false,
  10976. value : false,
  10977. onChange : function(percent, value, total){},
  10978. onSuccess : function(total){},
  10979. onActive : function(value, total){},
  10980. onError : function(value, total){},
  10981. onWarning : function(value, total){},
  10982. error : {
  10983. method : 'The method you called is not defined.',
  10984. nonNumeric : 'Progress value is non numeric',
  10985. tooHigh : 'Value specified is above 100%',
  10986. tooLow : 'Value specified is below 0%'
  10987. },
  10988. regExp: {
  10989. variable: /\{\$*[A-z0-9]+\}/g
  10990. },
  10991. metadata: {
  10992. percent : 'percent',
  10993. total : 'total',
  10994. value : 'value'
  10995. },
  10996. selector : {
  10997. bar : '> .bar',
  10998. label : '> .label',
  10999. progress : '.bar > .progress'
  11000. },
  11001. text : {
  11002. active : false,
  11003. error : false,
  11004. success : false,
  11005. warning : false,
  11006. percent : '{percent}%',
  11007. ratio : '{value} of {total}'
  11008. },
  11009. className : {
  11010. active : 'active',
  11011. error : 'error',
  11012. success : 'success',
  11013. warning : 'warning'
  11014. }
  11015. };
  11016. })( jQuery, window, document );
  11017. /*!
  11018. * # Semantic UI 2.1.6 - Rating
  11019. * http://github.com/semantic-org/semantic-ui/
  11020. *
  11021. *
  11022. * Copyright 2015 Contributors
  11023. * Released under the MIT license
  11024. * http://opensource.org/licenses/MIT
  11025. *
  11026. */
  11027. ;(function ($, window, document, undefined) {
  11028. "use strict";
  11029. $.fn.rating = function(parameters) {
  11030. var
  11031. $allModules = $(this),
  11032. moduleSelector = $allModules.selector || '',
  11033. time = new Date().getTime(),
  11034. performance = [],
  11035. query = arguments[0],
  11036. methodInvoked = (typeof query == 'string'),
  11037. queryArguments = [].slice.call(arguments, 1),
  11038. returnedValue
  11039. ;
  11040. $allModules
  11041. .each(function() {
  11042. var
  11043. settings = ( $.isPlainObject(parameters) )
  11044. ? $.extend(true, {}, $.fn.rating.settings, parameters)
  11045. : $.extend({}, $.fn.rating.settings),
  11046. namespace = settings.namespace,
  11047. className = settings.className,
  11048. metadata = settings.metadata,
  11049. selector = settings.selector,
  11050. error = settings.error,
  11051. eventNamespace = '.' + namespace,
  11052. moduleNamespace = 'module-' + namespace,
  11053. element = this,
  11054. instance = $(this).data(moduleNamespace),
  11055. $module = $(this),
  11056. $icon = $module.find(selector.icon),
  11057. module
  11058. ;
  11059. module = {
  11060. initialize: function() {
  11061. module.verbose('Initializing rating module', settings);
  11062. if($icon.length === 0) {
  11063. module.setup.layout();
  11064. }
  11065. if(settings.interactive) {
  11066. module.enable();
  11067. }
  11068. else {
  11069. module.disable();
  11070. }
  11071. module.set.rating( module.get.initialRating() );
  11072. module.instantiate();
  11073. },
  11074. instantiate: function() {
  11075. module.verbose('Instantiating module', settings);
  11076. instance = module;
  11077. $module
  11078. .data(moduleNamespace, module)
  11079. ;
  11080. },
  11081. destroy: function() {
  11082. module.verbose('Destroying previous instance', instance);
  11083. module.remove.events();
  11084. $module
  11085. .removeData(moduleNamespace)
  11086. ;
  11087. },
  11088. refresh: function() {
  11089. $icon = $module.find(selector.icon);
  11090. },
  11091. setup: {
  11092. layout: function() {
  11093. var
  11094. maxRating = module.get.maxRating(),
  11095. html = $.fn.rating.settings.templates.icon(maxRating)
  11096. ;
  11097. module.debug('Generating icon html dynamically');
  11098. $module
  11099. .html(html)
  11100. ;
  11101. module.refresh();
  11102. }
  11103. },
  11104. event: {
  11105. mouseenter: function() {
  11106. var
  11107. $activeIcon = $(this)
  11108. ;
  11109. $activeIcon
  11110. .nextAll()
  11111. .removeClass(className.selected)
  11112. ;
  11113. $module
  11114. .addClass(className.selected)
  11115. ;
  11116. $activeIcon
  11117. .addClass(className.selected)
  11118. .prevAll()
  11119. .addClass(className.selected)
  11120. ;
  11121. },
  11122. mouseleave: function() {
  11123. $module
  11124. .removeClass(className.selected)
  11125. ;
  11126. $icon
  11127. .removeClass(className.selected)
  11128. ;
  11129. },
  11130. click: function() {
  11131. var
  11132. $activeIcon = $(this),
  11133. currentRating = module.get.rating(),
  11134. rating = $icon.index($activeIcon) + 1,
  11135. canClear = (settings.clearable == 'auto')
  11136. ? ($icon.length === 1)
  11137. : settings.clearable
  11138. ;
  11139. if(canClear && currentRating == rating) {
  11140. module.clearRating();
  11141. }
  11142. else {
  11143. module.set.rating( rating );
  11144. }
  11145. }
  11146. },
  11147. clearRating: function() {
  11148. module.debug('Clearing current rating');
  11149. module.set.rating(0);
  11150. },
  11151. bind: {
  11152. events: function() {
  11153. module.verbose('Binding events');
  11154. $module
  11155. .on('mouseenter' + eventNamespace, selector.icon, module.event.mouseenter)
  11156. .on('mouseleave' + eventNamespace, selector.icon, module.event.mouseleave)
  11157. .on('click' + eventNamespace, selector.icon, module.event.click)
  11158. ;
  11159. }
  11160. },
  11161. remove: {
  11162. events: function() {
  11163. module.verbose('Removing events');
  11164. $module
  11165. .off(eventNamespace)
  11166. ;
  11167. }
  11168. },
  11169. enable: function() {
  11170. module.debug('Setting rating to interactive mode');
  11171. module.bind.events();
  11172. $module
  11173. .removeClass(className.disabled)
  11174. ;
  11175. },
  11176. disable: function() {
  11177. module.debug('Setting rating to read-only mode');
  11178. module.remove.events();
  11179. $module
  11180. .addClass(className.disabled)
  11181. ;
  11182. },
  11183. get: {
  11184. initialRating: function() {
  11185. if($module.data(metadata.rating) !== undefined) {
  11186. $module.removeData(metadata.rating);
  11187. return $module.data(metadata.rating);
  11188. }
  11189. return settings.initialRating;
  11190. },
  11191. maxRating: function() {
  11192. if($module.data(metadata.maxRating) !== undefined) {
  11193. $module.removeData(metadata.maxRating);
  11194. return $module.data(metadata.maxRating);
  11195. }
  11196. return settings.maxRating;
  11197. },
  11198. rating: function() {
  11199. var
  11200. currentRating = $icon.filter('.' + className.active).length
  11201. ;
  11202. module.verbose('Current rating retrieved', currentRating);
  11203. return currentRating;
  11204. }
  11205. },
  11206. set: {
  11207. rating: function(rating) {
  11208. var
  11209. ratingIndex = (rating - 1 >= 0)
  11210. ? (rating - 1)
  11211. : 0,
  11212. $activeIcon = $icon.eq(ratingIndex)
  11213. ;
  11214. $module
  11215. .removeClass(className.selected)
  11216. ;
  11217. $icon
  11218. .removeClass(className.selected)
  11219. .removeClass(className.active)
  11220. ;
  11221. if(rating > 0) {
  11222. module.verbose('Setting current rating to', rating);
  11223. $activeIcon
  11224. .prevAll()
  11225. .andSelf()
  11226. .addClass(className.active)
  11227. ;
  11228. }
  11229. settings.onRate.call(element, rating);
  11230. }
  11231. },
  11232. setting: function(name, value) {
  11233. module.debug('Changing setting', name, value);
  11234. if( $.isPlainObject(name) ) {
  11235. $.extend(true, settings, name);
  11236. }
  11237. else if(value !== undefined) {
  11238. settings[name] = value;
  11239. }
  11240. else {
  11241. return settings[name];
  11242. }
  11243. },
  11244. internal: function(name, value) {
  11245. if( $.isPlainObject(name) ) {
  11246. $.extend(true, module, name);
  11247. }
  11248. else if(value !== undefined) {
  11249. module[name] = value;
  11250. }
  11251. else {
  11252. return module[name];
  11253. }
  11254. },
  11255. debug: function() {
  11256. if(settings.debug) {
  11257. if(settings.performance) {
  11258. module.performance.log(arguments);
  11259. }
  11260. else {
  11261. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11262. module.debug.apply(console, arguments);
  11263. }
  11264. }
  11265. },
  11266. verbose: function() {
  11267. if(settings.verbose && settings.debug) {
  11268. if(settings.performance) {
  11269. module.performance.log(arguments);
  11270. }
  11271. else {
  11272. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  11273. module.verbose.apply(console, arguments);
  11274. }
  11275. }
  11276. },
  11277. error: function() {
  11278. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  11279. module.error.apply(console, arguments);
  11280. },
  11281. performance: {
  11282. log: function(message) {
  11283. var
  11284. currentTime,
  11285. executionTime,
  11286. previousTime
  11287. ;
  11288. if(settings.performance) {
  11289. currentTime = new Date().getTime();
  11290. previousTime = time || currentTime;
  11291. executionTime = currentTime - previousTime;
  11292. time = currentTime;
  11293. performance.push({
  11294. 'Name' : message[0],
  11295. 'Arguments' : [].slice.call(message, 1) || '',
  11296. 'Element' : element,
  11297. 'Execution Time' : executionTime
  11298. });
  11299. }
  11300. clearTimeout(module.performance.timer);
  11301. module.performance.timer = setTimeout(module.performance.display, 500);
  11302. },
  11303. display: function() {
  11304. var
  11305. title = settings.name + ':',
  11306. totalTime = 0
  11307. ;
  11308. time = false;
  11309. clearTimeout(module.performance.timer);
  11310. $.each(performance, function(index, data) {
  11311. totalTime += data['Execution Time'];
  11312. });
  11313. title += ' ' + totalTime + 'ms';
  11314. if(moduleSelector) {
  11315. title += ' \'' + moduleSelector + '\'';
  11316. }
  11317. if($allModules.length > 1) {
  11318. title += ' ' + '(' + $allModules.length + ')';
  11319. }
  11320. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  11321. console.groupCollapsed(title);
  11322. if(console.table) {
  11323. console.table(performance);
  11324. }
  11325. else {
  11326. $.each(performance, function(index, data) {
  11327. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  11328. });
  11329. }
  11330. console.groupEnd();
  11331. }
  11332. performance = [];
  11333. }
  11334. },
  11335. invoke: function(query, passedArguments, context) {
  11336. var
  11337. object = instance,
  11338. maxDepth,
  11339. found,
  11340. response
  11341. ;
  11342. passedArguments = passedArguments || queryArguments;
  11343. context = element || context;
  11344. if(typeof query == 'string' && object !== undefined) {
  11345. query = query.split(/[\. ]/);
  11346. maxDepth = query.length - 1;
  11347. $.each(query, function(depth, value) {
  11348. var camelCaseValue = (depth != maxDepth)
  11349. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  11350. : query
  11351. ;
  11352. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  11353. object = object[camelCaseValue];
  11354. }
  11355. else if( object[camelCaseValue] !== undefined ) {
  11356. found = object[camelCaseValue];
  11357. return false;
  11358. }
  11359. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  11360. object = object[value];
  11361. }
  11362. else if( object[value] !== undefined ) {
  11363. found = object[value];
  11364. return false;
  11365. }
  11366. else {
  11367. return false;
  11368. }
  11369. });
  11370. }
  11371. if ( $.isFunction( found ) ) {
  11372. response = found.apply(context, passedArguments);
  11373. }
  11374. else if(found !== undefined) {
  11375. response = found;
  11376. }
  11377. if($.isArray(returnedValue)) {
  11378. returnedValue.push(response);
  11379. }
  11380. else if(returnedValue !== undefined) {
  11381. returnedValue = [returnedValue, response];
  11382. }
  11383. else if(response !== undefined) {
  11384. returnedValue = response;
  11385. }
  11386. return found;
  11387. }
  11388. };
  11389. if(methodInvoked) {
  11390. if(instance === undefined) {
  11391. module.initialize();
  11392. }
  11393. module.invoke(query);
  11394. }
  11395. else {
  11396. if(instance !== undefined) {
  11397. instance.invoke('destroy');
  11398. }
  11399. module.initialize();
  11400. }
  11401. })
  11402. ;
  11403. return (returnedValue !== undefined)
  11404. ? returnedValue
  11405. : this
  11406. ;
  11407. };
  11408. $.fn.rating.settings = {
  11409. name : 'Rating',
  11410. namespace : 'rating',
  11411. debug : false,
  11412. verbose : false,
  11413. performance : true,
  11414. initialRating : 0,
  11415. interactive : true,
  11416. maxRating : 4,
  11417. clearable : 'auto',
  11418. onRate : function(rating){},
  11419. error : {
  11420. method : 'The method you called is not defined',
  11421. noMaximum : 'No maximum rating specified. Cannot generate HTML automatically'
  11422. },
  11423. metadata: {
  11424. rating : 'rating',
  11425. maxRating : 'maxRating'
  11426. },
  11427. className : {
  11428. active : 'active',
  11429. disabled : 'disabled',
  11430. selected : 'selected',
  11431. loading : 'loading'
  11432. },
  11433. selector : {
  11434. icon : '.icon'
  11435. },
  11436. templates: {
  11437. icon: function(maxRating) {
  11438. var
  11439. icon = 1,
  11440. html = ''
  11441. ;
  11442. while(icon <= maxRating) {
  11443. html += '<i class="icon"></i>';
  11444. icon++;
  11445. }
  11446. return html;
  11447. }
  11448. }
  11449. };
  11450. })( jQuery, window, document );
  11451. /*!
  11452. * # Semantic UI 2.1.6 - Search
  11453. * http://github.com/semantic-org/semantic-ui/
  11454. *
  11455. *
  11456. * Copyright 2015 Contributors
  11457. * Released under the MIT license
  11458. * http://opensource.org/licenses/MIT
  11459. *
  11460. */
  11461. ;(function ($, window, document, undefined) {
  11462. "use strict";
  11463. $.fn.search = function(parameters) {
  11464. var
  11465. $allModules = $(this),
  11466. moduleSelector = $allModules.selector || '',
  11467. time = new Date().getTime(),
  11468. performance = [],
  11469. query = arguments[0],
  11470. methodInvoked = (typeof query == 'string'),
  11471. queryArguments = [].slice.call(arguments, 1),
  11472. returnedValue
  11473. ;
  11474. $(this)
  11475. .each(function() {
  11476. var
  11477. settings = ( $.isPlainObject(parameters) )
  11478. ? $.extend(true, {}, $.fn.search.settings, parameters)
  11479. : $.extend({}, $.fn.search.settings),
  11480. className = settings.className,
  11481. metadata = settings.metadata,
  11482. regExp = settings.regExp,
  11483. fields = settings.fields,
  11484. selector = settings.selector,
  11485. error = settings.error,
  11486. namespace = settings.namespace,
  11487. eventNamespace = '.' + namespace,
  11488. moduleNamespace = namespace + '-module',
  11489. $module = $(this),
  11490. $prompt = $module.find(selector.prompt),
  11491. $searchButton = $module.find(selector.searchButton),
  11492. $results = $module.find(selector.results),
  11493. $result = $module.find(selector.result),
  11494. $category = $module.find(selector.category),
  11495. element = this,
  11496. instance = $module.data(moduleNamespace),
  11497. module
  11498. ;
  11499. module = {
  11500. initialize: function() {
  11501. module.verbose('Initializing module');
  11502. module.determine.searchFields();
  11503. module.bind.events();
  11504. module.set.type();
  11505. module.create.results();
  11506. module.instantiate();
  11507. },
  11508. instantiate: function() {
  11509. module.verbose('Storing instance of module', module);
  11510. instance = module;
  11511. $module
  11512. .data(moduleNamespace, module)
  11513. ;
  11514. },
  11515. destroy: function() {
  11516. module.verbose('Destroying instance');
  11517. $module
  11518. .off(eventNamespace)
  11519. .removeData(moduleNamespace)
  11520. ;
  11521. },
  11522. bind: {
  11523. events: function() {
  11524. module.verbose('Binding events to search');
  11525. if(settings.automatic) {
  11526. $module
  11527. .on(module.get.inputEvent() + eventNamespace, selector.prompt, module.event.input)
  11528. ;
  11529. $prompt
  11530. .attr('autocomplete', 'off')
  11531. ;
  11532. }
  11533. $module
  11534. // prompt
  11535. .on('focus' + eventNamespace, selector.prompt, module.event.focus)
  11536. .on('blur' + eventNamespace, selector.prompt, module.event.blur)
  11537. .on('keydown' + eventNamespace, selector.prompt, module.handleKeyboard)
  11538. // search button
  11539. .on('click' + eventNamespace, selector.searchButton, module.query)
  11540. // results
  11541. .on('mousedown' + eventNamespace, selector.results, module.event.result.mousedown)
  11542. .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup)
  11543. .on('click' + eventNamespace, selector.result, module.event.result.click)
  11544. ;
  11545. }
  11546. },
  11547. determine: {
  11548. searchFields: function() {
  11549. // this makes sure $.extend does not add specified search fields to default fields
  11550. // this is the only setting which should not extend defaults
  11551. if(parameters && parameters.searchFields !== undefined) {
  11552. settings.searchFields = parameters.searchFields;
  11553. }
  11554. }
  11555. },
  11556. event: {
  11557. input: function() {
  11558. clearTimeout(module.timer);
  11559. module.timer = setTimeout(module.query, settings.searchDelay);
  11560. },
  11561. focus: function() {
  11562. module.set.focus();
  11563. if( module.has.minimumCharacters() ) {
  11564. module.query();
  11565. if( module.can.show() ) {
  11566. module.showResults();
  11567. }
  11568. }
  11569. },
  11570. blur: function(event) {
  11571. var
  11572. pageLostFocus = (document.activeElement === this)
  11573. ;
  11574. if(!pageLostFocus && !module.resultsClicked) {
  11575. module.cancel.query();
  11576. module.remove.focus();
  11577. module.timer = setTimeout(module.hideResults, settings.hideDelay);
  11578. }
  11579. },
  11580. result: {
  11581. mousedown: function() {
  11582. module.resultsClicked = true;
  11583. },
  11584. mouseup: function() {
  11585. module.resultsClicked = false;
  11586. },
  11587. click: function(event) {
  11588. module.debug('Search result selected');
  11589. var
  11590. $result = $(this),
  11591. $title = $result.find(selector.title).eq(0),
  11592. $link = $result.find('a[href]').eq(0),
  11593. href = $link.attr('href') || false,
  11594. target = $link.attr('target') || false,
  11595. title = $title.html(),
  11596. // title is used for result lookup
  11597. value = ($title.length > 0)
  11598. ? $title.text()
  11599. : false,
  11600. results = module.get.results(),
  11601. result = $result.data(metadata.result) || module.get.result(value, results),
  11602. returnedValue
  11603. ;
  11604. if( $.isFunction(settings.onSelect) ) {
  11605. if(settings.onSelect.call(element, result, results) === false) {
  11606. module.debug('Custom onSelect callback cancelled default select action');
  11607. return;
  11608. }
  11609. }
  11610. module.hideResults();
  11611. if(value) {
  11612. module.set.value(value);
  11613. }
  11614. if(href) {
  11615. module.verbose('Opening search link found in result', $link);
  11616. if(target == '_blank' || event.ctrlKey) {
  11617. window.open(href);
  11618. }
  11619. else {
  11620. window.location.href = (href);
  11621. }
  11622. }
  11623. }
  11624. }
  11625. },
  11626. handleKeyboard: function(event) {
  11627. var
  11628. // force selector refresh
  11629. $result = $module.find(selector.result),
  11630. $category = $module.find(selector.category),
  11631. currentIndex = $result.index( $result.filter('.' + className.active) ),
  11632. resultSize = $result.length,
  11633. keyCode = event.which,
  11634. keys = {
  11635. backspace : 8,
  11636. enter : 13,
  11637. escape : 27,
  11638. upArrow : 38,
  11639. downArrow : 40
  11640. },
  11641. newIndex
  11642. ;
  11643. // search shortcuts
  11644. if(keyCode == keys.escape) {
  11645. module.verbose('Escape key pressed, blurring search field');
  11646. module.trigger.blur();
  11647. }
  11648. if( module.is.visible() ) {
  11649. if(keyCode == keys.enter) {
  11650. module.verbose('Enter key pressed, selecting active result');
  11651. if( $result.filter('.' + className.active).length > 0 ) {
  11652. module.event.result.click.call($result.filter('.' + className.active), event);
  11653. event.preventDefault();
  11654. return false;
  11655. }
  11656. }
  11657. else if(keyCode == keys.upArrow) {
  11658. module.verbose('Up key pressed, changing active result');
  11659. newIndex = (currentIndex - 1 < 0)
  11660. ? currentIndex
  11661. : currentIndex - 1
  11662. ;
  11663. $category
  11664. .removeClass(className.active)
  11665. ;
  11666. $result
  11667. .removeClass(className.active)
  11668. .eq(newIndex)
  11669. .addClass(className.active)
  11670. .closest($category)
  11671. .addClass(className.active)
  11672. ;
  11673. event.preventDefault();
  11674. }
  11675. else if(keyCode == keys.downArrow) {
  11676. module.verbose('Down key pressed, changing active result');
  11677. newIndex = (currentIndex + 1 >= resultSize)
  11678. ? currentIndex
  11679. : currentIndex + 1
  11680. ;
  11681. $category
  11682. .removeClass(className.active)
  11683. ;
  11684. $result
  11685. .removeClass(className.active)
  11686. .eq(newIndex)
  11687. .addClass(className.active)
  11688. .closest($category)
  11689. .addClass(className.active)
  11690. ;
  11691. event.preventDefault();
  11692. }
  11693. }
  11694. else {
  11695. // query shortcuts
  11696. if(keyCode == keys.enter) {
  11697. module.verbose('Enter key pressed, executing query');
  11698. module.query();
  11699. module.set.buttonPressed();
  11700. $prompt.one('keyup', module.remove.buttonFocus);
  11701. }
  11702. }
  11703. },
  11704. setup: {
  11705. api: function() {
  11706. var
  11707. apiSettings = {
  11708. debug : settings.debug,
  11709. on : false,
  11710. cache : 'local',
  11711. action : 'search',
  11712. onError : module.error
  11713. },
  11714. searchHTML
  11715. ;
  11716. module.verbose('First request, initializing API');
  11717. $module.api(apiSettings);
  11718. }
  11719. },
  11720. can: {
  11721. useAPI: function() {
  11722. return $.fn.api !== undefined;
  11723. },
  11724. show: function() {
  11725. return module.is.focused() && !module.is.visible() && !module.is.empty();
  11726. },
  11727. transition: function() {
  11728. return settings.transition && $.fn.transition !== undefined && $module.transition('is supported');
  11729. }
  11730. },
  11731. is: {
  11732. empty: function() {
  11733. return ($results.html() === '');
  11734. },
  11735. visible: function() {
  11736. return ($results.filter(':visible').length > 0);
  11737. },
  11738. focused: function() {
  11739. return ($prompt.filter(':focus').length > 0);
  11740. }
  11741. },
  11742. trigger: {
  11743. blur: function() {
  11744. var
  11745. events = document.createEvent('HTMLEvents'),
  11746. promptElement = $prompt[0]
  11747. ;
  11748. if(promptElement) {
  11749. module.verbose('Triggering native blur event');
  11750. events.initEvent('blur', false, false);
  11751. promptElement.dispatchEvent(events);
  11752. }
  11753. }
  11754. },
  11755. get: {
  11756. inputEvent: function() {
  11757. var
  11758. prompt = $prompt[0],
  11759. inputEvent = (prompt !== undefined && prompt.oninput !== undefined)
  11760. ? 'input'
  11761. : (prompt !== undefined && prompt.onpropertychange !== undefined)
  11762. ? 'propertychange'
  11763. : 'keyup'
  11764. ;
  11765. return inputEvent;
  11766. },
  11767. value: function() {
  11768. return $prompt.val();
  11769. },
  11770. results: function() {
  11771. var
  11772. results = $module.data(metadata.results)
  11773. ;
  11774. return results;
  11775. },
  11776. result: function(value, results) {
  11777. var
  11778. lookupFields = ['title', 'id'],
  11779. result = false
  11780. ;
  11781. value = (value !== undefined)
  11782. ? value
  11783. : module.get.value()
  11784. ;
  11785. results = (results !== undefined)
  11786. ? results
  11787. : module.get.results()
  11788. ;
  11789. if(settings.type === 'category') {
  11790. module.debug('Finding result that matches', value);
  11791. $.each(results, function(index, category) {
  11792. if($.isArray(category.results)) {
  11793. result = module.search.object(value, category.results, lookupFields)[0];
  11794. // don't continue searching if a result is found
  11795. if(result) {
  11796. return false;
  11797. }
  11798. }
  11799. });
  11800. }
  11801. else {
  11802. module.debug('Finding result in results object', value);
  11803. result = module.search.object(value, results, lookupFields)[0];
  11804. }
  11805. return result || false;
  11806. },
  11807. },
  11808. set: {
  11809. focus: function() {
  11810. $module.addClass(className.focus);
  11811. },
  11812. loading: function() {
  11813. $module.addClass(className.loading);
  11814. },
  11815. value: function(value) {
  11816. module.verbose('Setting search input value', value);
  11817. $prompt
  11818. .val(value)
  11819. ;
  11820. },
  11821. type: function(type) {
  11822. type = type || settings.type;
  11823. if(settings.type == 'category') {
  11824. $module.addClass(settings.type);
  11825. }
  11826. },
  11827. buttonPressed: function() {
  11828. $searchButton.addClass(className.pressed);
  11829. }
  11830. },
  11831. remove: {
  11832. loading: function() {
  11833. $module.removeClass(className.loading);
  11834. },
  11835. focus: function() {
  11836. $module.removeClass(className.focus);
  11837. },
  11838. buttonPressed: function() {
  11839. $searchButton.removeClass(className.pressed);
  11840. }
  11841. },
  11842. query: function() {
  11843. var
  11844. searchTerm = module.get.value(),
  11845. cache = module.read.cache(searchTerm)
  11846. ;
  11847. if( module.has.minimumCharacters() ) {
  11848. if(cache) {
  11849. module.debug('Reading result from cache', searchTerm);
  11850. module.save.results(cache.results);
  11851. module.addResults(cache.html);
  11852. module.inject.id(cache.results);
  11853. }
  11854. else {
  11855. module.debug('Querying for', searchTerm);
  11856. if($.isPlainObject(settings.source) || $.isArray(settings.source)) {
  11857. module.search.local(searchTerm);
  11858. }
  11859. else if( module.can.useAPI() ) {
  11860. module.search.remote(searchTerm);
  11861. }
  11862. else {
  11863. module.error(error.source);
  11864. }
  11865. }
  11866. settings.onSearchQuery.call(element, searchTerm);
  11867. }
  11868. else {
  11869. module.hideResults();
  11870. }
  11871. },
  11872. search: {
  11873. local: function(searchTerm) {
  11874. var
  11875. results = module.search.object(searchTerm, settings.content),
  11876. searchHTML
  11877. ;
  11878. module.set.loading();
  11879. module.save.results(results);
  11880. module.debug('Returned local search results', results);
  11881. searchHTML = module.generateResults({
  11882. results: results
  11883. });
  11884. module.remove.loading();
  11885. module.addResults(searchHTML);
  11886. module.inject.id(results);
  11887. module.write.cache(searchTerm, {
  11888. html : searchHTML,
  11889. results : results
  11890. });
  11891. },
  11892. remote: function(searchTerm) {
  11893. var
  11894. apiSettings = {
  11895. onSuccess : function(response) {
  11896. module.parse.response.call(element, response, searchTerm);
  11897. },
  11898. onFailure: function() {
  11899. module.displayMessage(error.serverError);
  11900. },
  11901. urlData: {
  11902. query: searchTerm
  11903. }
  11904. }
  11905. ;
  11906. if( !$module.api('get request') ) {
  11907. module.setup.api();
  11908. }
  11909. $.extend(true, apiSettings, settings.apiSettings);
  11910. module.debug('Executing search', apiSettings);
  11911. module.cancel.query();
  11912. $module
  11913. .api('setting', apiSettings)
  11914. .api('query')
  11915. ;
  11916. },
  11917. object: function(searchTerm, source, searchFields) {
  11918. var
  11919. results = [],
  11920. fuzzyResults = [],
  11921. searchExp = searchTerm.toString().replace(regExp.escape, '\\$&'),
  11922. matchRegExp = new RegExp(regExp.beginsWith + searchExp, 'i'),
  11923. // avoid duplicates when pushing results
  11924. addResult = function(array, result) {
  11925. var
  11926. notResult = ($.inArray(result, results) == -1),
  11927. notFuzzyResult = ($.inArray(result, fuzzyResults) == -1)
  11928. ;
  11929. if(notResult && notFuzzyResult) {
  11930. array.push(result);
  11931. }
  11932. }
  11933. ;
  11934. source = source || settings.source;
  11935. searchFields = (searchFields !== undefined)
  11936. ? searchFields
  11937. : settings.searchFields
  11938. ;
  11939. // search fields should be array to loop correctly
  11940. if(!$.isArray(searchFields)) {
  11941. searchFields = [searchFields];
  11942. }
  11943. // exit conditions if no source
  11944. if(source === undefined || source === false) {
  11945. module.error(error.source);
  11946. return [];
  11947. }
  11948. // iterate through search fields looking for matches
  11949. $.each(searchFields, function(index, field) {
  11950. $.each(source, function(label, content) {
  11951. var
  11952. fieldExists = (typeof content[field] == 'string')
  11953. ;
  11954. if(fieldExists) {
  11955. if( content[field].search(matchRegExp) !== -1) {
  11956. // content starts with value (first in results)
  11957. addResult(results, content);
  11958. }
  11959. else if(settings.searchFullText && module.fuzzySearch(searchTerm, content[field]) ) {
  11960. // content fuzzy matches (last in results)
  11961. addResult(fuzzyResults, content);
  11962. }
  11963. }
  11964. });
  11965. });
  11966. return $.merge(results, fuzzyResults);
  11967. }
  11968. },
  11969. fuzzySearch: function(query, term) {
  11970. var
  11971. termLength = term.length,
  11972. queryLength = query.length
  11973. ;
  11974. if(typeof query !== 'string') {
  11975. return false;
  11976. }
  11977. query = query.toLowerCase();
  11978. term = term.toLowerCase();
  11979. if(queryLength > termLength) {
  11980. return false;
  11981. }
  11982. if(queryLength === termLength) {
  11983. return (query === term);
  11984. }
  11985. search: for (var characterIndex = 0, nextCharacterIndex = 0; characterIndex < queryLength; characterIndex++) {
  11986. var
  11987. queryCharacter = query.charCodeAt(characterIndex)
  11988. ;
  11989. while(nextCharacterIndex < termLength) {
  11990. if(term.charCodeAt(nextCharacterIndex++) === queryCharacter) {
  11991. continue search;
  11992. }
  11993. }
  11994. return false;
  11995. }
  11996. return true;
  11997. },
  11998. parse: {
  11999. response: function(response, searchTerm) {
  12000. var
  12001. searchHTML = module.generateResults(response)
  12002. ;
  12003. module.verbose('Parsing server response', response);
  12004. if(response !== undefined) {
  12005. if(searchTerm !== undefined && response[fields.results] !== undefined) {
  12006. module.addResults(searchHTML);
  12007. module.inject.id(response[fields.results]);
  12008. module.write.cache(searchTerm, {
  12009. html : searchHTML,
  12010. results : response[fields.results]
  12011. });
  12012. module.save.results(response[fields.results]);
  12013. }
  12014. }
  12015. }
  12016. },
  12017. cancel: {
  12018. query: function() {
  12019. if( module.can.useAPI() ) {
  12020. $module.api('abort');
  12021. }
  12022. }
  12023. },
  12024. has: {
  12025. minimumCharacters: function() {
  12026. var
  12027. searchTerm = module.get.value(),
  12028. numCharacters = searchTerm.length
  12029. ;
  12030. return (numCharacters >= settings.minCharacters);
  12031. }
  12032. },
  12033. clear: {
  12034. cache: function(value) {
  12035. var
  12036. cache = $module.data(metadata.cache)
  12037. ;
  12038. if(!value) {
  12039. module.debug('Clearing cache', value);
  12040. $module.removeData(metadata.cache);
  12041. }
  12042. else if(value && cache && cache[value]) {
  12043. module.debug('Removing value from cache', value);
  12044. delete cache[value];
  12045. $module.data(metadata.cache, cache);
  12046. }
  12047. }
  12048. },
  12049. read: {
  12050. cache: function(name) {
  12051. var
  12052. cache = $module.data(metadata.cache)
  12053. ;
  12054. if(settings.cache) {
  12055. module.verbose('Checking cache for generated html for query', name);
  12056. return (typeof cache == 'object') && (cache[name] !== undefined)
  12057. ? cache[name]
  12058. : false
  12059. ;
  12060. }
  12061. return false;
  12062. }
  12063. },
  12064. create: {
  12065. id: function(resultIndex, categoryIndex) {
  12066. var
  12067. resultID = (resultIndex + 1), // not zero indexed
  12068. categoryID = (categoryIndex + 1),
  12069. firstCharCode,
  12070. letterID,
  12071. id
  12072. ;
  12073. if(categoryIndex !== undefined) {
  12074. // start char code for "A"
  12075. letterID = String.fromCharCode(97 + categoryIndex);
  12076. id = letterID + resultID;
  12077. module.verbose('Creating category result id', id);
  12078. }
  12079. else {
  12080. id = resultID;
  12081. module.verbose('Creating result id', id);
  12082. }
  12083. return id;
  12084. },
  12085. results: function() {
  12086. if($results.length === 0) {
  12087. $results = $('<div />')
  12088. .addClass(className.results)
  12089. .appendTo($module)
  12090. ;
  12091. }
  12092. }
  12093. },
  12094. inject: {
  12095. result: function(result, resultIndex, categoryIndex) {
  12096. module.verbose('Injecting result into results');
  12097. var
  12098. $selectedResult = (categoryIndex !== undefined)
  12099. ? $results
  12100. .children().eq(categoryIndex)
  12101. .children(selector.result).eq(resultIndex)
  12102. : $results
  12103. .children(selector.result).eq(resultIndex)
  12104. ;
  12105. module.verbose('Injecting results metadata', $selectedResult);
  12106. $selectedResult
  12107. .data(metadata.result, result)
  12108. ;
  12109. },
  12110. id: function(results) {
  12111. module.debug('Injecting unique ids into results');
  12112. var
  12113. // since results may be object, we must use counters
  12114. categoryIndex = 0,
  12115. resultIndex = 0
  12116. ;
  12117. if(settings.type === 'category') {
  12118. // iterate through each category result
  12119. $.each(results, function(index, category) {
  12120. resultIndex = 0;
  12121. $.each(category.results, function(index, value) {
  12122. var
  12123. result = category.results[index]
  12124. ;
  12125. if(result.id === undefined) {
  12126. result.id = module.create.id(resultIndex, categoryIndex);
  12127. }
  12128. module.inject.result(result, resultIndex, categoryIndex);
  12129. resultIndex++;
  12130. });
  12131. categoryIndex++;
  12132. });
  12133. }
  12134. else {
  12135. // top level
  12136. $.each(results, function(index, value) {
  12137. var
  12138. result = results[index]
  12139. ;
  12140. if(result.id === undefined) {
  12141. result.id = module.create.id(resultIndex);
  12142. }
  12143. module.inject.result(result, resultIndex);
  12144. resultIndex++;
  12145. });
  12146. }
  12147. return results;
  12148. }
  12149. },
  12150. save: {
  12151. results: function(results) {
  12152. module.verbose('Saving current search results to metadata', results);
  12153. $module.data(metadata.results, results);
  12154. }
  12155. },
  12156. write: {
  12157. cache: function(name, value) {
  12158. var
  12159. cache = ($module.data(metadata.cache) !== undefined)
  12160. ? $module.data(metadata.cache)
  12161. : {}
  12162. ;
  12163. if(settings.cache) {
  12164. module.verbose('Writing generated html to cache', name, value);
  12165. cache[name] = value;
  12166. $module
  12167. .data(metadata.cache, cache)
  12168. ;
  12169. }
  12170. }
  12171. },
  12172. addResults: function(html) {
  12173. if( $.isFunction(settings.onResultsAdd) ) {
  12174. if( settings.onResultsAdd.call($results, html) === false ) {
  12175. module.debug('onResultsAdd callback cancelled default action');
  12176. return false;
  12177. }
  12178. }
  12179. $results
  12180. .html(html)
  12181. ;
  12182. if( module.can.show() ) {
  12183. module.showResults();
  12184. }
  12185. },
  12186. showResults: function() {
  12187. if(!module.is.visible()) {
  12188. if( module.can.transition() ) {
  12189. module.debug('Showing results with css animations');
  12190. $results
  12191. .transition({
  12192. animation : settings.transition + ' in',
  12193. debug : settings.debug,
  12194. verbose : settings.verbose,
  12195. duration : settings.duration,
  12196. queue : true
  12197. })
  12198. ;
  12199. }
  12200. else {
  12201. module.debug('Showing results with javascript');
  12202. $results
  12203. .stop()
  12204. .fadeIn(settings.duration, settings.easing)
  12205. ;
  12206. }
  12207. settings.onResultsOpen.call($results);
  12208. }
  12209. },
  12210. hideResults: function() {
  12211. if( module.is.visible() ) {
  12212. if( module.can.transition() ) {
  12213. module.debug('Hiding results with css animations');
  12214. $results
  12215. .transition({
  12216. animation : settings.transition + ' out',
  12217. debug : settings.debug,
  12218. verbose : settings.verbose,
  12219. duration : settings.duration,
  12220. queue : true
  12221. })
  12222. ;
  12223. }
  12224. else {
  12225. module.debug('Hiding results with javascript');
  12226. $results
  12227. .stop()
  12228. .fadeOut(settings.duration, settings.easing)
  12229. ;
  12230. }
  12231. settings.onResultsClose.call($results);
  12232. }
  12233. },
  12234. generateResults: function(response) {
  12235. module.debug('Generating html from response', response);
  12236. var
  12237. template = settings.templates[settings.type],
  12238. isProperObject = ($.isPlainObject(response[fields.results]) && !$.isEmptyObject(response[fields.results])),
  12239. isProperArray = ($.isArray(response[fields.results]) && response[fields.results].length > 0),
  12240. html = ''
  12241. ;
  12242. if(isProperObject || isProperArray ) {
  12243. if(settings.maxResults > 0) {
  12244. if(isProperObject) {
  12245. if(settings.type == 'standard') {
  12246. module.error(error.maxResults);
  12247. }
  12248. }
  12249. else {
  12250. response[fields.results] = response[fields.results].slice(0, settings.maxResults);
  12251. }
  12252. }
  12253. if($.isFunction(template)) {
  12254. html = template(response, fields);
  12255. }
  12256. else {
  12257. module.error(error.noTemplate, false);
  12258. }
  12259. }
  12260. else {
  12261. html = module.displayMessage(error.noResults, 'empty');
  12262. }
  12263. settings.onResults.call(element, response);
  12264. return html;
  12265. },
  12266. displayMessage: function(text, type) {
  12267. type = type || 'standard';
  12268. module.debug('Displaying message', text, type);
  12269. module.addResults( settings.templates.message(text, type) );
  12270. return settings.templates.message(text, type);
  12271. },
  12272. setting: function(name, value) {
  12273. if( $.isPlainObject(name) ) {
  12274. $.extend(true, settings, name);
  12275. }
  12276. else if(value !== undefined) {
  12277. settings[name] = value;
  12278. }
  12279. else {
  12280. return settings[name];
  12281. }
  12282. },
  12283. internal: function(name, value) {
  12284. if( $.isPlainObject(name) ) {
  12285. $.extend(true, module, name);
  12286. }
  12287. else if(value !== undefined) {
  12288. module[name] = value;
  12289. }
  12290. else {
  12291. return module[name];
  12292. }
  12293. },
  12294. debug: function() {
  12295. if(settings.debug) {
  12296. if(settings.performance) {
  12297. module.performance.log(arguments);
  12298. }
  12299. else {
  12300. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12301. module.debug.apply(console, arguments);
  12302. }
  12303. }
  12304. },
  12305. verbose: function() {
  12306. if(settings.verbose && settings.debug) {
  12307. if(settings.performance) {
  12308. module.performance.log(arguments);
  12309. }
  12310. else {
  12311. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  12312. module.verbose.apply(console, arguments);
  12313. }
  12314. }
  12315. },
  12316. error: function() {
  12317. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  12318. module.error.apply(console, arguments);
  12319. },
  12320. performance: {
  12321. log: function(message) {
  12322. var
  12323. currentTime,
  12324. executionTime,
  12325. previousTime
  12326. ;
  12327. if(settings.performance) {
  12328. currentTime = new Date().getTime();
  12329. previousTime = time || currentTime;
  12330. executionTime = currentTime - previousTime;
  12331. time = currentTime;
  12332. performance.push({
  12333. 'Name' : message[0],
  12334. 'Arguments' : [].slice.call(message, 1) || '',
  12335. 'Element' : element,
  12336. 'Execution Time' : executionTime
  12337. });
  12338. }
  12339. clearTimeout(module.performance.timer);
  12340. module.performance.timer = setTimeout(module.performance.display, 500);
  12341. },
  12342. display: function() {
  12343. var
  12344. title = settings.name + ':',
  12345. totalTime = 0
  12346. ;
  12347. time = false;
  12348. clearTimeout(module.performance.timer);
  12349. $.each(performance, function(index, data) {
  12350. totalTime += data['Execution Time'];
  12351. });
  12352. title += ' ' + totalTime + 'ms';
  12353. if(moduleSelector) {
  12354. title += ' \'' + moduleSelector + '\'';
  12355. }
  12356. if($allModules.length > 1) {
  12357. title += ' ' + '(' + $allModules.length + ')';
  12358. }
  12359. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  12360. console.groupCollapsed(title);
  12361. if(console.table) {
  12362. console.table(performance);
  12363. }
  12364. else {
  12365. $.each(performance, function(index, data) {
  12366. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  12367. });
  12368. }
  12369. console.groupEnd();
  12370. }
  12371. performance = [];
  12372. }
  12373. },
  12374. invoke: function(query, passedArguments, context) {
  12375. var
  12376. object = instance,
  12377. maxDepth,
  12378. found,
  12379. response
  12380. ;
  12381. passedArguments = passedArguments || queryArguments;
  12382. context = element || context;
  12383. if(typeof query == 'string' && object !== undefined) {
  12384. query = query.split(/[\. ]/);
  12385. maxDepth = query.length - 1;
  12386. $.each(query, function(depth, value) {
  12387. var camelCaseValue = (depth != maxDepth)
  12388. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  12389. : query
  12390. ;
  12391. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  12392. object = object[camelCaseValue];
  12393. }
  12394. else if( object[camelCaseValue] !== undefined ) {
  12395. found = object[camelCaseValue];
  12396. return false;
  12397. }
  12398. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  12399. object = object[value];
  12400. }
  12401. else if( object[value] !== undefined ) {
  12402. found = object[value];
  12403. return false;
  12404. }
  12405. else {
  12406. return false;
  12407. }
  12408. });
  12409. }
  12410. if( $.isFunction( found ) ) {
  12411. response = found.apply(context, passedArguments);
  12412. }
  12413. else if(found !== undefined) {
  12414. response = found;
  12415. }
  12416. if($.isArray(returnedValue)) {
  12417. returnedValue.push(response);
  12418. }
  12419. else if(returnedValue !== undefined) {
  12420. returnedValue = [returnedValue, response];
  12421. }
  12422. else if(response !== undefined) {
  12423. returnedValue = response;
  12424. }
  12425. return found;
  12426. }
  12427. };
  12428. if(methodInvoked) {
  12429. if(instance === undefined) {
  12430. module.initialize();
  12431. }
  12432. module.invoke(query);
  12433. }
  12434. else {
  12435. if(instance !== undefined) {
  12436. instance.invoke('destroy');
  12437. }
  12438. module.initialize();
  12439. }
  12440. })
  12441. ;
  12442. return (returnedValue !== undefined)
  12443. ? returnedValue
  12444. : this
  12445. ;
  12446. };
  12447. $.fn.search.settings = {
  12448. name : 'Search',
  12449. namespace : 'search',
  12450. debug : false,
  12451. verbose : false,
  12452. performance : true,
  12453. type : 'standard',
  12454. // template to use (specified in settings.templates)
  12455. minCharacters : 1,
  12456. // minimum characters required to search
  12457. apiSettings : false,
  12458. // API config
  12459. source : false,
  12460. // object to search
  12461. searchFields : [
  12462. 'title',
  12463. 'description'
  12464. ],
  12465. // fields to search
  12466. displayField : '',
  12467. // field to display in standard results template
  12468. searchFullText : true,
  12469. // whether to include fuzzy results in local search
  12470. automatic : true,
  12471. // whether to add events to prompt automatically
  12472. hideDelay : 0,
  12473. // delay before hiding menu after blur
  12474. searchDelay : 200,
  12475. // delay before searching
  12476. maxResults : 7,
  12477. // maximum results returned from local
  12478. cache : true,
  12479. // whether to store lookups in local cache
  12480. // transition settings
  12481. transition : 'scale',
  12482. duration : 200,
  12483. easing : 'easeOutExpo',
  12484. // callbacks
  12485. onSelect : false,
  12486. onResultsAdd : false,
  12487. onSearchQuery : function(query){},
  12488. onResults : function(response){},
  12489. onResultsOpen : function(){},
  12490. onResultsClose : function(){},
  12491. className: {
  12492. active : 'active',
  12493. empty : 'empty',
  12494. focus : 'focus',
  12495. loading : 'loading',
  12496. results : 'results',
  12497. pressed : 'down'
  12498. },
  12499. error : {
  12500. source : 'Cannot search. No source used, and Semantic API module was not included',
  12501. noResults : 'Your search returned no results',
  12502. logging : 'Error in debug logging, exiting.',
  12503. noEndpoint : 'No search endpoint was specified',
  12504. noTemplate : 'A valid template name was not specified.',
  12505. serverError : 'There was an issue querying the server.',
  12506. maxResults : 'Results must be an array to use maxResults setting',
  12507. method : 'The method you called is not defined.'
  12508. },
  12509. metadata: {
  12510. cache : 'cache',
  12511. results : 'results',
  12512. result : 'result'
  12513. },
  12514. regExp: {
  12515. escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  12516. beginsWith : '(?:\s|^)'
  12517. },
  12518. // maps api response attributes to internal representation
  12519. fields: {
  12520. categories : 'results', // array of categories (category view)
  12521. categoryName : 'name', // name of category (category view)
  12522. categoryResults : 'results', // array of results (category view)
  12523. description : 'description', // result description
  12524. image : 'image', // result image
  12525. price : 'price', // result price
  12526. results : 'results', // array of results (standard)
  12527. title : 'title', // result title
  12528. url : 'url', // result url
  12529. action : 'action', // "view more" object name
  12530. actionText : 'text', // "view more" text
  12531. actionURL : 'url' // "view more" url
  12532. },
  12533. selector : {
  12534. prompt : '.prompt',
  12535. searchButton : '.search.button',
  12536. results : '.results',
  12537. category : '.category',
  12538. result : '.result',
  12539. title : '.title, .name'
  12540. },
  12541. templates: {
  12542. escape: function(string) {
  12543. var
  12544. badChars = /[&<>"'`]/g,
  12545. shouldEscape = /[&<>"'`]/,
  12546. escape = {
  12547. "&": "&amp;",
  12548. "<": "&lt;",
  12549. ">": "&gt;",
  12550. '"': "&quot;",
  12551. "'": "&#x27;",
  12552. "`": "&#x60;"
  12553. },
  12554. escapedChar = function(chr) {
  12555. return escape[chr];
  12556. }
  12557. ;
  12558. if(shouldEscape.test(string)) {
  12559. return string.replace(badChars, escapedChar);
  12560. }
  12561. return string;
  12562. },
  12563. message: function(message, type) {
  12564. var
  12565. html = ''
  12566. ;
  12567. if(message !== undefined && type !== undefined) {
  12568. html += ''
  12569. + '<div class="message ' + type + '">'
  12570. ;
  12571. // message type
  12572. if(type == 'empty') {
  12573. html += ''
  12574. + '<div class="header">No Results</div class="header">'
  12575. + '<div class="description">' + message + '</div class="description">'
  12576. ;
  12577. }
  12578. else {
  12579. html += ' <div class="description">' + message + '</div>';
  12580. }
  12581. html += '</div>';
  12582. }
  12583. return html;
  12584. },
  12585. category: function(response, fields) {
  12586. var
  12587. html = '',
  12588. escape = $.fn.search.settings.templates.escape
  12589. ;
  12590. if(response[fields.categoryResults] !== undefined) {
  12591. // each category
  12592. $.each(response[fields.categoryResults], function(index, category) {
  12593. if(category[fields.results] !== undefined && category.results.length > 0) {
  12594. html += '<div class="category">';
  12595. if(category[fields.categoryName] !== undefined) {
  12596. html += '<div class="name">' + category[fields.categoryName] + '</div>';
  12597. }
  12598. // each item inside category
  12599. $.each(category.results, function(index, result) {
  12600. if(result[fields.url]) {
  12601. html += '<a class="result" href="' + result[fields.url] + '">';
  12602. }
  12603. else {
  12604. html += '<a class="result">';
  12605. }
  12606. if(result[fields.image] !== undefined) {
  12607. html += ''
  12608. + '<div class="image">'
  12609. + ' <img src="' + result[fields.image] + '">'
  12610. + '</div>'
  12611. ;
  12612. }
  12613. html += '<div class="content">';
  12614. if(result[fields.price] !== undefined) {
  12615. html += '<div class="price">' + result[fields.price] + '</div>';
  12616. }
  12617. if(result[fields.title] !== undefined) {
  12618. html += '<div class="title">' + result[fields.title] + '</div>';
  12619. }
  12620. if(result[fields.description] !== undefined) {
  12621. html += '<div class="description">' + result[fields.description] + '</div>';
  12622. }
  12623. html += ''
  12624. + '</div>'
  12625. ;
  12626. html += '</a>';
  12627. });
  12628. html += ''
  12629. + '</div>'
  12630. ;
  12631. }
  12632. });
  12633. if(response[fields.action]) {
  12634. html += ''
  12635. + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">'
  12636. + response[fields.action][fields.actionText]
  12637. + '</a>';
  12638. }
  12639. return html;
  12640. }
  12641. return false;
  12642. },
  12643. standard: function(response, fields) {
  12644. var
  12645. html = ''
  12646. ;
  12647. if(response[fields.results] !== undefined) {
  12648. // each result
  12649. $.each(response[fields.results], function(index, result) {
  12650. if(result[fields.url]) {
  12651. html += '<a class="result" href="' + result[fields.url] + '">';
  12652. }
  12653. else {
  12654. html += '<a class="result">';
  12655. }
  12656. if(result[fields.image] !== undefined) {
  12657. html += ''
  12658. + '<div class="image">'
  12659. + ' <img src="' + result[fields.image] + '">'
  12660. + '</div>'
  12661. ;
  12662. }
  12663. html += '<div class="content">';
  12664. if(result[fields.price] !== undefined) {
  12665. html += '<div class="price">' + result[fields.price] + '</div>';
  12666. }
  12667. if(result[fields.title] !== undefined) {
  12668. html += '<div class="title">' + result[fields.title] + '</div>';
  12669. }
  12670. if(result[fields.description] !== undefined) {
  12671. html += '<div class="description">' + result[fields.description] + '</div>';
  12672. }
  12673. html += ''
  12674. + '</div>'
  12675. ;
  12676. html += '</a>';
  12677. });
  12678. if(response[fields.action]) {
  12679. html += ''
  12680. + '<a href="' + response[fields.action][fields.actionURL] + '" class="action">'
  12681. + response[fields.action][fields.actionText]
  12682. + '</a>';
  12683. }
  12684. return html;
  12685. }
  12686. return false;
  12687. }
  12688. }
  12689. };
  12690. })( jQuery, window, document );
  12691. /*!
  12692. * # Semantic UI 2.1.6 - Shape
  12693. * http://github.com/semantic-org/semantic-ui/
  12694. *
  12695. *
  12696. * Copyright 2015 Contributors
  12697. * Released under the MIT license
  12698. * http://opensource.org/licenses/MIT
  12699. *
  12700. */
  12701. ;(function ( $, window, document, undefined ) {
  12702. "use strict";
  12703. $.fn.shape = function(parameters) {
  12704. var
  12705. $allModules = $(this),
  12706. $body = $('body'),
  12707. time = new Date().getTime(),
  12708. performance = [],
  12709. query = arguments[0],
  12710. methodInvoked = (typeof query == 'string'),
  12711. queryArguments = [].slice.call(arguments, 1),
  12712. requestAnimationFrame = window.requestAnimationFrame
  12713. || window.mozRequestAnimationFrame
  12714. || window.webkitRequestAnimationFrame
  12715. || window.msRequestAnimationFrame
  12716. || function(callback) { setTimeout(callback, 0); },
  12717. returnedValue
  12718. ;
  12719. $allModules
  12720. .each(function() {
  12721. var
  12722. moduleSelector = $allModules.selector || '',
  12723. settings = ( $.isPlainObject(parameters) )
  12724. ? $.extend(true, {}, $.fn.shape.settings, parameters)
  12725. : $.extend({}, $.fn.shape.settings),
  12726. // internal aliases
  12727. namespace = settings.namespace,
  12728. selector = settings.selector,
  12729. error = settings.error,
  12730. className = settings.className,
  12731. // define namespaces for modules
  12732. eventNamespace = '.' + namespace,
  12733. moduleNamespace = 'module-' + namespace,
  12734. // selector cache
  12735. $module = $(this),
  12736. $sides = $module.find(selector.sides),
  12737. $side = $module.find(selector.side),
  12738. // private variables
  12739. nextIndex = false,
  12740. $activeSide,
  12741. $nextSide,
  12742. // standard module
  12743. element = this,
  12744. instance = $module.data(moduleNamespace),
  12745. module
  12746. ;
  12747. module = {
  12748. initialize: function() {
  12749. module.verbose('Initializing module for', element);
  12750. module.set.defaultSide();
  12751. module.instantiate();
  12752. },
  12753. instantiate: function() {
  12754. module.verbose('Storing instance of module', module);
  12755. instance = module;
  12756. $module
  12757. .data(moduleNamespace, instance)
  12758. ;
  12759. },
  12760. destroy: function() {
  12761. module.verbose('Destroying previous module for', element);
  12762. $module
  12763. .removeData(moduleNamespace)
  12764. .off(eventNamespace)
  12765. ;
  12766. },
  12767. refresh: function() {
  12768. module.verbose('Refreshing selector cache for', element);
  12769. $module = $(element);
  12770. $sides = $(this).find(selector.shape);
  12771. $side = $(this).find(selector.side);
  12772. },
  12773. repaint: function() {
  12774. module.verbose('Forcing repaint event');
  12775. var
  12776. shape = $sides[0] || document.createElement('div'),
  12777. fakeAssignment = shape.offsetWidth
  12778. ;
  12779. },
  12780. animate: function(propertyObject, callback) {
  12781. module.verbose('Animating box with properties', propertyObject);
  12782. callback = callback || function(event) {
  12783. module.verbose('Executing animation callback');
  12784. if(event !== undefined) {
  12785. event.stopPropagation();
  12786. }
  12787. module.reset();
  12788. module.set.active();
  12789. };
  12790. settings.beforeChange.call($nextSide[0]);
  12791. if(module.get.transitionEvent()) {
  12792. module.verbose('Starting CSS animation');
  12793. $module
  12794. .addClass(className.animating)
  12795. ;
  12796. $sides
  12797. .css(propertyObject)
  12798. .one(module.get.transitionEvent(), callback)
  12799. ;
  12800. module.set.duration(settings.duration);
  12801. requestAnimationFrame(function() {
  12802. $module
  12803. .addClass(className.animating)
  12804. ;
  12805. $activeSide
  12806. .addClass(className.hidden)
  12807. ;
  12808. });
  12809. }
  12810. else {
  12811. callback();
  12812. }
  12813. },
  12814. queue: function(method) {
  12815. module.debug('Queueing animation of', method);
  12816. $sides
  12817. .one(module.get.transitionEvent(), function() {
  12818. module.debug('Executing queued animation');
  12819. setTimeout(function(){
  12820. $module.shape(method);
  12821. }, 0);
  12822. })
  12823. ;
  12824. },
  12825. reset: function() {
  12826. module.verbose('Animating states reset');
  12827. $module
  12828. .removeClass(className.animating)
  12829. .attr('style', '')
  12830. .removeAttr('style')
  12831. ;
  12832. // removeAttr style does not consistently work in safari
  12833. $sides
  12834. .attr('style', '')
  12835. .removeAttr('style')
  12836. ;
  12837. $side
  12838. .attr('style', '')
  12839. .removeAttr('style')
  12840. .removeClass(className.hidden)
  12841. ;
  12842. $nextSide
  12843. .removeClass(className.animating)
  12844. .attr('style', '')
  12845. .removeAttr('style')
  12846. ;
  12847. },
  12848. is: {
  12849. complete: function() {
  12850. return ($side.filter('.' + className.active)[0] == $nextSide[0]);
  12851. },
  12852. animating: function() {
  12853. return $module.hasClass(className.animating);
  12854. }
  12855. },
  12856. set: {
  12857. defaultSide: function() {
  12858. $activeSide = $module.find('.' + settings.className.active);
  12859. $nextSide = ( $activeSide.next(selector.side).length > 0 )
  12860. ? $activeSide.next(selector.side)
  12861. : $module.find(selector.side).first()
  12862. ;
  12863. nextIndex = false;
  12864. module.verbose('Active side set to', $activeSide);
  12865. module.verbose('Next side set to', $nextSide);
  12866. },
  12867. duration: function(duration) {
  12868. duration = duration || settings.duration;
  12869. duration = (typeof duration == 'number')
  12870. ? duration + 'ms'
  12871. : duration
  12872. ;
  12873. module.verbose('Setting animation duration', duration);
  12874. if(settings.duration || settings.duration === 0) {
  12875. $sides.add($side)
  12876. .css({
  12877. '-webkit-transition-duration': duration,
  12878. '-moz-transition-duration': duration,
  12879. '-ms-transition-duration': duration,
  12880. '-o-transition-duration': duration,
  12881. 'transition-duration': duration
  12882. })
  12883. ;
  12884. }
  12885. },
  12886. currentStageSize: function() {
  12887. var
  12888. $activeSide = $module.find('.' + settings.className.active),
  12889. width = $activeSide.outerWidth(true),
  12890. height = $activeSide.outerHeight(true)
  12891. ;
  12892. $module
  12893. .css({
  12894. width: width,
  12895. height: height
  12896. })
  12897. ;
  12898. },
  12899. stageSize: function() {
  12900. var
  12901. $clone = $module.clone().addClass(className.loading),
  12902. $activeSide = $clone.find('.' + settings.className.active),
  12903. $nextSide = (nextIndex)
  12904. ? $clone.find(selector.side).eq(nextIndex)
  12905. : ( $activeSide.next(selector.side).length > 0 )
  12906. ? $activeSide.next(selector.side)
  12907. : $clone.find(selector.side).first(),
  12908. newSize = {}
  12909. ;
  12910. module.set.currentStageSize();
  12911. $activeSide.removeClass(className.active);
  12912. $nextSide.addClass(className.active);
  12913. $clone.insertAfter($module);
  12914. newSize = {
  12915. width : $nextSide.outerWidth(true),
  12916. height : $nextSide.outerHeight(true)
  12917. };
  12918. $clone.remove();
  12919. $module
  12920. .css(newSize)
  12921. ;
  12922. module.verbose('Resizing stage to fit new content', newSize);
  12923. },
  12924. nextSide: function(selector) {
  12925. nextIndex = selector;
  12926. $nextSide = $side.filter(selector);
  12927. nextIndex = $side.index($nextSide);
  12928. if($nextSide.length === 0) {
  12929. module.set.defaultSide();
  12930. module.error(error.side);
  12931. }
  12932. module.verbose('Next side manually set to', $nextSide);
  12933. },
  12934. active: function() {
  12935. module.verbose('Setting new side to active', $nextSide);
  12936. $side
  12937. .removeClass(className.active)
  12938. ;
  12939. $nextSide
  12940. .addClass(className.active)
  12941. ;
  12942. settings.onChange.call($nextSide[0]);
  12943. module.set.defaultSide();
  12944. }
  12945. },
  12946. flip: {
  12947. up: function() {
  12948. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12949. module.debug('Side already visible', $nextSide);
  12950. return;
  12951. }
  12952. if( !module.is.animating()) {
  12953. module.debug('Flipping up', $nextSide);
  12954. module.set.stageSize();
  12955. module.stage.above();
  12956. module.animate( module.get.transform.up() );
  12957. }
  12958. else {
  12959. module.queue('flip up');
  12960. }
  12961. },
  12962. down: function() {
  12963. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12964. module.debug('Side already visible', $nextSide);
  12965. return;
  12966. }
  12967. if( !module.is.animating()) {
  12968. module.debug('Flipping down', $nextSide);
  12969. module.set.stageSize();
  12970. module.stage.below();
  12971. module.animate( module.get.transform.down() );
  12972. }
  12973. else {
  12974. module.queue('flip down');
  12975. }
  12976. },
  12977. left: function() {
  12978. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12979. module.debug('Side already visible', $nextSide);
  12980. return;
  12981. }
  12982. if( !module.is.animating()) {
  12983. module.debug('Flipping left', $nextSide);
  12984. module.set.stageSize();
  12985. module.stage.left();
  12986. module.animate(module.get.transform.left() );
  12987. }
  12988. else {
  12989. module.queue('flip left');
  12990. }
  12991. },
  12992. right: function() {
  12993. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  12994. module.debug('Side already visible', $nextSide);
  12995. return;
  12996. }
  12997. if( !module.is.animating()) {
  12998. module.debug('Flipping right', $nextSide);
  12999. module.set.stageSize();
  13000. module.stage.right();
  13001. module.animate(module.get.transform.right() );
  13002. }
  13003. else {
  13004. module.queue('flip right');
  13005. }
  13006. },
  13007. over: function() {
  13008. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  13009. module.debug('Side already visible', $nextSide);
  13010. return;
  13011. }
  13012. if( !module.is.animating()) {
  13013. module.debug('Flipping over', $nextSide);
  13014. module.set.stageSize();
  13015. module.stage.behind();
  13016. module.animate(module.get.transform.over() );
  13017. }
  13018. else {
  13019. module.queue('flip over');
  13020. }
  13021. },
  13022. back: function() {
  13023. if(module.is.complete() && !module.is.animating() && !settings.allowRepeats) {
  13024. module.debug('Side already visible', $nextSide);
  13025. return;
  13026. }
  13027. if( !module.is.animating()) {
  13028. module.debug('Flipping back', $nextSide);
  13029. module.set.stageSize();
  13030. module.stage.behind();
  13031. module.animate(module.get.transform.back() );
  13032. }
  13033. else {
  13034. module.queue('flip back');
  13035. }
  13036. }
  13037. },
  13038. get: {
  13039. transform: {
  13040. up: function() {
  13041. var
  13042. translate = {
  13043. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  13044. z: -($activeSide.outerHeight(true) / 2)
  13045. }
  13046. ;
  13047. return {
  13048. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)'
  13049. };
  13050. },
  13051. down: function() {
  13052. var
  13053. translate = {
  13054. y: -(($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  13055. z: -($activeSide.outerHeight(true) / 2)
  13056. }
  13057. ;
  13058. return {
  13059. transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)'
  13060. };
  13061. },
  13062. left: function() {
  13063. var
  13064. translate = {
  13065. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  13066. z : -($activeSide.outerWidth(true) / 2)
  13067. }
  13068. ;
  13069. return {
  13070. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)'
  13071. };
  13072. },
  13073. right: function() {
  13074. var
  13075. translate = {
  13076. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2),
  13077. z : -($activeSide.outerWidth(true) / 2)
  13078. }
  13079. ;
  13080. return {
  13081. transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)'
  13082. };
  13083. },
  13084. over: function() {
  13085. var
  13086. translate = {
  13087. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  13088. }
  13089. ;
  13090. return {
  13091. transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
  13092. };
  13093. },
  13094. back: function() {
  13095. var
  13096. translate = {
  13097. x : -(($activeSide.outerWidth(true) - $nextSide.outerWidth(true)) / 2)
  13098. }
  13099. ;
  13100. return {
  13101. transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)'
  13102. };
  13103. }
  13104. },
  13105. transitionEvent: function() {
  13106. var
  13107. element = document.createElement('element'),
  13108. transitions = {
  13109. 'transition' :'transitionend',
  13110. 'OTransition' :'oTransitionEnd',
  13111. 'MozTransition' :'transitionend',
  13112. 'WebkitTransition' :'webkitTransitionEnd'
  13113. },
  13114. transition
  13115. ;
  13116. for(transition in transitions){
  13117. if( element.style[transition] !== undefined ){
  13118. return transitions[transition];
  13119. }
  13120. }
  13121. },
  13122. nextSide: function() {
  13123. return ( $activeSide.next(selector.side).length > 0 )
  13124. ? $activeSide.next(selector.side)
  13125. : $module.find(selector.side).first()
  13126. ;
  13127. }
  13128. },
  13129. stage: {
  13130. above: function() {
  13131. var
  13132. box = {
  13133. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  13134. depth : {
  13135. active : ($nextSide.outerHeight(true) / 2),
  13136. next : ($activeSide.outerHeight(true) / 2)
  13137. }
  13138. }
  13139. ;
  13140. module.verbose('Setting the initial animation position as above', $nextSide, box);
  13141. $sides
  13142. .css({
  13143. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  13144. })
  13145. ;
  13146. $activeSide
  13147. .css({
  13148. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  13149. })
  13150. ;
  13151. $nextSide
  13152. .addClass(className.animating)
  13153. .css({
  13154. 'top' : box.origin + 'px',
  13155. 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)'
  13156. })
  13157. ;
  13158. },
  13159. below: function() {
  13160. var
  13161. box = {
  13162. origin : (($activeSide.outerHeight(true) - $nextSide.outerHeight(true)) / 2),
  13163. depth : {
  13164. active : ($nextSide.outerHeight(true) / 2),
  13165. next : ($activeSide.outerHeight(true) / 2)
  13166. }
  13167. }
  13168. ;
  13169. module.verbose('Setting the initial animation position as below', $nextSide, box);
  13170. $sides
  13171. .css({
  13172. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  13173. })
  13174. ;
  13175. $activeSide
  13176. .css({
  13177. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  13178. })
  13179. ;
  13180. $nextSide
  13181. .addClass(className.animating)
  13182. .css({
  13183. 'top' : box.origin + 'px',
  13184. 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)'
  13185. })
  13186. ;
  13187. },
  13188. left: function() {
  13189. var
  13190. height = {
  13191. active : $activeSide.outerWidth(true),
  13192. next : $nextSide.outerWidth(true)
  13193. },
  13194. box = {
  13195. origin : ( ( height.active - height.next ) / 2),
  13196. depth : {
  13197. active : (height.next / 2),
  13198. next : (height.active / 2)
  13199. }
  13200. }
  13201. ;
  13202. module.verbose('Setting the initial animation position as left', $nextSide, box);
  13203. $sides
  13204. .css({
  13205. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  13206. })
  13207. ;
  13208. $activeSide
  13209. .css({
  13210. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  13211. })
  13212. ;
  13213. $nextSide
  13214. .addClass(className.animating)
  13215. .css({
  13216. 'left' : box.origin + 'px',
  13217. 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)'
  13218. })
  13219. ;
  13220. },
  13221. right: function() {
  13222. var
  13223. height = {
  13224. active : $activeSide.outerWidth(true),
  13225. next : $nextSide.outerWidth(true)
  13226. },
  13227. box = {
  13228. origin : ( ( height.active - height.next ) / 2),
  13229. depth : {
  13230. active : (height.next / 2),
  13231. next : (height.active / 2)
  13232. }
  13233. }
  13234. ;
  13235. module.verbose('Setting the initial animation position as left', $nextSide, box);
  13236. $sides
  13237. .css({
  13238. 'transform' : 'translateZ(-' + box.depth.active + 'px)'
  13239. })
  13240. ;
  13241. $activeSide
  13242. .css({
  13243. 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
  13244. })
  13245. ;
  13246. $nextSide
  13247. .addClass(className.animating)
  13248. .css({
  13249. 'left' : box.origin + 'px',
  13250. 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)'
  13251. })
  13252. ;
  13253. },
  13254. behind: function() {
  13255. var
  13256. height = {
  13257. active : $activeSide.outerWidth(true),
  13258. next : $nextSide.outerWidth(true)
  13259. },
  13260. box = {
  13261. origin : ( ( height.active - height.next ) / 2),
  13262. depth : {
  13263. active : (height.next / 2),
  13264. next : (height.active / 2)
  13265. }
  13266. }
  13267. ;
  13268. module.verbose('Setting the initial animation position as behind', $nextSide, box);
  13269. $activeSide
  13270. .css({
  13271. 'transform' : 'rotateY(0deg)'
  13272. })
  13273. ;
  13274. $nextSide
  13275. .addClass(className.animating)
  13276. .css({
  13277. 'left' : box.origin + 'px',
  13278. 'transform' : 'rotateY(-180deg)'
  13279. })
  13280. ;
  13281. }
  13282. },
  13283. setting: function(name, value) {
  13284. module.debug('Changing setting', name, value);
  13285. if( $.isPlainObject(name) ) {
  13286. $.extend(true, settings, name);
  13287. }
  13288. else if(value !== undefined) {
  13289. settings[name] = value;
  13290. }
  13291. else {
  13292. return settings[name];
  13293. }
  13294. },
  13295. internal: function(name, value) {
  13296. if( $.isPlainObject(name) ) {
  13297. $.extend(true, module, name);
  13298. }
  13299. else if(value !== undefined) {
  13300. module[name] = value;
  13301. }
  13302. else {
  13303. return module[name];
  13304. }
  13305. },
  13306. debug: function() {
  13307. if(settings.debug) {
  13308. if(settings.performance) {
  13309. module.performance.log(arguments);
  13310. }
  13311. else {
  13312. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13313. module.debug.apply(console, arguments);
  13314. }
  13315. }
  13316. },
  13317. verbose: function() {
  13318. if(settings.verbose && settings.debug) {
  13319. if(settings.performance) {
  13320. module.performance.log(arguments);
  13321. }
  13322. else {
  13323. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  13324. module.verbose.apply(console, arguments);
  13325. }
  13326. }
  13327. },
  13328. error: function() {
  13329. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  13330. module.error.apply(console, arguments);
  13331. },
  13332. performance: {
  13333. log: function(message) {
  13334. var
  13335. currentTime,
  13336. executionTime,
  13337. previousTime
  13338. ;
  13339. if(settings.performance) {
  13340. currentTime = new Date().getTime();
  13341. previousTime = time || currentTime;
  13342. executionTime = currentTime - previousTime;
  13343. time = currentTime;
  13344. performance.push({
  13345. 'Name' : message[0],
  13346. 'Arguments' : [].slice.call(message, 1) || '',
  13347. 'Element' : element,
  13348. 'Execution Time' : executionTime
  13349. });
  13350. }
  13351. clearTimeout(module.performance.timer);
  13352. module.performance.timer = setTimeout(module.performance.display, 500);
  13353. },
  13354. display: function() {
  13355. var
  13356. title = settings.name + ':',
  13357. totalTime = 0
  13358. ;
  13359. time = false;
  13360. clearTimeout(module.performance.timer);
  13361. $.each(performance, function(index, data) {
  13362. totalTime += data['Execution Time'];
  13363. });
  13364. title += ' ' + totalTime + 'ms';
  13365. if(moduleSelector) {
  13366. title += ' \'' + moduleSelector + '\'';
  13367. }
  13368. if($allModules.length > 1) {
  13369. title += ' ' + '(' + $allModules.length + ')';
  13370. }
  13371. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  13372. console.groupCollapsed(title);
  13373. if(console.table) {
  13374. console.table(performance);
  13375. }
  13376. else {
  13377. $.each(performance, function(index, data) {
  13378. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  13379. });
  13380. }
  13381. console.groupEnd();
  13382. }
  13383. performance = [];
  13384. }
  13385. },
  13386. invoke: function(query, passedArguments, context) {
  13387. var
  13388. object = instance,
  13389. maxDepth,
  13390. found,
  13391. response
  13392. ;
  13393. passedArguments = passedArguments || queryArguments;
  13394. context = element || context;
  13395. if(typeof query == 'string' && object !== undefined) {
  13396. query = query.split(/[\. ]/);
  13397. maxDepth = query.length - 1;
  13398. $.each(query, function(depth, value) {
  13399. var camelCaseValue = (depth != maxDepth)
  13400. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  13401. : query
  13402. ;
  13403. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  13404. object = object[camelCaseValue];
  13405. }
  13406. else if( object[camelCaseValue] !== undefined ) {
  13407. found = object[camelCaseValue];
  13408. return false;
  13409. }
  13410. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  13411. object = object[value];
  13412. }
  13413. else if( object[value] !== undefined ) {
  13414. found = object[value];
  13415. return false;
  13416. }
  13417. else {
  13418. return false;
  13419. }
  13420. });
  13421. }
  13422. if ( $.isFunction( found ) ) {
  13423. response = found.apply(context, passedArguments);
  13424. }
  13425. else if(found !== undefined) {
  13426. response = found;
  13427. }
  13428. if($.isArray(returnedValue)) {
  13429. returnedValue.push(response);
  13430. }
  13431. else if(returnedValue !== undefined) {
  13432. returnedValue = [returnedValue, response];
  13433. }
  13434. else if(response !== undefined) {
  13435. returnedValue = response;
  13436. }
  13437. return found;
  13438. }
  13439. };
  13440. if(methodInvoked) {
  13441. if(instance === undefined) {
  13442. module.initialize();
  13443. }
  13444. module.invoke(query);
  13445. }
  13446. else {
  13447. if(instance !== undefined) {
  13448. instance.invoke('destroy');
  13449. }
  13450. module.initialize();
  13451. }
  13452. })
  13453. ;
  13454. return (returnedValue !== undefined)
  13455. ? returnedValue
  13456. : this
  13457. ;
  13458. };
  13459. $.fn.shape.settings = {
  13460. // module info
  13461. name : 'Shape',
  13462. // debug content outputted to console
  13463. debug : false,
  13464. // verbose debug output
  13465. verbose : false,
  13466. // performance data output
  13467. performance: true,
  13468. // event namespace
  13469. namespace : 'shape',
  13470. // callback occurs on side change
  13471. beforeChange : function() {},
  13472. onChange : function() {},
  13473. // allow animation to same side
  13474. allowRepeats: false,
  13475. // animation duration
  13476. duration : false,
  13477. // possible errors
  13478. error: {
  13479. side : 'You tried to switch to a side that does not exist.',
  13480. method : 'The method you called is not defined'
  13481. },
  13482. // classnames used
  13483. className : {
  13484. animating : 'animating',
  13485. hidden : 'hidden',
  13486. loading : 'loading',
  13487. active : 'active'
  13488. },
  13489. // selectors used
  13490. selector : {
  13491. sides : '.sides',
  13492. side : '.side'
  13493. }
  13494. };
  13495. })( jQuery, window, document );
  13496. /*!
  13497. * # Semantic UI 2.1.6 - Sidebar
  13498. * http://github.com/semantic-org/semantic-ui/
  13499. *
  13500. *
  13501. * Copyright 2015 Contributors
  13502. * Released under the MIT license
  13503. * http://opensource.org/licenses/MIT
  13504. *
  13505. */
  13506. ;(function ( $, window, document, undefined ) {
  13507. "use strict";
  13508. $.fn.sidebar = function(parameters) {
  13509. var
  13510. $allModules = $(this),
  13511. $window = $(window),
  13512. $document = $(document),
  13513. $html = $('html'),
  13514. $head = $('head'),
  13515. moduleSelector = $allModules.selector || '',
  13516. time = new Date().getTime(),
  13517. performance = [],
  13518. query = arguments[0],
  13519. methodInvoked = (typeof query == 'string'),
  13520. queryArguments = [].slice.call(arguments, 1),
  13521. requestAnimationFrame = window.requestAnimationFrame
  13522. || window.mozRequestAnimationFrame
  13523. || window.webkitRequestAnimationFrame
  13524. || window.msRequestAnimationFrame
  13525. || function(callback) { setTimeout(callback, 0); },
  13526. returnedValue
  13527. ;
  13528. $allModules
  13529. .each(function() {
  13530. var
  13531. settings = ( $.isPlainObject(parameters) )
  13532. ? $.extend(true, {}, $.fn.sidebar.settings, parameters)
  13533. : $.extend({}, $.fn.sidebar.settings),
  13534. selector = settings.selector,
  13535. className = settings.className,
  13536. namespace = settings.namespace,
  13537. regExp = settings.regExp,
  13538. error = settings.error,
  13539. eventNamespace = '.' + namespace,
  13540. moduleNamespace = 'module-' + namespace,
  13541. $module = $(this),
  13542. $context = $(settings.context),
  13543. $sidebars = $module.children(selector.sidebar),
  13544. $fixed = $context.children(selector.fixed),
  13545. $pusher = $context.children(selector.pusher),
  13546. $style,
  13547. element = this,
  13548. instance = $module.data(moduleNamespace),
  13549. elementNamespace,
  13550. id,
  13551. currentScroll,
  13552. transitionEvent,
  13553. module
  13554. ;
  13555. module = {
  13556. initialize: function() {
  13557. module.debug('Initializing sidebar', parameters);
  13558. module.create.id();
  13559. transitionEvent = module.get.transitionEvent();
  13560. if(module.is.ios()) {
  13561. module.set.ios();
  13562. }
  13563. // avoids locking rendering if initialized in onReady
  13564. if(settings.delaySetup) {
  13565. requestAnimationFrame(module.setup.layout);
  13566. }
  13567. else {
  13568. module.setup.layout();
  13569. }
  13570. requestAnimationFrame(function() {
  13571. module.setup.cache();
  13572. });
  13573. module.instantiate();
  13574. },
  13575. instantiate: function() {
  13576. module.verbose('Storing instance of module', module);
  13577. instance = module;
  13578. $module
  13579. .data(moduleNamespace, module)
  13580. ;
  13581. },
  13582. create: {
  13583. id: function() {
  13584. id = (Math.random().toString(16) + '000000000').substr(2,8);
  13585. elementNamespace = '.' + id;
  13586. module.verbose('Creating unique id for element', id);
  13587. }
  13588. },
  13589. destroy: function() {
  13590. module.verbose('Destroying previous module for', $module);
  13591. $module
  13592. .off(eventNamespace)
  13593. .removeData(moduleNamespace)
  13594. ;
  13595. if(module.is.ios()) {
  13596. module.remove.ios();
  13597. }
  13598. // bound by uuid
  13599. $context.off(elementNamespace);
  13600. $window.off(elementNamespace);
  13601. $document.off(elementNamespace);
  13602. },
  13603. event: {
  13604. clickaway: function(event) {
  13605. var
  13606. clickedInPusher = ($pusher.find(event.target).length > 0 || $pusher.is(event.target)),
  13607. clickedContext = ($context.is(event.target))
  13608. ;
  13609. if(clickedInPusher) {
  13610. module.verbose('User clicked on dimmed page');
  13611. module.hide();
  13612. }
  13613. if(clickedContext) {
  13614. module.verbose('User clicked on dimmable context (scaled out page)');
  13615. module.hide();
  13616. }
  13617. },
  13618. touch: function(event) {
  13619. //event.stopPropagation();
  13620. },
  13621. containScroll: function(event) {
  13622. if(element.scrollTop <= 0) {
  13623. element.scrollTop = 1;
  13624. }
  13625. if((element.scrollTop + element.offsetHeight) >= element.scrollHeight) {
  13626. element.scrollTop = element.scrollHeight - element.offsetHeight - 1;
  13627. }
  13628. },
  13629. scroll: function(event) {
  13630. if( $(event.target).closest(selector.sidebar).length === 0 ) {
  13631. event.preventDefault();
  13632. }
  13633. }
  13634. },
  13635. bind: {
  13636. clickaway: function() {
  13637. module.verbose('Adding clickaway events to context', $context);
  13638. if(settings.closable) {
  13639. $context
  13640. .on('click' + elementNamespace, module.event.clickaway)
  13641. .on('touchend' + elementNamespace, module.event.clickaway)
  13642. ;
  13643. }
  13644. },
  13645. scrollLock: function() {
  13646. if(settings.scrollLock) {
  13647. module.debug('Disabling page scroll');
  13648. $window
  13649. .on('DOMMouseScroll' + elementNamespace, module.event.scroll)
  13650. ;
  13651. }
  13652. module.verbose('Adding events to contain sidebar scroll');
  13653. $document
  13654. .on('touchmove' + elementNamespace, module.event.touch)
  13655. ;
  13656. $module
  13657. .on('scroll' + eventNamespace, module.event.containScroll)
  13658. ;
  13659. }
  13660. },
  13661. unbind: {
  13662. clickaway: function() {
  13663. module.verbose('Removing clickaway events from context', $context);
  13664. $context.off(elementNamespace);
  13665. },
  13666. scrollLock: function() {
  13667. module.verbose('Removing scroll lock from page');
  13668. $document.off(elementNamespace);
  13669. $window.off(elementNamespace);
  13670. $module.off('scroll' + eventNamespace);
  13671. }
  13672. },
  13673. add: {
  13674. inlineCSS: function() {
  13675. var
  13676. width = module.cache.width || $module.outerWidth(),
  13677. height = module.cache.height || $module.outerHeight(),
  13678. isRTL = module.is.rtl(),
  13679. direction = module.get.direction(),
  13680. distance = {
  13681. left : width,
  13682. right : -width,
  13683. top : height,
  13684. bottom : -height
  13685. },
  13686. style
  13687. ;
  13688. if(isRTL){
  13689. module.verbose('RTL detected, flipping widths');
  13690. distance.left = -width;
  13691. distance.right = width;
  13692. }
  13693. style = '<style>';
  13694. if(direction === 'left' || direction === 'right') {
  13695. module.debug('Adding CSS rules for animation distance', width);
  13696. style += ''
  13697. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  13698. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  13699. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  13700. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  13701. + ' }'
  13702. ;
  13703. }
  13704. else if(direction === 'top' || direction == 'bottom') {
  13705. style += ''
  13706. + ' .ui.visible.' + direction + '.sidebar ~ .fixed,'
  13707. + ' .ui.visible.' + direction + '.sidebar ~ .pusher {'
  13708. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  13709. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  13710. + ' }'
  13711. ;
  13712. }
  13713. /* IE is only browser not to create context with transforms */
  13714. /* https://www.w3.org/Bugs/Public/show_bug.cgi?id=16328 */
  13715. if( module.is.ie() ) {
  13716. if(direction === 'left' || direction === 'right') {
  13717. module.debug('Adding CSS rules for animation distance', width);
  13718. style += ''
  13719. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  13720. + ' -webkit-transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  13721. + ' transform: translate3d('+ distance[direction] + 'px, 0, 0);'
  13722. + ' }'
  13723. ;
  13724. }
  13725. else if(direction === 'top' || direction == 'bottom') {
  13726. style += ''
  13727. + ' body.pushable > .ui.visible.' + direction + '.sidebar ~ .pusher:after {'
  13728. + ' -webkit-transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  13729. + ' transform: translate3d(0, ' + distance[direction] + 'px, 0);'
  13730. + ' }'
  13731. ;
  13732. }
  13733. /* opposite sides visible forces content overlay */
  13734. style += ''
  13735. + ' body.pushable > .ui.visible.left.sidebar ~ .ui.visible.right.sidebar ~ .pusher:after,'
  13736. + ' body.pushable > .ui.visible.right.sidebar ~ .ui.visible.left.sidebar ~ .pusher:after {'
  13737. + ' -webkit-transform: translate3d(0px, 0, 0);'
  13738. + ' transform: translate3d(0px, 0, 0);'
  13739. + ' }'
  13740. ;
  13741. }
  13742. style += '</style>';
  13743. $style = $(style)
  13744. .appendTo($head)
  13745. ;
  13746. module.debug('Adding sizing css to head', $style);
  13747. }
  13748. },
  13749. refresh: function() {
  13750. module.verbose('Refreshing selector cache');
  13751. $context = $(settings.context);
  13752. $sidebars = $context.children(selector.sidebar);
  13753. $pusher = $context.children(selector.pusher);
  13754. $fixed = $context.children(selector.fixed);
  13755. module.clear.cache();
  13756. },
  13757. refreshSidebars: function() {
  13758. module.verbose('Refreshing other sidebars');
  13759. $sidebars = $context.children(selector.sidebar);
  13760. },
  13761. repaint: function() {
  13762. module.verbose('Forcing repaint event');
  13763. element.style.display = 'none';
  13764. var ignored = element.offsetHeight;
  13765. element.scrollTop = element.scrollTop;
  13766. element.style.display = '';
  13767. },
  13768. setup: {
  13769. cache: function() {
  13770. module.cache = {
  13771. width : $module.outerWidth(),
  13772. height : $module.outerHeight(),
  13773. rtl : ($module.css('direction') == 'rtl')
  13774. };
  13775. },
  13776. layout: function() {
  13777. if( $context.children(selector.pusher).length === 0 ) {
  13778. module.debug('Adding wrapper element for sidebar');
  13779. module.error(error.pusher);
  13780. $pusher = $('<div class="pusher" />');
  13781. $context
  13782. .children()
  13783. .not(selector.omitted)
  13784. .not($sidebars)
  13785. .wrapAll($pusher)
  13786. ;
  13787. module.refresh();
  13788. }
  13789. if($module.nextAll(selector.pusher).length === 0 || $module.nextAll(selector.pusher)[0] !== $pusher[0]) {
  13790. module.debug('Moved sidebar to correct parent element');
  13791. module.error(error.movedSidebar, element);
  13792. $module.detach().prependTo($context);
  13793. module.refresh();
  13794. }
  13795. module.clear.cache();
  13796. module.set.pushable();
  13797. module.set.direction();
  13798. }
  13799. },
  13800. attachEvents: function(selector, event) {
  13801. var
  13802. $toggle = $(selector)
  13803. ;
  13804. event = $.isFunction(module[event])
  13805. ? module[event]
  13806. : module.toggle
  13807. ;
  13808. if($toggle.length > 0) {
  13809. module.debug('Attaching sidebar events to element', selector, event);
  13810. $toggle
  13811. .on('click' + eventNamespace, event)
  13812. ;
  13813. }
  13814. else {
  13815. module.error(error.notFound, selector);
  13816. }
  13817. },
  13818. show: function(callback) {
  13819. callback = $.isFunction(callback)
  13820. ? callback
  13821. : function(){}
  13822. ;
  13823. if(module.is.hidden()) {
  13824. module.refreshSidebars();
  13825. if(settings.overlay) {
  13826. module.error(error.overlay);
  13827. settings.transition = 'overlay';
  13828. }
  13829. module.refresh();
  13830. if(module.othersActive()) {
  13831. module.debug('Other sidebars currently visible');
  13832. if(settings.exclusive) {
  13833. // if not overlay queue animation after hide
  13834. if(settings.transition != 'overlay') {
  13835. module.hideOthers(module.show);
  13836. return;
  13837. }
  13838. else {
  13839. module.hideOthers();
  13840. }
  13841. }
  13842. else {
  13843. settings.transition = 'overlay';
  13844. }
  13845. }
  13846. module.pushPage(function() {
  13847. callback.call(element);
  13848. settings.onShow.call(element);
  13849. });
  13850. settings.onChange.call(element);
  13851. settings.onVisible.call(element);
  13852. }
  13853. else {
  13854. module.debug('Sidebar is already visible');
  13855. }
  13856. },
  13857. hide: function(callback) {
  13858. callback = $.isFunction(callback)
  13859. ? callback
  13860. : function(){}
  13861. ;
  13862. if(module.is.visible() || module.is.animating()) {
  13863. module.debug('Hiding sidebar', callback);
  13864. module.refreshSidebars();
  13865. module.pullPage(function() {
  13866. callback.call(element);
  13867. settings.onHidden.call(element);
  13868. });
  13869. settings.onChange.call(element);
  13870. settings.onHide.call(element);
  13871. }
  13872. },
  13873. othersAnimating: function() {
  13874. return ($sidebars.not($module).filter('.' + className.animating).length > 0);
  13875. },
  13876. othersVisible: function() {
  13877. return ($sidebars.not($module).filter('.' + className.visible).length > 0);
  13878. },
  13879. othersActive: function() {
  13880. return(module.othersVisible() || module.othersAnimating());
  13881. },
  13882. hideOthers: function(callback) {
  13883. var
  13884. $otherSidebars = $sidebars.not($module).filter('.' + className.visible),
  13885. sidebarCount = $otherSidebars.length,
  13886. callbackCount = 0
  13887. ;
  13888. callback = callback || function(){};
  13889. $otherSidebars
  13890. .sidebar('hide', function() {
  13891. callbackCount++;
  13892. if(callbackCount == sidebarCount) {
  13893. callback();
  13894. }
  13895. })
  13896. ;
  13897. },
  13898. toggle: function() {
  13899. module.verbose('Determining toggled direction');
  13900. if(module.is.hidden()) {
  13901. module.show();
  13902. }
  13903. else {
  13904. module.hide();
  13905. }
  13906. },
  13907. pushPage: function(callback) {
  13908. var
  13909. transition = module.get.transition(),
  13910. $transition = (transition === 'overlay' || module.othersActive())
  13911. ? $module
  13912. : $pusher,
  13913. animate,
  13914. dim,
  13915. transitionEnd
  13916. ;
  13917. callback = $.isFunction(callback)
  13918. ? callback
  13919. : function(){}
  13920. ;
  13921. if(settings.transition == 'scale down') {
  13922. module.scrollToTop();
  13923. }
  13924. module.set.transition(transition);
  13925. module.repaint();
  13926. animate = function() {
  13927. module.bind.clickaway();
  13928. module.add.inlineCSS();
  13929. module.set.animating();
  13930. module.set.visible();
  13931. };
  13932. dim = function() {
  13933. module.set.dimmed();
  13934. };
  13935. transitionEnd = function(event) {
  13936. if( event.target == $transition[0] ) {
  13937. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  13938. module.remove.animating();
  13939. module.bind.scrollLock();
  13940. callback.call(element);
  13941. }
  13942. };
  13943. $transition.off(transitionEvent + elementNamespace);
  13944. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  13945. requestAnimationFrame(animate);
  13946. if(settings.dimPage && !module.othersVisible()) {
  13947. requestAnimationFrame(dim);
  13948. }
  13949. },
  13950. pullPage: function(callback) {
  13951. var
  13952. transition = module.get.transition(),
  13953. $transition = (transition == 'overlay' || module.othersActive())
  13954. ? $module
  13955. : $pusher,
  13956. animate,
  13957. transitionEnd
  13958. ;
  13959. callback = $.isFunction(callback)
  13960. ? callback
  13961. : function(){}
  13962. ;
  13963. module.verbose('Removing context push state', module.get.direction());
  13964. module.unbind.clickaway();
  13965. module.unbind.scrollLock();
  13966. animate = function() {
  13967. module.set.transition(transition);
  13968. module.set.animating();
  13969. module.remove.visible();
  13970. if(settings.dimPage && !module.othersVisible()) {
  13971. $pusher.removeClass(className.dimmed);
  13972. }
  13973. };
  13974. transitionEnd = function(event) {
  13975. if( event.target == $transition[0] ) {
  13976. $transition.off(transitionEvent + elementNamespace, transitionEnd);
  13977. module.remove.animating();
  13978. module.remove.transition();
  13979. module.remove.inlineCSS();
  13980. if(transition == 'scale down' || (settings.returnScroll && module.is.mobile()) ) {
  13981. module.scrollBack();
  13982. }
  13983. callback.call(element);
  13984. }
  13985. };
  13986. $transition.off(transitionEvent + elementNamespace);
  13987. $transition.on(transitionEvent + elementNamespace, transitionEnd);
  13988. requestAnimationFrame(animate);
  13989. },
  13990. scrollToTop: function() {
  13991. module.verbose('Scrolling to top of page to avoid animation issues');
  13992. currentScroll = $(window).scrollTop();
  13993. $module.scrollTop(0);
  13994. window.scrollTo(0, 0);
  13995. },
  13996. scrollBack: function() {
  13997. module.verbose('Scrolling back to original page position');
  13998. window.scrollTo(0, currentScroll);
  13999. },
  14000. clear: {
  14001. cache: function() {
  14002. module.verbose('Clearing cached dimensions');
  14003. module.cache = {};
  14004. }
  14005. },
  14006. set: {
  14007. // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
  14008. ios: function() {
  14009. $html.addClass(className.ios);
  14010. },
  14011. // container
  14012. pushed: function() {
  14013. $context.addClass(className.pushed);
  14014. },
  14015. pushable: function() {
  14016. $context.addClass(className.pushable);
  14017. },
  14018. // pusher
  14019. dimmed: function() {
  14020. $pusher.addClass(className.dimmed);
  14021. },
  14022. // sidebar
  14023. active: function() {
  14024. $module.addClass(className.active);
  14025. },
  14026. animating: function() {
  14027. $module.addClass(className.animating);
  14028. },
  14029. transition: function(transition) {
  14030. transition = transition || module.get.transition();
  14031. $module.addClass(transition);
  14032. },
  14033. direction: function(direction) {
  14034. direction = direction || module.get.direction();
  14035. $module.addClass(className[direction]);
  14036. },
  14037. visible: function() {
  14038. $module.addClass(className.visible);
  14039. },
  14040. overlay: function() {
  14041. $module.addClass(className.overlay);
  14042. }
  14043. },
  14044. remove: {
  14045. inlineCSS: function() {
  14046. module.debug('Removing inline css styles', $style);
  14047. if($style && $style.length > 0) {
  14048. $style.remove();
  14049. }
  14050. },
  14051. // ios scroll on html not document
  14052. ios: function() {
  14053. $html.removeClass(className.ios);
  14054. },
  14055. // context
  14056. pushed: function() {
  14057. $context.removeClass(className.pushed);
  14058. },
  14059. pushable: function() {
  14060. $context.removeClass(className.pushable);
  14061. },
  14062. // sidebar
  14063. active: function() {
  14064. $module.removeClass(className.active);
  14065. },
  14066. animating: function() {
  14067. $module.removeClass(className.animating);
  14068. },
  14069. transition: function(transition) {
  14070. transition = transition || module.get.transition();
  14071. $module.removeClass(transition);
  14072. },
  14073. direction: function(direction) {
  14074. direction = direction || module.get.direction();
  14075. $module.removeClass(className[direction]);
  14076. },
  14077. visible: function() {
  14078. $module.removeClass(className.visible);
  14079. },
  14080. overlay: function() {
  14081. $module.removeClass(className.overlay);
  14082. }
  14083. },
  14084. get: {
  14085. direction: function() {
  14086. if($module.hasClass(className.top)) {
  14087. return className.top;
  14088. }
  14089. else if($module.hasClass(className.right)) {
  14090. return className.right;
  14091. }
  14092. else if($module.hasClass(className.bottom)) {
  14093. return className.bottom;
  14094. }
  14095. return className.left;
  14096. },
  14097. transition: function() {
  14098. var
  14099. direction = module.get.direction(),
  14100. transition
  14101. ;
  14102. transition = ( module.is.mobile() )
  14103. ? (settings.mobileTransition == 'auto')
  14104. ? settings.defaultTransition.mobile[direction]
  14105. : settings.mobileTransition
  14106. : (settings.transition == 'auto')
  14107. ? settings.defaultTransition.computer[direction]
  14108. : settings.transition
  14109. ;
  14110. module.verbose('Determined transition', transition);
  14111. return transition;
  14112. },
  14113. transitionEvent: function() {
  14114. var
  14115. element = document.createElement('element'),
  14116. transitions = {
  14117. 'transition' :'transitionend',
  14118. 'OTransition' :'oTransitionEnd',
  14119. 'MozTransition' :'transitionend',
  14120. 'WebkitTransition' :'webkitTransitionEnd'
  14121. },
  14122. transition
  14123. ;
  14124. for(transition in transitions){
  14125. if( element.style[transition] !== undefined ){
  14126. return transitions[transition];
  14127. }
  14128. }
  14129. }
  14130. },
  14131. is: {
  14132. ie: function() {
  14133. var
  14134. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  14135. isIE = ('ActiveXObject' in window)
  14136. ;
  14137. return (isIE11 || isIE);
  14138. },
  14139. ios: function() {
  14140. var
  14141. userAgent = navigator.userAgent,
  14142. isIOS = userAgent.match(regExp.ios),
  14143. isMobileChrome = userAgent.match(regExp.mobileChrome)
  14144. ;
  14145. if(isIOS && !isMobileChrome) {
  14146. module.verbose('Browser was found to be iOS', userAgent);
  14147. return true;
  14148. }
  14149. else {
  14150. return false;
  14151. }
  14152. },
  14153. mobile: function() {
  14154. var
  14155. userAgent = navigator.userAgent,
  14156. isMobile = userAgent.match(regExp.mobile)
  14157. ;
  14158. if(isMobile) {
  14159. module.verbose('Browser was found to be mobile', userAgent);
  14160. return true;
  14161. }
  14162. else {
  14163. module.verbose('Browser is not mobile, using regular transition', userAgent);
  14164. return false;
  14165. }
  14166. },
  14167. hidden: function() {
  14168. return !module.is.visible();
  14169. },
  14170. visible: function() {
  14171. return $module.hasClass(className.visible);
  14172. },
  14173. // alias
  14174. open: function() {
  14175. return module.is.visible();
  14176. },
  14177. closed: function() {
  14178. return module.is.hidden();
  14179. },
  14180. vertical: function() {
  14181. return $module.hasClass(className.top);
  14182. },
  14183. animating: function() {
  14184. return $context.hasClass(className.animating);
  14185. },
  14186. rtl: function () {
  14187. if(module.cache.rtl === undefined) {
  14188. module.cache.rtl = ($module.css('direction') == 'rtl');
  14189. }
  14190. return module.cache.rtl;
  14191. }
  14192. },
  14193. setting: function(name, value) {
  14194. module.debug('Changing setting', name, value);
  14195. if( $.isPlainObject(name) ) {
  14196. $.extend(true, settings, name);
  14197. }
  14198. else if(value !== undefined) {
  14199. settings[name] = value;
  14200. }
  14201. else {
  14202. return settings[name];
  14203. }
  14204. },
  14205. internal: function(name, value) {
  14206. if( $.isPlainObject(name) ) {
  14207. $.extend(true, module, name);
  14208. }
  14209. else if(value !== undefined) {
  14210. module[name] = value;
  14211. }
  14212. else {
  14213. return module[name];
  14214. }
  14215. },
  14216. debug: function() {
  14217. if(settings.debug) {
  14218. if(settings.performance) {
  14219. module.performance.log(arguments);
  14220. }
  14221. else {
  14222. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14223. module.debug.apply(console, arguments);
  14224. }
  14225. }
  14226. },
  14227. verbose: function() {
  14228. if(settings.verbose && settings.debug) {
  14229. if(settings.performance) {
  14230. module.performance.log(arguments);
  14231. }
  14232. else {
  14233. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  14234. module.verbose.apply(console, arguments);
  14235. }
  14236. }
  14237. },
  14238. error: function() {
  14239. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  14240. module.error.apply(console, arguments);
  14241. },
  14242. performance: {
  14243. log: function(message) {
  14244. var
  14245. currentTime,
  14246. executionTime,
  14247. previousTime
  14248. ;
  14249. if(settings.performance) {
  14250. currentTime = new Date().getTime();
  14251. previousTime = time || currentTime;
  14252. executionTime = currentTime - previousTime;
  14253. time = currentTime;
  14254. performance.push({
  14255. 'Name' : message[0],
  14256. 'Arguments' : [].slice.call(message, 1) || '',
  14257. 'Element' : element,
  14258. 'Execution Time' : executionTime
  14259. });
  14260. }
  14261. clearTimeout(module.performance.timer);
  14262. module.performance.timer = setTimeout(module.performance.display, 500);
  14263. },
  14264. display: function() {
  14265. var
  14266. title = settings.name + ':',
  14267. totalTime = 0
  14268. ;
  14269. time = false;
  14270. clearTimeout(module.performance.timer);
  14271. $.each(performance, function(index, data) {
  14272. totalTime += data['Execution Time'];
  14273. });
  14274. title += ' ' + totalTime + 'ms';
  14275. if(moduleSelector) {
  14276. title += ' \'' + moduleSelector + '\'';
  14277. }
  14278. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  14279. console.groupCollapsed(title);
  14280. if(console.table) {
  14281. console.table(performance);
  14282. }
  14283. else {
  14284. $.each(performance, function(index, data) {
  14285. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  14286. });
  14287. }
  14288. console.groupEnd();
  14289. }
  14290. performance = [];
  14291. }
  14292. },
  14293. invoke: function(query, passedArguments, context) {
  14294. var
  14295. object = instance,
  14296. maxDepth,
  14297. found,
  14298. response
  14299. ;
  14300. passedArguments = passedArguments || queryArguments;
  14301. context = element || context;
  14302. if(typeof query == 'string' && object !== undefined) {
  14303. query = query.split(/[\. ]/);
  14304. maxDepth = query.length - 1;
  14305. $.each(query, function(depth, value) {
  14306. var camelCaseValue = (depth != maxDepth)
  14307. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  14308. : query
  14309. ;
  14310. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  14311. object = object[camelCaseValue];
  14312. }
  14313. else if( object[camelCaseValue] !== undefined ) {
  14314. found = object[camelCaseValue];
  14315. return false;
  14316. }
  14317. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  14318. object = object[value];
  14319. }
  14320. else if( object[value] !== undefined ) {
  14321. found = object[value];
  14322. return false;
  14323. }
  14324. else {
  14325. module.error(error.method, query);
  14326. return false;
  14327. }
  14328. });
  14329. }
  14330. if ( $.isFunction( found ) ) {
  14331. response = found.apply(context, passedArguments);
  14332. }
  14333. else if(found !== undefined) {
  14334. response = found;
  14335. }
  14336. if($.isArray(returnedValue)) {
  14337. returnedValue.push(response);
  14338. }
  14339. else if(returnedValue !== undefined) {
  14340. returnedValue = [returnedValue, response];
  14341. }
  14342. else if(response !== undefined) {
  14343. returnedValue = response;
  14344. }
  14345. return found;
  14346. }
  14347. }
  14348. ;
  14349. if(methodInvoked) {
  14350. if(instance === undefined) {
  14351. module.initialize();
  14352. }
  14353. module.invoke(query);
  14354. }
  14355. else {
  14356. if(instance !== undefined) {
  14357. module.invoke('destroy');
  14358. }
  14359. module.initialize();
  14360. }
  14361. });
  14362. return (returnedValue !== undefined)
  14363. ? returnedValue
  14364. : this
  14365. ;
  14366. };
  14367. $.fn.sidebar.settings = {
  14368. name : 'Sidebar',
  14369. namespace : 'sidebar',
  14370. debug : false,
  14371. verbose : false,
  14372. performance : true,
  14373. transition : 'auto',
  14374. mobileTransition : 'auto',
  14375. defaultTransition : {
  14376. computer: {
  14377. left : 'uncover',
  14378. right : 'uncover',
  14379. top : 'overlay',
  14380. bottom : 'overlay'
  14381. },
  14382. mobile: {
  14383. left : 'uncover',
  14384. right : 'uncover',
  14385. top : 'overlay',
  14386. bottom : 'overlay'
  14387. }
  14388. },
  14389. context : 'body',
  14390. exclusive : false,
  14391. closable : true,
  14392. dimPage : true,
  14393. scrollLock : false,
  14394. returnScroll : false,
  14395. delaySetup : false,
  14396. duration : 500,
  14397. onChange : function(){},
  14398. onShow : function(){},
  14399. onHide : function(){},
  14400. onHidden : function(){},
  14401. onVisible : function(){},
  14402. className : {
  14403. active : 'active',
  14404. animating : 'animating',
  14405. dimmed : 'dimmed',
  14406. ios : 'ios',
  14407. pushable : 'pushable',
  14408. pushed : 'pushed',
  14409. right : 'right',
  14410. top : 'top',
  14411. left : 'left',
  14412. bottom : 'bottom',
  14413. visible : 'visible'
  14414. },
  14415. selector: {
  14416. fixed : '.fixed',
  14417. omitted : 'script, link, style, .ui.modal, .ui.dimmer, .ui.nag, .ui.fixed',
  14418. pusher : '.pusher',
  14419. sidebar : '.ui.sidebar'
  14420. },
  14421. regExp: {
  14422. ios : /(iPad|iPhone|iPod)/g,
  14423. mobileChrome : /(CriOS)/g,
  14424. 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
  14425. },
  14426. error : {
  14427. method : 'The method you called is not defined.',
  14428. pusher : 'Had to add pusher element. For optimal performance make sure body content is inside a pusher element',
  14429. movedSidebar : 'Had to move sidebar. For optimal performance make sure sidebar and pusher are direct children of your body tag',
  14430. overlay : 'The overlay setting is no longer supported, use animation: overlay',
  14431. notFound : 'There were no elements that matched the specified selector'
  14432. }
  14433. };
  14434. })( jQuery, window, document );
  14435. /*!
  14436. * # Semantic UI 2.1.6 - Sticky
  14437. * http://github.com/semantic-org/semantic-ui/
  14438. *
  14439. *
  14440. * Copyright 2015 Contributors
  14441. * Released under the MIT license
  14442. * http://opensource.org/licenses/MIT
  14443. *
  14444. */
  14445. ;(function ( $, window, document, undefined ) {
  14446. "use strict";
  14447. $.fn.sticky = function(parameters) {
  14448. var
  14449. $allModules = $(this),
  14450. moduleSelector = $allModules.selector || '',
  14451. time = new Date().getTime(),
  14452. performance = [],
  14453. query = arguments[0],
  14454. methodInvoked = (typeof query == 'string'),
  14455. queryArguments = [].slice.call(arguments, 1),
  14456. returnedValue
  14457. ;
  14458. $allModules
  14459. .each(function() {
  14460. var
  14461. settings = ( $.isPlainObject(parameters) )
  14462. ? $.extend(true, {}, $.fn.sticky.settings, parameters)
  14463. : $.extend({}, $.fn.sticky.settings),
  14464. className = settings.className,
  14465. namespace = settings.namespace,
  14466. error = settings.error,
  14467. eventNamespace = '.' + namespace,
  14468. moduleNamespace = 'module-' + namespace,
  14469. $module = $(this),
  14470. $window = $(window),
  14471. $scroll = $(settings.scrollContext),
  14472. $container,
  14473. $context,
  14474. selector = $module.selector || '',
  14475. instance = $module.data(moduleNamespace),
  14476. requestAnimationFrame = window.requestAnimationFrame
  14477. || window.mozRequestAnimationFrame
  14478. || window.webkitRequestAnimationFrame
  14479. || window.msRequestAnimationFrame
  14480. || function(callback) { setTimeout(callback, 0); },
  14481. element = this,
  14482. observer,
  14483. module
  14484. ;
  14485. module = {
  14486. initialize: function() {
  14487. module.determineContainer();
  14488. module.determineContext();
  14489. module.verbose('Initializing sticky', settings, $container);
  14490. module.save.positions();
  14491. module.checkErrors();
  14492. module.bind.events();
  14493. if(settings.observeChanges) {
  14494. module.observeChanges();
  14495. }
  14496. module.instantiate();
  14497. },
  14498. instantiate: function() {
  14499. module.verbose('Storing instance of module', module);
  14500. instance = module;
  14501. $module
  14502. .data(moduleNamespace, module)
  14503. ;
  14504. },
  14505. destroy: function() {
  14506. module.verbose('Destroying previous instance');
  14507. module.reset();
  14508. if(observer) {
  14509. observer.disconnect();
  14510. }
  14511. $window
  14512. .off('load' + eventNamespace, module.event.load)
  14513. .off('resize' + eventNamespace, module.event.resize)
  14514. ;
  14515. $scroll
  14516. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  14517. ;
  14518. $module.removeData(moduleNamespace);
  14519. },
  14520. observeChanges: function() {
  14521. var
  14522. context = $context[0]
  14523. ;
  14524. if('MutationObserver' in window) {
  14525. observer = new MutationObserver(function(mutations) {
  14526. clearTimeout(module.timer);
  14527. module.timer = setTimeout(function() {
  14528. module.verbose('DOM tree modified, updating sticky menu', mutations);
  14529. module.refresh();
  14530. }, 100);
  14531. });
  14532. observer.observe(element, {
  14533. childList : true,
  14534. subtree : true
  14535. });
  14536. observer.observe(context, {
  14537. childList : true,
  14538. subtree : true
  14539. });
  14540. module.debug('Setting up mutation observer', observer);
  14541. }
  14542. },
  14543. determineContainer: function() {
  14544. $container = $module.offsetParent();
  14545. },
  14546. determineContext: function() {
  14547. if(settings.context) {
  14548. $context = $(settings.context);
  14549. }
  14550. else {
  14551. $context = $container;
  14552. }
  14553. if($context.length === 0) {
  14554. module.error(error.invalidContext, settings.context, $module);
  14555. return;
  14556. }
  14557. },
  14558. checkErrors: function() {
  14559. if( module.is.hidden() ) {
  14560. module.error(error.visible, $module);
  14561. }
  14562. if(module.cache.element.height > module.cache.context.height) {
  14563. module.reset();
  14564. module.error(error.elementSize, $module);
  14565. return;
  14566. }
  14567. },
  14568. bind: {
  14569. events: function() {
  14570. $window
  14571. .on('load' + eventNamespace, module.event.load)
  14572. .on('resize' + eventNamespace, module.event.resize)
  14573. ;
  14574. // pub/sub pattern
  14575. $scroll
  14576. .off('scroll' + eventNamespace)
  14577. .on('scroll' + eventNamespace, module.event.scroll)
  14578. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  14579. ;
  14580. }
  14581. },
  14582. event: {
  14583. load: function() {
  14584. module.verbose('Page contents finished loading');
  14585. requestAnimationFrame(module.refresh);
  14586. },
  14587. resize: function() {
  14588. module.verbose('Window resized');
  14589. requestAnimationFrame(module.refresh);
  14590. },
  14591. scroll: function() {
  14592. requestAnimationFrame(function() {
  14593. $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
  14594. });
  14595. },
  14596. scrollchange: function(event, scrollPosition) {
  14597. module.stick(scrollPosition);
  14598. settings.onScroll.call(element);
  14599. }
  14600. },
  14601. refresh: function(hardRefresh) {
  14602. module.reset();
  14603. if(!settings.context) {
  14604. module.determineContext();
  14605. }
  14606. if(hardRefresh) {
  14607. module.determineContainer();
  14608. }
  14609. module.save.positions();
  14610. module.stick();
  14611. settings.onReposition.call(element);
  14612. },
  14613. supports: {
  14614. sticky: function() {
  14615. var
  14616. $element = $('<div/>'),
  14617. element = $element[0]
  14618. ;
  14619. $element.addClass(className.supported);
  14620. return($element.css('position').match('sticky'));
  14621. }
  14622. },
  14623. save: {
  14624. lastScroll: function(scroll) {
  14625. module.lastScroll = scroll;
  14626. },
  14627. elementScroll: function(scroll) {
  14628. module.elementScroll = scroll;
  14629. },
  14630. positions: function() {
  14631. var
  14632. scrollContext = {
  14633. height : $scroll.height()
  14634. },
  14635. element = {
  14636. margin: {
  14637. top : parseInt($module.css('margin-top'), 10),
  14638. bottom : parseInt($module.css('margin-bottom'), 10),
  14639. },
  14640. offset : $module.offset(),
  14641. width : $module.outerWidth(),
  14642. height : $module.outerHeight()
  14643. },
  14644. context = {
  14645. offset : $context.offset(),
  14646. height : $context.outerHeight()
  14647. },
  14648. container = {
  14649. height: $container.outerHeight()
  14650. }
  14651. ;
  14652. if( !module.is.standardScroll() ) {
  14653. module.debug('Non-standard scroll. Removing scroll offset from element offset');
  14654. scrollContext.top = $scroll.scrollTop();
  14655. scrollContext.left = $scroll.scrollLeft();
  14656. element.offset.top += scrollContext.top;
  14657. context.offset.top += scrollContext.top;
  14658. element.offset.left += scrollContext.left;
  14659. context.offset.left += scrollContext.left;
  14660. }
  14661. module.cache = {
  14662. fits : ( element.height < scrollContext.height ),
  14663. scrollContext : {
  14664. height : scrollContext.height
  14665. },
  14666. element: {
  14667. margin : element.margin,
  14668. top : element.offset.top - element.margin.top,
  14669. left : element.offset.left,
  14670. width : element.width,
  14671. height : element.height,
  14672. bottom : element.offset.top + element.height
  14673. },
  14674. context: {
  14675. top : context.offset.top,
  14676. height : context.height,
  14677. bottom : context.offset.top + context.height
  14678. }
  14679. };
  14680. module.set.containerSize();
  14681. module.set.size();
  14682. module.stick();
  14683. module.debug('Caching element positions', module.cache);
  14684. }
  14685. },
  14686. get: {
  14687. direction: function(scroll) {
  14688. var
  14689. direction = 'down'
  14690. ;
  14691. scroll = scroll || $scroll.scrollTop();
  14692. if(module.lastScroll !== undefined) {
  14693. if(module.lastScroll < scroll) {
  14694. direction = 'down';
  14695. }
  14696. else if(module.lastScroll > scroll) {
  14697. direction = 'up';
  14698. }
  14699. }
  14700. return direction;
  14701. },
  14702. scrollChange: function(scroll) {
  14703. scroll = scroll || $scroll.scrollTop();
  14704. return (module.lastScroll)
  14705. ? (scroll - module.lastScroll)
  14706. : 0
  14707. ;
  14708. },
  14709. currentElementScroll: function() {
  14710. if(module.elementScroll) {
  14711. return module.elementScroll;
  14712. }
  14713. return ( module.is.top() )
  14714. ? Math.abs(parseInt($module.css('top'), 10)) || 0
  14715. : Math.abs(parseInt($module.css('bottom'), 10)) || 0
  14716. ;
  14717. },
  14718. elementScroll: function(scroll) {
  14719. scroll = scroll || $scroll.scrollTop();
  14720. var
  14721. element = module.cache.element,
  14722. scrollContext = module.cache.scrollContext,
  14723. delta = module.get.scrollChange(scroll),
  14724. maxScroll = (element.height - scrollContext.height + settings.offset),
  14725. elementScroll = module.get.currentElementScroll(),
  14726. possibleScroll = (elementScroll + delta)
  14727. ;
  14728. if(module.cache.fits || possibleScroll < 0) {
  14729. elementScroll = 0;
  14730. }
  14731. else if(possibleScroll > maxScroll ) {
  14732. elementScroll = maxScroll;
  14733. }
  14734. else {
  14735. elementScroll = possibleScroll;
  14736. }
  14737. return elementScroll;
  14738. }
  14739. },
  14740. remove: {
  14741. lastScroll: function() {
  14742. delete module.lastScroll;
  14743. },
  14744. elementScroll: function(scroll) {
  14745. delete module.elementScroll;
  14746. },
  14747. offset: function() {
  14748. $module.css('margin-top', '');
  14749. }
  14750. },
  14751. set: {
  14752. offset: function() {
  14753. module.verbose('Setting offset on element', settings.offset);
  14754. $module
  14755. .css('margin-top', settings.offset)
  14756. ;
  14757. },
  14758. containerSize: function() {
  14759. var
  14760. tagName = $container.get(0).tagName
  14761. ;
  14762. if(tagName === 'HTML' || tagName == 'body') {
  14763. // this can trigger for too many reasons
  14764. //module.error(error.container, tagName, $module);
  14765. module.determineContainer();
  14766. }
  14767. else {
  14768. if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
  14769. module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
  14770. $container.css({
  14771. height: module.cache.context.height
  14772. });
  14773. }
  14774. }
  14775. },
  14776. minimumSize: function() {
  14777. var
  14778. element = module.cache.element
  14779. ;
  14780. $container
  14781. .css('min-height', element.height)
  14782. ;
  14783. },
  14784. scroll: function(scroll) {
  14785. module.debug('Setting scroll on element', scroll);
  14786. if(module.elementScroll == scroll) {
  14787. return;
  14788. }
  14789. if( module.is.top() ) {
  14790. $module
  14791. .css('bottom', '')
  14792. .css('top', -scroll)
  14793. ;
  14794. }
  14795. if( module.is.bottom() ) {
  14796. $module
  14797. .css('top', '')
  14798. .css('bottom', scroll)
  14799. ;
  14800. }
  14801. },
  14802. size: function() {
  14803. if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
  14804. element.style.setProperty('width', module.cache.element.width + 'px', 'important');
  14805. element.style.setProperty('height', module.cache.element.height + 'px', 'important');
  14806. }
  14807. }
  14808. },
  14809. is: {
  14810. standardScroll: function() {
  14811. return ($scroll[0] == window);
  14812. },
  14813. top: function() {
  14814. return $module.hasClass(className.top);
  14815. },
  14816. bottom: function() {
  14817. return $module.hasClass(className.bottom);
  14818. },
  14819. initialPosition: function() {
  14820. return (!module.is.fixed() && !module.is.bound());
  14821. },
  14822. hidden: function() {
  14823. return (!$module.is(':visible'));
  14824. },
  14825. bound: function() {
  14826. return $module.hasClass(className.bound);
  14827. },
  14828. fixed: function() {
  14829. return $module.hasClass(className.fixed);
  14830. }
  14831. },
  14832. stick: function(scroll) {
  14833. var
  14834. cachedPosition = scroll || $scroll.scrollTop(),
  14835. cache = module.cache,
  14836. fits = cache.fits,
  14837. element = cache.element,
  14838. scrollContext = cache.scrollContext,
  14839. context = cache.context,
  14840. offset = (module.is.bottom() && settings.pushing)
  14841. ? settings.bottomOffset
  14842. : settings.offset,
  14843. scroll = {
  14844. top : cachedPosition + offset,
  14845. bottom : cachedPosition + offset + scrollContext.height
  14846. },
  14847. direction = module.get.direction(scroll.top),
  14848. elementScroll = (fits)
  14849. ? 0
  14850. : module.get.elementScroll(scroll.top),
  14851. // shorthand
  14852. doesntFit = !fits,
  14853. elementVisible = (element.height !== 0)
  14854. ;
  14855. if(elementVisible) {
  14856. if( module.is.initialPosition() ) {
  14857. if(scroll.top >= context.bottom) {
  14858. module.debug('Initial element position is bottom of container');
  14859. module.bindBottom();
  14860. }
  14861. else if(scroll.top > element.top) {
  14862. if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  14863. module.debug('Initial element position is bottom of container');
  14864. module.bindBottom();
  14865. }
  14866. else {
  14867. module.debug('Initial element position is fixed');
  14868. module.fixTop();
  14869. }
  14870. }
  14871. }
  14872. else if( module.is.fixed() ) {
  14873. // currently fixed top
  14874. if( module.is.top() ) {
  14875. if( scroll.top <= element.top ) {
  14876. module.debug('Fixed element reached top of container');
  14877. module.setInitialPosition();
  14878. }
  14879. else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  14880. module.debug('Fixed element reached bottom of container');
  14881. module.bindBottom();
  14882. }
  14883. // scroll element if larger than screen
  14884. else if(doesntFit) {
  14885. module.set.scroll(elementScroll);
  14886. module.save.lastScroll(scroll.top);
  14887. module.save.elementScroll(elementScroll);
  14888. }
  14889. }
  14890. // currently fixed bottom
  14891. else if(module.is.bottom() ) {
  14892. // top edge
  14893. if( (scroll.bottom - element.height) <= element.top) {
  14894. module.debug('Bottom fixed rail has reached top of container');
  14895. module.setInitialPosition();
  14896. }
  14897. // bottom edge
  14898. else if(scroll.bottom >= context.bottom) {
  14899. module.debug('Bottom fixed rail has reached bottom of container');
  14900. module.bindBottom();
  14901. }
  14902. // scroll element if larger than screen
  14903. else if(doesntFit) {
  14904. module.set.scroll(elementScroll);
  14905. module.save.lastScroll(scroll.top);
  14906. module.save.elementScroll(elementScroll);
  14907. }
  14908. }
  14909. }
  14910. else if( module.is.bottom() ) {
  14911. if( scroll.top <= element.top ) {
  14912. module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
  14913. module.setInitialPosition();
  14914. }
  14915. else {
  14916. if(settings.pushing) {
  14917. if(module.is.bound() && scroll.bottom <= context.bottom ) {
  14918. module.debug('Fixing bottom attached element to bottom of browser.');
  14919. module.fixBottom();
  14920. }
  14921. }
  14922. else {
  14923. if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
  14924. module.debug('Fixing bottom attached element to top of browser.');
  14925. module.fixTop();
  14926. }
  14927. }
  14928. }
  14929. }
  14930. }
  14931. },
  14932. bindTop: function() {
  14933. module.debug('Binding element to top of parent container');
  14934. module.remove.offset();
  14935. $module
  14936. .css({
  14937. left : '',
  14938. top : '',
  14939. marginBottom : ''
  14940. })
  14941. .removeClass(className.fixed)
  14942. .removeClass(className.bottom)
  14943. .addClass(className.bound)
  14944. .addClass(className.top)
  14945. ;
  14946. settings.onTop.call(element);
  14947. settings.onUnstick.call(element);
  14948. },
  14949. bindBottom: function() {
  14950. module.debug('Binding element to bottom of parent container');
  14951. module.remove.offset();
  14952. $module
  14953. .css({
  14954. left : '',
  14955. top : ''
  14956. })
  14957. .removeClass(className.fixed)
  14958. .removeClass(className.top)
  14959. .addClass(className.bound)
  14960. .addClass(className.bottom)
  14961. ;
  14962. settings.onBottom.call(element);
  14963. settings.onUnstick.call(element);
  14964. },
  14965. setInitialPosition: function() {
  14966. module.debug('Returning to initial position');
  14967. module.unfix();
  14968. module.unbind();
  14969. },
  14970. fixTop: function() {
  14971. module.debug('Fixing element to top of page');
  14972. module.set.minimumSize();
  14973. module.set.offset();
  14974. $module
  14975. .css({
  14976. left : module.cache.element.left,
  14977. bottom : '',
  14978. marginBottom : ''
  14979. })
  14980. .removeClass(className.bound)
  14981. .removeClass(className.bottom)
  14982. .addClass(className.fixed)
  14983. .addClass(className.top)
  14984. ;
  14985. settings.onStick.call(element);
  14986. },
  14987. fixBottom: function() {
  14988. module.debug('Sticking element to bottom of page');
  14989. module.set.minimumSize();
  14990. module.set.offset();
  14991. $module
  14992. .css({
  14993. left : module.cache.element.left,
  14994. bottom : '',
  14995. marginBottom : ''
  14996. })
  14997. .removeClass(className.bound)
  14998. .removeClass(className.top)
  14999. .addClass(className.fixed)
  15000. .addClass(className.bottom)
  15001. ;
  15002. settings.onStick.call(element);
  15003. },
  15004. unbind: function() {
  15005. if( module.is.bound() ) {
  15006. module.debug('Removing container bound position on element');
  15007. module.remove.offset();
  15008. $module
  15009. .removeClass(className.bound)
  15010. .removeClass(className.top)
  15011. .removeClass(className.bottom)
  15012. ;
  15013. }
  15014. },
  15015. unfix: function() {
  15016. if( module.is.fixed() ) {
  15017. module.debug('Removing fixed position on element');
  15018. module.remove.offset();
  15019. $module
  15020. .removeClass(className.fixed)
  15021. .removeClass(className.top)
  15022. .removeClass(className.bottom)
  15023. ;
  15024. settings.onUnstick.call(element);
  15025. }
  15026. },
  15027. reset: function() {
  15028. module.debug('Reseting elements position');
  15029. module.unbind();
  15030. module.unfix();
  15031. module.resetCSS();
  15032. module.remove.offset();
  15033. module.remove.lastScroll();
  15034. },
  15035. resetCSS: function() {
  15036. $module
  15037. .css({
  15038. width : '',
  15039. height : ''
  15040. })
  15041. ;
  15042. $container
  15043. .css({
  15044. height: ''
  15045. })
  15046. ;
  15047. },
  15048. setting: function(name, value) {
  15049. if( $.isPlainObject(name) ) {
  15050. $.extend(true, settings, name);
  15051. }
  15052. else if(value !== undefined) {
  15053. settings[name] = value;
  15054. }
  15055. else {
  15056. return settings[name];
  15057. }
  15058. },
  15059. internal: function(name, value) {
  15060. if( $.isPlainObject(name) ) {
  15061. $.extend(true, module, name);
  15062. }
  15063. else if(value !== undefined) {
  15064. module[name] = value;
  15065. }
  15066. else {
  15067. return module[name];
  15068. }
  15069. },
  15070. debug: function() {
  15071. if(settings.debug) {
  15072. if(settings.performance) {
  15073. module.performance.log(arguments);
  15074. }
  15075. else {
  15076. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15077. module.debug.apply(console, arguments);
  15078. }
  15079. }
  15080. },
  15081. verbose: function() {
  15082. if(settings.verbose && settings.debug) {
  15083. if(settings.performance) {
  15084. module.performance.log(arguments);
  15085. }
  15086. else {
  15087. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15088. module.verbose.apply(console, arguments);
  15089. }
  15090. }
  15091. },
  15092. error: function() {
  15093. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  15094. module.error.apply(console, arguments);
  15095. },
  15096. performance: {
  15097. log: function(message) {
  15098. var
  15099. currentTime,
  15100. executionTime,
  15101. previousTime
  15102. ;
  15103. if(settings.performance) {
  15104. currentTime = new Date().getTime();
  15105. previousTime = time || currentTime;
  15106. executionTime = currentTime - previousTime;
  15107. time = currentTime;
  15108. performance.push({
  15109. 'Name' : message[0],
  15110. 'Arguments' : [].slice.call(message, 1) || '',
  15111. 'Element' : element,
  15112. 'Execution Time' : executionTime
  15113. });
  15114. }
  15115. clearTimeout(module.performance.timer);
  15116. module.performance.timer = setTimeout(module.performance.display, 0);
  15117. },
  15118. display: function() {
  15119. var
  15120. title = settings.name + ':',
  15121. totalTime = 0
  15122. ;
  15123. time = false;
  15124. clearTimeout(module.performance.timer);
  15125. $.each(performance, function(index, data) {
  15126. totalTime += data['Execution Time'];
  15127. });
  15128. title += ' ' + totalTime + 'ms';
  15129. if(moduleSelector) {
  15130. title += ' \'' + moduleSelector + '\'';
  15131. }
  15132. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  15133. console.groupCollapsed(title);
  15134. if(console.table) {
  15135. console.table(performance);
  15136. }
  15137. else {
  15138. $.each(performance, function(index, data) {
  15139. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  15140. });
  15141. }
  15142. console.groupEnd();
  15143. }
  15144. performance = [];
  15145. }
  15146. },
  15147. invoke: function(query, passedArguments, context) {
  15148. var
  15149. object = instance,
  15150. maxDepth,
  15151. found,
  15152. response
  15153. ;
  15154. passedArguments = passedArguments || queryArguments;
  15155. context = element || context;
  15156. if(typeof query == 'string' && object !== undefined) {
  15157. query = query.split(/[\. ]/);
  15158. maxDepth = query.length - 1;
  15159. $.each(query, function(depth, value) {
  15160. var camelCaseValue = (depth != maxDepth)
  15161. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  15162. : query
  15163. ;
  15164. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  15165. object = object[camelCaseValue];
  15166. }
  15167. else if( object[camelCaseValue] !== undefined ) {
  15168. found = object[camelCaseValue];
  15169. return false;
  15170. }
  15171. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  15172. object = object[value];
  15173. }
  15174. else if( object[value] !== undefined ) {
  15175. found = object[value];
  15176. return false;
  15177. }
  15178. else {
  15179. return false;
  15180. }
  15181. });
  15182. }
  15183. if ( $.isFunction( found ) ) {
  15184. response = found.apply(context, passedArguments);
  15185. }
  15186. else if(found !== undefined) {
  15187. response = found;
  15188. }
  15189. if($.isArray(returnedValue)) {
  15190. returnedValue.push(response);
  15191. }
  15192. else if(returnedValue !== undefined) {
  15193. returnedValue = [returnedValue, response];
  15194. }
  15195. else if(response !== undefined) {
  15196. returnedValue = response;
  15197. }
  15198. return found;
  15199. }
  15200. };
  15201. if(methodInvoked) {
  15202. if(instance === undefined) {
  15203. module.initialize();
  15204. }
  15205. module.invoke(query);
  15206. }
  15207. else {
  15208. if(instance !== undefined) {
  15209. instance.invoke('destroy');
  15210. }
  15211. module.initialize();
  15212. }
  15213. })
  15214. ;
  15215. return (returnedValue !== undefined)
  15216. ? returnedValue
  15217. : this
  15218. ;
  15219. };
  15220. $.fn.sticky.settings = {
  15221. name : 'Sticky',
  15222. namespace : 'sticky',
  15223. debug : false,
  15224. verbose : true,
  15225. performance : true,
  15226. // whether to stick in the opposite direction on scroll up
  15227. pushing : false,
  15228. context : false,
  15229. // Context to watch scroll events
  15230. scrollContext : window,
  15231. // Offset to adjust scroll
  15232. offset : 0,
  15233. // Offset to adjust scroll when attached to bottom of screen
  15234. bottomOffset : 0,
  15235. jitter : 5, // will only set container height if difference between context and container is larger than this number
  15236. // Whether to automatically observe changes with Mutation Observers
  15237. observeChanges : false,
  15238. // Called when position is recalculated
  15239. onReposition : function(){},
  15240. // Called on each scroll
  15241. onScroll : function(){},
  15242. // Called when element is stuck to viewport
  15243. onStick : function(){},
  15244. // Called when element is unstuck from viewport
  15245. onUnstick : function(){},
  15246. // Called when element reaches top of context
  15247. onTop : function(){},
  15248. // Called when element reaches bottom of context
  15249. onBottom : function(){},
  15250. error : {
  15251. container : 'Sticky element must be inside a relative container',
  15252. visible : 'Element is hidden, you must call refresh after element becomes visible',
  15253. method : 'The method you called is not defined.',
  15254. invalidContext : 'Context specified does not exist',
  15255. elementSize : 'Sticky element is larger than its container, cannot create sticky.'
  15256. },
  15257. className : {
  15258. bound : 'bound',
  15259. fixed : 'fixed',
  15260. supported : 'native',
  15261. top : 'top',
  15262. bottom : 'bottom'
  15263. }
  15264. };
  15265. })( jQuery, window, document );
  15266. /*!
  15267. * # Semantic UI 2.1.6 - Tab
  15268. * http://github.com/semantic-org/semantic-ui/
  15269. *
  15270. *
  15271. * Copyright 2015 Contributors
  15272. * Released under the MIT license
  15273. * http://opensource.org/licenses/MIT
  15274. *
  15275. */
  15276. ;(function ($, window, document, undefined) {
  15277. "use strict";
  15278. $.fn.tab = function(parameters) {
  15279. var
  15280. // use window context if none specified
  15281. $allModules = $.isFunction(this)
  15282. ? $(window)
  15283. : $(this),
  15284. moduleSelector = $allModules.selector || '',
  15285. time = new Date().getTime(),
  15286. performance = [],
  15287. query = arguments[0],
  15288. methodInvoked = (typeof query == 'string'),
  15289. queryArguments = [].slice.call(arguments, 1),
  15290. initializedHistory = false,
  15291. returnedValue
  15292. ;
  15293. $allModules
  15294. .each(function() {
  15295. var
  15296. settings = ( $.isPlainObject(parameters) )
  15297. ? $.extend(true, {}, $.fn.tab.settings, parameters)
  15298. : $.extend({}, $.fn.tab.settings),
  15299. className = settings.className,
  15300. metadata = settings.metadata,
  15301. selector = settings.selector,
  15302. error = settings.error,
  15303. eventNamespace = '.' + settings.namespace,
  15304. moduleNamespace = 'module-' + settings.namespace,
  15305. $module = $(this),
  15306. $context,
  15307. $tabs,
  15308. cache = {},
  15309. firstLoad = true,
  15310. recursionDepth = 0,
  15311. element = this,
  15312. instance = $module.data(moduleNamespace),
  15313. activeTabPath,
  15314. parameterArray,
  15315. module,
  15316. historyEvent
  15317. ;
  15318. module = {
  15319. initialize: function() {
  15320. module.debug('Initializing tab menu item', $module);
  15321. module.fix.callbacks();
  15322. module.determineTabs();
  15323. module.debug('Determining tabs', settings.context, $tabs);
  15324. // set up automatic routing
  15325. if(settings.auto) {
  15326. module.set.auto();
  15327. }
  15328. module.bind.events();
  15329. if(settings.history && !initializedHistory) {
  15330. module.initializeHistory();
  15331. initializedHistory = true;
  15332. }
  15333. module.instantiate();
  15334. },
  15335. instantiate: function () {
  15336. module.verbose('Storing instance of module', module);
  15337. instance = module;
  15338. $module
  15339. .data(moduleNamespace, module)
  15340. ;
  15341. },
  15342. destroy: function() {
  15343. module.debug('Destroying tabs', $module);
  15344. $module
  15345. .removeData(moduleNamespace)
  15346. .off(eventNamespace)
  15347. ;
  15348. },
  15349. bind: {
  15350. events: function() {
  15351. // if using $.tab don't add events
  15352. if( !$.isWindow( element ) ) {
  15353. module.debug('Attaching tab activation events to element', $module);
  15354. $module
  15355. .on('click' + eventNamespace, module.event.click)
  15356. ;
  15357. }
  15358. }
  15359. },
  15360. determineTabs: function() {
  15361. var
  15362. $reference
  15363. ;
  15364. // determine tab context
  15365. if(settings.context === 'parent') {
  15366. if($module.closest(selector.ui).length > 0) {
  15367. $reference = $module.closest(selector.ui);
  15368. module.verbose('Using closest UI element as parent', $reference);
  15369. }
  15370. else {
  15371. $reference = $module;
  15372. }
  15373. $context = $reference.parent();
  15374. module.verbose('Determined parent element for creating context', $context);
  15375. }
  15376. else if(settings.context) {
  15377. $context = $(settings.context);
  15378. module.verbose('Using selector for tab context', settings.context, $context);
  15379. }
  15380. else {
  15381. $context = $('body');
  15382. }
  15383. // find tabs
  15384. if(settings.childrenOnly) {
  15385. $tabs = $context.children(selector.tabs);
  15386. module.debug('Searching tab context children for tabs', $context, $tabs);
  15387. }
  15388. else {
  15389. $tabs = $context.find(selector.tabs);
  15390. module.debug('Searching tab context for tabs', $context, $tabs);
  15391. }
  15392. },
  15393. fix: {
  15394. callbacks: function() {
  15395. if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
  15396. if(parameters.onTabLoad) {
  15397. parameters.onLoad = parameters.onTabLoad;
  15398. delete parameters.onTabLoad;
  15399. module.error(error.legacyLoad, parameters.onLoad);
  15400. }
  15401. if(parameters.onTabInit) {
  15402. parameters.onFirstLoad = parameters.onTabInit;
  15403. delete parameters.onTabInit;
  15404. module.error(error.legacyInit, parameters.onFirstLoad);
  15405. }
  15406. settings = $.extend(true, {}, $.fn.tab.settings, parameters);
  15407. }
  15408. }
  15409. },
  15410. initializeHistory: function() {
  15411. module.debug('Initializing page state');
  15412. if( $.address === undefined ) {
  15413. module.error(error.state);
  15414. return false;
  15415. }
  15416. else {
  15417. if(settings.historyType == 'state') {
  15418. module.debug('Using HTML5 to manage state');
  15419. if(settings.path !== false) {
  15420. $.address
  15421. .history(true)
  15422. .state(settings.path)
  15423. ;
  15424. }
  15425. else {
  15426. module.error(error.path);
  15427. return false;
  15428. }
  15429. }
  15430. $.address
  15431. .bind('change', module.event.history.change)
  15432. ;
  15433. }
  15434. },
  15435. event: {
  15436. click: function(event) {
  15437. var
  15438. tabPath = $(this).data(metadata.tab)
  15439. ;
  15440. if(tabPath !== undefined) {
  15441. if(settings.history) {
  15442. module.verbose('Updating page state', event);
  15443. $.address.value(tabPath);
  15444. }
  15445. else {
  15446. module.verbose('Changing tab', event);
  15447. module.changeTab(tabPath);
  15448. }
  15449. event.preventDefault();
  15450. }
  15451. else {
  15452. module.debug('No tab specified');
  15453. }
  15454. },
  15455. history: {
  15456. change: function(event) {
  15457. var
  15458. tabPath = event.pathNames.join('/') || module.get.initialPath(),
  15459. pageTitle = settings.templates.determineTitle(tabPath) || false
  15460. ;
  15461. module.performance.display();
  15462. module.debug('History change event', tabPath, event);
  15463. historyEvent = event;
  15464. if(tabPath !== undefined) {
  15465. module.changeTab(tabPath);
  15466. }
  15467. if(pageTitle) {
  15468. $.address.title(pageTitle);
  15469. }
  15470. }
  15471. }
  15472. },
  15473. refresh: function() {
  15474. if(activeTabPath) {
  15475. module.debug('Refreshing tab', activeTabPath);
  15476. module.changeTab(activeTabPath);
  15477. }
  15478. },
  15479. cache: {
  15480. read: function(cacheKey) {
  15481. return (cacheKey !== undefined)
  15482. ? cache[cacheKey]
  15483. : false
  15484. ;
  15485. },
  15486. add: function(cacheKey, content) {
  15487. cacheKey = cacheKey || activeTabPath;
  15488. module.debug('Adding cached content for', cacheKey);
  15489. cache[cacheKey] = content;
  15490. },
  15491. remove: function(cacheKey) {
  15492. cacheKey = cacheKey || activeTabPath;
  15493. module.debug('Removing cached content for', cacheKey);
  15494. delete cache[cacheKey];
  15495. }
  15496. },
  15497. set: {
  15498. auto: function() {
  15499. var
  15500. url = (typeof settings.path == 'string')
  15501. ? settings.path.replace(/\/$/, '') + '/{$tab}'
  15502. : '/{$tab}'
  15503. ;
  15504. module.verbose('Setting up automatic tab retrieval from server', url);
  15505. if($.isPlainObject(settings.apiSettings)) {
  15506. settings.apiSettings.url = url;
  15507. }
  15508. else {
  15509. settings.apiSettings = {
  15510. url: url
  15511. };
  15512. }
  15513. },
  15514. loading: function(tabPath) {
  15515. var
  15516. $tab = module.get.tabElement(tabPath),
  15517. isLoading = $tab.hasClass(className.loading)
  15518. ;
  15519. if(!isLoading) {
  15520. module.verbose('Setting loading state for', $tab);
  15521. $tab
  15522. .addClass(className.loading)
  15523. .siblings($tabs)
  15524. .removeClass(className.active + ' ' + className.loading)
  15525. ;
  15526. if($tab.length > 0) {
  15527. settings.onRequest.call($tab[0], tabPath);
  15528. }
  15529. }
  15530. },
  15531. state: function(state) {
  15532. $.address.value(state);
  15533. }
  15534. },
  15535. changeTab: function(tabPath) {
  15536. var
  15537. pushStateAvailable = (window.history && window.history.pushState),
  15538. shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
  15539. remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
  15540. // only add default path if not remote content
  15541. pathArray = (remoteContent && !shouldIgnoreLoad)
  15542. ? module.utilities.pathToArray(tabPath)
  15543. : module.get.defaultPathArray(tabPath)
  15544. ;
  15545. tabPath = module.utilities.arrayToPath(pathArray);
  15546. $.each(pathArray, function(index, tab) {
  15547. var
  15548. currentPathArray = pathArray.slice(0, index + 1),
  15549. currentPath = module.utilities.arrayToPath(currentPathArray),
  15550. isTab = module.is.tab(currentPath),
  15551. isLastIndex = (index + 1 == pathArray.length),
  15552. $tab = module.get.tabElement(currentPath),
  15553. $anchor,
  15554. nextPathArray,
  15555. nextPath,
  15556. isLastTab
  15557. ;
  15558. module.verbose('Looking for tab', tab);
  15559. if(isTab) {
  15560. module.verbose('Tab was found', tab);
  15561. // scope up
  15562. activeTabPath = currentPath;
  15563. parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
  15564. if(isLastIndex) {
  15565. isLastTab = true;
  15566. }
  15567. else {
  15568. nextPathArray = pathArray.slice(0, index + 2);
  15569. nextPath = module.utilities.arrayToPath(nextPathArray);
  15570. isLastTab = ( !module.is.tab(nextPath) );
  15571. if(isLastTab) {
  15572. module.verbose('Tab parameters found', nextPathArray);
  15573. }
  15574. }
  15575. if(isLastTab && remoteContent) {
  15576. if(!shouldIgnoreLoad) {
  15577. module.activate.navigation(currentPath);
  15578. module.fetch.content(currentPath, tabPath);
  15579. }
  15580. else {
  15581. module.debug('Ignoring remote content on first tab load', currentPath);
  15582. firstLoad = false;
  15583. module.cache.add(tabPath, $tab.html());
  15584. module.activate.all(currentPath);
  15585. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  15586. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  15587. }
  15588. return false;
  15589. }
  15590. else {
  15591. module.debug('Opened local tab', currentPath);
  15592. module.activate.all(currentPath);
  15593. if( !module.cache.read(currentPath) ) {
  15594. module.cache.add(currentPath, true);
  15595. module.debug('First time tab loaded calling tab init');
  15596. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  15597. }
  15598. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  15599. }
  15600. }
  15601. else if(tabPath.search('/') == -1 && tabPath !== '') {
  15602. // look for in page anchor
  15603. $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
  15604. currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
  15605. $tab = module.get.tabElement(currentPath);
  15606. // if anchor exists use parent tab
  15607. if($anchor && $anchor.length > 0 && currentPath) {
  15608. module.debug('Anchor link used, opening parent tab', $tab, $anchor);
  15609. if( !$tab.hasClass(className.active) ) {
  15610. setTimeout(function() {
  15611. module.scrollTo($anchor);
  15612. }, 0);
  15613. }
  15614. module.activate.all(currentPath);
  15615. if( !module.cache.read(currentPath) ) {
  15616. module.cache.add(currentPath, true);
  15617. module.debug('First time tab loaded calling tab init');
  15618. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  15619. }
  15620. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  15621. return false;
  15622. }
  15623. }
  15624. else {
  15625. module.error(error.missingTab, $module, $context, currentPath);
  15626. return false;
  15627. }
  15628. });
  15629. },
  15630. scrollTo: function($element) {
  15631. var
  15632. scrollOffset = ($element && $element.length > 0)
  15633. ? $element.offset().top
  15634. : false
  15635. ;
  15636. if(scrollOffset !== false) {
  15637. module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
  15638. $(document).scrollTop(scrollOffset);
  15639. }
  15640. },
  15641. update: {
  15642. content: function(tabPath, html, evaluateScripts) {
  15643. var
  15644. $tab = module.get.tabElement(tabPath),
  15645. tab = $tab[0]
  15646. ;
  15647. evaluateScripts = (evaluateScripts !== undefined)
  15648. ? evaluateScripts
  15649. : settings.evaluateScripts
  15650. ;
  15651. if(evaluateScripts) {
  15652. module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
  15653. $tab.html(html);
  15654. }
  15655. else {
  15656. module.debug('Updating HTML', tabPath, html);
  15657. tab.innerHTML = html;
  15658. }
  15659. }
  15660. },
  15661. fetch: {
  15662. content: function(tabPath, fullTabPath) {
  15663. var
  15664. $tab = module.get.tabElement(tabPath),
  15665. apiSettings = {
  15666. dataType : 'html',
  15667. encodeParameters : false,
  15668. on : 'now',
  15669. cache : settings.alwaysRefresh,
  15670. headers : {
  15671. 'X-Remote': true
  15672. },
  15673. onSuccess : function(response) {
  15674. module.cache.add(fullTabPath, response);
  15675. module.update.content(tabPath, response);
  15676. if(tabPath == activeTabPath) {
  15677. module.debug('Content loaded', tabPath);
  15678. module.activate.tab(tabPath);
  15679. }
  15680. else {
  15681. module.debug('Content loaded in background', tabPath);
  15682. }
  15683. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  15684. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  15685. },
  15686. urlData: {
  15687. tab: fullTabPath
  15688. }
  15689. },
  15690. request = $tab.api('get request') || false,
  15691. existingRequest = ( request && request.state() === 'pending' ),
  15692. requestSettings,
  15693. cachedContent
  15694. ;
  15695. fullTabPath = fullTabPath || tabPath;
  15696. cachedContent = module.cache.read(fullTabPath);
  15697. if(settings.cache && cachedContent) {
  15698. module.activate.tab(tabPath);
  15699. module.debug('Adding cached content', fullTabPath);
  15700. if(settings.evaluateScripts == 'once') {
  15701. module.update.content(tabPath, cachedContent, false);
  15702. }
  15703. else {
  15704. module.update.content(tabPath, cachedContent);
  15705. }
  15706. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  15707. }
  15708. else if(existingRequest) {
  15709. module.set.loading(tabPath);
  15710. module.debug('Content is already loading', fullTabPath);
  15711. }
  15712. else if($.api !== undefined) {
  15713. requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
  15714. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  15715. module.set.loading(tabPath);
  15716. $tab.api(requestSettings);
  15717. }
  15718. else {
  15719. module.error(error.api);
  15720. }
  15721. }
  15722. },
  15723. activate: {
  15724. all: function(tabPath) {
  15725. module.activate.tab(tabPath);
  15726. module.activate.navigation(tabPath);
  15727. },
  15728. tab: function(tabPath) {
  15729. var
  15730. $tab = module.get.tabElement(tabPath),
  15731. isActive = $tab.hasClass(className.active)
  15732. ;
  15733. module.verbose('Showing tab content for', $tab);
  15734. if(!isActive) {
  15735. $tab
  15736. .addClass(className.active)
  15737. .siblings($tabs)
  15738. .removeClass(className.active + ' ' + className.loading)
  15739. ;
  15740. if($tab.length > 0) {
  15741. settings.onVisible.call($tab[0], tabPath);
  15742. }
  15743. }
  15744. },
  15745. navigation: function(tabPath) {
  15746. var
  15747. $navigation = module.get.navElement(tabPath),
  15748. isActive = $navigation.hasClass(className.active)
  15749. ;
  15750. module.verbose('Activating tab navigation for', $navigation, tabPath);
  15751. if(!isActive) {
  15752. $navigation
  15753. .addClass(className.active)
  15754. .siblings($allModules)
  15755. .removeClass(className.active + ' ' + className.loading)
  15756. ;
  15757. }
  15758. }
  15759. },
  15760. deactivate: {
  15761. all: function() {
  15762. module.deactivate.navigation();
  15763. module.deactivate.tabs();
  15764. },
  15765. navigation: function() {
  15766. $allModules
  15767. .removeClass(className.active)
  15768. ;
  15769. },
  15770. tabs: function() {
  15771. $tabs
  15772. .removeClass(className.active + ' ' + className.loading)
  15773. ;
  15774. }
  15775. },
  15776. is: {
  15777. tab: function(tabName) {
  15778. return (tabName !== undefined)
  15779. ? ( module.get.tabElement(tabName).length > 0 )
  15780. : false
  15781. ;
  15782. }
  15783. },
  15784. get: {
  15785. initialPath: function() {
  15786. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  15787. },
  15788. path: function() {
  15789. return $.address.value();
  15790. },
  15791. // adds default tabs to tab path
  15792. defaultPathArray: function(tabPath) {
  15793. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  15794. },
  15795. defaultPath: function(tabPath) {
  15796. var
  15797. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0),
  15798. defaultTab = $defaultNav.data(metadata.tab) || false
  15799. ;
  15800. if( defaultTab ) {
  15801. module.debug('Found default tab', defaultTab);
  15802. if(recursionDepth < settings.maxDepth) {
  15803. recursionDepth++;
  15804. return module.get.defaultPath(defaultTab);
  15805. }
  15806. module.error(error.recursion);
  15807. }
  15808. else {
  15809. module.debug('No default tabs found for', tabPath, $tabs);
  15810. }
  15811. recursionDepth = 0;
  15812. return tabPath;
  15813. },
  15814. navElement: function(tabPath) {
  15815. tabPath = tabPath || activeTabPath;
  15816. return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  15817. },
  15818. tabElement: function(tabPath) {
  15819. var
  15820. $fullPathTab,
  15821. $simplePathTab,
  15822. tabPathArray,
  15823. lastTab
  15824. ;
  15825. tabPath = tabPath || activeTabPath;
  15826. tabPathArray = module.utilities.pathToArray(tabPath);
  15827. lastTab = module.utilities.last(tabPathArray);
  15828. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  15829. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]');
  15830. return ($fullPathTab.length > 0)
  15831. ? $fullPathTab
  15832. : $simplePathTab
  15833. ;
  15834. },
  15835. tab: function() {
  15836. return activeTabPath;
  15837. }
  15838. },
  15839. utilities: {
  15840. filterArray: function(keepArray, removeArray) {
  15841. return $.grep(keepArray, function(keepValue) {
  15842. return ( $.inArray(keepValue, removeArray) == -1);
  15843. });
  15844. },
  15845. last: function(array) {
  15846. return $.isArray(array)
  15847. ? array[ array.length - 1]
  15848. : false
  15849. ;
  15850. },
  15851. pathToArray: function(pathName) {
  15852. if(pathName === undefined) {
  15853. pathName = activeTabPath;
  15854. }
  15855. return typeof pathName == 'string'
  15856. ? pathName.split('/')
  15857. : [pathName]
  15858. ;
  15859. },
  15860. arrayToPath: function(pathArray) {
  15861. return $.isArray(pathArray)
  15862. ? pathArray.join('/')
  15863. : false
  15864. ;
  15865. }
  15866. },
  15867. setting: function(name, value) {
  15868. module.debug('Changing setting', name, value);
  15869. if( $.isPlainObject(name) ) {
  15870. $.extend(true, settings, name);
  15871. }
  15872. else if(value !== undefined) {
  15873. settings[name] = value;
  15874. }
  15875. else {
  15876. return settings[name];
  15877. }
  15878. },
  15879. internal: function(name, value) {
  15880. if( $.isPlainObject(name) ) {
  15881. $.extend(true, module, name);
  15882. }
  15883. else if(value !== undefined) {
  15884. module[name] = value;
  15885. }
  15886. else {
  15887. return module[name];
  15888. }
  15889. },
  15890. debug: function() {
  15891. if(settings.debug) {
  15892. if(settings.performance) {
  15893. module.performance.log(arguments);
  15894. }
  15895. else {
  15896. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15897. module.debug.apply(console, arguments);
  15898. }
  15899. }
  15900. },
  15901. verbose: function() {
  15902. if(settings.verbose && settings.debug) {
  15903. if(settings.performance) {
  15904. module.performance.log(arguments);
  15905. }
  15906. else {
  15907. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  15908. module.verbose.apply(console, arguments);
  15909. }
  15910. }
  15911. },
  15912. error: function() {
  15913. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  15914. module.error.apply(console, arguments);
  15915. },
  15916. performance: {
  15917. log: function(message) {
  15918. var
  15919. currentTime,
  15920. executionTime,
  15921. previousTime
  15922. ;
  15923. if(settings.performance) {
  15924. currentTime = new Date().getTime();
  15925. previousTime = time || currentTime;
  15926. executionTime = currentTime - previousTime;
  15927. time = currentTime;
  15928. performance.push({
  15929. 'Name' : message[0],
  15930. 'Arguments' : [].slice.call(message, 1) || '',
  15931. 'Element' : element,
  15932. 'Execution Time' : executionTime
  15933. });
  15934. }
  15935. clearTimeout(module.performance.timer);
  15936. module.performance.timer = setTimeout(module.performance.display, 500);
  15937. },
  15938. display: function() {
  15939. var
  15940. title = settings.name + ':',
  15941. totalTime = 0
  15942. ;
  15943. time = false;
  15944. clearTimeout(module.performance.timer);
  15945. $.each(performance, function(index, data) {
  15946. totalTime += data['Execution Time'];
  15947. });
  15948. title += ' ' + totalTime + 'ms';
  15949. if(moduleSelector) {
  15950. title += ' \'' + moduleSelector + '\'';
  15951. }
  15952. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  15953. console.groupCollapsed(title);
  15954. if(console.table) {
  15955. console.table(performance);
  15956. }
  15957. else {
  15958. $.each(performance, function(index, data) {
  15959. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  15960. });
  15961. }
  15962. console.groupEnd();
  15963. }
  15964. performance = [];
  15965. }
  15966. },
  15967. invoke: function(query, passedArguments, context) {
  15968. var
  15969. object = instance,
  15970. maxDepth,
  15971. found,
  15972. response
  15973. ;
  15974. passedArguments = passedArguments || queryArguments;
  15975. context = element || context;
  15976. if(typeof query == 'string' && object !== undefined) {
  15977. query = query.split(/[\. ]/);
  15978. maxDepth = query.length - 1;
  15979. $.each(query, function(depth, value) {
  15980. var camelCaseValue = (depth != maxDepth)
  15981. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  15982. : query
  15983. ;
  15984. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  15985. object = object[camelCaseValue];
  15986. }
  15987. else if( object[camelCaseValue] !== undefined ) {
  15988. found = object[camelCaseValue];
  15989. return false;
  15990. }
  15991. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  15992. object = object[value];
  15993. }
  15994. else if( object[value] !== undefined ) {
  15995. found = object[value];
  15996. return false;
  15997. }
  15998. else {
  15999. module.error(error.method, query);
  16000. return false;
  16001. }
  16002. });
  16003. }
  16004. if ( $.isFunction( found ) ) {
  16005. response = found.apply(context, passedArguments);
  16006. }
  16007. else if(found !== undefined) {
  16008. response = found;
  16009. }
  16010. if($.isArray(returnedValue)) {
  16011. returnedValue.push(response);
  16012. }
  16013. else if(returnedValue !== undefined) {
  16014. returnedValue = [returnedValue, response];
  16015. }
  16016. else if(response !== undefined) {
  16017. returnedValue = response;
  16018. }
  16019. return found;
  16020. }
  16021. };
  16022. if(methodInvoked) {
  16023. if(instance === undefined) {
  16024. module.initialize();
  16025. }
  16026. module.invoke(query);
  16027. }
  16028. else {
  16029. if(instance !== undefined) {
  16030. instance.invoke('destroy');
  16031. }
  16032. module.initialize();
  16033. }
  16034. })
  16035. ;
  16036. return (returnedValue !== undefined)
  16037. ? returnedValue
  16038. : this
  16039. ;
  16040. };
  16041. // shortcut for tabbed content with no defined navigation
  16042. $.tab = function() {
  16043. $(window).tab.apply(this, arguments);
  16044. };
  16045. $.fn.tab.settings = {
  16046. name : 'Tab',
  16047. namespace : 'tab',
  16048. debug : false,
  16049. verbose : false,
  16050. performance : true,
  16051. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  16052. history : false, // use browser history
  16053. historyType : 'hash', // #/ or html5 state
  16054. path : false, // base path of url
  16055. context : false, // specify a context that tabs must appear inside
  16056. childrenOnly : false, // use only tabs that are children of context
  16057. maxDepth : 25, // max depth a tab can be nested
  16058. alwaysRefresh : false, // load tab content new every tab click
  16059. cache : true, // cache the content requests to pull locally
  16060. ignoreFirstLoad : false, // don't load remote content on first load
  16061. apiSettings : false, // settings for api call
  16062. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  16063. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  16064. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  16065. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  16066. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  16067. templates : {
  16068. determineTitle: function(tabArray) {} // returns page title for path
  16069. },
  16070. error: {
  16071. api : 'You attempted to load content without API module',
  16072. method : 'The method you called is not defined',
  16073. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  16074. noContent : 'The tab you specified is missing a content url.',
  16075. path : 'History enabled, but no path was specified',
  16076. recursion : 'Max recursive depth reached',
  16077. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  16078. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  16079. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  16080. },
  16081. metadata : {
  16082. tab : 'tab',
  16083. loaded : 'loaded',
  16084. promise: 'promise'
  16085. },
  16086. className : {
  16087. loading : 'loading',
  16088. active : 'active'
  16089. },
  16090. selector : {
  16091. tabs : '.ui.tab',
  16092. ui : '.ui'
  16093. }
  16094. };
  16095. })( jQuery, window, document );
  16096. /*!
  16097. * # Semantic UI 2.1.6 - Transition
  16098. * http://github.com/semantic-org/semantic-ui/
  16099. *
  16100. *
  16101. * Copyright 2015 Contributors
  16102. * Released under the MIT license
  16103. * http://opensource.org/licenses/MIT
  16104. *
  16105. */
  16106. ;(function ( $, window, document, undefined ) {
  16107. "use strict";
  16108. $.fn.transition = function() {
  16109. var
  16110. $allModules = $(this),
  16111. moduleSelector = $allModules.selector || '',
  16112. time = new Date().getTime(),
  16113. performance = [],
  16114. moduleArguments = arguments,
  16115. query = moduleArguments[0],
  16116. queryArguments = [].slice.call(arguments, 1),
  16117. methodInvoked = (typeof query === 'string'),
  16118. requestAnimationFrame = window.requestAnimationFrame
  16119. || window.mozRequestAnimationFrame
  16120. || window.webkitRequestAnimationFrame
  16121. || window.msRequestAnimationFrame
  16122. || function(callback) { setTimeout(callback, 0); },
  16123. returnedValue
  16124. ;
  16125. $allModules
  16126. .each(function(index) {
  16127. var
  16128. $module = $(this),
  16129. element = this,
  16130. // set at run time
  16131. settings,
  16132. instance,
  16133. error,
  16134. className,
  16135. metadata,
  16136. animationEnd,
  16137. animationName,
  16138. namespace,
  16139. moduleNamespace,
  16140. eventNamespace,
  16141. module
  16142. ;
  16143. module = {
  16144. initialize: function() {
  16145. // get full settings
  16146. settings = module.get.settings.apply(element, moduleArguments);
  16147. // shorthand
  16148. className = settings.className;
  16149. error = settings.error;
  16150. metadata = settings.metadata;
  16151. // define namespace
  16152. eventNamespace = '.' + settings.namespace;
  16153. moduleNamespace = 'module-' + settings.namespace;
  16154. instance = $module.data(moduleNamespace) || module;
  16155. // get vendor specific events
  16156. animationEnd = module.get.animationEndEvent();
  16157. if(methodInvoked) {
  16158. methodInvoked = module.invoke(query);
  16159. }
  16160. // method not invoked, lets run an animation
  16161. if(methodInvoked === false) {
  16162. module.verbose('Converted arguments into settings object', settings);
  16163. if(settings.interval) {
  16164. module.delay(settings.animate);
  16165. }
  16166. else {
  16167. module.animate();
  16168. }
  16169. module.instantiate();
  16170. }
  16171. },
  16172. instantiate: function() {
  16173. module.verbose('Storing instance of module', module);
  16174. instance = module;
  16175. $module
  16176. .data(moduleNamespace, instance)
  16177. ;
  16178. },
  16179. destroy: function() {
  16180. module.verbose('Destroying previous module for', element);
  16181. $module
  16182. .removeData(moduleNamespace)
  16183. ;
  16184. },
  16185. refresh: function() {
  16186. module.verbose('Refreshing display type on next animation');
  16187. delete module.displayType;
  16188. },
  16189. forceRepaint: function() {
  16190. module.verbose('Forcing element repaint');
  16191. var
  16192. $parentElement = $module.parent(),
  16193. $nextElement = $module.next()
  16194. ;
  16195. if($nextElement.length === 0) {
  16196. $module.detach().appendTo($parentElement);
  16197. }
  16198. else {
  16199. $module.detach().insertBefore($nextElement);
  16200. }
  16201. },
  16202. repaint: function() {
  16203. module.verbose('Repainting element');
  16204. var
  16205. fakeAssignment = element.offsetWidth
  16206. ;
  16207. },
  16208. delay: function(interval) {
  16209. var
  16210. direction = module.get.animationDirection(),
  16211. shouldReverse,
  16212. delay
  16213. ;
  16214. if(!direction) {
  16215. direction = module.can.transition()
  16216. ? module.get.direction()
  16217. : 'static'
  16218. ;
  16219. }
  16220. interval = (interval !== undefined)
  16221. ? interval
  16222. : settings.interval
  16223. ;
  16224. shouldReverse = (settings.reverse == 'auto' && direction == className.outward);
  16225. delay = (shouldReverse || settings.reverse == true)
  16226. ? ($allModules.length - index) * settings.interval
  16227. : index * settings.interval
  16228. ;
  16229. module.debug('Delaying animation by', delay);
  16230. setTimeout(module.animate, delay);
  16231. },
  16232. animate: function(overrideSettings) {
  16233. settings = overrideSettings || settings;
  16234. if(!module.is.supported()) {
  16235. module.error(error.support);
  16236. return false;
  16237. }
  16238. module.debug('Preparing animation', settings.animation);
  16239. if(module.is.animating()) {
  16240. if(settings.queue) {
  16241. if(!settings.allowRepeats && module.has.direction() && module.is.occurring() && module.queuing !== true) {
  16242. module.debug('Animation is currently occurring, preventing queueing same animation', settings.animation);
  16243. }
  16244. else {
  16245. module.queue(settings.animation);
  16246. }
  16247. return false;
  16248. }
  16249. else if(!settings.allowRepeats && module.is.occurring()) {
  16250. module.debug('Animation is already occurring, will not execute repeated animation', settings.animation);
  16251. return false;
  16252. }
  16253. else {
  16254. module.debug('New animation started, completing previous early', settings.animation);
  16255. instance.complete();
  16256. }
  16257. }
  16258. if( module.can.animate() ) {
  16259. module.set.animating(settings.animation);
  16260. }
  16261. else {
  16262. module.error(error.noAnimation, settings.animation, element);
  16263. }
  16264. },
  16265. reset: function() {
  16266. module.debug('Resetting animation to beginning conditions');
  16267. module.remove.animationCallbacks();
  16268. module.restore.conditions();
  16269. module.remove.animating();
  16270. },
  16271. queue: function(animation) {
  16272. module.debug('Queueing animation of', animation);
  16273. module.queuing = true;
  16274. $module
  16275. .one(animationEnd + '.queue' + eventNamespace, function() {
  16276. module.queuing = false;
  16277. module.repaint();
  16278. module.animate.apply(this, settings);
  16279. })
  16280. ;
  16281. },
  16282. complete: function (event) {
  16283. module.debug('Animation complete', settings.animation);
  16284. module.remove.completeCallback();
  16285. module.remove.failSafe();
  16286. if(!module.is.looping()) {
  16287. if( module.is.outward() ) {
  16288. module.verbose('Animation is outward, hiding element');
  16289. module.restore.conditions();
  16290. module.hide();
  16291. }
  16292. else if( module.is.inward() ) {
  16293. module.verbose('Animation is outward, showing element');
  16294. module.restore.conditions();
  16295. module.show();
  16296. }
  16297. else {
  16298. module.verbose('Static animation completed');
  16299. module.restore.conditions();
  16300. settings.onComplete.call(element);
  16301. }
  16302. }
  16303. },
  16304. force: {
  16305. visible: function() {
  16306. var
  16307. style = $module.attr('style'),
  16308. userStyle = module.get.userStyle(),
  16309. displayType = module.get.displayType(),
  16310. overrideStyle = userStyle + 'display: ' + displayType + ' !important;',
  16311. currentDisplay = $module.css('display'),
  16312. emptyStyle = (style === undefined || style === '')
  16313. ;
  16314. if(currentDisplay !== displayType) {
  16315. module.verbose('Overriding default display to show element', displayType);
  16316. $module
  16317. .attr('style', overrideStyle)
  16318. ;
  16319. }
  16320. else if(emptyStyle) {
  16321. $module.removeAttr('style');
  16322. }
  16323. },
  16324. hidden: function() {
  16325. var
  16326. style = $module.attr('style'),
  16327. currentDisplay = $module.css('display'),
  16328. emptyStyle = (style === undefined || style === '')
  16329. ;
  16330. if(currentDisplay !== 'none' && !module.is.hidden()) {
  16331. module.verbose('Overriding default display to hide element');
  16332. $module
  16333. .css('display', 'none')
  16334. ;
  16335. }
  16336. else if(emptyStyle) {
  16337. $module
  16338. .removeAttr('style')
  16339. ;
  16340. }
  16341. }
  16342. },
  16343. has: {
  16344. direction: function(animation) {
  16345. var
  16346. hasDirection = false
  16347. ;
  16348. animation = animation || settings.animation;
  16349. if(typeof animation === 'string') {
  16350. animation = animation.split(' ');
  16351. $.each(animation, function(index, word){
  16352. if(word === className.inward || word === className.outward) {
  16353. hasDirection = true;
  16354. }
  16355. });
  16356. }
  16357. return hasDirection;
  16358. },
  16359. inlineDisplay: function() {
  16360. var
  16361. style = $module.attr('style') || ''
  16362. ;
  16363. return $.isArray(style.match(/display.*?;/, ''));
  16364. }
  16365. },
  16366. set: {
  16367. animating: function(animation) {
  16368. var
  16369. animationClass,
  16370. direction
  16371. ;
  16372. // remove previous callbacks
  16373. module.remove.completeCallback();
  16374. // determine exact animation
  16375. animation = animation || settings.animation;
  16376. animationClass = module.get.animationClass(animation);
  16377. // save animation class in cache to restore class names
  16378. module.save.animation(animationClass);
  16379. // override display if necessary so animation appears visibly
  16380. module.force.visible();
  16381. module.remove.hidden();
  16382. module.remove.direction();
  16383. module.start.animation(animationClass);
  16384. },
  16385. duration: function(animationName, duration) {
  16386. duration = duration || settings.duration;
  16387. duration = (typeof duration == 'number')
  16388. ? duration + 'ms'
  16389. : duration
  16390. ;
  16391. if(duration || duration === 0) {
  16392. module.verbose('Setting animation duration', duration);
  16393. $module
  16394. .css({
  16395. 'animation-duration': duration
  16396. })
  16397. ;
  16398. }
  16399. },
  16400. direction: function(direction) {
  16401. direction = direction || module.get.direction();
  16402. if(direction == className.inward) {
  16403. module.set.inward();
  16404. }
  16405. else {
  16406. module.set.outward();
  16407. }
  16408. },
  16409. looping: function() {
  16410. module.debug('Transition set to loop');
  16411. $module
  16412. .addClass(className.looping)
  16413. ;
  16414. },
  16415. hidden: function() {
  16416. $module
  16417. .addClass(className.transition)
  16418. .addClass(className.hidden)
  16419. ;
  16420. },
  16421. inward: function() {
  16422. module.debug('Setting direction to inward');
  16423. $module
  16424. .removeClass(className.outward)
  16425. .addClass(className.inward)
  16426. ;
  16427. },
  16428. outward: function() {
  16429. module.debug('Setting direction to outward');
  16430. $module
  16431. .removeClass(className.inward)
  16432. .addClass(className.outward)
  16433. ;
  16434. },
  16435. visible: function() {
  16436. $module
  16437. .addClass(className.transition)
  16438. .addClass(className.visible)
  16439. ;
  16440. }
  16441. },
  16442. start: {
  16443. animation: function(animationClass) {
  16444. animationClass = animationClass || module.get.animationClass();
  16445. module.debug('Starting tween', animationClass);
  16446. $module
  16447. .addClass(animationClass)
  16448. .one(animationEnd + '.complete' + eventNamespace, module.complete)
  16449. ;
  16450. if(settings.useFailSafe) {
  16451. module.add.failSafe();
  16452. }
  16453. module.set.duration(settings.duration);
  16454. settings.onStart.call(element);
  16455. }
  16456. },
  16457. save: {
  16458. animation: function(animation) {
  16459. if(!module.cache) {
  16460. module.cache = {};
  16461. }
  16462. module.cache.animation = animation;
  16463. },
  16464. displayType: function(displayType) {
  16465. if(displayType !== 'none') {
  16466. $module.data(metadata.displayType, displayType);
  16467. }
  16468. },
  16469. transitionExists: function(animation, exists) {
  16470. $.fn.transition.exists[animation] = exists;
  16471. module.verbose('Saving existence of transition', animation, exists);
  16472. }
  16473. },
  16474. restore: {
  16475. conditions: function() {
  16476. var
  16477. animation = module.get.currentAnimation()
  16478. ;
  16479. if(animation) {
  16480. $module
  16481. .removeClass(animation)
  16482. ;
  16483. module.verbose('Removing animation class', module.cache);
  16484. }
  16485. module.remove.duration();
  16486. }
  16487. },
  16488. add: {
  16489. failSafe: function() {
  16490. var
  16491. duration = module.get.duration()
  16492. ;
  16493. module.timer = setTimeout(function() {
  16494. $module.triggerHandler(animationEnd);
  16495. }, duration + settings.failSafeDelay);
  16496. module.verbose('Adding fail safe timer', module.timer);
  16497. }
  16498. },
  16499. remove: {
  16500. animating: function() {
  16501. $module.removeClass(className.animating);
  16502. },
  16503. animationCallbacks: function() {
  16504. module.remove.queueCallback();
  16505. module.remove.completeCallback();
  16506. },
  16507. queueCallback: function() {
  16508. $module.off('.queue' + eventNamespace);
  16509. },
  16510. completeCallback: function() {
  16511. $module.off('.complete' + eventNamespace);
  16512. },
  16513. display: function() {
  16514. $module.css('display', '');
  16515. },
  16516. direction: function() {
  16517. $module
  16518. .removeClass(className.inward)
  16519. .removeClass(className.outward)
  16520. ;
  16521. },
  16522. duration: function() {
  16523. $module
  16524. .css('animation-duration', '')
  16525. ;
  16526. },
  16527. failSafe: function() {
  16528. module.verbose('Removing fail safe timer', module.timer);
  16529. if(module.timer) {
  16530. clearTimeout(module.timer);
  16531. }
  16532. },
  16533. hidden: function() {
  16534. $module.removeClass(className.hidden);
  16535. },
  16536. visible: function() {
  16537. $module.removeClass(className.visible);
  16538. },
  16539. looping: function() {
  16540. module.debug('Transitions are no longer looping');
  16541. if( module.is.looping() ) {
  16542. module.reset();
  16543. $module
  16544. .removeClass(className.looping)
  16545. ;
  16546. }
  16547. },
  16548. transition: function() {
  16549. $module
  16550. .removeClass(className.visible)
  16551. .removeClass(className.hidden)
  16552. ;
  16553. }
  16554. },
  16555. get: {
  16556. settings: function(animation, duration, onComplete) {
  16557. // single settings object
  16558. if(typeof animation == 'object') {
  16559. return $.extend(true, {}, $.fn.transition.settings, animation);
  16560. }
  16561. // all arguments provided
  16562. else if(typeof onComplete == 'function') {
  16563. return $.extend({}, $.fn.transition.settings, {
  16564. animation : animation,
  16565. onComplete : onComplete,
  16566. duration : duration
  16567. });
  16568. }
  16569. // only duration provided
  16570. else if(typeof duration == 'string' || typeof duration == 'number') {
  16571. return $.extend({}, $.fn.transition.settings, {
  16572. animation : animation,
  16573. duration : duration
  16574. });
  16575. }
  16576. // duration is actually settings object
  16577. else if(typeof duration == 'object') {
  16578. return $.extend({}, $.fn.transition.settings, duration, {
  16579. animation : animation
  16580. });
  16581. }
  16582. // duration is actually callback
  16583. else if(typeof duration == 'function') {
  16584. return $.extend({}, $.fn.transition.settings, {
  16585. animation : animation,
  16586. onComplete : duration
  16587. });
  16588. }
  16589. // only animation provided
  16590. else {
  16591. return $.extend({}, $.fn.transition.settings, {
  16592. animation : animation
  16593. });
  16594. }
  16595. return $.fn.transition.settings;
  16596. },
  16597. animationClass: function(animation) {
  16598. var
  16599. animationClass = animation || settings.animation,
  16600. directionClass = (module.can.transition() && !module.has.direction())
  16601. ? module.get.direction() + ' '
  16602. : ''
  16603. ;
  16604. return className.animating + ' '
  16605. + className.transition + ' '
  16606. + directionClass
  16607. + animationClass
  16608. ;
  16609. },
  16610. currentAnimation: function() {
  16611. return (module.cache && module.cache.animation !== undefined)
  16612. ? module.cache.animation
  16613. : false
  16614. ;
  16615. },
  16616. currentDirection: function() {
  16617. return module.is.inward()
  16618. ? className.inward
  16619. : className.outward
  16620. ;
  16621. },
  16622. direction: function() {
  16623. return module.is.hidden() || !module.is.visible()
  16624. ? className.inward
  16625. : className.outward
  16626. ;
  16627. },
  16628. animationDirection: function(animation) {
  16629. var
  16630. direction
  16631. ;
  16632. animation = animation || settings.animation;
  16633. if(typeof animation === 'string') {
  16634. animation = animation.split(' ');
  16635. // search animation name for out/in class
  16636. $.each(animation, function(index, word){
  16637. if(word === className.inward) {
  16638. direction = className.inward;
  16639. }
  16640. else if(word === className.outward) {
  16641. direction = className.outward;
  16642. }
  16643. });
  16644. }
  16645. // return found direction
  16646. if(direction) {
  16647. return direction;
  16648. }
  16649. return false;
  16650. },
  16651. duration: function(duration) {
  16652. duration = duration || settings.duration;
  16653. if(duration === false) {
  16654. duration = $module.css('animation-duration') || 0;
  16655. }
  16656. return (typeof duration === 'string')
  16657. ? (duration.indexOf('ms') > -1)
  16658. ? parseFloat(duration)
  16659. : parseFloat(duration) * 1000
  16660. : duration
  16661. ;
  16662. },
  16663. displayType: function() {
  16664. if(settings.displayType) {
  16665. return settings.displayType;
  16666. }
  16667. if($module.data(metadata.displayType) === undefined) {
  16668. // create fake element to determine display state
  16669. module.can.transition(true);
  16670. }
  16671. return $module.data(metadata.displayType);
  16672. },
  16673. userStyle: function(style) {
  16674. style = style || $module.attr('style') || '';
  16675. return style.replace(/display.*?;/, '');
  16676. },
  16677. transitionExists: function(animation) {
  16678. return $.fn.transition.exists[animation];
  16679. },
  16680. animationStartEvent: function() {
  16681. var
  16682. element = document.createElement('div'),
  16683. animations = {
  16684. 'animation' :'animationstart',
  16685. 'OAnimation' :'oAnimationStart',
  16686. 'MozAnimation' :'mozAnimationStart',
  16687. 'WebkitAnimation' :'webkitAnimationStart'
  16688. },
  16689. animation
  16690. ;
  16691. for(animation in animations){
  16692. if( element.style[animation] !== undefined ){
  16693. return animations[animation];
  16694. }
  16695. }
  16696. return false;
  16697. },
  16698. animationEndEvent: function() {
  16699. var
  16700. element = document.createElement('div'),
  16701. animations = {
  16702. 'animation' :'animationend',
  16703. 'OAnimation' :'oAnimationEnd',
  16704. 'MozAnimation' :'mozAnimationEnd',
  16705. 'WebkitAnimation' :'webkitAnimationEnd'
  16706. },
  16707. animation
  16708. ;
  16709. for(animation in animations){
  16710. if( element.style[animation] !== undefined ){
  16711. return animations[animation];
  16712. }
  16713. }
  16714. return false;
  16715. }
  16716. },
  16717. can: {
  16718. transition: function(forced) {
  16719. var
  16720. animation = settings.animation,
  16721. transitionExists = module.get.transitionExists(animation),
  16722. elementClass,
  16723. tagName,
  16724. $clone,
  16725. currentAnimation,
  16726. inAnimation,
  16727. directionExists,
  16728. displayType
  16729. ;
  16730. if( transitionExists === undefined || forced) {
  16731. module.verbose('Determining whether animation exists');
  16732. elementClass = $module.attr('class');
  16733. tagName = $module.prop('tagName');
  16734. $clone = $('<' + tagName + ' />').addClass( elementClass ).insertAfter($module);
  16735. currentAnimation = $clone
  16736. .addClass(animation)
  16737. .removeClass(className.inward)
  16738. .removeClass(className.outward)
  16739. .addClass(className.animating)
  16740. .addClass(className.transition)
  16741. .css('animationName')
  16742. ;
  16743. inAnimation = $clone
  16744. .addClass(className.inward)
  16745. .css('animationName')
  16746. ;
  16747. displayType = $clone
  16748. .attr('class', elementClass)
  16749. .removeAttr('style')
  16750. .removeClass(className.hidden)
  16751. .removeClass(className.visible)
  16752. .show()
  16753. .css('display')
  16754. ;
  16755. module.verbose('Determining final display state', displayType);
  16756. module.save.displayType(displayType);
  16757. $clone.remove();
  16758. if(currentAnimation != inAnimation) {
  16759. module.debug('Direction exists for animation', animation);
  16760. directionExists = true;
  16761. }
  16762. else if(currentAnimation == 'none' || !currentAnimation) {
  16763. module.debug('No animation defined in css', animation);
  16764. return;
  16765. }
  16766. else {
  16767. module.debug('Static animation found', animation, displayType);
  16768. directionExists = false;
  16769. }
  16770. module.save.transitionExists(animation, directionExists);
  16771. }
  16772. return (transitionExists !== undefined)
  16773. ? transitionExists
  16774. : directionExists
  16775. ;
  16776. },
  16777. animate: function() {
  16778. // can transition does not return a value if animation does not exist
  16779. return (module.can.transition() !== undefined);
  16780. }
  16781. },
  16782. is: {
  16783. animating: function() {
  16784. return $module.hasClass(className.animating);
  16785. },
  16786. inward: function() {
  16787. return $module.hasClass(className.inward);
  16788. },
  16789. outward: function() {
  16790. return $module.hasClass(className.outward);
  16791. },
  16792. looping: function() {
  16793. return $module.hasClass(className.looping);
  16794. },
  16795. occurring: function(animation) {
  16796. animation = animation || settings.animation;
  16797. animation = '.' + animation.replace(' ', '.');
  16798. return ( $module.filter(animation).length > 0 );
  16799. },
  16800. visible: function() {
  16801. return $module.is(':visible');
  16802. },
  16803. hidden: function() {
  16804. return $module.css('visibility') === 'hidden';
  16805. },
  16806. supported: function() {
  16807. return(animationEnd !== false);
  16808. }
  16809. },
  16810. hide: function() {
  16811. module.verbose('Hiding element');
  16812. if( module.is.animating() ) {
  16813. module.reset();
  16814. }
  16815. element.blur(); // IE will trigger focus change if element is not blurred before hiding
  16816. module.remove.display();
  16817. module.remove.visible();
  16818. module.set.hidden();
  16819. module.force.hidden();
  16820. settings.onHide.call(element);
  16821. settings.onComplete.call(element);
  16822. // module.repaint();
  16823. },
  16824. show: function(display) {
  16825. module.verbose('Showing element', display);
  16826. module.remove.hidden();
  16827. module.set.visible();
  16828. module.force.visible();
  16829. settings.onShow.call(element);
  16830. settings.onComplete.call(element);
  16831. // module.repaint();
  16832. },
  16833. toggle: function() {
  16834. if( module.is.visible() ) {
  16835. module.hide();
  16836. }
  16837. else {
  16838. module.show();
  16839. }
  16840. },
  16841. stop: function() {
  16842. module.debug('Stopping current animation');
  16843. $module.triggerHandler(animationEnd);
  16844. },
  16845. stopAll: function() {
  16846. module.debug('Stopping all animation');
  16847. module.remove.queueCallback();
  16848. $module.triggerHandler(animationEnd);
  16849. },
  16850. clear: {
  16851. queue: function() {
  16852. module.debug('Clearing animation queue');
  16853. module.remove.queueCallback();
  16854. }
  16855. },
  16856. enable: function() {
  16857. module.verbose('Starting animation');
  16858. $module.removeClass(className.disabled);
  16859. },
  16860. disable: function() {
  16861. module.debug('Stopping animation');
  16862. $module.addClass(className.disabled);
  16863. },
  16864. setting: function(name, value) {
  16865. module.debug('Changing setting', name, value);
  16866. if( $.isPlainObject(name) ) {
  16867. $.extend(true, settings, name);
  16868. }
  16869. else if(value !== undefined) {
  16870. settings[name] = value;
  16871. }
  16872. else {
  16873. return settings[name];
  16874. }
  16875. },
  16876. internal: function(name, value) {
  16877. if( $.isPlainObject(name) ) {
  16878. $.extend(true, module, name);
  16879. }
  16880. else if(value !== undefined) {
  16881. module[name] = value;
  16882. }
  16883. else {
  16884. return module[name];
  16885. }
  16886. },
  16887. debug: function() {
  16888. if(settings.debug) {
  16889. if(settings.performance) {
  16890. module.performance.log(arguments);
  16891. }
  16892. else {
  16893. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16894. module.debug.apply(console, arguments);
  16895. }
  16896. }
  16897. },
  16898. verbose: function() {
  16899. if(settings.verbose && settings.debug) {
  16900. if(settings.performance) {
  16901. module.performance.log(arguments);
  16902. }
  16903. else {
  16904. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  16905. module.verbose.apply(console, arguments);
  16906. }
  16907. }
  16908. },
  16909. error: function() {
  16910. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  16911. module.error.apply(console, arguments);
  16912. },
  16913. performance: {
  16914. log: function(message) {
  16915. var
  16916. currentTime,
  16917. executionTime,
  16918. previousTime
  16919. ;
  16920. if(settings.performance) {
  16921. currentTime = new Date().getTime();
  16922. previousTime = time || currentTime;
  16923. executionTime = currentTime - previousTime;
  16924. time = currentTime;
  16925. performance.push({
  16926. 'Name' : message[0],
  16927. 'Arguments' : [].slice.call(message, 1) || '',
  16928. 'Element' : element,
  16929. 'Execution Time' : executionTime
  16930. });
  16931. }
  16932. clearTimeout(module.performance.timer);
  16933. module.performance.timer = setTimeout(module.performance.display, 500);
  16934. },
  16935. display: function() {
  16936. var
  16937. title = settings.name + ':',
  16938. totalTime = 0
  16939. ;
  16940. time = false;
  16941. clearTimeout(module.performance.timer);
  16942. $.each(performance, function(index, data) {
  16943. totalTime += data['Execution Time'];
  16944. });
  16945. title += ' ' + totalTime + 'ms';
  16946. if(moduleSelector) {
  16947. title += ' \'' + moduleSelector + '\'';
  16948. }
  16949. if($allModules.length > 1) {
  16950. title += ' ' + '(' + $allModules.length + ')';
  16951. }
  16952. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  16953. console.groupCollapsed(title);
  16954. if(console.table) {
  16955. console.table(performance);
  16956. }
  16957. else {
  16958. $.each(performance, function(index, data) {
  16959. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  16960. });
  16961. }
  16962. console.groupEnd();
  16963. }
  16964. performance = [];
  16965. }
  16966. },
  16967. // modified for transition to return invoke success
  16968. invoke: function(query, passedArguments, context) {
  16969. var
  16970. object = instance,
  16971. maxDepth,
  16972. found,
  16973. response
  16974. ;
  16975. passedArguments = passedArguments || queryArguments;
  16976. context = element || context;
  16977. if(typeof query == 'string' && object !== undefined) {
  16978. query = query.split(/[\. ]/);
  16979. maxDepth = query.length - 1;
  16980. $.each(query, function(depth, value) {
  16981. var camelCaseValue = (depth != maxDepth)
  16982. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  16983. : query
  16984. ;
  16985. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  16986. object = object[camelCaseValue];
  16987. }
  16988. else if( object[camelCaseValue] !== undefined ) {
  16989. found = object[camelCaseValue];
  16990. return false;
  16991. }
  16992. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  16993. object = object[value];
  16994. }
  16995. else if( object[value] !== undefined ) {
  16996. found = object[value];
  16997. return false;
  16998. }
  16999. else {
  17000. return false;
  17001. }
  17002. });
  17003. }
  17004. if ( $.isFunction( found ) ) {
  17005. response = found.apply(context, passedArguments);
  17006. }
  17007. else if(found !== undefined) {
  17008. response = found;
  17009. }
  17010. if($.isArray(returnedValue)) {
  17011. returnedValue.push(response);
  17012. }
  17013. else if(returnedValue !== undefined) {
  17014. returnedValue = [returnedValue, response];
  17015. }
  17016. else if(response !== undefined) {
  17017. returnedValue = response;
  17018. }
  17019. return (found !== undefined)
  17020. ? found
  17021. : false
  17022. ;
  17023. }
  17024. };
  17025. module.initialize();
  17026. })
  17027. ;
  17028. return (returnedValue !== undefined)
  17029. ? returnedValue
  17030. : this
  17031. ;
  17032. };
  17033. // Records if CSS transition is available
  17034. $.fn.transition.exists = {};
  17035. $.fn.transition.settings = {
  17036. // module info
  17037. name : 'Transition',
  17038. // debug content outputted to console
  17039. debug : false,
  17040. // verbose debug output
  17041. verbose : false,
  17042. // performance data output
  17043. performance : true,
  17044. // event namespace
  17045. namespace : 'transition',
  17046. // delay between animations in group
  17047. interval : 0,
  17048. // whether group animations should be reversed
  17049. reverse : 'auto',
  17050. // animation callback event
  17051. onStart : function() {},
  17052. onComplete : function() {},
  17053. onShow : function() {},
  17054. onHide : function() {},
  17055. // whether timeout should be used to ensure callback fires in cases animationend does not
  17056. useFailSafe : true,
  17057. // delay in ms for fail safe
  17058. failSafeDelay : 100,
  17059. // whether EXACT animation can occur twice in a row
  17060. allowRepeats : false,
  17061. // Override final display type on visible
  17062. displayType : false,
  17063. // animation duration
  17064. animation : 'fade',
  17065. duration : false,
  17066. // new animations will occur after previous ones
  17067. queue : true,
  17068. metadata : {
  17069. displayType: 'display'
  17070. },
  17071. className : {
  17072. animating : 'animating',
  17073. disabled : 'disabled',
  17074. hidden : 'hidden',
  17075. inward : 'in',
  17076. loading : 'loading',
  17077. looping : 'looping',
  17078. outward : 'out',
  17079. transition : 'transition',
  17080. visible : 'visible'
  17081. },
  17082. // possible errors
  17083. error: {
  17084. 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.',
  17085. repeated : 'That animation is already occurring, cancelling repeated animation',
  17086. method : 'The method you called is not defined',
  17087. support : 'This browser does not support CSS animations'
  17088. }
  17089. };
  17090. })( jQuery, window, document );
  17091. /*!
  17092. * # Semantic UI 2.1.6 - API
  17093. * http://github.com/semantic-org/semantic-ui/
  17094. *
  17095. *
  17096. * Copyright 2015 Contributors
  17097. * Released under the MIT license
  17098. * http://opensource.org/licenses/MIT
  17099. *
  17100. */
  17101. ;(function ( $, window, document, undefined ) {
  17102. "use strict";
  17103. $.api = $.fn.api = function(parameters) {
  17104. var
  17105. // use window context if none specified
  17106. $allModules = $.isFunction(this)
  17107. ? $(window)
  17108. : $(this),
  17109. moduleSelector = $allModules.selector || '',
  17110. time = new Date().getTime(),
  17111. performance = [],
  17112. query = arguments[0],
  17113. methodInvoked = (typeof query == 'string'),
  17114. queryArguments = [].slice.call(arguments, 1),
  17115. returnedValue
  17116. ;
  17117. $allModules
  17118. .each(function() {
  17119. var
  17120. settings = ( $.isPlainObject(parameters) )
  17121. ? $.extend(true, {}, $.fn.api.settings, parameters)
  17122. : $.extend({}, $.fn.api.settings),
  17123. // internal aliases
  17124. namespace = settings.namespace,
  17125. metadata = settings.metadata,
  17126. selector = settings.selector,
  17127. error = settings.error,
  17128. className = settings.className,
  17129. // define namespaces for modules
  17130. eventNamespace = '.' + namespace,
  17131. moduleNamespace = 'module-' + namespace,
  17132. // element that creates request
  17133. $module = $(this),
  17134. $form = $module.closest(selector.form),
  17135. // context used for state
  17136. $context = (settings.stateContext)
  17137. ? $(settings.stateContext)
  17138. : $module,
  17139. // request details
  17140. ajaxSettings,
  17141. requestSettings,
  17142. url,
  17143. data,
  17144. requestStartTime,
  17145. // standard module
  17146. element = this,
  17147. context = $context[0],
  17148. instance = $module.data(moduleNamespace),
  17149. module
  17150. ;
  17151. module = {
  17152. initialize: function() {
  17153. if(!methodInvoked) {
  17154. module.bind.events();
  17155. }
  17156. module.instantiate();
  17157. },
  17158. instantiate: function() {
  17159. module.verbose('Storing instance of module', module);
  17160. instance = module;
  17161. $module
  17162. .data(moduleNamespace, instance)
  17163. ;
  17164. },
  17165. destroy: function() {
  17166. module.verbose('Destroying previous module for', element);
  17167. $module
  17168. .removeData(moduleNamespace)
  17169. .off(eventNamespace)
  17170. ;
  17171. },
  17172. bind: {
  17173. events: function() {
  17174. var
  17175. triggerEvent = module.get.event()
  17176. ;
  17177. if( triggerEvent ) {
  17178. module.verbose('Attaching API events to element', triggerEvent);
  17179. $module
  17180. .on(triggerEvent + eventNamespace, module.event.trigger)
  17181. ;
  17182. }
  17183. else if(settings.on == 'now') {
  17184. module.debug('Querying API endpoint immediately');
  17185. module.query();
  17186. }
  17187. }
  17188. },
  17189. decode: {
  17190. json: function(response) {
  17191. if(response !== undefined && typeof response == 'string') {
  17192. try {
  17193. response = JSON.parse(response);
  17194. }
  17195. catch(e) {
  17196. // isnt json string
  17197. }
  17198. }
  17199. return response;
  17200. }
  17201. },
  17202. read: {
  17203. cachedResponse: function(url) {
  17204. var
  17205. response
  17206. ;
  17207. if(window.Storage === undefined) {
  17208. module.error(error.noStorage);
  17209. return;
  17210. }
  17211. response = sessionStorage.getItem(url);
  17212. module.debug('Using cached response', url, response);
  17213. response = module.decode.json(response);
  17214. return false;
  17215. }
  17216. },
  17217. write: {
  17218. cachedResponse: function(url, response) {
  17219. if(response && response === '') {
  17220. module.debug('Response empty, not caching', response);
  17221. return;
  17222. }
  17223. if(window.Storage === undefined) {
  17224. module.error(error.noStorage);
  17225. return;
  17226. }
  17227. if( $.isPlainObject(response) ) {
  17228. response = JSON.stringify(response);
  17229. }
  17230. sessionStorage.setItem(url, response);
  17231. module.verbose('Storing cached response for url', url, response);
  17232. }
  17233. },
  17234. query: function() {
  17235. if(module.is.disabled()) {
  17236. module.debug('Element is disabled API request aborted');
  17237. return;
  17238. }
  17239. if(module.is.loading()) {
  17240. if(settings.interruptRequests) {
  17241. module.debug('Interrupting previous request');
  17242. module.abort();
  17243. }
  17244. else {
  17245. module.debug('Cancelling request, previous request is still pending');
  17246. return;
  17247. }
  17248. }
  17249. // pass element metadata to url (value, text)
  17250. if(settings.defaultData) {
  17251. $.extend(true, settings.urlData, module.get.defaultData());
  17252. }
  17253. // Add form content
  17254. if(settings.serializeForm) {
  17255. settings.data = module.add.formData(settings.data);
  17256. }
  17257. // call beforesend and get any settings changes
  17258. requestSettings = module.get.settings();
  17259. // check if before send cancelled request
  17260. if(requestSettings === false) {
  17261. module.cancelled = true;
  17262. module.error(error.beforeSend);
  17263. return;
  17264. }
  17265. else {
  17266. module.cancelled = false;
  17267. }
  17268. // get url
  17269. url = module.get.templatedURL();
  17270. if(!url && !module.is.mocked()) {
  17271. module.error(error.missingURL);
  17272. return;
  17273. }
  17274. // replace variables
  17275. url = module.add.urlData( url );
  17276. // missing url parameters
  17277. if( !url && !module.is.mocked()) {
  17278. return;
  17279. }
  17280. // look for jQuery ajax parameters in settings
  17281. ajaxSettings = $.extend(true, {}, settings, {
  17282. type : settings.method || settings.type,
  17283. data : data,
  17284. url : settings.base + url,
  17285. beforeSend : settings.beforeXHR,
  17286. success : function() {},
  17287. failure : function() {},
  17288. complete : function() {}
  17289. });
  17290. module.debug('Querying URL', ajaxSettings.url);
  17291. module.verbose('Using AJAX settings', ajaxSettings);
  17292. if(settings.cache === 'local' && module.read.cachedResponse(url)) {
  17293. module.debug('Response returned from local cache');
  17294. module.request = module.create.request();
  17295. module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
  17296. return;
  17297. }
  17298. if( !settings.throttle ) {
  17299. module.debug('Sending request', data, ajaxSettings.method);
  17300. module.send.request();
  17301. }
  17302. else {
  17303. if(!settings.throttleFirstRequest && !module.timer) {
  17304. module.debug('Sending request', data, ajaxSettings.method);
  17305. module.send.request();
  17306. module.timer = setTimeout(function(){}, settings.throttle);
  17307. }
  17308. else {
  17309. module.debug('Throttling request', settings.throttle);
  17310. clearTimeout(module.timer);
  17311. module.timer = setTimeout(function() {
  17312. if(module.timer) {
  17313. delete module.timer;
  17314. }
  17315. module.debug('Sending throttled request', data, ajaxSettings.method);
  17316. module.send.request();
  17317. }, settings.throttle);
  17318. }
  17319. }
  17320. },
  17321. should: {
  17322. removeError: function() {
  17323. return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
  17324. }
  17325. },
  17326. is: {
  17327. disabled: function() {
  17328. return ($module.filter(selector.disabled).length > 0);
  17329. },
  17330. form: function() {
  17331. return $module.is('form') || $context.is('form');
  17332. },
  17333. mocked: function() {
  17334. return (settings.mockResponse || settings.mockResponseAsync);
  17335. },
  17336. input: function() {
  17337. return $module.is('input');
  17338. },
  17339. loading: function() {
  17340. return (module.request && module.request.state() == 'pending');
  17341. },
  17342. abortedRequest: function(xhr) {
  17343. if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
  17344. module.verbose('XHR request determined to be aborted');
  17345. return true;
  17346. }
  17347. else {
  17348. module.verbose('XHR request was not aborted');
  17349. return false;
  17350. }
  17351. },
  17352. validResponse: function(response) {
  17353. if( (settings.dataType !== 'json' && settings.dataType !== 'jsonp') || !$.isFunction(settings.successTest) ) {
  17354. module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
  17355. return true;
  17356. }
  17357. module.debug('Checking JSON returned success', settings.successTest, response);
  17358. if( settings.successTest(response) ) {
  17359. module.debug('Response passed success test', response);
  17360. return true;
  17361. }
  17362. else {
  17363. module.debug('Response failed success test', response);
  17364. return false;
  17365. }
  17366. }
  17367. },
  17368. was: {
  17369. cancelled: function() {
  17370. return (module.cancelled || false);
  17371. },
  17372. succesful: function() {
  17373. return (module.request && module.request.state() == 'resolved');
  17374. },
  17375. failure: function() {
  17376. return (module.request && module.request.state() == 'rejected');
  17377. },
  17378. complete: function() {
  17379. return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
  17380. }
  17381. },
  17382. add: {
  17383. urlData: function(url, urlData) {
  17384. var
  17385. requiredVariables,
  17386. optionalVariables
  17387. ;
  17388. if(url) {
  17389. requiredVariables = url.match(settings.regExp.required);
  17390. optionalVariables = url.match(settings.regExp.optional);
  17391. urlData = urlData || settings.urlData;
  17392. if(requiredVariables) {
  17393. module.debug('Looking for required URL variables', requiredVariables);
  17394. $.each(requiredVariables, function(index, templatedString) {
  17395. var
  17396. // allow legacy {$var} style
  17397. variable = (templatedString.indexOf('$') !== -1)
  17398. ? templatedString.substr(2, templatedString.length - 3)
  17399. : templatedString.substr(1, templatedString.length - 2),
  17400. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  17401. ? urlData[variable]
  17402. : ($module.data(variable) !== undefined)
  17403. ? $module.data(variable)
  17404. : ($context.data(variable) !== undefined)
  17405. ? $context.data(variable)
  17406. : urlData[variable]
  17407. ;
  17408. // remove value
  17409. if(value === undefined) {
  17410. module.error(error.requiredParameter, variable, url);
  17411. url = false;
  17412. return false;
  17413. }
  17414. else {
  17415. module.verbose('Found required variable', variable, value);
  17416. value = (settings.encodeParameters)
  17417. ? module.get.urlEncodedValue(value)
  17418. : value
  17419. ;
  17420. url = url.replace(templatedString, value);
  17421. }
  17422. });
  17423. }
  17424. if(optionalVariables) {
  17425. module.debug('Looking for optional URL variables', requiredVariables);
  17426. $.each(optionalVariables, function(index, templatedString) {
  17427. var
  17428. // allow legacy {/$var} style
  17429. variable = (templatedString.indexOf('$') !== -1)
  17430. ? templatedString.substr(3, templatedString.length - 4)
  17431. : templatedString.substr(2, templatedString.length - 3),
  17432. value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
  17433. ? urlData[variable]
  17434. : ($module.data(variable) !== undefined)
  17435. ? $module.data(variable)
  17436. : ($context.data(variable) !== undefined)
  17437. ? $context.data(variable)
  17438. : urlData[variable]
  17439. ;
  17440. // optional replacement
  17441. if(value !== undefined) {
  17442. module.verbose('Optional variable Found', variable, value);
  17443. url = url.replace(templatedString, value);
  17444. }
  17445. else {
  17446. module.verbose('Optional variable not found', variable);
  17447. // remove preceding slash if set
  17448. if(url.indexOf('/' + templatedString) !== -1) {
  17449. url = url.replace('/' + templatedString, '');
  17450. }
  17451. else {
  17452. url = url.replace(templatedString, '');
  17453. }
  17454. }
  17455. });
  17456. }
  17457. }
  17458. return url;
  17459. },
  17460. formData: function(data) {
  17461. var
  17462. canSerialize = ($.fn.serializeObject !== undefined),
  17463. formData = (canSerialize)
  17464. ? $form.serializeObject()
  17465. : $form.serialize(),
  17466. hasOtherData
  17467. ;
  17468. data = data || settings.data;
  17469. hasOtherData = $.isPlainObject(data);
  17470. if(hasOtherData) {
  17471. if(canSerialize) {
  17472. module.debug('Extending existing data with form data', data, formData);
  17473. data = $.extend(true, {}, data, formData);
  17474. }
  17475. else {
  17476. module.error(error.missingSerialize);
  17477. module.debug('Cant extend data. Replacing data with form data', data, formData);
  17478. data = formData;
  17479. }
  17480. }
  17481. else {
  17482. module.debug('Adding form data', formData);
  17483. data = formData;
  17484. }
  17485. return data;
  17486. }
  17487. },
  17488. send: {
  17489. request: function() {
  17490. module.set.loading();
  17491. module.request = module.create.request();
  17492. if( module.is.mocked() ) {
  17493. module.mockedXHR = module.create.mockedXHR();
  17494. }
  17495. else {
  17496. module.xhr = module.create.xhr();
  17497. }
  17498. settings.onRequest.call(context, module.request, module.xhr);
  17499. }
  17500. },
  17501. event: {
  17502. trigger: function(event) {
  17503. module.query();
  17504. if(event.type == 'submit' || event.type == 'click') {
  17505. event.preventDefault();
  17506. }
  17507. },
  17508. xhr: {
  17509. always: function() {
  17510. // nothing special
  17511. },
  17512. done: function(response, textStatus, xhr) {
  17513. var
  17514. context = this,
  17515. elapsedTime = (new Date().getTime() - requestStartTime),
  17516. timeLeft = (settings.loadingDuration - elapsedTime),
  17517. translatedResponse = ( $.isFunction(settings.onResponse) )
  17518. ? settings.onResponse.call(context, $.extend(true, {}, response))
  17519. : false
  17520. ;
  17521. timeLeft = (timeLeft > 0)
  17522. ? timeLeft
  17523. : 0
  17524. ;
  17525. if(translatedResponse) {
  17526. module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
  17527. response = translatedResponse;
  17528. }
  17529. if(timeLeft > 0) {
  17530. module.debug('Response completed early delaying state change by', timeLeft);
  17531. }
  17532. setTimeout(function() {
  17533. if( module.is.validResponse(response) ) {
  17534. module.request.resolveWith(context, [response, xhr]);
  17535. }
  17536. else {
  17537. module.request.rejectWith(context, [xhr, 'invalid']);
  17538. }
  17539. }, timeLeft);
  17540. },
  17541. fail: function(xhr, status, httpMessage) {
  17542. var
  17543. context = this,
  17544. elapsedTime = (new Date().getTime() - requestStartTime),
  17545. timeLeft = (settings.loadingDuration - elapsedTime)
  17546. ;
  17547. timeLeft = (timeLeft > 0)
  17548. ? timeLeft
  17549. : 0
  17550. ;
  17551. if(timeLeft > 0) {
  17552. module.debug('Response completed early delaying state change by', timeLeft);
  17553. }
  17554. setTimeout(function() {
  17555. if( module.is.abortedRequest(xhr) ) {
  17556. module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
  17557. }
  17558. else {
  17559. module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
  17560. }
  17561. }, timeLeft);
  17562. }
  17563. },
  17564. request: {
  17565. done: function(response, xhr) {
  17566. module.debug('Successful API Response', response);
  17567. if(settings.cache === 'local' && url) {
  17568. module.write.cachedResponse(url, response);
  17569. module.debug('Saving server response locally', module.cache);
  17570. }
  17571. settings.onSuccess.call(context, response, $module, xhr);
  17572. },
  17573. complete: function(firstParameter, secondParameter) {
  17574. var
  17575. xhr,
  17576. response
  17577. ;
  17578. // have to guess callback parameters based on request success
  17579. if( module.was.succesful() ) {
  17580. response = firstParameter;
  17581. xhr = secondParameter;
  17582. }
  17583. else {
  17584. xhr = firstParameter;
  17585. response = module.get.responseFromXHR(xhr);
  17586. }
  17587. module.remove.loading();
  17588. settings.onComplete.call(context, response, $module, xhr);
  17589. },
  17590. fail: function(xhr, status, httpMessage) {
  17591. var
  17592. // pull response from xhr if available
  17593. response = module.get.responseFromXHR(xhr),
  17594. errorMessage = module.get.errorFromRequest(response, status, httpMessage)
  17595. ;
  17596. if(status == 'aborted') {
  17597. module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
  17598. settings.onAbort.call(context, status, $module, xhr);
  17599. }
  17600. else if(status == 'invalid') {
  17601. module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
  17602. }
  17603. else if(status == 'error') {
  17604. if(xhr !== undefined) {
  17605. module.debug('XHR produced a server error', status, httpMessage);
  17606. // make sure we have an error to display to console
  17607. if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
  17608. module.error(error.statusMessage + httpMessage, ajaxSettings.url);
  17609. }
  17610. settings.onError.call(context, errorMessage, $module, xhr);
  17611. }
  17612. }
  17613. if(settings.errorDuration && status !== 'aborted') {
  17614. module.debug('Adding error state');
  17615. module.set.error();
  17616. if( module.should.removeError() ) {
  17617. setTimeout(module.remove.error, settings.errorDuration);
  17618. }
  17619. }
  17620. module.debug('API Request failed', errorMessage, xhr);
  17621. settings.onFailure.call(context, response, $module, xhr);
  17622. }
  17623. }
  17624. },
  17625. create: {
  17626. request: function() {
  17627. // api request promise
  17628. return $.Deferred()
  17629. .always(module.event.request.complete)
  17630. .done(module.event.request.done)
  17631. .fail(module.event.request.fail)
  17632. ;
  17633. },
  17634. mockedXHR: function () {
  17635. var
  17636. // xhr does not simulate these properties of xhr but must return them
  17637. textStatus = false,
  17638. status = false,
  17639. httpMessage = false,
  17640. asyncCallback,
  17641. response,
  17642. mockedXHR
  17643. ;
  17644. mockedXHR = $.Deferred()
  17645. .always(module.event.xhr.complete)
  17646. .done(module.event.xhr.done)
  17647. .fail(module.event.xhr.fail)
  17648. ;
  17649. if(settings.mockResponse) {
  17650. if( $.isFunction(settings.mockResponse) ) {
  17651. module.debug('Using mocked callback returning response', settings.mockResponse);
  17652. response = settings.mockResponse.call(context, settings);
  17653. }
  17654. else {
  17655. module.debug('Using specified response', settings.mockResponse);
  17656. response = settings.mockResponse;
  17657. }
  17658. // simulating response
  17659. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  17660. }
  17661. else if( $.isFunction(settings.mockResponseAsync) ) {
  17662. asyncCallback = function(response) {
  17663. module.debug('Async callback returned response', response);
  17664. if(response) {
  17665. mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
  17666. }
  17667. else {
  17668. mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
  17669. }
  17670. };
  17671. module.debug('Using async mocked response', settings.mockResponseAsync);
  17672. settings.mockResponseAsync.call(context, settings, asyncCallback);
  17673. }
  17674. return mockedXHR;
  17675. },
  17676. xhr: function() {
  17677. var
  17678. xhr
  17679. ;
  17680. // ajax request promise
  17681. xhr = $.ajax(ajaxSettings)
  17682. .always(module.event.xhr.always)
  17683. .done(module.event.xhr.done)
  17684. .fail(module.event.xhr.fail)
  17685. ;
  17686. module.verbose('Created server request', xhr);
  17687. return xhr;
  17688. }
  17689. },
  17690. set: {
  17691. error: function() {
  17692. module.verbose('Adding error state to element', $context);
  17693. $context.addClass(className.error);
  17694. },
  17695. loading: function() {
  17696. module.verbose('Adding loading state to element', $context);
  17697. $context.addClass(className.loading);
  17698. requestStartTime = new Date().getTime();
  17699. }
  17700. },
  17701. remove: {
  17702. error: function() {
  17703. module.verbose('Removing error state from element', $context);
  17704. $context.removeClass(className.error);
  17705. },
  17706. loading: function() {
  17707. module.verbose('Removing loading state from element', $context);
  17708. $context.removeClass(className.loading);
  17709. }
  17710. },
  17711. get: {
  17712. responseFromXHR: function(xhr) {
  17713. return $.isPlainObject(xhr)
  17714. ? (settings.dataType == 'json' || settings.dataType == 'jsonp')
  17715. ? module.decode.json(xhr.responseText)
  17716. : xhr.responseText
  17717. : false
  17718. ;
  17719. },
  17720. errorFromRequest: function(response, status, httpMessage) {
  17721. return ($.isPlainObject(response) && response.error !== undefined)
  17722. ? response.error // use json error message
  17723. : (settings.error[status] !== undefined) // use server error message
  17724. ? settings.error[status]
  17725. : httpMessage
  17726. ;
  17727. },
  17728. request: function() {
  17729. return module.request || false;
  17730. },
  17731. xhr: function() {
  17732. return module.xhr || false;
  17733. },
  17734. settings: function() {
  17735. var
  17736. runSettings
  17737. ;
  17738. runSettings = settings.beforeSend.call(context, settings);
  17739. if(runSettings) {
  17740. if(runSettings.success !== undefined) {
  17741. module.debug('Legacy success callback detected', runSettings);
  17742. module.error(error.legacyParameters, runSettings.success);
  17743. runSettings.onSuccess = runSettings.success;
  17744. }
  17745. if(runSettings.failure !== undefined) {
  17746. module.debug('Legacy failure callback detected', runSettings);
  17747. module.error(error.legacyParameters, runSettings.failure);
  17748. runSettings.onFailure = runSettings.failure;
  17749. }
  17750. if(runSettings.complete !== undefined) {
  17751. module.debug('Legacy complete callback detected', runSettings);
  17752. module.error(error.legacyParameters, runSettings.complete);
  17753. runSettings.onComplete = runSettings.complete;
  17754. }
  17755. }
  17756. if(runSettings === undefined) {
  17757. module.error(error.noReturnedValue);
  17758. }
  17759. return (runSettings !== undefined)
  17760. ? runSettings
  17761. : settings
  17762. ;
  17763. },
  17764. urlEncodedValue: function(value) {
  17765. var
  17766. decodedValue = window.decodeURIComponent(value),
  17767. encodedValue = window.encodeURIComponent(value),
  17768. alreadyEncoded = (decodedValue !== value)
  17769. ;
  17770. if(alreadyEncoded) {
  17771. module.debug('URL value is already encoded, avoiding double encoding', value);
  17772. return value;
  17773. }
  17774. module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
  17775. return encodedValue;
  17776. },
  17777. defaultData: function() {
  17778. var
  17779. data = {}
  17780. ;
  17781. if( !$.isWindow(element) ) {
  17782. if( module.is.input() ) {
  17783. data.value = $module.val();
  17784. }
  17785. else if( !module.is.form() ) {
  17786. }
  17787. else {
  17788. data.text = $module.text();
  17789. }
  17790. }
  17791. return data;
  17792. },
  17793. event: function() {
  17794. if( $.isWindow(element) || settings.on == 'now' ) {
  17795. module.debug('API called without element, no events attached');
  17796. return false;
  17797. }
  17798. else if(settings.on == 'auto') {
  17799. if( $module.is('input') ) {
  17800. return (element.oninput !== undefined)
  17801. ? 'input'
  17802. : (element.onpropertychange !== undefined)
  17803. ? 'propertychange'
  17804. : 'keyup'
  17805. ;
  17806. }
  17807. else if( $module.is('form') ) {
  17808. return 'submit';
  17809. }
  17810. else {
  17811. return 'click';
  17812. }
  17813. }
  17814. else {
  17815. return settings.on;
  17816. }
  17817. },
  17818. templatedURL: function(action) {
  17819. action = action || $module.data(metadata.action) || settings.action || false;
  17820. url = $module.data(metadata.url) || settings.url || false;
  17821. if(url) {
  17822. module.debug('Using specified url', url);
  17823. return url;
  17824. }
  17825. if(action) {
  17826. module.debug('Looking up url for action', action, settings.api);
  17827. if(settings.api[action] === undefined && !module.is.mocked()) {
  17828. module.error(error.missingAction, settings.action, settings.api);
  17829. return;
  17830. }
  17831. url = settings.api[action];
  17832. }
  17833. else if( module.is.form() ) {
  17834. url = $module.attr('action') || $context.attr('action') || false;
  17835. module.debug('No url or action specified, defaulting to form action', url);
  17836. }
  17837. return url;
  17838. }
  17839. },
  17840. abort: function() {
  17841. var
  17842. xhr = module.get.xhr()
  17843. ;
  17844. if( xhr && xhr.state() !== 'resolved') {
  17845. module.debug('Cancelling API request');
  17846. xhr.abort();
  17847. }
  17848. },
  17849. // reset state
  17850. reset: function() {
  17851. module.remove.error();
  17852. module.remove.loading();
  17853. },
  17854. setting: function(name, value) {
  17855. module.debug('Changing setting', name, value);
  17856. if( $.isPlainObject(name) ) {
  17857. $.extend(true, settings, name);
  17858. }
  17859. else if(value !== undefined) {
  17860. settings[name] = value;
  17861. }
  17862. else {
  17863. return settings[name];
  17864. }
  17865. },
  17866. internal: function(name, value) {
  17867. if( $.isPlainObject(name) ) {
  17868. $.extend(true, module, name);
  17869. }
  17870. else if(value !== undefined) {
  17871. module[name] = value;
  17872. }
  17873. else {
  17874. return module[name];
  17875. }
  17876. },
  17877. debug: function() {
  17878. if(settings.debug) {
  17879. if(settings.performance) {
  17880. module.performance.log(arguments);
  17881. }
  17882. else {
  17883. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17884. module.debug.apply(console, arguments);
  17885. }
  17886. }
  17887. },
  17888. verbose: function() {
  17889. if(settings.verbose && settings.debug) {
  17890. if(settings.performance) {
  17891. module.performance.log(arguments);
  17892. }
  17893. else {
  17894. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  17895. module.verbose.apply(console, arguments);
  17896. }
  17897. }
  17898. },
  17899. error: function() {
  17900. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  17901. module.error.apply(console, arguments);
  17902. },
  17903. performance: {
  17904. log: function(message) {
  17905. var
  17906. currentTime,
  17907. executionTime,
  17908. previousTime
  17909. ;
  17910. if(settings.performance) {
  17911. currentTime = new Date().getTime();
  17912. previousTime = time || currentTime;
  17913. executionTime = currentTime - previousTime;
  17914. time = currentTime;
  17915. performance.push({
  17916. 'Name' : message[0],
  17917. 'Arguments' : [].slice.call(message, 1) || '',
  17918. //'Element' : element,
  17919. 'Execution Time' : executionTime
  17920. });
  17921. }
  17922. clearTimeout(module.performance.timer);
  17923. module.performance.timer = setTimeout(module.performance.display, 500);
  17924. },
  17925. display: function() {
  17926. var
  17927. title = settings.name + ':',
  17928. totalTime = 0
  17929. ;
  17930. time = false;
  17931. clearTimeout(module.performance.timer);
  17932. $.each(performance, function(index, data) {
  17933. totalTime += data['Execution Time'];
  17934. });
  17935. title += ' ' + totalTime + 'ms';
  17936. if(moduleSelector) {
  17937. title += ' \'' + moduleSelector + '\'';
  17938. }
  17939. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  17940. console.groupCollapsed(title);
  17941. if(console.table) {
  17942. console.table(performance);
  17943. }
  17944. else {
  17945. $.each(performance, function(index, data) {
  17946. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  17947. });
  17948. }
  17949. console.groupEnd();
  17950. }
  17951. performance = [];
  17952. }
  17953. },
  17954. invoke: function(query, passedArguments, context) {
  17955. var
  17956. object = instance,
  17957. maxDepth,
  17958. found,
  17959. response
  17960. ;
  17961. passedArguments = passedArguments || queryArguments;
  17962. context = element || context;
  17963. if(typeof query == 'string' && object !== undefined) {
  17964. query = query.split(/[\. ]/);
  17965. maxDepth = query.length - 1;
  17966. $.each(query, function(depth, value) {
  17967. var camelCaseValue = (depth != maxDepth)
  17968. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  17969. : query
  17970. ;
  17971. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  17972. object = object[camelCaseValue];
  17973. }
  17974. else if( object[camelCaseValue] !== undefined ) {
  17975. found = object[camelCaseValue];
  17976. return false;
  17977. }
  17978. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  17979. object = object[value];
  17980. }
  17981. else if( object[value] !== undefined ) {
  17982. found = object[value];
  17983. return false;
  17984. }
  17985. else {
  17986. module.error(error.method, query);
  17987. return false;
  17988. }
  17989. });
  17990. }
  17991. if ( $.isFunction( found ) ) {
  17992. response = found.apply(context, passedArguments);
  17993. }
  17994. else if(found !== undefined) {
  17995. response = found;
  17996. }
  17997. if($.isArray(returnedValue)) {
  17998. returnedValue.push(response);
  17999. }
  18000. else if(returnedValue !== undefined) {
  18001. returnedValue = [returnedValue, response];
  18002. }
  18003. else if(response !== undefined) {
  18004. returnedValue = response;
  18005. }
  18006. return found;
  18007. }
  18008. };
  18009. if(methodInvoked) {
  18010. if(instance === undefined) {
  18011. module.initialize();
  18012. }
  18013. module.invoke(query);
  18014. }
  18015. else {
  18016. if(instance !== undefined) {
  18017. instance.invoke('destroy');
  18018. }
  18019. module.initialize();
  18020. }
  18021. })
  18022. ;
  18023. return (returnedValue !== undefined)
  18024. ? returnedValue
  18025. : this
  18026. ;
  18027. };
  18028. $.api.settings = {
  18029. name : 'API',
  18030. namespace : 'api',
  18031. debug : false,
  18032. verbose : false,
  18033. performance : true,
  18034. // object containing all templates endpoints
  18035. api : {},
  18036. // whether to cache responses
  18037. cache : true,
  18038. // whether new requests should abort previous requests
  18039. interruptRequests : true,
  18040. // event binding
  18041. on : 'auto',
  18042. // context for applying state classes
  18043. stateContext : false,
  18044. // duration for loading state
  18045. loadingDuration : 0,
  18046. // whether to hide errors after a period of time
  18047. hideError : 'auto',
  18048. // duration for error state
  18049. errorDuration : 2000,
  18050. // whether parameters should be encoded with encodeURIComponent
  18051. encodeParameters : true,
  18052. // API action to use
  18053. action : false,
  18054. // templated URL to use
  18055. url : false,
  18056. // base URL to apply to all endpoints
  18057. base : '',
  18058. // data that will
  18059. urlData : {},
  18060. // whether to add default data to url data
  18061. defaultData : true,
  18062. // whether to serialize closest form
  18063. serializeForm : false,
  18064. // how long to wait before request should occur
  18065. throttle : 0,
  18066. // whether to throttle first request or only repeated
  18067. throttleFirstRequest : true,
  18068. // standard ajax settings
  18069. method : 'get',
  18070. data : {},
  18071. dataType : 'json',
  18072. // mock response
  18073. mockResponse : false,
  18074. mockResponseAsync : false,
  18075. // callbacks before request
  18076. beforeSend : function(settings) { return settings; },
  18077. beforeXHR : function(xhr) {},
  18078. onRequest : function(promise, xhr) {},
  18079. // after request
  18080. onResponse : false, // function(response) { },
  18081. // response was successful, if JSON passed validation
  18082. onSuccess : function(response, $module) {},
  18083. // request finished without aborting
  18084. onComplete : function(response, $module) {},
  18085. // failed JSON success test
  18086. onFailure : function(response, $module) {},
  18087. // server error
  18088. onError : function(errorMessage, $module) {},
  18089. // request aborted
  18090. onAbort : function(errorMessage, $module) {},
  18091. successTest : false,
  18092. // errors
  18093. error : {
  18094. beforeSend : 'The before send function has aborted the request',
  18095. error : 'There was an error with your request',
  18096. exitConditions : 'API Request Aborted. Exit conditions met',
  18097. JSONParse : 'JSON could not be parsed during error handling',
  18098. legacyParameters : 'You are using legacy API success callback names',
  18099. method : 'The method you called is not defined',
  18100. missingAction : 'API action used but no url was defined',
  18101. missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
  18102. missingURL : 'No URL specified for api event',
  18103. noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
  18104. noStorage : 'Caching responses locally requires session storage',
  18105. parseError : 'There was an error parsing your request',
  18106. requiredParameter : 'Missing a required URL parameter: ',
  18107. statusMessage : 'Server gave an error: ',
  18108. timeout : 'Your request timed out'
  18109. },
  18110. regExp : {
  18111. required : /\{\$*[A-z0-9]+\}/g,
  18112. optional : /\{\/\$*[A-z0-9]+\}/g,
  18113. },
  18114. className: {
  18115. loading : 'loading',
  18116. error : 'error'
  18117. },
  18118. selector: {
  18119. disabled : '.disabled',
  18120. form : 'form'
  18121. },
  18122. metadata: {
  18123. action : 'action',
  18124. url : 'url'
  18125. }
  18126. };
  18127. })( jQuery, window, document );
  18128. /*!
  18129. * # Semantic UI 2.1.6 - State
  18130. * http://github.com/semantic-org/semantic-ui/
  18131. *
  18132. *
  18133. * Copyright 2015 Contributors
  18134. * Released under the MIT license
  18135. * http://opensource.org/licenses/MIT
  18136. *
  18137. */
  18138. ;(function ( $, window, document, undefined ) {
  18139. "use strict";
  18140. $.fn.state = function(parameters) {
  18141. var
  18142. $allModules = $(this),
  18143. moduleSelector = $allModules.selector || '',
  18144. hasTouch = ('ontouchstart' in document.documentElement),
  18145. time = new Date().getTime(),
  18146. performance = [],
  18147. query = arguments[0],
  18148. methodInvoked = (typeof query == 'string'),
  18149. queryArguments = [].slice.call(arguments, 1),
  18150. returnedValue
  18151. ;
  18152. $allModules
  18153. .each(function() {
  18154. var
  18155. settings = ( $.isPlainObject(parameters) )
  18156. ? $.extend(true, {}, $.fn.state.settings, parameters)
  18157. : $.extend({}, $.fn.state.settings),
  18158. error = settings.error,
  18159. metadata = settings.metadata,
  18160. className = settings.className,
  18161. namespace = settings.namespace,
  18162. states = settings.states,
  18163. text = settings.text,
  18164. eventNamespace = '.' + namespace,
  18165. moduleNamespace = namespace + '-module',
  18166. $module = $(this),
  18167. element = this,
  18168. instance = $module.data(moduleNamespace),
  18169. module
  18170. ;
  18171. module = {
  18172. initialize: function() {
  18173. module.verbose('Initializing module');
  18174. // allow module to guess desired state based on element
  18175. if(settings.automatic) {
  18176. module.add.defaults();
  18177. }
  18178. // bind events with delegated events
  18179. if(settings.context && moduleSelector !== '') {
  18180. $(settings.context)
  18181. .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text)
  18182. .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text)
  18183. .on(moduleSelector, 'click' + eventNamespace, module.toggle.state)
  18184. ;
  18185. }
  18186. else {
  18187. $module
  18188. .on('mouseenter' + eventNamespace, module.change.text)
  18189. .on('mouseleave' + eventNamespace, module.reset.text)
  18190. .on('click' + eventNamespace, module.toggle.state)
  18191. ;
  18192. }
  18193. module.instantiate();
  18194. },
  18195. instantiate: function() {
  18196. module.verbose('Storing instance of module', module);
  18197. instance = module;
  18198. $module
  18199. .data(moduleNamespace, module)
  18200. ;
  18201. },
  18202. destroy: function() {
  18203. module.verbose('Destroying previous module', instance);
  18204. $module
  18205. .off(eventNamespace)
  18206. .removeData(moduleNamespace)
  18207. ;
  18208. },
  18209. refresh: function() {
  18210. module.verbose('Refreshing selector cache');
  18211. $module = $(element);
  18212. },
  18213. add: {
  18214. defaults: function() {
  18215. var
  18216. userStates = parameters && $.isPlainObject(parameters.states)
  18217. ? parameters.states
  18218. : {}
  18219. ;
  18220. $.each(settings.defaults, function(type, typeStates) {
  18221. if( module.is[type] !== undefined && module.is[type]() ) {
  18222. module.verbose('Adding default states', type, element);
  18223. $.extend(settings.states, typeStates, userStates);
  18224. }
  18225. });
  18226. }
  18227. },
  18228. is: {
  18229. active: function() {
  18230. return $module.hasClass(className.active);
  18231. },
  18232. loading: function() {
  18233. return $module.hasClass(className.loading);
  18234. },
  18235. inactive: function() {
  18236. return !( $module.hasClass(className.active) );
  18237. },
  18238. state: function(state) {
  18239. if(className[state] === undefined) {
  18240. return false;
  18241. }
  18242. return $module.hasClass( className[state] );
  18243. },
  18244. enabled: function() {
  18245. return !( $module.is(settings.filter.active) );
  18246. },
  18247. disabled: function() {
  18248. return ( $module.is(settings.filter.active) );
  18249. },
  18250. textEnabled: function() {
  18251. return !( $module.is(settings.filter.text) );
  18252. },
  18253. // definitions for automatic type detection
  18254. button: function() {
  18255. return $module.is('.button:not(a, .submit)');
  18256. },
  18257. input: function() {
  18258. return $module.is('input');
  18259. },
  18260. progress: function() {
  18261. return $module.is('.ui.progress');
  18262. }
  18263. },
  18264. allow: function(state) {
  18265. module.debug('Now allowing state', state);
  18266. states[state] = true;
  18267. },
  18268. disallow: function(state) {
  18269. module.debug('No longer allowing', state);
  18270. states[state] = false;
  18271. },
  18272. allows: function(state) {
  18273. return states[state] || false;
  18274. },
  18275. enable: function() {
  18276. $module.removeClass(className.disabled);
  18277. },
  18278. disable: function() {
  18279. $module.addClass(className.disabled);
  18280. },
  18281. setState: function(state) {
  18282. if(module.allows(state)) {
  18283. $module.addClass( className[state] );
  18284. }
  18285. },
  18286. removeState: function(state) {
  18287. if(module.allows(state)) {
  18288. $module.removeClass( className[state] );
  18289. }
  18290. },
  18291. toggle: {
  18292. state: function() {
  18293. var
  18294. apiRequest,
  18295. requestCancelled
  18296. ;
  18297. if( module.allows('active') && module.is.enabled() ) {
  18298. module.refresh();
  18299. if($.fn.api !== undefined) {
  18300. apiRequest = $module.api('get request');
  18301. requestCancelled = $module.api('was cancelled');
  18302. if( requestCancelled ) {
  18303. module.debug('API Request cancelled by beforesend');
  18304. settings.activateTest = function(){ return false; };
  18305. settings.deactivateTest = function(){ return false; };
  18306. }
  18307. else if(apiRequest) {
  18308. module.listenTo(apiRequest);
  18309. return;
  18310. }
  18311. }
  18312. module.change.state();
  18313. }
  18314. }
  18315. },
  18316. listenTo: function(apiRequest) {
  18317. module.debug('API request detected, waiting for state signal', apiRequest);
  18318. if(apiRequest) {
  18319. if(text.loading) {
  18320. module.update.text(text.loading);
  18321. }
  18322. $.when(apiRequest)
  18323. .then(function() {
  18324. if(apiRequest.state() == 'resolved') {
  18325. module.debug('API request succeeded');
  18326. settings.activateTest = function(){ return true; };
  18327. settings.deactivateTest = function(){ return true; };
  18328. }
  18329. else {
  18330. module.debug('API request failed');
  18331. settings.activateTest = function(){ return false; };
  18332. settings.deactivateTest = function(){ return false; };
  18333. }
  18334. module.change.state();
  18335. })
  18336. ;
  18337. }
  18338. },
  18339. // checks whether active/inactive state can be given
  18340. change: {
  18341. state: function() {
  18342. module.debug('Determining state change direction');
  18343. // inactive to active change
  18344. if( module.is.inactive() ) {
  18345. module.activate();
  18346. }
  18347. else {
  18348. module.deactivate();
  18349. }
  18350. if(settings.sync) {
  18351. module.sync();
  18352. }
  18353. settings.onChange.call(element);
  18354. },
  18355. text: function() {
  18356. if( module.is.textEnabled() ) {
  18357. if(module.is.disabled() ) {
  18358. module.verbose('Changing text to disabled text', text.hover);
  18359. module.update.text(text.disabled);
  18360. }
  18361. else if( module.is.active() ) {
  18362. if(text.hover) {
  18363. module.verbose('Changing text to hover text', text.hover);
  18364. module.update.text(text.hover);
  18365. }
  18366. else if(text.deactivate) {
  18367. module.verbose('Changing text to deactivating text', text.deactivate);
  18368. module.update.text(text.deactivate);
  18369. }
  18370. }
  18371. else {
  18372. if(text.hover) {
  18373. module.verbose('Changing text to hover text', text.hover);
  18374. module.update.text(text.hover);
  18375. }
  18376. else if(text.activate){
  18377. module.verbose('Changing text to activating text', text.activate);
  18378. module.update.text(text.activate);
  18379. }
  18380. }
  18381. }
  18382. }
  18383. },
  18384. activate: function() {
  18385. if( settings.activateTest.call(element) ) {
  18386. module.debug('Setting state to active');
  18387. $module
  18388. .addClass(className.active)
  18389. ;
  18390. module.update.text(text.active);
  18391. settings.onActivate.call(element);
  18392. }
  18393. },
  18394. deactivate: function() {
  18395. if( settings.deactivateTest.call(element) ) {
  18396. module.debug('Setting state to inactive');
  18397. $module
  18398. .removeClass(className.active)
  18399. ;
  18400. module.update.text(text.inactive);
  18401. settings.onDeactivate.call(element);
  18402. }
  18403. },
  18404. sync: function() {
  18405. module.verbose('Syncing other buttons to current state');
  18406. if( module.is.active() ) {
  18407. $allModules
  18408. .not($module)
  18409. .state('activate');
  18410. }
  18411. else {
  18412. $allModules
  18413. .not($module)
  18414. .state('deactivate')
  18415. ;
  18416. }
  18417. },
  18418. get: {
  18419. text: function() {
  18420. return (settings.selector.text)
  18421. ? $module.find(settings.selector.text).text()
  18422. : $module.html()
  18423. ;
  18424. },
  18425. textFor: function(state) {
  18426. return text[state] || false;
  18427. }
  18428. },
  18429. flash: {
  18430. text: function(text, duration, callback) {
  18431. var
  18432. previousText = module.get.text()
  18433. ;
  18434. module.debug('Flashing text message', text, duration);
  18435. text = text || settings.text.flash;
  18436. duration = duration || settings.flashDuration;
  18437. callback = callback || function() {};
  18438. module.update.text(text);
  18439. setTimeout(function(){
  18440. module.update.text(previousText);
  18441. callback.call(element);
  18442. }, duration);
  18443. }
  18444. },
  18445. reset: {
  18446. // on mouseout sets text to previous value
  18447. text: function() {
  18448. var
  18449. activeText = text.active || $module.data(metadata.storedText),
  18450. inactiveText = text.inactive || $module.data(metadata.storedText)
  18451. ;
  18452. if( module.is.textEnabled() ) {
  18453. if( module.is.active() && activeText) {
  18454. module.verbose('Resetting active text', activeText);
  18455. module.update.text(activeText);
  18456. }
  18457. else if(inactiveText) {
  18458. module.verbose('Resetting inactive text', activeText);
  18459. module.update.text(inactiveText);
  18460. }
  18461. }
  18462. }
  18463. },
  18464. update: {
  18465. text: function(text) {
  18466. var
  18467. currentText = module.get.text()
  18468. ;
  18469. if(text && text !== currentText) {
  18470. module.debug('Updating text', text);
  18471. if(settings.selector.text) {
  18472. $module
  18473. .data(metadata.storedText, text)
  18474. .find(settings.selector.text)
  18475. .text(text)
  18476. ;
  18477. }
  18478. else {
  18479. $module
  18480. .data(metadata.storedText, text)
  18481. .html(text)
  18482. ;
  18483. }
  18484. }
  18485. else {
  18486. module.debug('Text is already set, ignoring update', text);
  18487. }
  18488. }
  18489. },
  18490. setting: function(name, value) {
  18491. module.debug('Changing setting', name, value);
  18492. if( $.isPlainObject(name) ) {
  18493. $.extend(true, settings, name);
  18494. }
  18495. else if(value !== undefined) {
  18496. settings[name] = value;
  18497. }
  18498. else {
  18499. return settings[name];
  18500. }
  18501. },
  18502. internal: function(name, value) {
  18503. if( $.isPlainObject(name) ) {
  18504. $.extend(true, module, name);
  18505. }
  18506. else if(value !== undefined) {
  18507. module[name] = value;
  18508. }
  18509. else {
  18510. return module[name];
  18511. }
  18512. },
  18513. debug: function() {
  18514. if(settings.debug) {
  18515. if(settings.performance) {
  18516. module.performance.log(arguments);
  18517. }
  18518. else {
  18519. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18520. module.debug.apply(console, arguments);
  18521. }
  18522. }
  18523. },
  18524. verbose: function() {
  18525. if(settings.verbose && settings.debug) {
  18526. if(settings.performance) {
  18527. module.performance.log(arguments);
  18528. }
  18529. else {
  18530. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  18531. module.verbose.apply(console, arguments);
  18532. }
  18533. }
  18534. },
  18535. error: function() {
  18536. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  18537. module.error.apply(console, arguments);
  18538. },
  18539. performance: {
  18540. log: function(message) {
  18541. var
  18542. currentTime,
  18543. executionTime,
  18544. previousTime
  18545. ;
  18546. if(settings.performance) {
  18547. currentTime = new Date().getTime();
  18548. previousTime = time || currentTime;
  18549. executionTime = currentTime - previousTime;
  18550. time = currentTime;
  18551. performance.push({
  18552. 'Name' : message[0],
  18553. 'Arguments' : [].slice.call(message, 1) || '',
  18554. 'Element' : element,
  18555. 'Execution Time' : executionTime
  18556. });
  18557. }
  18558. clearTimeout(module.performance.timer);
  18559. module.performance.timer = setTimeout(module.performance.display, 500);
  18560. },
  18561. display: function() {
  18562. var
  18563. title = settings.name + ':',
  18564. totalTime = 0
  18565. ;
  18566. time = false;
  18567. clearTimeout(module.performance.timer);
  18568. $.each(performance, function(index, data) {
  18569. totalTime += data['Execution Time'];
  18570. });
  18571. title += ' ' + totalTime + 'ms';
  18572. if(moduleSelector) {
  18573. title += ' \'' + moduleSelector + '\'';
  18574. }
  18575. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  18576. console.groupCollapsed(title);
  18577. if(console.table) {
  18578. console.table(performance);
  18579. }
  18580. else {
  18581. $.each(performance, function(index, data) {
  18582. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  18583. });
  18584. }
  18585. console.groupEnd();
  18586. }
  18587. performance = [];
  18588. }
  18589. },
  18590. invoke: function(query, passedArguments, context) {
  18591. var
  18592. object = instance,
  18593. maxDepth,
  18594. found,
  18595. response
  18596. ;
  18597. passedArguments = passedArguments || queryArguments;
  18598. context = element || context;
  18599. if(typeof query == 'string' && object !== undefined) {
  18600. query = query.split(/[\. ]/);
  18601. maxDepth = query.length - 1;
  18602. $.each(query, function(depth, value) {
  18603. var camelCaseValue = (depth != maxDepth)
  18604. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  18605. : query
  18606. ;
  18607. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  18608. object = object[camelCaseValue];
  18609. }
  18610. else if( object[camelCaseValue] !== undefined ) {
  18611. found = object[camelCaseValue];
  18612. return false;
  18613. }
  18614. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  18615. object = object[value];
  18616. }
  18617. else if( object[value] !== undefined ) {
  18618. found = object[value];
  18619. return false;
  18620. }
  18621. else {
  18622. module.error(error.method, query);
  18623. return false;
  18624. }
  18625. });
  18626. }
  18627. if ( $.isFunction( found ) ) {
  18628. response = found.apply(context, passedArguments);
  18629. }
  18630. else if(found !== undefined) {
  18631. response = found;
  18632. }
  18633. if($.isArray(returnedValue)) {
  18634. returnedValue.push(response);
  18635. }
  18636. else if(returnedValue !== undefined) {
  18637. returnedValue = [returnedValue, response];
  18638. }
  18639. else if(response !== undefined) {
  18640. returnedValue = response;
  18641. }
  18642. return found;
  18643. }
  18644. };
  18645. if(methodInvoked) {
  18646. if(instance === undefined) {
  18647. module.initialize();
  18648. }
  18649. module.invoke(query);
  18650. }
  18651. else {
  18652. if(instance !== undefined) {
  18653. instance.invoke('destroy');
  18654. }
  18655. module.initialize();
  18656. }
  18657. })
  18658. ;
  18659. return (returnedValue !== undefined)
  18660. ? returnedValue
  18661. : this
  18662. ;
  18663. };
  18664. $.fn.state.settings = {
  18665. // module info
  18666. name : 'State',
  18667. // debug output
  18668. debug : false,
  18669. // verbose debug output
  18670. verbose : false,
  18671. // namespace for events
  18672. namespace : 'state',
  18673. // debug data includes performance
  18674. performance : true,
  18675. // callback occurs on state change
  18676. onActivate : function() {},
  18677. onDeactivate : function() {},
  18678. onChange : function() {},
  18679. // state test functions
  18680. activateTest : function() { return true; },
  18681. deactivateTest : function() { return true; },
  18682. // whether to automatically map default states
  18683. automatic : true,
  18684. // activate / deactivate changes all elements instantiated at same time
  18685. sync : false,
  18686. // default flash text duration, used for temporarily changing text of an element
  18687. flashDuration : 1000,
  18688. // selector filter
  18689. filter : {
  18690. text : '.loading, .disabled',
  18691. active : '.disabled'
  18692. },
  18693. context : false,
  18694. // error
  18695. error: {
  18696. beforeSend : 'The before send function has cancelled state change',
  18697. method : 'The method you called is not defined.'
  18698. },
  18699. // metadata
  18700. metadata: {
  18701. promise : 'promise',
  18702. storedText : 'stored-text'
  18703. },
  18704. // change class on state
  18705. className: {
  18706. active : 'active',
  18707. disabled : 'disabled',
  18708. error : 'error',
  18709. loading : 'loading',
  18710. success : 'success',
  18711. warning : 'warning'
  18712. },
  18713. selector: {
  18714. // selector for text node
  18715. text: false
  18716. },
  18717. defaults : {
  18718. input: {
  18719. disabled : true,
  18720. loading : true,
  18721. active : true
  18722. },
  18723. button: {
  18724. disabled : true,
  18725. loading : true,
  18726. active : true,
  18727. },
  18728. progress: {
  18729. active : true,
  18730. success : true,
  18731. warning : true,
  18732. error : true
  18733. }
  18734. },
  18735. states : {
  18736. active : true,
  18737. disabled : true,
  18738. error : true,
  18739. loading : true,
  18740. success : true,
  18741. warning : true
  18742. },
  18743. text : {
  18744. disabled : false,
  18745. flash : false,
  18746. hover : false,
  18747. active : false,
  18748. inactive : false,
  18749. activate : false,
  18750. deactivate : false
  18751. }
  18752. };
  18753. })( jQuery, window, document );
  18754. /*!
  18755. * # Semantic UI 2.1.6 - Visibility
  18756. * http://github.com/semantic-org/semantic-ui/
  18757. *
  18758. *
  18759. * Copyright 2015 Contributors
  18760. * Released under the MIT license
  18761. * http://opensource.org/licenses/MIT
  18762. *
  18763. */
  18764. ;(function ( $, window, document, undefined ) {
  18765. "use strict";
  18766. $.fn.visibility = function(parameters) {
  18767. var
  18768. $allModules = $(this),
  18769. moduleSelector = $allModules.selector || '',
  18770. time = new Date().getTime(),
  18771. performance = [],
  18772. query = arguments[0],
  18773. methodInvoked = (typeof query == 'string'),
  18774. queryArguments = [].slice.call(arguments, 1),
  18775. returnedValue
  18776. ;
  18777. $allModules
  18778. .each(function() {
  18779. var
  18780. settings = ( $.isPlainObject(parameters) )
  18781. ? $.extend(true, {}, $.fn.visibility.settings, parameters)
  18782. : $.extend({}, $.fn.visibility.settings),
  18783. className = settings.className,
  18784. namespace = settings.namespace,
  18785. error = settings.error,
  18786. metadata = settings.metadata,
  18787. eventNamespace = '.' + namespace,
  18788. moduleNamespace = 'module-' + namespace,
  18789. $window = $(window),
  18790. $module = $(this),
  18791. $context = $(settings.context),
  18792. $placeholder,
  18793. selector = $module.selector || '',
  18794. instance = $module.data(moduleNamespace),
  18795. requestAnimationFrame = window.requestAnimationFrame
  18796. || window.mozRequestAnimationFrame
  18797. || window.webkitRequestAnimationFrame
  18798. || window.msRequestAnimationFrame
  18799. || function(callback) { setTimeout(callback, 0); },
  18800. element = this,
  18801. disabled = false,
  18802. observer,
  18803. module
  18804. ;
  18805. module = {
  18806. initialize: function() {
  18807. module.debug('Initializing', settings);
  18808. module.setup.cache();
  18809. if( module.should.trackChanges() ) {
  18810. if(settings.type == 'image') {
  18811. module.setup.image();
  18812. }
  18813. if(settings.type == 'fixed') {
  18814. module.setup.fixed();
  18815. }
  18816. if(settings.observeChanges) {
  18817. module.observeChanges();
  18818. }
  18819. module.bind.events();
  18820. }
  18821. module.save.position();
  18822. if( !module.is.visible() ) {
  18823. module.error(error.visible, $module);
  18824. }
  18825. if(settings.initialCheck) {
  18826. module.checkVisibility();
  18827. }
  18828. module.instantiate();
  18829. },
  18830. instantiate: function() {
  18831. module.debug('Storing instance', module);
  18832. $module
  18833. .data(moduleNamespace, module)
  18834. ;
  18835. instance = module;
  18836. },
  18837. destroy: function() {
  18838. module.verbose('Destroying previous module');
  18839. if(observer) {
  18840. observer.disconnect();
  18841. }
  18842. $window
  18843. .off('load' + eventNamespace, module.event.load)
  18844. .off('resize' + eventNamespace, module.event.resize)
  18845. ;
  18846. $context
  18847. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  18848. ;
  18849. $module
  18850. .off(eventNamespace)
  18851. .removeData(moduleNamespace)
  18852. ;
  18853. },
  18854. observeChanges: function() {
  18855. if('MutationObserver' in window) {
  18856. observer = new MutationObserver(function(mutations) {
  18857. module.verbose('DOM tree modified, updating visibility calculations');
  18858. module.timer = setTimeout(function() {
  18859. module.verbose('DOM tree modified, updating sticky menu');
  18860. module.refresh();
  18861. }, 100);
  18862. });
  18863. observer.observe(element, {
  18864. childList : true,
  18865. subtree : true
  18866. });
  18867. module.debug('Setting up mutation observer', observer);
  18868. }
  18869. },
  18870. bind: {
  18871. events: function() {
  18872. module.verbose('Binding visibility events to scroll and resize');
  18873. if(settings.refreshOnLoad) {
  18874. $window
  18875. .on('load' + eventNamespace, module.event.load)
  18876. ;
  18877. }
  18878. $window
  18879. .on('resize' + eventNamespace, module.event.resize)
  18880. ;
  18881. // pub/sub pattern
  18882. $context
  18883. .off('scroll' + eventNamespace)
  18884. .on('scroll' + eventNamespace, module.event.scroll)
  18885. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  18886. ;
  18887. }
  18888. },
  18889. event: {
  18890. resize: function() {
  18891. module.debug('Window resized');
  18892. if(settings.refreshOnResize) {
  18893. requestAnimationFrame(module.refresh);
  18894. }
  18895. },
  18896. load: function() {
  18897. module.debug('Page finished loading');
  18898. requestAnimationFrame(module.refresh);
  18899. },
  18900. // publishes scrollchange event on one scroll
  18901. scroll: function() {
  18902. if(settings.throttle) {
  18903. clearTimeout(module.timer);
  18904. module.timer = setTimeout(function() {
  18905. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  18906. }, settings.throttle);
  18907. }
  18908. else {
  18909. requestAnimationFrame(function() {
  18910. $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]);
  18911. });
  18912. }
  18913. },
  18914. // subscribes to scrollchange
  18915. scrollchange: function(event, scrollPosition) {
  18916. module.checkVisibility(scrollPosition);
  18917. },
  18918. },
  18919. precache: function(images, callback) {
  18920. if (!(images instanceof Array)) {
  18921. images = [images];
  18922. }
  18923. var
  18924. imagesLength = images.length,
  18925. loadedCounter = 0,
  18926. cache = [],
  18927. cacheImage = document.createElement('img'),
  18928. handleLoad = function() {
  18929. loadedCounter++;
  18930. if (loadedCounter >= images.length) {
  18931. if ($.isFunction(callback)) {
  18932. callback();
  18933. }
  18934. }
  18935. }
  18936. ;
  18937. while (imagesLength--) {
  18938. cacheImage = document.createElement('img');
  18939. cacheImage.onload = handleLoad;
  18940. cacheImage.onerror = handleLoad;
  18941. cacheImage.src = images[imagesLength];
  18942. cache.push(cacheImage);
  18943. }
  18944. },
  18945. enableCallbacks: function() {
  18946. module.debug('Allowing callbacks to occur');
  18947. disabled = false;
  18948. },
  18949. disableCallbacks: function() {
  18950. module.debug('Disabling all callbacks temporarily');
  18951. disabled = true;
  18952. },
  18953. should: {
  18954. trackChanges: function() {
  18955. if(methodInvoked) {
  18956. module.debug('One time query, no need to bind events');
  18957. return false;
  18958. }
  18959. module.debug('Callbacks being attached');
  18960. return true;
  18961. }
  18962. },
  18963. setup: {
  18964. cache: function() {
  18965. module.cache = {
  18966. occurred : {},
  18967. screen : {},
  18968. element : {},
  18969. };
  18970. },
  18971. image: function() {
  18972. var
  18973. src = $module.data(metadata.src)
  18974. ;
  18975. if(src) {
  18976. module.verbose('Lazy loading image', src);
  18977. settings.once = true;
  18978. settings.observeChanges = false;
  18979. // show when top visible
  18980. settings.onOnScreen = function() {
  18981. module.debug('Image on screen', element);
  18982. module.precache(src, function() {
  18983. module.set.image(src);
  18984. });
  18985. };
  18986. }
  18987. },
  18988. fixed: function() {
  18989. module.debug('Setting up fixed');
  18990. settings.once = false;
  18991. settings.observeChanges = false;
  18992. settings.initialCheck = true;
  18993. settings.refreshOnLoad = true;
  18994. if(!parameters.transition) {
  18995. settings.transition = false;
  18996. }
  18997. module.create.placeholder();
  18998. module.debug('Added placeholder', $placeholder);
  18999. settings.onTopPassed = function() {
  19000. module.debug('Element passed, adding fixed position', $module);
  19001. module.show.placeholder();
  19002. module.set.fixed();
  19003. if(settings.transition) {
  19004. if($.fn.transition !== undefined) {
  19005. $module.transition(settings.transition, settings.duration);
  19006. }
  19007. }
  19008. };
  19009. settings.onTopPassedReverse = function() {
  19010. module.debug('Element returned to position, removing fixed', $module);
  19011. module.hide.placeholder();
  19012. module.remove.fixed();
  19013. };
  19014. }
  19015. },
  19016. create: {
  19017. placeholder: function() {
  19018. module.verbose('Creating fixed position placeholder');
  19019. $placeholder = $module
  19020. .clone(false)
  19021. .css('display', 'none')
  19022. .addClass(className.placeholder)
  19023. .insertAfter($module)
  19024. ;
  19025. }
  19026. },
  19027. show: {
  19028. placeholder: function() {
  19029. module.verbose('Showing placeholder');
  19030. $placeholder
  19031. .css('display', 'block')
  19032. .css('visibility', 'hidden')
  19033. ;
  19034. }
  19035. },
  19036. hide: {
  19037. placeholder: function() {
  19038. module.verbose('Hiding placeholder');
  19039. $placeholder
  19040. .css('display', 'none')
  19041. .css('visibility', '')
  19042. ;
  19043. }
  19044. },
  19045. set: {
  19046. fixed: function() {
  19047. module.verbose('Setting element to fixed position');
  19048. $module
  19049. .addClass(className.fixed)
  19050. .css({
  19051. position : 'fixed',
  19052. top : settings.offset + 'px',
  19053. left : 'auto',
  19054. zIndex : '1'
  19055. })
  19056. ;
  19057. },
  19058. image: function(src) {
  19059. $module
  19060. .attr('src', src)
  19061. ;
  19062. if(settings.transition) {
  19063. if( $.fn.transition !== undefined ) {
  19064. $module.transition(settings.transition, settings.duration);
  19065. }
  19066. else {
  19067. $module.fadeIn(settings.duration);
  19068. }
  19069. }
  19070. else {
  19071. $module.show();
  19072. }
  19073. }
  19074. },
  19075. is: {
  19076. onScreen: function() {
  19077. var
  19078. calculations = module.get.elementCalculations()
  19079. ;
  19080. return calculations.onScreen;
  19081. },
  19082. offScreen: function() {
  19083. var
  19084. calculations = module.get.elementCalculations()
  19085. ;
  19086. return calculations.offScreen;
  19087. },
  19088. visible: function() {
  19089. if(module.cache && module.cache.element) {
  19090. return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0);
  19091. }
  19092. return false;
  19093. }
  19094. },
  19095. refresh: function() {
  19096. module.debug('Refreshing constants (width/height)');
  19097. if(settings.type == 'fixed') {
  19098. module.remove.fixed();
  19099. module.remove.occurred();
  19100. }
  19101. module.reset();
  19102. module.save.position();
  19103. if(settings.checkOnRefresh) {
  19104. module.checkVisibility();
  19105. }
  19106. settings.onRefresh.call(element);
  19107. },
  19108. reset: function() {
  19109. module.verbose('Reseting all cached values');
  19110. if( $.isPlainObject(module.cache) ) {
  19111. module.cache.screen = {};
  19112. module.cache.element = {};
  19113. }
  19114. },
  19115. checkVisibility: function(scroll) {
  19116. module.verbose('Checking visibility of element', module.cache.element);
  19117. if( !disabled && module.is.visible() ) {
  19118. // save scroll position
  19119. module.save.scroll(scroll);
  19120. // update calculations derived from scroll
  19121. module.save.calculations();
  19122. // percentage
  19123. module.passed();
  19124. // reverse (must be first)
  19125. module.passingReverse();
  19126. module.topVisibleReverse();
  19127. module.bottomVisibleReverse();
  19128. module.topPassedReverse();
  19129. module.bottomPassedReverse();
  19130. // one time
  19131. module.onScreen();
  19132. module.offScreen();
  19133. module.passing();
  19134. module.topVisible();
  19135. module.bottomVisible();
  19136. module.topPassed();
  19137. module.bottomPassed();
  19138. // on update callback
  19139. if(settings.onUpdate) {
  19140. settings.onUpdate.call(element, module.get.elementCalculations());
  19141. }
  19142. }
  19143. },
  19144. passed: function(amount, newCallback) {
  19145. var
  19146. calculations = module.get.elementCalculations(),
  19147. amountInPixels
  19148. ;
  19149. // assign callback
  19150. if(amount && newCallback) {
  19151. settings.onPassed[amount] = newCallback;
  19152. }
  19153. else if(amount !== undefined) {
  19154. return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
  19155. }
  19156. else if(calculations.passing) {
  19157. $.each(settings.onPassed, function(amount, callback) {
  19158. if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
  19159. module.execute(callback, amount);
  19160. }
  19161. else if(!settings.once) {
  19162. module.remove.occurred(callback);
  19163. }
  19164. });
  19165. }
  19166. },
  19167. onScreen: function(newCallback) {
  19168. var
  19169. calculations = module.get.elementCalculations(),
  19170. callback = newCallback || settings.onOnScreen,
  19171. callbackName = 'onScreen'
  19172. ;
  19173. if(newCallback) {
  19174. module.debug('Adding callback for onScreen', newCallback);
  19175. settings.onOnScreen = newCallback;
  19176. }
  19177. if(calculations.onScreen) {
  19178. module.execute(callback, callbackName);
  19179. }
  19180. else if(!settings.once) {
  19181. module.remove.occurred(callbackName);
  19182. }
  19183. if(newCallback !== undefined) {
  19184. return calculations.onOnScreen;
  19185. }
  19186. },
  19187. offScreen: function(newCallback) {
  19188. var
  19189. calculations = module.get.elementCalculations(),
  19190. callback = newCallback || settings.onOffScreen,
  19191. callbackName = 'offScreen'
  19192. ;
  19193. if(newCallback) {
  19194. module.debug('Adding callback for offScreen', newCallback);
  19195. settings.onOffScreen = newCallback;
  19196. }
  19197. if(calculations.offScreen) {
  19198. module.execute(callback, callbackName);
  19199. }
  19200. else if(!settings.once) {
  19201. module.remove.occurred(callbackName);
  19202. }
  19203. if(newCallback !== undefined) {
  19204. return calculations.onOffScreen;
  19205. }
  19206. },
  19207. passing: function(newCallback) {
  19208. var
  19209. calculations = module.get.elementCalculations(),
  19210. callback = newCallback || settings.onPassing,
  19211. callbackName = 'passing'
  19212. ;
  19213. if(newCallback) {
  19214. module.debug('Adding callback for passing', newCallback);
  19215. settings.onPassing = newCallback;
  19216. }
  19217. if(calculations.passing) {
  19218. module.execute(callback, callbackName);
  19219. }
  19220. else if(!settings.once) {
  19221. module.remove.occurred(callbackName);
  19222. }
  19223. if(newCallback !== undefined) {
  19224. return calculations.passing;
  19225. }
  19226. },
  19227. topVisible: function(newCallback) {
  19228. var
  19229. calculations = module.get.elementCalculations(),
  19230. callback = newCallback || settings.onTopVisible,
  19231. callbackName = 'topVisible'
  19232. ;
  19233. if(newCallback) {
  19234. module.debug('Adding callback for top visible', newCallback);
  19235. settings.onTopVisible = newCallback;
  19236. }
  19237. if(calculations.topVisible) {
  19238. module.execute(callback, callbackName);
  19239. }
  19240. else if(!settings.once) {
  19241. module.remove.occurred(callbackName);
  19242. }
  19243. if(newCallback === undefined) {
  19244. return calculations.topVisible;
  19245. }
  19246. },
  19247. bottomVisible: function(newCallback) {
  19248. var
  19249. calculations = module.get.elementCalculations(),
  19250. callback = newCallback || settings.onBottomVisible,
  19251. callbackName = 'bottomVisible'
  19252. ;
  19253. if(newCallback) {
  19254. module.debug('Adding callback for bottom visible', newCallback);
  19255. settings.onBottomVisible = newCallback;
  19256. }
  19257. if(calculations.bottomVisible) {
  19258. module.execute(callback, callbackName);
  19259. }
  19260. else if(!settings.once) {
  19261. module.remove.occurred(callbackName);
  19262. }
  19263. if(newCallback === undefined) {
  19264. return calculations.bottomVisible;
  19265. }
  19266. },
  19267. topPassed: function(newCallback) {
  19268. var
  19269. calculations = module.get.elementCalculations(),
  19270. callback = newCallback || settings.onTopPassed,
  19271. callbackName = 'topPassed'
  19272. ;
  19273. if(newCallback) {
  19274. module.debug('Adding callback for top passed', newCallback);
  19275. settings.onTopPassed = newCallback;
  19276. }
  19277. if(calculations.topPassed) {
  19278. module.execute(callback, callbackName);
  19279. }
  19280. else if(!settings.once) {
  19281. module.remove.occurred(callbackName);
  19282. }
  19283. if(newCallback === undefined) {
  19284. return calculations.topPassed;
  19285. }
  19286. },
  19287. bottomPassed: function(newCallback) {
  19288. var
  19289. calculations = module.get.elementCalculations(),
  19290. callback = newCallback || settings.onBottomPassed,
  19291. callbackName = 'bottomPassed'
  19292. ;
  19293. if(newCallback) {
  19294. module.debug('Adding callback for bottom passed', newCallback);
  19295. settings.onBottomPassed = newCallback;
  19296. }
  19297. if(calculations.bottomPassed) {
  19298. module.execute(callback, callbackName);
  19299. }
  19300. else if(!settings.once) {
  19301. module.remove.occurred(callbackName);
  19302. }
  19303. if(newCallback === undefined) {
  19304. return calculations.bottomPassed;
  19305. }
  19306. },
  19307. passingReverse: function(newCallback) {
  19308. var
  19309. calculations = module.get.elementCalculations(),
  19310. callback = newCallback || settings.onPassingReverse,
  19311. callbackName = 'passingReverse'
  19312. ;
  19313. if(newCallback) {
  19314. module.debug('Adding callback for passing reverse', newCallback);
  19315. settings.onPassingReverse = newCallback;
  19316. }
  19317. if(!calculations.passing) {
  19318. if(module.get.occurred('passing')) {
  19319. module.execute(callback, callbackName);
  19320. }
  19321. }
  19322. else if(!settings.once) {
  19323. module.remove.occurred(callbackName);
  19324. }
  19325. if(newCallback !== undefined) {
  19326. return !calculations.passing;
  19327. }
  19328. },
  19329. topVisibleReverse: function(newCallback) {
  19330. var
  19331. calculations = module.get.elementCalculations(),
  19332. callback = newCallback || settings.onTopVisibleReverse,
  19333. callbackName = 'topVisibleReverse'
  19334. ;
  19335. if(newCallback) {
  19336. module.debug('Adding callback for top visible reverse', newCallback);
  19337. settings.onTopVisibleReverse = newCallback;
  19338. }
  19339. if(!calculations.topVisible) {
  19340. if(module.get.occurred('topVisible')) {
  19341. module.execute(callback, callbackName);
  19342. }
  19343. }
  19344. else if(!settings.once) {
  19345. module.remove.occurred(callbackName);
  19346. }
  19347. if(newCallback === undefined) {
  19348. return !calculations.topVisible;
  19349. }
  19350. },
  19351. bottomVisibleReverse: function(newCallback) {
  19352. var
  19353. calculations = module.get.elementCalculations(),
  19354. callback = newCallback || settings.onBottomVisibleReverse,
  19355. callbackName = 'bottomVisibleReverse'
  19356. ;
  19357. if(newCallback) {
  19358. module.debug('Adding callback for bottom visible reverse', newCallback);
  19359. settings.onBottomVisibleReverse = newCallback;
  19360. }
  19361. if(!calculations.bottomVisible) {
  19362. if(module.get.occurred('bottomVisible')) {
  19363. module.execute(callback, callbackName);
  19364. }
  19365. }
  19366. else if(!settings.once) {
  19367. module.remove.occurred(callbackName);
  19368. }
  19369. if(newCallback === undefined) {
  19370. return !calculations.bottomVisible;
  19371. }
  19372. },
  19373. topPassedReverse: function(newCallback) {
  19374. var
  19375. calculations = module.get.elementCalculations(),
  19376. callback = newCallback || settings.onTopPassedReverse,
  19377. callbackName = 'topPassedReverse'
  19378. ;
  19379. if(newCallback) {
  19380. module.debug('Adding callback for top passed reverse', newCallback);
  19381. settings.onTopPassedReverse = newCallback;
  19382. }
  19383. if(!calculations.topPassed) {
  19384. if(module.get.occurred('topPassed')) {
  19385. module.execute(callback, callbackName);
  19386. }
  19387. }
  19388. else if(!settings.once) {
  19389. module.remove.occurred(callbackName);
  19390. }
  19391. if(newCallback === undefined) {
  19392. return !calculations.onTopPassed;
  19393. }
  19394. },
  19395. bottomPassedReverse: function(newCallback) {
  19396. var
  19397. calculations = module.get.elementCalculations(),
  19398. callback = newCallback || settings.onBottomPassedReverse,
  19399. callbackName = 'bottomPassedReverse'
  19400. ;
  19401. if(newCallback) {
  19402. module.debug('Adding callback for bottom passed reverse', newCallback);
  19403. settings.onBottomPassedReverse = newCallback;
  19404. }
  19405. if(!calculations.bottomPassed) {
  19406. if(module.get.occurred('bottomPassed')) {
  19407. module.execute(callback, callbackName);
  19408. }
  19409. }
  19410. else if(!settings.once) {
  19411. module.remove.occurred(callbackName);
  19412. }
  19413. if(newCallback === undefined) {
  19414. return !calculations.bottomPassed;
  19415. }
  19416. },
  19417. execute: function(callback, callbackName) {
  19418. var
  19419. calculations = module.get.elementCalculations(),
  19420. screen = module.get.screenCalculations()
  19421. ;
  19422. callback = callback || false;
  19423. if(callback) {
  19424. if(settings.continuous) {
  19425. module.debug('Callback being called continuously', callbackName, calculations);
  19426. callback.call(element, calculations, screen);
  19427. }
  19428. else if(!module.get.occurred(callbackName)) {
  19429. module.debug('Conditions met', callbackName, calculations);
  19430. callback.call(element, calculations, screen);
  19431. }
  19432. }
  19433. module.save.occurred(callbackName);
  19434. },
  19435. remove: {
  19436. fixed: function() {
  19437. module.debug('Removing fixed position');
  19438. $module
  19439. .removeClass(className.fixed)
  19440. .css({
  19441. position : '',
  19442. top : '',
  19443. left : '',
  19444. zIndex : ''
  19445. })
  19446. ;
  19447. },
  19448. occurred: function(callback) {
  19449. if(callback) {
  19450. var
  19451. occurred = module.cache.occurred
  19452. ;
  19453. if(occurred[callback] !== undefined && occurred[callback] === true) {
  19454. module.debug('Callback can now be called again', callback);
  19455. module.cache.occurred[callback] = false;
  19456. }
  19457. }
  19458. else {
  19459. module.cache.occurred = {};
  19460. }
  19461. }
  19462. },
  19463. save: {
  19464. calculations: function() {
  19465. module.verbose('Saving all calculations necessary to determine positioning');
  19466. module.save.direction();
  19467. module.save.screenCalculations();
  19468. module.save.elementCalculations();
  19469. },
  19470. occurred: function(callback) {
  19471. if(callback) {
  19472. if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
  19473. module.verbose('Saving callback occurred', callback);
  19474. module.cache.occurred[callback] = true;
  19475. }
  19476. }
  19477. },
  19478. scroll: function(scrollPosition) {
  19479. scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset;
  19480. module.cache.scroll = scrollPosition;
  19481. },
  19482. direction: function() {
  19483. var
  19484. scroll = module.get.scroll(),
  19485. lastScroll = module.get.lastScroll(),
  19486. direction
  19487. ;
  19488. if(scroll > lastScroll && lastScroll) {
  19489. direction = 'down';
  19490. }
  19491. else if(scroll < lastScroll && lastScroll) {
  19492. direction = 'up';
  19493. }
  19494. else {
  19495. direction = 'static';
  19496. }
  19497. module.cache.direction = direction;
  19498. return module.cache.direction;
  19499. },
  19500. elementPosition: function() {
  19501. var
  19502. element = module.cache.element,
  19503. screen = module.get.screenSize()
  19504. ;
  19505. module.verbose('Saving element position');
  19506. // (quicker than $.extend)
  19507. element.fits = (element.height < screen.height);
  19508. element.offset = $module.offset();
  19509. element.width = $module.outerWidth();
  19510. element.height = $module.outerHeight();
  19511. // store
  19512. module.cache.element = element;
  19513. return element;
  19514. },
  19515. elementCalculations: function() {
  19516. var
  19517. screen = module.get.screenCalculations(),
  19518. element = module.get.elementPosition()
  19519. ;
  19520. // offset
  19521. if(settings.includeMargin) {
  19522. element.margin = {};
  19523. element.margin.top = parseInt($module.css('margin-top'), 10);
  19524. element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
  19525. element.top = element.offset.top - element.margin.top;
  19526. element.bottom = element.offset.top + element.height + element.margin.bottom;
  19527. }
  19528. else {
  19529. element.top = element.offset.top;
  19530. element.bottom = element.offset.top + element.height;
  19531. }
  19532. // visibility
  19533. element.topVisible = (screen.bottom >= element.top);
  19534. element.topPassed = (screen.top >= element.top);
  19535. element.bottomVisible = (screen.bottom >= element.bottom);
  19536. element.bottomPassed = (screen.top >= element.bottom);
  19537. element.pixelsPassed = 0;
  19538. element.percentagePassed = 0;
  19539. // meta calculations
  19540. element.onScreen = (element.topVisible && !element.bottomPassed);
  19541. element.passing = (element.topPassed && !element.bottomPassed);
  19542. element.offScreen = (!element.onScreen);
  19543. // passing calculations
  19544. if(element.passing) {
  19545. element.pixelsPassed = (screen.top - element.top);
  19546. element.percentagePassed = (screen.top - element.top) / element.height;
  19547. }
  19548. module.cache.element = element;
  19549. module.verbose('Updated element calculations', element);
  19550. return element;
  19551. },
  19552. screenCalculations: function() {
  19553. var
  19554. scroll = module.get.scroll()
  19555. ;
  19556. module.save.direction();
  19557. module.cache.screen.top = scroll;
  19558. module.cache.screen.bottom = scroll + module.cache.screen.height;
  19559. return module.cache.screen;
  19560. },
  19561. screenSize: function() {
  19562. module.verbose('Saving window position');
  19563. module.cache.screen = {
  19564. height: $context.height()
  19565. };
  19566. },
  19567. position: function() {
  19568. module.save.screenSize();
  19569. module.save.elementPosition();
  19570. }
  19571. },
  19572. get: {
  19573. pixelsPassed: function(amount) {
  19574. var
  19575. element = module.get.elementCalculations()
  19576. ;
  19577. if(amount.search('%') > -1) {
  19578. return ( element.height * (parseInt(amount, 10) / 100) );
  19579. }
  19580. return parseInt(amount, 10);
  19581. },
  19582. occurred: function(callback) {
  19583. return (module.cache.occurred !== undefined)
  19584. ? module.cache.occurred[callback] || false
  19585. : false
  19586. ;
  19587. },
  19588. direction: function() {
  19589. if(module.cache.direction === undefined) {
  19590. module.save.direction();
  19591. }
  19592. return module.cache.direction;
  19593. },
  19594. elementPosition: function() {
  19595. if(module.cache.element === undefined) {
  19596. module.save.elementPosition();
  19597. }
  19598. return module.cache.element;
  19599. },
  19600. elementCalculations: function() {
  19601. if(module.cache.element === undefined) {
  19602. module.save.elementCalculations();
  19603. }
  19604. return module.cache.element;
  19605. },
  19606. screenCalculations: function() {
  19607. if(module.cache.screen === undefined) {
  19608. module.save.screenCalculations();
  19609. }
  19610. return module.cache.screen;
  19611. },
  19612. screenSize: function() {
  19613. if(module.cache.screen === undefined) {
  19614. module.save.screenSize();
  19615. }
  19616. return module.cache.screen;
  19617. },
  19618. scroll: function() {
  19619. if(module.cache.scroll === undefined) {
  19620. module.save.scroll();
  19621. }
  19622. return module.cache.scroll;
  19623. },
  19624. lastScroll: function() {
  19625. if(module.cache.screen === undefined) {
  19626. module.debug('First scroll event, no last scroll could be found');
  19627. return false;
  19628. }
  19629. return module.cache.screen.top;
  19630. }
  19631. },
  19632. setting: function(name, value) {
  19633. if( $.isPlainObject(name) ) {
  19634. $.extend(true, settings, name);
  19635. }
  19636. else if(value !== undefined) {
  19637. settings[name] = value;
  19638. }
  19639. else {
  19640. return settings[name];
  19641. }
  19642. },
  19643. internal: function(name, value) {
  19644. if( $.isPlainObject(name) ) {
  19645. $.extend(true, module, name);
  19646. }
  19647. else if(value !== undefined) {
  19648. module[name] = value;
  19649. }
  19650. else {
  19651. return module[name];
  19652. }
  19653. },
  19654. debug: function() {
  19655. if(settings.debug) {
  19656. if(settings.performance) {
  19657. module.performance.log(arguments);
  19658. }
  19659. else {
  19660. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19661. module.debug.apply(console, arguments);
  19662. }
  19663. }
  19664. },
  19665. verbose: function() {
  19666. if(settings.verbose && settings.debug) {
  19667. if(settings.performance) {
  19668. module.performance.log(arguments);
  19669. }
  19670. else {
  19671. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  19672. module.verbose.apply(console, arguments);
  19673. }
  19674. }
  19675. },
  19676. error: function() {
  19677. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  19678. module.error.apply(console, arguments);
  19679. },
  19680. performance: {
  19681. log: function(message) {
  19682. var
  19683. currentTime,
  19684. executionTime,
  19685. previousTime
  19686. ;
  19687. if(settings.performance) {
  19688. currentTime = new Date().getTime();
  19689. previousTime = time || currentTime;
  19690. executionTime = currentTime - previousTime;
  19691. time = currentTime;
  19692. performance.push({
  19693. 'Name' : message[0],
  19694. 'Arguments' : [].slice.call(message, 1) || '',
  19695. 'Element' : element,
  19696. 'Execution Time' : executionTime
  19697. });
  19698. }
  19699. clearTimeout(module.performance.timer);
  19700. module.performance.timer = setTimeout(module.performance.display, 500);
  19701. },
  19702. display: function() {
  19703. var
  19704. title = settings.name + ':',
  19705. totalTime = 0
  19706. ;
  19707. time = false;
  19708. clearTimeout(module.performance.timer);
  19709. $.each(performance, function(index, data) {
  19710. totalTime += data['Execution Time'];
  19711. });
  19712. title += ' ' + totalTime + 'ms';
  19713. if(moduleSelector) {
  19714. title += ' \'' + moduleSelector + '\'';
  19715. }
  19716. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  19717. console.groupCollapsed(title);
  19718. if(console.table) {
  19719. console.table(performance);
  19720. }
  19721. else {
  19722. $.each(performance, function(index, data) {
  19723. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  19724. });
  19725. }
  19726. console.groupEnd();
  19727. }
  19728. performance = [];
  19729. }
  19730. },
  19731. invoke: function(query, passedArguments, context) {
  19732. var
  19733. object = instance,
  19734. maxDepth,
  19735. found,
  19736. response
  19737. ;
  19738. passedArguments = passedArguments || queryArguments;
  19739. context = element || context;
  19740. if(typeof query == 'string' && object !== undefined) {
  19741. query = query.split(/[\. ]/);
  19742. maxDepth = query.length - 1;
  19743. $.each(query, function(depth, value) {
  19744. var camelCaseValue = (depth != maxDepth)
  19745. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  19746. : query
  19747. ;
  19748. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  19749. object = object[camelCaseValue];
  19750. }
  19751. else if( object[camelCaseValue] !== undefined ) {
  19752. found = object[camelCaseValue];
  19753. return false;
  19754. }
  19755. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  19756. object = object[value];
  19757. }
  19758. else if( object[value] !== undefined ) {
  19759. found = object[value];
  19760. return false;
  19761. }
  19762. else {
  19763. module.error(error.method, query);
  19764. return false;
  19765. }
  19766. });
  19767. }
  19768. if ( $.isFunction( found ) ) {
  19769. response = found.apply(context, passedArguments);
  19770. }
  19771. else if(found !== undefined) {
  19772. response = found;
  19773. }
  19774. if($.isArray(returnedValue)) {
  19775. returnedValue.push(response);
  19776. }
  19777. else if(returnedValue !== undefined) {
  19778. returnedValue = [returnedValue, response];
  19779. }
  19780. else if(response !== undefined) {
  19781. returnedValue = response;
  19782. }
  19783. return found;
  19784. }
  19785. };
  19786. if(methodInvoked) {
  19787. if(instance === undefined) {
  19788. module.initialize();
  19789. }
  19790. instance.save.scroll();
  19791. instance.save.calculations();
  19792. module.invoke(query);
  19793. }
  19794. else {
  19795. if(instance !== undefined) {
  19796. instance.invoke('destroy');
  19797. }
  19798. module.initialize();
  19799. }
  19800. })
  19801. ;
  19802. return (returnedValue !== undefined)
  19803. ? returnedValue
  19804. : this
  19805. ;
  19806. };
  19807. $.fn.visibility.settings = {
  19808. name : 'Visibility',
  19809. namespace : 'visibility',
  19810. debug : false,
  19811. verbose : false,
  19812. performance : true,
  19813. // whether to use mutation observers to follow changes
  19814. observeChanges : true,
  19815. // check position immediately on init
  19816. initialCheck : true,
  19817. // whether to refresh calculations after all page images load
  19818. refreshOnLoad : true,
  19819. // whether to refresh calculations after page resize event
  19820. refreshOnResize : true,
  19821. // should call callbacks on refresh event (resize, etc)
  19822. checkOnRefresh : true,
  19823. // callback should only occur one time
  19824. once : true,
  19825. // callback should fire continuously whe evaluates to true
  19826. continuous : false,
  19827. // offset to use with scroll top
  19828. offset : 0,
  19829. // whether to include margin in elements position
  19830. includeMargin : false,
  19831. // scroll context for visibility checks
  19832. context : window,
  19833. // visibility check delay in ms (defaults to animationFrame)
  19834. throttle : false,
  19835. // special visibility type (image, fixed)
  19836. type : false,
  19837. // image only animation settings
  19838. transition : 'fade in',
  19839. duration : 1000,
  19840. // array of callbacks for percentage
  19841. onPassed : {},
  19842. // standard callbacks
  19843. onOnScreen : false,
  19844. onOffScreen : false,
  19845. onPassing : false,
  19846. onTopVisible : false,
  19847. onBottomVisible : false,
  19848. onTopPassed : false,
  19849. onBottomPassed : false,
  19850. // reverse callbacks
  19851. onPassingReverse : false,
  19852. onTopVisibleReverse : false,
  19853. onBottomVisibleReverse : false,
  19854. onTopPassedReverse : false,
  19855. onBottomPassedReverse : false,
  19856. // utility callbacks
  19857. onUpdate : false, // disabled by default for performance
  19858. onRefresh : function(){},
  19859. metadata : {
  19860. src: 'src'
  19861. },
  19862. className: {
  19863. fixed : 'fixed',
  19864. placeholder : 'placeholder'
  19865. },
  19866. error : {
  19867. method : 'The method you called is not defined.',
  19868. visible : 'Element is hidden, you must call refresh after element becomes visible'
  19869. }
  19870. };
  19871. })( jQuery, window, document );