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.

1742 lines
56 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /*
  2. * # Semantic - Dropdown
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributor
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ( $, window, document, undefined ) {
  12. "use strict";
  13. $.fn.dropdown = function(parameters) {
  14. var
  15. $allModules = $(this),
  16. $document = $(document),
  17. moduleSelector = $allModules.selector || '',
  18. hasTouch = ('ontouchstart' in document.documentElement),
  19. time = new Date().getTime(),
  20. performance = [],
  21. query = arguments[0],
  22. methodInvoked = (typeof query == 'string'),
  23. queryArguments = [].slice.call(arguments, 1),
  24. returnedValue
  25. ;
  26. $allModules
  27. .each(function() {
  28. var
  29. settings = ( $.isPlainObject(parameters) )
  30. ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
  31. : $.extend({}, $.fn.dropdown.settings),
  32. className = settings.className,
  33. metadata = settings.metadata,
  34. namespace = settings.namespace,
  35. selector = settings.selector,
  36. error = settings.error,
  37. eventNamespace = '.' + namespace,
  38. moduleNamespace = 'module-' + namespace,
  39. $module = $(this),
  40. $text = $module.find(selector.text),
  41. $search = $module.find(selector.search),
  42. $input = $module.find(selector.input),
  43. $combo = ($module.prev().find(selector.text).length > 0)
  44. ? $module.prev().find(selector.text)
  45. : $module.prev(),
  46. $menu = $module.children(selector.menu),
  47. $item = $menu.find(selector.item),
  48. activated = false,
  49. itemActivated = false,
  50. element = this,
  51. instance = $module.data(moduleNamespace),
  52. elementNamespace,
  53. id,
  54. observer,
  55. module
  56. ;
  57. module = {
  58. initialize: function() {
  59. module.debug('Initializing dropdown', settings);
  60. if( module.is.alreadySetup() ) {
  61. module.error(error.alreadySetup);
  62. }
  63. else {
  64. module.setup.layout();
  65. }
  66. module.save.defaults();
  67. module.set.selected();
  68. module.create.id();
  69. if(hasTouch) {
  70. module.bind.touchEvents();
  71. }
  72. module.bind.mouseEvents();
  73. module.bind.keyboardEvents();
  74. module.observeChanges();
  75. module.instantiate();
  76. },
  77. instantiate: function() {
  78. module.verbose('Storing instance of dropdown', module);
  79. instance = module;
  80. $module
  81. .data(moduleNamespace, module)
  82. ;
  83. },
  84. destroy: function() {
  85. module.verbose('Destroying previous dropdown for', $module);
  86. module.remove.tabbable();
  87. $module
  88. .off(eventNamespace)
  89. .removeData(moduleNamespace)
  90. ;
  91. $menu
  92. .off(eventNamespace)
  93. ;
  94. $document
  95. .off(elementNamespace)
  96. ;
  97. },
  98. observeChanges: function() {
  99. if('MutationObserver' in window) {
  100. observer = new MutationObserver(function(mutations) {
  101. if( module.is.selectMutation(mutations) ) {
  102. module.debug('<select> modified, recreating menu');
  103. module.setup.select();
  104. }
  105. else {
  106. module.debug('DOM tree modified, updating selector cache');
  107. module.refresh();
  108. }
  109. });
  110. observer.observe(element, {
  111. childList : true,
  112. subtree : true
  113. });
  114. module.debug('Setting up mutation observer', observer);
  115. }
  116. },
  117. create: {
  118. id: function() {
  119. module.verbose('Creating unique id for element');
  120. id = module.get.uniqueID();
  121. elementNamespace = '.' + id;
  122. }
  123. },
  124. search: function() {
  125. var
  126. query
  127. ;
  128. query = $search.val();
  129. module.verbose('Searching for query', query);
  130. module.filter(query);
  131. if(module.is.searchSelection() && module.can.show() ) {
  132. module.show();
  133. }
  134. },
  135. setup: {
  136. layout: function() {
  137. if( $module.is('select') ) {
  138. module.setup.select();
  139. }
  140. if( module.is.search() && !module.is.searchable() ) {
  141. $search = $('<input />')
  142. .addClass(className.search)
  143. .insertBefore($text)
  144. ;
  145. }
  146. if(settings.allowTab) {
  147. module.set.tabbable();
  148. }
  149. },
  150. select: function() {
  151. var
  152. selectValues = module.get.selectValues()
  153. ;
  154. module.debug('Dropdown initialized on a select', selectValues);
  155. if( $module.is('select') ) {
  156. $input = $module;
  157. }
  158. // see if select is placed correctly already
  159. if($input.parent(selector.dropdown).length > 0) {
  160. module.debug('UI dropdown already exists. Creating dropdown menu only');
  161. $module = $input.closest(selector.dropdown);
  162. $menu = $module.children(selector.menu);
  163. if($menu.length === 0) {
  164. $menu = $('<div />')
  165. .addClass(className.menu)
  166. .appendTo($module)
  167. ;
  168. }
  169. $menu.html( settings.templates.menu( selectValues ));
  170. }
  171. else {
  172. module.debug('Creating entire dropdown from select');
  173. $module = $('<div />')
  174. .attr('class', $input.attr('class') )
  175. .addClass(className.selection)
  176. .addClass(className.dropdown)
  177. .html( settings.templates.dropdown(selectValues) )
  178. .insertBefore($input)
  179. ;
  180. $input
  181. .removeAttr('class')
  182. .prependTo($module)
  183. ;
  184. }
  185. module.refresh();
  186. }
  187. },
  188. refresh: function() {
  189. module.verbose('Refreshing selector cache');
  190. $text = $module.find(selector.text);
  191. $search = $module.find(selector.search);
  192. $input = $module.find(selector.input);
  193. $combo = ($module.prev().find(selector.text).length > 0)
  194. ? $module.prev().find(selector.text)
  195. : $module.prev()
  196. ;
  197. $menu = $module.children(selector.menu);
  198. $item = $menu.find(selector.item);
  199. },
  200. toggle: function() {
  201. module.verbose('Toggling menu visibility');
  202. if( !module.is.active() ) {
  203. module.show();
  204. }
  205. else {
  206. module.hide();
  207. }
  208. },
  209. show: function(callback) {
  210. callback = $.isFunction(callback)
  211. ? callback
  212. : function(){}
  213. ;
  214. if( module.is.searchSelection() && module.is.allFiltered() ) {
  215. return;
  216. }
  217. if( module.can.show() && !module.is.active() ) {
  218. module.debug('Showing dropdown');
  219. module.animate.show(function() {
  220. if( module.can.click() ) {
  221. module.bind.intent();
  222. }
  223. module.set.visible();
  224. callback.call(element);
  225. });
  226. settings.onShow.call(element);
  227. }
  228. },
  229. hide: function(callback) {
  230. callback = $.isFunction(callback)
  231. ? callback
  232. : function(){}
  233. ;
  234. if( module.is.active() ) {
  235. module.debug('Hiding dropdown');
  236. module.animate.hide(function() {
  237. module.remove.visible();
  238. callback.call(element);
  239. });
  240. settings.onHide.call(element);
  241. }
  242. },
  243. hideOthers: function() {
  244. module.verbose('Finding other dropdowns to hide');
  245. $allModules
  246. .not($module)
  247. .has(selector.menu + ':visible:not(.' + className.animating + ')')
  248. .dropdown('hide')
  249. ;
  250. },
  251. hideSubMenus: function() {
  252. var
  253. $subMenus = $menu.find(selector.menu)
  254. ;
  255. $subMenus.transition('hide');
  256. },
  257. bind: {
  258. keyboardEvents: function() {
  259. module.debug('Binding keyboard events');
  260. $module
  261. .on('keydown' + eventNamespace, module.event.keydown)
  262. ;
  263. if( module.is.searchable() ) {
  264. $module
  265. .on(module.get.inputEvent(), selector.search, module.event.input)
  266. ;
  267. }
  268. },
  269. touchEvents: function() {
  270. module.debug('Touch device detected binding additional touch events');
  271. if( module.is.searchSelection() ) {
  272. // do nothing special yet
  273. }
  274. else {
  275. $module
  276. .on('touchstart' + eventNamespace, module.event.test.toggle)
  277. ;
  278. }
  279. $menu
  280. .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
  281. ;
  282. },
  283. mouseEvents: function() {
  284. module.verbose('Mouse detected binding mouse events');
  285. if( module.is.searchSelection() ) {
  286. $module
  287. .on('mousedown' + eventNamespace, selector.menu, module.event.menu.activate)
  288. .on('mouseup' + eventNamespace, selector.menu, module.event.menu.deactivate)
  289. .on('click' + eventNamespace, selector.search, module.show)
  290. .on('focus' + eventNamespace, selector.search, module.event.searchFocus)
  291. .on('blur' + eventNamespace, selector.search, module.event.searchBlur)
  292. .on('click' + eventNamespace, selector.text, module.event.searchTextFocus)
  293. ;
  294. }
  295. else {
  296. if(settings.on == 'click') {
  297. $module
  298. .on('click' + eventNamespace, module.event.test.toggle)
  299. ;
  300. }
  301. else if(settings.on == 'hover') {
  302. $module
  303. .on('mouseenter' + eventNamespace, module.delay.show)
  304. .on('mouseleave' + eventNamespace, module.delay.hide)
  305. ;
  306. }
  307. else {
  308. $module
  309. .on(settings.on + eventNamespace, module.toggle)
  310. ;
  311. }
  312. $module
  313. .on('mousedown' + eventNamespace, module.event.mousedown)
  314. .on('mouseup' + eventNamespace, module.event.mouseup)
  315. .on('focus' + eventNamespace, module.event.focus)
  316. .on('blur' + eventNamespace, module.event.blur)
  317. ;
  318. }
  319. $menu
  320. .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
  321. .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
  322. .on('click' + eventNamespace, selector.item, module.event.item.click)
  323. ;
  324. },
  325. intent: function() {
  326. module.verbose('Binding hide intent event to document');
  327. if(hasTouch) {
  328. $document
  329. .on('touchstart' + elementNamespace, module.event.test.touch)
  330. .on('touchmove' + elementNamespace, module.event.test.touch)
  331. ;
  332. }
  333. $document
  334. .on('click' + elementNamespace, module.event.test.hide)
  335. ;
  336. }
  337. },
  338. unbind: {
  339. intent: function() {
  340. module.verbose('Removing hide intent event from document');
  341. if(hasTouch) {
  342. $document
  343. .off('touchstart' + elementNamespace)
  344. .off('touchmove' + elementNamespace)
  345. ;
  346. }
  347. $document
  348. .off('click' + elementNamespace)
  349. ;
  350. }
  351. },
  352. filter: function(searchTerm) {
  353. var
  354. $results = $(),
  355. escapedTerm = module.escape.regExp(searchTerm),
  356. exactRegExp = new RegExp('^' + escapedTerm, 'igm'),
  357. fullTextRegExp = new RegExp(escapedTerm, 'ig'),
  358. allItemsFiltered
  359. ;
  360. module.verbose('Searching for matching values');
  361. $item
  362. .each(function(){
  363. var
  364. $choice = $(this),
  365. text = String(module.get.choiceText($choice, false)),
  366. value = String(module.get.choiceValue($choice, text))
  367. ;
  368. if( text.match(exactRegExp) || value.match(exactRegExp) ) {
  369. $results = $results.add($choice);
  370. }
  371. else if(settings.fullTextSearch) {
  372. if( text.match(fullTextRegExp) || value.match(fullTextRegExp) ) {
  373. $results = $results.add($choice);
  374. }
  375. }
  376. })
  377. ;
  378. module.debug('Setting filter', searchTerm);
  379. module.remove.filteredItem();
  380. $item
  381. .not($results)
  382. .addClass(className.filtered)
  383. ;
  384. module.verbose('Selecting first non-filtered element');
  385. module.remove.selectedItem();
  386. $item
  387. .not('.' + className.filtered)
  388. .eq(0)
  389. .addClass(className.selected)
  390. ;
  391. if( module.is.allFiltered() ) {
  392. module.debug('All items filtered, hiding dropdown', searchTerm);
  393. if(module.is.searchSelection()) {
  394. module.hide();
  395. }
  396. settings.onNoResults.call(element, searchTerm);
  397. }
  398. },
  399. focusSearch: function() {
  400. if( module.is.search() ) {
  401. $search
  402. .focus()
  403. ;
  404. }
  405. },
  406. event: {
  407. // prevents focus callback from occuring on mousedown
  408. mousedown: function() {
  409. activated = true;
  410. },
  411. mouseup: function() {
  412. activated = false;
  413. },
  414. focus: function() {
  415. if(!activated && module.is.hidden()) {
  416. module.show();
  417. }
  418. },
  419. blur: function(event) {
  420. var
  421. pageLostFocus = (document.activeElement === this)
  422. ;
  423. if(!activated && !pageLostFocus) {
  424. module.hide();
  425. }
  426. },
  427. searchFocus: function() {
  428. activated = true;
  429. module.show();
  430. },
  431. searchBlur: function(event) {
  432. var
  433. pageLostFocus = (document.activeElement === this)
  434. ;
  435. if(!itemActivated && !pageLostFocus) {
  436. module.hide();
  437. }
  438. },
  439. searchTextFocus: function(event) {
  440. activated = true;
  441. $search.focus();
  442. },
  443. input: function(event) {
  444. if(module.is.searchSelection()) {
  445. module.set.filtered();
  446. }
  447. clearTimeout(module.timer);
  448. module.timer = setTimeout(module.search, settings.delay.search);
  449. },
  450. keydown: function(event) {
  451. var
  452. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  453. $activeItem = $menu.children('.' + className.active).eq(0),
  454. $selectedItem = ($currentlySelected.length > 0)
  455. ? $currentlySelected
  456. : $activeItem,
  457. $visibleItems = ($selectedItem.length > 0)
  458. ? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf()
  459. : $menu.children(':not(.' + className.filtered +')'),
  460. $subMenu = $selectedItem.children(selector.menu),
  461. $parentMenu = $selectedItem.closest(selector.menu),
  462. isSubMenuItem = $parentMenu[0] !== $menu[0],
  463. inVisibleMenu = $parentMenu.is(':visible'),
  464. pressedKey = event.which,
  465. keys = {
  466. enter : 13,
  467. escape : 27,
  468. leftArrow : 37,
  469. upArrow : 38,
  470. rightArrow : 39,
  471. downArrow : 40
  472. },
  473. hasSubMenu = ($subMenu.length> 0),
  474. hasSelectedItem = ($selectedItem.length > 0),
  475. lastVisibleIndex = ($visibleItems.size() - 1),
  476. $nextItem,
  477. newIndex
  478. ;
  479. // visible menu keyboard shortcuts
  480. if(module.is.visible()) {
  481. // enter (select or sub-menu)
  482. if(pressedKey == keys.enter && hasSelectedItem) {
  483. if(hasSubMenu && !settings.allowCategorySelection) {
  484. module.verbose('Pressed enter on unselectable category, opening sub menu');
  485. pressedKey = keys.rightArrow;
  486. }
  487. else {
  488. module.verbose('Enter key pressed, choosing selected item');
  489. module.event.item.click.call($selectedItem, event);
  490. }
  491. }
  492. // left arrow (hide sub-menu)
  493. if(pressedKey == keys.leftArrow) {
  494. if(isSubMenuItem) {
  495. module.verbose('Left key pressed, closing sub-menu');
  496. module.animate.hide(false, $parentMenu);
  497. $selectedItem
  498. .removeClass(className.selected)
  499. ;
  500. $parentMenu
  501. .closest(selector.item)
  502. .addClass(className.selected)
  503. ;
  504. }
  505. event.preventDefault();
  506. }
  507. // right arrow (show sub-menu)
  508. if(pressedKey == keys.rightArrow) {
  509. if(hasSubMenu) {
  510. module.verbose('Right key pressed, opening sub-menu');
  511. module.animate.show(false, $subMenu);
  512. $selectedItem
  513. .removeClass(className.selected)
  514. ;
  515. $subMenu
  516. .find(selector.item).eq(0)
  517. .addClass(className.selected)
  518. ;
  519. }
  520. event.preventDefault();
  521. }
  522. // up arrow (traverse menu up)
  523. if(pressedKey == keys.upArrow) {
  524. $nextItem = (hasSelectedItem && inVisibleMenu)
  525. ? $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0)
  526. : $item.eq(0)
  527. ;
  528. if($visibleItems.index( $nextItem ) < 0) {
  529. module.verbose('Up key pressed but reached top of current menu');
  530. return;
  531. }
  532. else {
  533. module.verbose('Up key pressed, changing active item');
  534. $selectedItem
  535. .removeClass(className.selected)
  536. ;
  537. $nextItem
  538. .addClass(className.selected)
  539. ;
  540. module.set.scrollPosition($nextItem);
  541. }
  542. event.preventDefault();
  543. }
  544. // down arrow (traverse menu down)
  545. if(pressedKey == keys.downArrow) {
  546. $nextItem = (hasSelectedItem && inVisibleMenu)
  547. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0)
  548. : $item.eq(0)
  549. ;
  550. if($nextItem.length === 0) {
  551. module.verbose('Down key pressed but reached bottom of current menu');
  552. return;
  553. }
  554. else {
  555. module.verbose('Down key pressed, changing active item');
  556. $item
  557. .removeClass(className.selected)
  558. ;
  559. $nextItem
  560. .addClass(className.selected)
  561. ;
  562. module.set.scrollPosition($nextItem);
  563. }
  564. event.preventDefault();
  565. }
  566. }
  567. else {
  568. // enter (open menu)
  569. if(pressedKey == keys.enter) {
  570. module.verbose('Enter key pressed, showing dropdown');
  571. module.show();
  572. }
  573. // escape (close menu)
  574. if(pressedKey == keys.escape) {
  575. module.verbose('Escape key pressed, closing dropdown');
  576. module.hide();
  577. }
  578. // down arrow (open menu)
  579. if(pressedKey == keys.downArrow) {
  580. module.verbose('Down key pressed, showing dropdown');
  581. module.show();
  582. }
  583. }
  584. },
  585. test: {
  586. toggle: function(event) {
  587. if( module.determine.eventInMenu(event, module.toggle) ) {
  588. event.preventDefault();
  589. }
  590. },
  591. touch: function(event) {
  592. module.determine.eventInMenu(event, function() {
  593. if(event.type == 'touchstart') {
  594. module.timer = setTimeout(module.hide, settings.delay.touch);
  595. }
  596. else if(event.type == 'touchmove') {
  597. clearTimeout(module.timer);
  598. }
  599. });
  600. event.stopPropagation();
  601. },
  602. hide: function(event) {
  603. module.determine.eventInModule(event, module.hide);
  604. }
  605. },
  606. menu: {
  607. activate: function() {
  608. itemActivated = true;
  609. },
  610. deactivate: function() {
  611. itemActivated = false;
  612. }
  613. },
  614. item: {
  615. mouseenter: function(event) {
  616. var
  617. $subMenu = $(this).children(selector.menu),
  618. $otherMenus = $(this).siblings(selector.item).children(selector.menu)
  619. ;
  620. if( $subMenu.length > 0 ) {
  621. clearTimeout(module.itemTimer);
  622. module.itemTimer = setTimeout(function() {
  623. module.verbose('Showing sub-menu', $subMenu);
  624. $.each($otherMenus, function() {
  625. module.animate.hide(false, $(this));
  626. });
  627. module.animate.show(false, $subMenu);
  628. }, settings.delay.show);
  629. event.preventDefault();
  630. }
  631. },
  632. mouseleave: function(event) {
  633. var
  634. $subMenu = $(this).children(selector.menu)
  635. ;
  636. if($subMenu.length > 0) {
  637. clearTimeout(module.itemTimer);
  638. module.itemTimer = setTimeout(function() {
  639. module.verbose('Hiding sub-menu', $subMenu);
  640. module.animate.hide(false, $subMenu);
  641. }, settings.delay.hide);
  642. }
  643. },
  644. click: function (event) {
  645. var
  646. $choice = $(this),
  647. $target = $(event.target),
  648. $subMenu = $choice.find(selector.menu),
  649. text = module.get.choiceText($choice),
  650. value = module.get.choiceValue($choice, text),
  651. callback = function() {
  652. module.remove.searchTerm();
  653. module.determine.selectAction(text, value);
  654. },
  655. hasSubMenu = ($subMenu.length > 0),
  656. isBubbledEvent = ($subMenu.find($target).length > 0)
  657. ;
  658. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  659. callback();
  660. }
  661. }
  662. },
  663. resetStyle: function() {
  664. $(this).removeAttr('style');
  665. }
  666. },
  667. determine: {
  668. selectAction: function(text, value) {
  669. module.verbose('Determining action', settings.action);
  670. if( $.isFunction( module.action[settings.action] ) ) {
  671. module.verbose('Triggering preset action', settings.action, text, value);
  672. module.action[ settings.action ](text, value);
  673. }
  674. else if( $.isFunction(settings.action) ) {
  675. module.verbose('Triggering user action', settings.action, text, value);
  676. settings.action(text, value);
  677. }
  678. else {
  679. module.error(error.action, settings.action);
  680. }
  681. },
  682. eventInModule: function(event, callback) {
  683. callback = $.isFunction(callback)
  684. ? callback
  685. : function(){}
  686. ;
  687. if( $(event.target).closest($module).length === 0 ) {
  688. module.verbose('Triggering event', callback);
  689. callback();
  690. return true;
  691. }
  692. else {
  693. module.verbose('Event occurred in dropdown, canceling callback');
  694. return false;
  695. }
  696. },
  697. eventInMenu: function(event, callback) {
  698. callback = $.isFunction(callback)
  699. ? callback
  700. : function(){}
  701. ;
  702. if( $(event.target).closest($menu).length === 0 ) {
  703. module.verbose('Triggering event', callback);
  704. callback();
  705. return true;
  706. }
  707. else {
  708. module.verbose('Event occurred in dropdown menu, canceling callback');
  709. return false;
  710. }
  711. }
  712. },
  713. action: {
  714. nothing: function() {},
  715. hide: function() {
  716. module.hide(function() {
  717. module.remove.filteredItem();
  718. });
  719. },
  720. select: function(text, value) {
  721. value = (value !== undefined)
  722. ? value
  723. : text
  724. ;
  725. module.set.selected(value);
  726. module.set.value(value);
  727. module.hide(function() {
  728. module.remove.filteredItem();
  729. });
  730. },
  731. activate: function(text, value) {
  732. value = (value !== undefined)
  733. ? value
  734. : text
  735. ;
  736. module.set.selected(value);
  737. module.set.value(value);
  738. module.hide(function() {
  739. module.remove.filteredItem();
  740. });
  741. },
  742. combo: function(text, value) {
  743. value = (value !== undefined)
  744. ? value
  745. : text
  746. ;
  747. module.set.selected(value);
  748. module.set.value(value);
  749. module.hide(function() {
  750. module.remove.filteredItem();
  751. });
  752. }
  753. },
  754. get: {
  755. text: function() {
  756. return $text.text();
  757. },
  758. value: function() {
  759. return ($input.length > 0)
  760. ? $input.val()
  761. : $module.data(metadata.value)
  762. ;
  763. },
  764. choiceText: function($choice, preserveHTML) {
  765. preserveHTML = (preserveHTML !== undefined)
  766. ? preserveHTML
  767. : settings.preserveHTML
  768. ;
  769. if($choice !== undefined) {
  770. if($choice.find(selector.menu).length > 0) {
  771. module.verbose('Retreiving text of element with sub-menu');
  772. $choice = $choice.clone();
  773. $choice.find(selector.menu).remove();
  774. $choice.find(selector.menuIcon).remove();
  775. }
  776. return ($choice.data(metadata.text) !== undefined)
  777. ? $choice.data(metadata.text)
  778. : (preserveHTML)
  779. ? $choice.html().trim()
  780. : $choice.text().trim()
  781. ;
  782. }
  783. },
  784. choiceValue: function($choice, choiceText) {
  785. choiceText = choiceText || module.get.choiceText($text);
  786. return ($choice.data(metadata.value) !== undefined)
  787. ? $choice.data(metadata.value)
  788. : (typeof choiceText === 'string')
  789. ? choiceText.toLowerCase().trim()
  790. : choiceText.trim()
  791. ;
  792. },
  793. inputEvent: function() {
  794. var
  795. input = $search[0]
  796. ;
  797. if(input) {
  798. return (input.oninput !== undefined)
  799. ? 'input'
  800. : (input.onpropertychange !== undefined)
  801. ? 'propertychange'
  802. : 'keyup'
  803. ;
  804. }
  805. return false;
  806. },
  807. selectValues: function() {
  808. var
  809. select = {}
  810. ;
  811. select.values = (settings.sortSelect)
  812. ? {} // properties will be sorted in object when re-accessed
  813. : [] // properties will keep original order in array
  814. ;
  815. $module
  816. .find('option')
  817. .each(function() {
  818. var
  819. name = $(this).html(),
  820. value = ( $(this).attr('value') !== undefined )
  821. ? $(this).attr('value')
  822. : name
  823. ;
  824. if(value === '') {
  825. select.placeholder = name;
  826. }
  827. else {
  828. if(settings.sortSelect) {
  829. select.values[value] = {
  830. name : name,
  831. value : value
  832. };
  833. }
  834. else {
  835. select.values.push({
  836. name: name,
  837. value: value
  838. });
  839. }
  840. }
  841. })
  842. ;
  843. if(settings.sortSelect) {
  844. module.debug('Retrieved and sorted values from select', select);
  845. }
  846. else {
  847. module.debug('Retreived values from select', select);
  848. }
  849. return select;
  850. },
  851. activeItem: function() {
  852. return $item.filter('.' + className.active);
  853. },
  854. item: function(value, strict) {
  855. var
  856. $selectedItem = false
  857. ;
  858. value = (value !== undefined)
  859. ? value
  860. : ( module.get.value() !== undefined)
  861. ? module.get.value()
  862. : module.get.text()
  863. ;
  864. strict = (value === '' || value === 0)
  865. ? true
  866. : strict || false
  867. ;
  868. if(value !== undefined) {
  869. $item
  870. .each(function() {
  871. var
  872. $choice = $(this),
  873. optionText = module.get.choiceText($choice),
  874. optionValue = module.get.choiceValue($choice, optionText)
  875. ;
  876. if(strict) {
  877. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  878. if( optionValue === value ) {
  879. $selectedItem = $(this);
  880. }
  881. else if( !$selectedItem && optionText === value ) {
  882. $selectedItem = $(this);
  883. }
  884. }
  885. else {
  886. if( optionValue == value ) {
  887. module.verbose('Found select item by value', optionValue, value);
  888. $selectedItem = $(this);
  889. }
  890. else if( !$selectedItem && optionText == value ) {
  891. module.verbose('Found select item by text', optionText, value);
  892. $selectedItem = $(this);
  893. }
  894. }
  895. })
  896. ;
  897. }
  898. else {
  899. value = module.get.text();
  900. }
  901. return $selectedItem || false;
  902. },
  903. uniqueID: function() {
  904. return (Math.random().toString(16) + '000000000').substr(2,8);
  905. }
  906. },
  907. restore: {
  908. defaults: function() {
  909. module.restore.defaultText();
  910. module.restore.defaultValue();
  911. },
  912. defaultText: function() {
  913. var
  914. defaultText = $module.data(metadata.defaultText)
  915. ;
  916. module.debug('Restoring default text', defaultText);
  917. module.set.text(defaultText);
  918. $text.addClass(settings.className.placeholder);
  919. },
  920. defaultValue: function() {
  921. var
  922. defaultValue = $module.data(metadata.defaultValue)
  923. ;
  924. if(defaultValue !== undefined) {
  925. module.debug('Restoring default value', defaultValue);
  926. if(defaultValue.length) {
  927. module.set.selected(defaultValue);
  928. module.set.value(defaultValue);
  929. }
  930. else {
  931. module.remove.activeItem();
  932. module.remove.selectedItem();
  933. }
  934. }
  935. }
  936. },
  937. save: {
  938. defaults: function() {
  939. module.save.defaultText();
  940. module.save.defaultValue();
  941. },
  942. defaultValue: function() {
  943. $module.data(metadata.defaultValue, module.get.value() );
  944. },
  945. defaultText: function() {
  946. $module.data(metadata.defaultText, $text.text() );
  947. }
  948. },
  949. set: {
  950. filtered: function() {
  951. var
  952. searchValue = $search.val(),
  953. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0)
  954. ;
  955. if(hasSearchValue) {
  956. $text.addClass(className.filtered);
  957. }
  958. else {
  959. $text.removeClass(className.filtered);
  960. }
  961. },
  962. tabbable: function() {
  963. if( module.is.searchable() ) {
  964. module.debug('Searchable dropdown initialized');
  965. $search
  966. .val('')
  967. .attr('tabindex', 0)
  968. ;
  969. $menu
  970. .attr('tabindex', '-1')
  971. ;
  972. }
  973. else {
  974. module.debug('Simple selection dropdown initialized');
  975. if(!$module.attr('tabindex') ) {
  976. $module
  977. .attr('tabindex', 0)
  978. ;
  979. $menu
  980. .attr('tabindex', '-1')
  981. ;
  982. }
  983. }
  984. },
  985. scrollPosition: function($item, forceScroll) {
  986. var
  987. edgeTolerance = 5,
  988. hasActive,
  989. offset,
  990. itemHeight,
  991. itemOffset,
  992. menuOffset,
  993. menuScroll,
  994. menuHeight,
  995. abovePage,
  996. belowPage
  997. ;
  998. $item = $item || module.get.activeItem();
  999. hasActive = ($item && $item.length > 0);
  1000. forceScroll = (forceScroll !== undefined)
  1001. ? forceScroll
  1002. : false
  1003. ;
  1004. if($item && hasActive) {
  1005. if(!$menu.hasClass(className.visible)) {
  1006. $menu.addClass(className.loading);
  1007. }
  1008. menuHeight = $menu.height();
  1009. itemHeight = $item.height();
  1010. menuScroll = $menu.scrollTop();
  1011. menuOffset = $menu.offset().top;
  1012. itemOffset = $item.offset().top;
  1013. offset = menuScroll - menuOffset + itemOffset;
  1014. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  1015. abovePage = ((offset - edgeTolerance) < menuScroll);
  1016. module.debug('Scrolling to active item', offset);
  1017. if(abovePage || belowPage || forceScroll) {
  1018. $menu
  1019. .scrollTop(offset)
  1020. .removeClass(className.loading)
  1021. ;
  1022. }
  1023. }
  1024. },
  1025. text: function(text) {
  1026. if(settings.action == 'combo') {
  1027. module.debug('Changing combo button text', text, $combo);
  1028. if(settings.preserveHTML) {
  1029. $combo.html(text);
  1030. }
  1031. else {
  1032. $combo.text(text);
  1033. }
  1034. }
  1035. else if(settings.action !== 'select') {
  1036. module.debug('Changing text', text, $text);
  1037. $text
  1038. .removeClass(className.filtered)
  1039. .removeClass(className.placeholder)
  1040. ;
  1041. if(settings.preserveHTML) {
  1042. $text.html(text);
  1043. }
  1044. else {
  1045. $text.text(text);
  1046. }
  1047. }
  1048. },
  1049. value: function(value) {
  1050. module.debug('Adding selected value to hidden input', value, $input);
  1051. if($input.length > 0) {
  1052. $input
  1053. .val(value)
  1054. .trigger('change')
  1055. ;
  1056. }
  1057. else {
  1058. $module.data(metadata.value, value);
  1059. }
  1060. },
  1061. active: function() {
  1062. $module
  1063. .addClass(className.active)
  1064. ;
  1065. },
  1066. visible: function() {
  1067. $module.addClass(className.visible);
  1068. },
  1069. selected: function(value) {
  1070. var
  1071. $selectedItem = module.get.item(value),
  1072. selectedText
  1073. ;
  1074. if($selectedItem) {
  1075. module.debug('Setting selected menu item to', $selectedItem);
  1076. module.remove.activeItem();
  1077. module.remove.selectedItem();
  1078. $selectedItem
  1079. .addClass(className.active)
  1080. .addClass(className.selected)
  1081. ;
  1082. selectedText = module.get.choiceText($selectedItem);
  1083. module.set.text(selectedText);
  1084. settings.onChange.call(element, value, selectedText, $selectedItem);
  1085. }
  1086. }
  1087. },
  1088. remove: {
  1089. active: function() {
  1090. $module.removeClass(className.active);
  1091. },
  1092. visible: function() {
  1093. $module.removeClass(className.visible);
  1094. },
  1095. activeItem: function() {
  1096. $item.removeClass(className.active);
  1097. },
  1098. filteredItem: function() {
  1099. $item.removeClass(className.filtered);
  1100. },
  1101. searchTerm: function() {
  1102. $search.val('');
  1103. },
  1104. selectedItem: function() {
  1105. $item.removeClass(className.selected);
  1106. },
  1107. tabbable: function() {
  1108. if( module.is.searchable() ) {
  1109. module.debug('Searchable dropdown initialized');
  1110. $search
  1111. .attr('tabindex', '-1')
  1112. ;
  1113. $menu
  1114. .attr('tabindex', '-1')
  1115. ;
  1116. }
  1117. else {
  1118. module.debug('Simple selection dropdown initialized');
  1119. $module
  1120. .attr('tabindex', '-1')
  1121. ;
  1122. $menu
  1123. .attr('tabindex', '-1')
  1124. ;
  1125. }
  1126. }
  1127. },
  1128. is: {
  1129. active: function() {
  1130. return $module.hasClass(className.active);
  1131. },
  1132. alreadySetup: function() {
  1133. return ($module.is('select') && $module.parent(selector.dropdown).length > 0);
  1134. },
  1135. animating: function($subMenu) {
  1136. return ($subMenu)
  1137. ? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating')
  1138. : $menu.is(':animated') || $menu.transition && $menu.transition('is animating')
  1139. ;
  1140. },
  1141. allFiltered: function() {
  1142. return ($item.filter('.' + className.filtered).length === $item.length);
  1143. },
  1144. hidden: function($subMenu) {
  1145. return ($subMenu)
  1146. ? $subMenu.is(':hidden')
  1147. : $menu.is(':hidden')
  1148. ;
  1149. },
  1150. selectMutation: function(mutations) {
  1151. var
  1152. selectChanged = false
  1153. ;
  1154. $.each(mutations, function(index, mutation) {
  1155. if(mutation.target && $(mutation.target).is('select')) {
  1156. selectChanged = true;
  1157. return true;
  1158. }
  1159. });
  1160. return selectChanged;
  1161. },
  1162. search: function() {
  1163. return $module.hasClass(className.search);
  1164. },
  1165. searchable: function() {
  1166. return ($search.length > 0);
  1167. },
  1168. searchSelection: function() {
  1169. return ( module.is.searchable() && $search.parent().is($module) );
  1170. },
  1171. selection: function() {
  1172. return $module.hasClass(className.selection);
  1173. },
  1174. upward: function() {
  1175. return $module.hasClass(className.upward);
  1176. },
  1177. visible: function($subMenu) {
  1178. return ($subMenu)
  1179. ? $subMenu.is(':visible')
  1180. : $menu.is(':visible')
  1181. ;
  1182. }
  1183. },
  1184. can: {
  1185. click: function() {
  1186. return (hasTouch || settings.on == 'click');
  1187. },
  1188. show: function() {
  1189. return !$module.hasClass(className.disabled);
  1190. }
  1191. },
  1192. animate: {
  1193. show: function(callback, $subMenu) {
  1194. var
  1195. $currentMenu = $subMenu || $menu,
  1196. start = ($subMenu)
  1197. ? function() {}
  1198. : function() {
  1199. module.hideSubMenus();
  1200. module.hideOthers();
  1201. module.set.active();
  1202. }
  1203. ;
  1204. callback = $.isFunction(callback)
  1205. ? callback
  1206. : function(){}
  1207. ;
  1208. module.set.scrollPosition(module.get.activeItem(), true);
  1209. module.verbose('Doing menu show animation', $currentMenu);
  1210. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  1211. if(settings.transition == 'auto') {
  1212. settings.transition = module.is.upward()
  1213. ? 'slide up'
  1214. : 'slide down'
  1215. ;
  1216. module.verbose('Automatically determining animation based on animation direction', settings.transition);
  1217. }
  1218. if(settings.transition == 'none') {
  1219. callback.call(element);
  1220. }
  1221. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  1222. $currentMenu
  1223. .transition({
  1224. animation : settings.transition + ' in',
  1225. debug : settings.debug,
  1226. verbose : settings.verbose,
  1227. duration : settings.duration,
  1228. queue : true,
  1229. onStart : start,
  1230. onComplete : function() {
  1231. callback.call(element);
  1232. }
  1233. })
  1234. ;
  1235. }
  1236. else if(settings.transition == 'slide down') {
  1237. start();
  1238. $currentMenu
  1239. .hide()
  1240. .clearQueue()
  1241. .children()
  1242. .clearQueue()
  1243. .css('opacity', 0)
  1244. .delay(50)
  1245. .animate({
  1246. opacity : 1
  1247. }, settings.duration, 'easeOutQuad', module.event.resetStyle)
  1248. .end()
  1249. .slideDown(100, 'easeOutQuad', function() {
  1250. module.event.resetStyle.call(this);
  1251. callback.call(element);
  1252. })
  1253. ;
  1254. }
  1255. else if(settings.transition == 'fade') {
  1256. start();
  1257. $currentMenu
  1258. .hide()
  1259. .clearQueue()
  1260. .fadeIn(settings.duration, function() {
  1261. module.event.resetStyle.call(this);
  1262. callback.call(element);
  1263. })
  1264. ;
  1265. }
  1266. else {
  1267. module.error(error.transition, settings.transition);
  1268. }
  1269. }
  1270. },
  1271. hide: function(callback, $subMenu) {
  1272. var
  1273. $currentMenu = $subMenu || $menu,
  1274. duration = ($subMenu)
  1275. ? (settings.duration * 0.9)
  1276. : settings.duration,
  1277. start = ($subMenu)
  1278. ? function() {}
  1279. : function() {
  1280. if( module.can.click() ) {
  1281. module.unbind.intent();
  1282. }
  1283. module.focusSearch();
  1284. module.remove.active();
  1285. }
  1286. ;
  1287. callback = $.isFunction(callback)
  1288. ? callback
  1289. : function(){}
  1290. ;
  1291. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  1292. module.verbose('Doing menu hide animation', $currentMenu);
  1293. if(settings.transition == 'auto') {
  1294. settings.transition = module.is.upward()
  1295. ? 'slide up'
  1296. : 'slide down'
  1297. ;
  1298. }
  1299. if(settings.transition == 'none') {
  1300. callback.call(element);
  1301. }
  1302. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  1303. $currentMenu
  1304. .transition({
  1305. animation : settings.transition + ' out',
  1306. duration : settings.duration,
  1307. debug : settings.debug,
  1308. verbose : settings.verbose,
  1309. queue : true,
  1310. onStart : start,
  1311. onComplete : function() {
  1312. callback.call(element);
  1313. }
  1314. })
  1315. ;
  1316. }
  1317. else if(settings.transition == 'slide down') {
  1318. start();
  1319. $currentMenu
  1320. .show()
  1321. .clearQueue()
  1322. .children()
  1323. .clearQueue()
  1324. .css('opacity', 1)
  1325. .animate({
  1326. opacity : 0
  1327. }, 100, 'easeOutQuad', module.event.resetStyle)
  1328. .end()
  1329. .delay(50)
  1330. .slideUp(100, 'easeOutQuad', function() {
  1331. module.event.resetStyle.call(this);
  1332. callback.call(element);
  1333. })
  1334. ;
  1335. }
  1336. else if(settings.transition == 'fade') {
  1337. start();
  1338. $currentMenu
  1339. .show()
  1340. .clearQueue()
  1341. .fadeOut(150, function() {
  1342. module.event.resetStyle.call(this);
  1343. callback.call(element);
  1344. })
  1345. ;
  1346. }
  1347. else {
  1348. module.error(error.transition);
  1349. }
  1350. }
  1351. }
  1352. },
  1353. delay: {
  1354. show: function() {
  1355. module.verbose('Delaying show event to ensure user intent');
  1356. clearTimeout(module.timer);
  1357. module.timer = setTimeout(module.show, settings.delay.show);
  1358. },
  1359. hide: function() {
  1360. module.verbose('Delaying hide event to ensure user intent');
  1361. clearTimeout(module.timer);
  1362. module.timer = setTimeout(module.hide, settings.delay.hide);
  1363. }
  1364. },
  1365. escape: {
  1366. regExp: function(text) {
  1367. text = String(text);
  1368. return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
  1369. }
  1370. },
  1371. setting: function(name, value) {
  1372. module.debug('Changing setting', name, value);
  1373. if( $.isPlainObject(name) ) {
  1374. $.extend(true, settings, name);
  1375. }
  1376. else if(value !== undefined) {
  1377. settings[name] = value;
  1378. }
  1379. else {
  1380. return settings[name];
  1381. }
  1382. },
  1383. internal: function(name, value) {
  1384. if( $.isPlainObject(name) ) {
  1385. $.extend(true, module, name);
  1386. }
  1387. else if(value !== undefined) {
  1388. module[name] = value;
  1389. }
  1390. else {
  1391. return module[name];
  1392. }
  1393. },
  1394. debug: function() {
  1395. if(settings.debug) {
  1396. if(settings.performance) {
  1397. module.performance.log(arguments);
  1398. }
  1399. else {
  1400. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1401. module.debug.apply(console, arguments);
  1402. }
  1403. }
  1404. },
  1405. verbose: function() {
  1406. if(settings.verbose && settings.debug) {
  1407. if(settings.performance) {
  1408. module.performance.log(arguments);
  1409. }
  1410. else {
  1411. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1412. module.verbose.apply(console, arguments);
  1413. }
  1414. }
  1415. },
  1416. error: function() {
  1417. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  1418. module.error.apply(console, arguments);
  1419. },
  1420. performance: {
  1421. log: function(message) {
  1422. var
  1423. currentTime,
  1424. executionTime,
  1425. previousTime
  1426. ;
  1427. if(settings.performance) {
  1428. currentTime = new Date().getTime();
  1429. previousTime = time || currentTime;
  1430. executionTime = currentTime - previousTime;
  1431. time = currentTime;
  1432. performance.push({
  1433. 'Name' : message[0],
  1434. 'Arguments' : [].slice.call(message, 1) || '',
  1435. 'Element' : element,
  1436. 'Execution Time' : executionTime
  1437. });
  1438. }
  1439. clearTimeout(module.performance.timer);
  1440. module.performance.timer = setTimeout(module.performance.display, 100);
  1441. },
  1442. display: function() {
  1443. var
  1444. title = settings.name + ':',
  1445. totalTime = 0
  1446. ;
  1447. time = false;
  1448. clearTimeout(module.performance.timer);
  1449. $.each(performance, function(index, data) {
  1450. totalTime += data['Execution Time'];
  1451. });
  1452. title += ' ' + totalTime + 'ms';
  1453. if(moduleSelector) {
  1454. title += ' \'' + moduleSelector + '\'';
  1455. }
  1456. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  1457. console.groupCollapsed(title);
  1458. if(console.table) {
  1459. console.table(performance);
  1460. }
  1461. else {
  1462. $.each(performance, function(index, data) {
  1463. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  1464. });
  1465. }
  1466. console.groupEnd();
  1467. }
  1468. performance = [];
  1469. }
  1470. },
  1471. invoke: function(query, passedArguments, context) {
  1472. var
  1473. object = instance,
  1474. maxDepth,
  1475. found,
  1476. response
  1477. ;
  1478. passedArguments = passedArguments || queryArguments;
  1479. context = element || context;
  1480. if(typeof query == 'string' && object !== undefined) {
  1481. query = query.split(/[\. ]/);
  1482. maxDepth = query.length - 1;
  1483. $.each(query, function(depth, value) {
  1484. var camelCaseValue = (depth != maxDepth)
  1485. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  1486. : query
  1487. ;
  1488. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  1489. object = object[camelCaseValue];
  1490. }
  1491. else if( object[camelCaseValue] !== undefined ) {
  1492. found = object[camelCaseValue];
  1493. return false;
  1494. }
  1495. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  1496. object = object[value];
  1497. }
  1498. else if( object[value] !== undefined ) {
  1499. found = object[value];
  1500. return false;
  1501. }
  1502. else {
  1503. module.error(error.method, query);
  1504. return false;
  1505. }
  1506. });
  1507. }
  1508. if ( $.isFunction( found ) ) {
  1509. response = found.apply(context, passedArguments);
  1510. }
  1511. else if(found !== undefined) {
  1512. response = found;
  1513. }
  1514. if($.isArray(returnedValue)) {
  1515. returnedValue.push(response);
  1516. }
  1517. else if(returnedValue !== undefined) {
  1518. returnedValue = [returnedValue, response];
  1519. }
  1520. else if(response !== undefined) {
  1521. returnedValue = response;
  1522. }
  1523. return found;
  1524. }
  1525. };
  1526. if(methodInvoked) {
  1527. if(instance === undefined) {
  1528. module.initialize();
  1529. }
  1530. module.invoke(query);
  1531. }
  1532. else {
  1533. if(instance !== undefined) {
  1534. module.destroy();
  1535. }
  1536. module.initialize();
  1537. }
  1538. })
  1539. ;
  1540. return (returnedValue !== undefined)
  1541. ? returnedValue
  1542. : this
  1543. ;
  1544. };
  1545. $.fn.dropdown.settings = {
  1546. debug : false,
  1547. verbose : true,
  1548. performance : true,
  1549. on : 'click',
  1550. action : 'activate',
  1551. allowTab : true,
  1552. fullTextSearch : false,
  1553. preserveHTML : true,
  1554. sortSelect : false,
  1555. allowCategorySelection : false,
  1556. delay : {
  1557. hide : 300,
  1558. show : 200,
  1559. search : 50,
  1560. touch : 50
  1561. },
  1562. transition : 'auto',
  1563. duration : 250,
  1564. /* Callbacks */
  1565. onNoResults : function(searchTerm){},
  1566. onChange : function(value, text){},
  1567. onShow : function(){},
  1568. onHide : function(){},
  1569. /* Component */
  1570. name : 'Dropdown',
  1571. namespace : 'dropdown',
  1572. error : {
  1573. action : 'You called a dropdown action that was not defined',
  1574. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  1575. method : 'The method you called is not defined.',
  1576. transition : 'The requested transition was not found'
  1577. },
  1578. metadata: {
  1579. defaultText : 'defaultText',
  1580. defaultValue : 'defaultValue',
  1581. text : 'text',
  1582. value : 'value'
  1583. },
  1584. selector : {
  1585. dropdown : '.ui.dropdown',
  1586. input : '> input[type="hidden"], > select',
  1587. item : '.item',
  1588. menu : '.menu',
  1589. menuIcon : '.dropdown.icon',
  1590. search : '> input.search, .menu > .search > input, .menu > input.search',
  1591. text : '> .text:not(.icon)'
  1592. },
  1593. className : {
  1594. active : 'active',
  1595. animating : 'animating',
  1596. disabled : 'disabled',
  1597. dropdown : 'ui dropdown',
  1598. filtered : 'filtered',
  1599. loading : 'loading',
  1600. menu : 'menu',
  1601. placeholder : 'default',
  1602. search : 'search',
  1603. selected : 'selected',
  1604. selection : 'selection',
  1605. upward : 'upward',
  1606. visible : 'visible'
  1607. }
  1608. };
  1609. /* Templates */
  1610. $.fn.dropdown.settings.templates = {
  1611. menu: function(select) {
  1612. var
  1613. placeholder = select.placeholder || false,
  1614. values = select.values || {},
  1615. html = ''
  1616. ;
  1617. $.each(select.values, function(index, option) {
  1618. html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>';
  1619. });
  1620. return html;
  1621. },
  1622. dropdown: function(select) {
  1623. var
  1624. placeholder = select.placeholder || false,
  1625. values = select.values || {},
  1626. html = ''
  1627. ;
  1628. html += '<i class="dropdown icon"></i>';
  1629. if(select.placeholder) {
  1630. html += '<div class="default text">' + placeholder + '</div>';
  1631. }
  1632. else {
  1633. html += '<div class="text"></div>';
  1634. }
  1635. html += '<div class="menu">';
  1636. $.each(select.values, function(index, option) {
  1637. html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>';
  1638. });
  1639. html += '</div>';
  1640. return html;
  1641. }
  1642. };
  1643. /* Dependencies */
  1644. $.extend( $.easing, {
  1645. easeOutQuad: function (x, t, b, c, d) {
  1646. return -c *(t/=d)*(t-2) + b;
  1647. },
  1648. });
  1649. })( jQuery, window , document );