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.

1782 lines
58 KiB

9 years ago
9 years ago
10 years ago
9 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
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 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
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 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
9 years ago
10 years ago
9 years ago
10 years ago
9 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
9 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
9 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 UI 1.10.4 - Dropdown
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributors
  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. forceSelection: function() {
  407. var
  408. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  409. $activeItem = $item.filter('.' + className.active).eq(0),
  410. $selectedItem = ($currentlySelected.length > 0)
  411. ? $currentlySelected
  412. : $activeItem,
  413. hasSelected = ($selectedItem.size() > 0)
  414. ;
  415. if(hasSelected) {
  416. module.event.item.click.call($selectedItem);
  417. }
  418. },
  419. event: {
  420. // prevents focus callback from occuring on mousedown
  421. mousedown: function() {
  422. activated = true;
  423. },
  424. mouseup: function() {
  425. activated = false;
  426. },
  427. focus: function() {
  428. if(!activated && module.is.hidden()) {
  429. module.show();
  430. }
  431. },
  432. blur: function(event) {
  433. var
  434. pageLostFocus = (document.activeElement === this)
  435. ;
  436. if(!activated && !pageLostFocus) {
  437. module.hide();
  438. }
  439. },
  440. searchFocus: function() {
  441. activated = true;
  442. module.show();
  443. },
  444. searchBlur: function(event) {
  445. var
  446. pageLostFocus = (document.activeElement === this)
  447. ;
  448. if(!itemActivated && !pageLostFocus) {
  449. if(settings.forceSelection) {
  450. module.forceSelection();
  451. }
  452. else {
  453. module.hide();
  454. }
  455. }
  456. },
  457. searchTextFocus: function(event) {
  458. activated = true;
  459. $search.focus();
  460. },
  461. input: function(event) {
  462. if(module.is.searchSelection()) {
  463. module.set.filtered();
  464. }
  465. clearTimeout(module.timer);
  466. module.timer = setTimeout(module.search, settings.delay.search);
  467. },
  468. keydown: function(event) {
  469. var
  470. $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
  471. $activeItem = $menu.children('.' + className.active).eq(0),
  472. $selectedItem = ($currentlySelected.length > 0)
  473. ? $currentlySelected
  474. : $activeItem,
  475. $visibleItems = ($selectedItem.length > 0)
  476. ? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf()
  477. : $menu.children(':not(.' + className.filtered +')'),
  478. $subMenu = $selectedItem.children(selector.menu),
  479. $parentMenu = $selectedItem.closest(selector.menu),
  480. isSubMenuItem = $parentMenu[0] !== $menu[0],
  481. inVisibleMenu = $parentMenu.is(':visible'),
  482. pressedKey = event.which,
  483. keys = {
  484. enter : 13,
  485. escape : 27,
  486. leftArrow : 37,
  487. upArrow : 38,
  488. rightArrow : 39,
  489. downArrow : 40
  490. },
  491. hasSubMenu = ($subMenu.length> 0),
  492. hasSelectedItem = ($selectedItem.length > 0),
  493. lastVisibleIndex = ($visibleItems.size() - 1),
  494. $nextItem,
  495. newIndex
  496. ;
  497. // visible menu keyboard shortcuts
  498. if(module.is.visible()) {
  499. // enter (select or sub-menu)
  500. if(pressedKey == keys.enter && hasSelectedItem) {
  501. if(hasSubMenu && !settings.allowCategorySelection) {
  502. module.verbose('Pressed enter on unselectable category, opening sub menu');
  503. pressedKey = keys.rightArrow;
  504. }
  505. else {
  506. module.verbose('Enter key pressed, choosing selected item');
  507. module.event.item.click.call($selectedItem, event);
  508. }
  509. }
  510. // left arrow (hide sub-menu)
  511. if(pressedKey == keys.leftArrow) {
  512. if(isSubMenuItem) {
  513. module.verbose('Left key pressed, closing sub-menu');
  514. module.animate.hide(false, $parentMenu);
  515. $selectedItem
  516. .removeClass(className.selected)
  517. ;
  518. $parentMenu
  519. .closest(selector.item)
  520. .addClass(className.selected)
  521. ;
  522. }
  523. event.preventDefault();
  524. }
  525. // right arrow (show sub-menu)
  526. if(pressedKey == keys.rightArrow) {
  527. if(hasSubMenu) {
  528. module.verbose('Right key pressed, opening sub-menu');
  529. module.animate.show(false, $subMenu);
  530. $selectedItem
  531. .removeClass(className.selected)
  532. ;
  533. $subMenu
  534. .find(selector.item).eq(0)
  535. .addClass(className.selected)
  536. ;
  537. }
  538. event.preventDefault();
  539. }
  540. // up arrow (traverse menu up)
  541. if(pressedKey == keys.upArrow) {
  542. $nextItem = (hasSelectedItem && inVisibleMenu)
  543. ? $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0)
  544. : $item.eq(0)
  545. ;
  546. if($visibleItems.index( $nextItem ) < 0) {
  547. module.verbose('Up key pressed but reached top of current menu');
  548. return;
  549. }
  550. else {
  551. module.verbose('Up key pressed, changing active item');
  552. $selectedItem
  553. .removeClass(className.selected)
  554. ;
  555. $nextItem
  556. .addClass(className.selected)
  557. ;
  558. module.set.scrollPosition($nextItem);
  559. }
  560. event.preventDefault();
  561. }
  562. // down arrow (traverse menu down)
  563. if(pressedKey == keys.downArrow) {
  564. $nextItem = (hasSelectedItem && inVisibleMenu)
  565. ? $nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0)
  566. : $item.eq(0)
  567. ;
  568. if($nextItem.length === 0) {
  569. module.verbose('Down key pressed but reached bottom of current menu');
  570. return;
  571. }
  572. else {
  573. module.verbose('Down key pressed, changing active item');
  574. $item
  575. .removeClass(className.selected)
  576. ;
  577. $nextItem
  578. .addClass(className.selected)
  579. ;
  580. module.set.scrollPosition($nextItem);
  581. }
  582. event.preventDefault();
  583. }
  584. }
  585. else {
  586. // enter (open menu)
  587. if(pressedKey == keys.enter) {
  588. module.verbose('Enter key pressed, showing dropdown');
  589. module.show();
  590. }
  591. // escape (close menu)
  592. if(pressedKey == keys.escape) {
  593. module.verbose('Escape key pressed, closing dropdown');
  594. module.hide();
  595. }
  596. // down arrow (open menu)
  597. if(pressedKey == keys.downArrow) {
  598. module.verbose('Down key pressed, showing dropdown');
  599. module.show();
  600. }
  601. }
  602. },
  603. test: {
  604. toggle: function(event) {
  605. if( module.determine.eventInMenu(event, module.toggle) ) {
  606. event.preventDefault();
  607. }
  608. },
  609. touch: function(event) {
  610. module.determine.eventInMenu(event, function() {
  611. if(event.type == 'touchstart') {
  612. module.timer = setTimeout(module.hide, settings.delay.touch);
  613. }
  614. else if(event.type == 'touchmove') {
  615. clearTimeout(module.timer);
  616. }
  617. });
  618. event.stopPropagation();
  619. },
  620. hide: function(event) {
  621. module.determine.eventInModule(event, module.hide);
  622. }
  623. },
  624. menu: {
  625. activate: function() {
  626. itemActivated = true;
  627. },
  628. deactivate: function() {
  629. itemActivated = false;
  630. }
  631. },
  632. item: {
  633. mouseenter: function(event) {
  634. var
  635. $subMenu = $(this).children(selector.menu),
  636. $otherMenus = $(this).siblings(selector.item).children(selector.menu)
  637. ;
  638. if( $subMenu.length > 0 ) {
  639. clearTimeout(module.itemTimer);
  640. module.itemTimer = setTimeout(function() {
  641. module.verbose('Showing sub-menu', $subMenu);
  642. $.each($otherMenus, function() {
  643. module.animate.hide(false, $(this));
  644. });
  645. module.animate.show(false, $subMenu);
  646. }, settings.delay.show);
  647. event.preventDefault();
  648. }
  649. },
  650. mouseleave: function(event) {
  651. var
  652. $subMenu = $(this).children(selector.menu)
  653. ;
  654. if($subMenu.length > 0) {
  655. clearTimeout(module.itemTimer);
  656. module.itemTimer = setTimeout(function() {
  657. module.verbose('Hiding sub-menu', $subMenu);
  658. module.animate.hide(false, $subMenu);
  659. }, settings.delay.hide);
  660. }
  661. },
  662. click: function (event) {
  663. var
  664. $choice = $(this),
  665. $target = (event)
  666. ? $(event.target)
  667. : $(''),
  668. $subMenu = $choice.find(selector.menu),
  669. text = module.get.choiceText($choice),
  670. value = module.get.choiceValue($choice, text),
  671. callback = function() {
  672. module.remove.searchTerm();
  673. module.determine.selectAction(text, value);
  674. },
  675. hasSubMenu = ($subMenu.length > 0),
  676. isBubbledEvent = ($subMenu.find($target).length > 0)
  677. ;
  678. if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
  679. callback();
  680. }
  681. }
  682. },
  683. resetStyle: function() {
  684. $(this).removeAttr('style');
  685. }
  686. },
  687. determine: {
  688. selectAction: function(text, value) {
  689. module.verbose('Determining action', settings.action);
  690. if( $.isFunction( module.action[settings.action] ) ) {
  691. module.verbose('Triggering preset action', settings.action, text, value);
  692. module.action[ settings.action ](text, value);
  693. }
  694. else if( $.isFunction(settings.action) ) {
  695. module.verbose('Triggering user action', settings.action, text, value);
  696. settings.action(text, value);
  697. }
  698. else {
  699. module.error(error.action, settings.action);
  700. }
  701. },
  702. eventInModule: function(event, callback) {
  703. callback = $.isFunction(callback)
  704. ? callback
  705. : function(){}
  706. ;
  707. if( $(event.target).closest($module).length === 0 ) {
  708. module.verbose('Triggering event', callback);
  709. callback();
  710. return true;
  711. }
  712. else {
  713. module.verbose('Event occurred in dropdown, canceling callback');
  714. return false;
  715. }
  716. },
  717. eventInMenu: function(event, callback) {
  718. callback = $.isFunction(callback)
  719. ? callback
  720. : function(){}
  721. ;
  722. if( $(event.target).closest($menu).length === 0 ) {
  723. module.verbose('Triggering event', callback);
  724. callback();
  725. return true;
  726. }
  727. else {
  728. module.verbose('Event occurred in dropdown menu, canceling callback');
  729. return false;
  730. }
  731. }
  732. },
  733. action: {
  734. nothing: function() {},
  735. activate: function(text, value) {
  736. value = (value !== undefined)
  737. ? value
  738. : text
  739. ;
  740. module.set.selected(value);
  741. module.hide(function() {
  742. module.remove.filteredItem();
  743. });
  744. },
  745. select: function(text, value) {
  746. value = (value !== undefined)
  747. ? value
  748. : text
  749. ;
  750. module.set.selected(value);
  751. module.hide(function() {
  752. module.remove.filteredItem();
  753. });
  754. },
  755. combo: function(text, value) {
  756. value = (value !== undefined)
  757. ? value
  758. : text
  759. ;
  760. module.set.selected(value);
  761. module.hide(function() {
  762. module.remove.filteredItem();
  763. });
  764. },
  765. hide: function() {
  766. module.hide(function() {
  767. module.remove.filteredItem();
  768. });
  769. }
  770. },
  771. get: {
  772. text: function() {
  773. return $text.text();
  774. },
  775. value: function() {
  776. return ($input.length > 0)
  777. ? $input.val()
  778. : $module.data(metadata.value)
  779. ;
  780. },
  781. choiceText: function($choice, preserveHTML) {
  782. preserveHTML = (preserveHTML !== undefined)
  783. ? preserveHTML
  784. : settings.preserveHTML
  785. ;
  786. if($choice !== undefined) {
  787. if($choice.find(selector.menu).length > 0) {
  788. module.verbose('Retreiving text of element with sub-menu');
  789. $choice = $choice.clone();
  790. $choice.find(selector.menu).remove();
  791. $choice.find(selector.menuIcon).remove();
  792. }
  793. return ($choice.data(metadata.text) !== undefined)
  794. ? $choice.data(metadata.text)
  795. : (preserveHTML)
  796. ? $choice.html().trim()
  797. : $choice.text().trim()
  798. ;
  799. }
  800. },
  801. choiceValue: function($choice, choiceText) {
  802. choiceText = choiceText || module.get.choiceText($choice);
  803. return ($choice.data(metadata.value) !== undefined)
  804. ? $choice.data(metadata.value)
  805. : (typeof choiceText === 'string')
  806. ? choiceText.toLowerCase().trim()
  807. : choiceText.trim()
  808. ;
  809. },
  810. inputEvent: function() {
  811. var
  812. input = $search[0]
  813. ;
  814. if(input) {
  815. return (input.oninput !== undefined)
  816. ? 'input'
  817. : (input.onpropertychange !== undefined)
  818. ? 'propertychange'
  819. : 'keyup'
  820. ;
  821. }
  822. return false;
  823. },
  824. selectValues: function() {
  825. var
  826. select = {}
  827. ;
  828. select.values = (settings.sortSelect)
  829. ? {} // properties will be sorted in object when re-accessed
  830. : [] // properties will keep original order in array
  831. ;
  832. $module
  833. .find('option')
  834. .each(function() {
  835. var
  836. name = $(this).html(),
  837. value = ( $(this).attr('value') !== undefined )
  838. ? $(this).attr('value')
  839. : name
  840. ;
  841. if(value === '') {
  842. select.placeholder = name;
  843. }
  844. else {
  845. if(settings.sortSelect) {
  846. select.values[value] = {
  847. name : name,
  848. value : value
  849. };
  850. }
  851. else {
  852. select.values.push({
  853. name: name,
  854. value: value
  855. });
  856. }
  857. }
  858. })
  859. ;
  860. if(settings.sortSelect) {
  861. module.debug('Retrieved and sorted values from select', select);
  862. }
  863. else {
  864. module.debug('Retreived values from select', select);
  865. }
  866. return select;
  867. },
  868. activeItem: function() {
  869. return $item.filter('.' + className.active);
  870. },
  871. item: function(value, strict) {
  872. var
  873. $selectedItem = false
  874. ;
  875. value = (value !== undefined)
  876. ? value
  877. : ( module.get.value() !== undefined)
  878. ? module.get.value()
  879. : module.get.text()
  880. ;
  881. strict = (value === '' || value === 0)
  882. ? true
  883. : strict || false
  884. ;
  885. if(value !== undefined) {
  886. $item
  887. .each(function() {
  888. var
  889. $choice = $(this),
  890. optionText = module.get.choiceText($choice),
  891. optionValue = module.get.choiceValue($choice, optionText)
  892. ;
  893. if(strict) {
  894. module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
  895. if( optionValue === value ) {
  896. $selectedItem = $(this);
  897. }
  898. else if( !$selectedItem && optionText === value ) {
  899. $selectedItem = $(this);
  900. }
  901. }
  902. else {
  903. if( optionValue == value ) {
  904. module.verbose('Found select item by value', optionValue, value);
  905. $selectedItem = $(this);
  906. }
  907. else if( !$selectedItem && optionText == value ) {
  908. module.verbose('Found select item by text', optionText, value);
  909. $selectedItem = $(this);
  910. }
  911. }
  912. })
  913. ;
  914. }
  915. else {
  916. value = module.get.text();
  917. }
  918. return $selectedItem || false;
  919. },
  920. uniqueID: function() {
  921. return (Math.random().toString(16) + '000000000').substr(2,8);
  922. }
  923. },
  924. restore: {
  925. defaults: function() {
  926. module.restore.defaultText();
  927. module.restore.defaultValue();
  928. },
  929. defaultText: function() {
  930. var
  931. defaultText = $module.data(metadata.defaultText)
  932. ;
  933. module.debug('Restoring default text', defaultText);
  934. module.set.text(defaultText);
  935. $text.addClass(className.placeholder);
  936. },
  937. defaultValue: function() {
  938. var
  939. defaultValue = $module.data(metadata.defaultValue)
  940. ;
  941. if(defaultValue !== undefined) {
  942. module.debug('Restoring default value', defaultValue);
  943. if(defaultValue.length) {
  944. module.set.selected(defaultValue);
  945. }
  946. else {
  947. module.remove.activeItem();
  948. module.remove.selectedItem();
  949. }
  950. }
  951. }
  952. },
  953. save: {
  954. defaults: function() {
  955. module.save.defaultText();
  956. module.save.placeholderText();
  957. module.save.defaultValue();
  958. },
  959. defaultValue: function() {
  960. $module.data(metadata.defaultValue, module.get.value() );
  961. },
  962. defaultText: function() {
  963. $module.data(metadata.defaultText, $text.text() );
  964. },
  965. placeholderText: function() {
  966. if($text.hasClass(className.placeholder)) {
  967. $module.data(metadata.placeholderText, $text.text());
  968. }
  969. }
  970. },
  971. clear: function() {
  972. var
  973. placeholderText = $module.data(metadata.placeholderText)
  974. ;
  975. module.set.text(placeholderText);
  976. module.set.value('');
  977. module.remove.activeItem();
  978. module.remove.selectedItem();
  979. $text.addClass(className.placeholder);
  980. },
  981. set: {
  982. filtered: function() {
  983. var
  984. searchValue = $search.val(),
  985. hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0)
  986. ;
  987. if(hasSearchValue) {
  988. $text.addClass(className.filtered);
  989. }
  990. else {
  991. $text.removeClass(className.filtered);
  992. }
  993. },
  994. tabbable: function() {
  995. if( module.is.searchable() ) {
  996. module.debug('Searchable dropdown initialized');
  997. $search
  998. .val('')
  999. .attr('tabindex', 0)
  1000. ;
  1001. $menu
  1002. .attr('tabindex', '-1')
  1003. ;
  1004. }
  1005. else {
  1006. module.debug('Simple selection dropdown initialized');
  1007. if(!$module.attr('tabindex') ) {
  1008. $module
  1009. .attr('tabindex', 0)
  1010. ;
  1011. $menu
  1012. .attr('tabindex', '-1')
  1013. ;
  1014. }
  1015. }
  1016. },
  1017. scrollPosition: function($item, forceScroll) {
  1018. var
  1019. edgeTolerance = 5,
  1020. hasActive,
  1021. offset,
  1022. itemHeight,
  1023. itemOffset,
  1024. menuOffset,
  1025. menuScroll,
  1026. menuHeight,
  1027. abovePage,
  1028. belowPage
  1029. ;
  1030. $item = $item || module.get.activeItem();
  1031. hasActive = ($item && $item.length > 0);
  1032. forceScroll = (forceScroll !== undefined)
  1033. ? forceScroll
  1034. : false
  1035. ;
  1036. if($item && hasActive) {
  1037. if(!$menu.hasClass(className.visible)) {
  1038. $menu.addClass(className.loading);
  1039. }
  1040. menuHeight = $menu.height();
  1041. itemHeight = $item.height();
  1042. menuScroll = $menu.scrollTop();
  1043. menuOffset = $menu.offset().top;
  1044. itemOffset = $item.offset().top;
  1045. offset = menuScroll - menuOffset + itemOffset;
  1046. belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
  1047. abovePage = ((offset - edgeTolerance) < menuScroll);
  1048. module.debug('Scrolling to active item', offset);
  1049. if(abovePage || belowPage || forceScroll) {
  1050. $menu
  1051. .scrollTop(offset)
  1052. .removeClass(className.loading)
  1053. ;
  1054. }
  1055. }
  1056. },
  1057. text: function(text) {
  1058. if(settings.action == 'combo') {
  1059. module.debug('Changing combo button text', text, $combo);
  1060. if(settings.preserveHTML) {
  1061. $combo.html(text);
  1062. }
  1063. else {
  1064. $combo.text(text);
  1065. }
  1066. }
  1067. else if(settings.action !== 'select') {
  1068. module.debug('Changing text', text, $text);
  1069. $text
  1070. .removeClass(className.filtered)
  1071. .removeClass(className.placeholder)
  1072. ;
  1073. if(settings.preserveHTML) {
  1074. $text.html(text);
  1075. }
  1076. else {
  1077. $text.text(text);
  1078. }
  1079. }
  1080. },
  1081. value: function(value) {
  1082. module.debug('Adding selected value to hidden input', value, $input);
  1083. if($input.length > 0) {
  1084. $input
  1085. .val(value)
  1086. .trigger('change')
  1087. ;
  1088. }
  1089. else {
  1090. $module.data(metadata.value, value);
  1091. }
  1092. },
  1093. active: function() {
  1094. $module
  1095. .addClass(className.active)
  1096. ;
  1097. },
  1098. visible: function() {
  1099. $module.addClass(className.visible);
  1100. },
  1101. selected: function(value) {
  1102. var
  1103. $selectedItem = module.get.item(value),
  1104. selectedText,
  1105. selectedValue
  1106. ;
  1107. if($selectedItem) {
  1108. module.debug('Setting selected menu item to', $selectedItem);
  1109. module.remove.activeItem();
  1110. module.remove.selectedItem();
  1111. $selectedItem
  1112. .addClass(className.active)
  1113. .addClass(className.selected)
  1114. ;
  1115. selectedText = module.get.choiceText($selectedItem);
  1116. selectedValue = module.get.choiceValue($selectedItem, selectedText);
  1117. module.set.text(selectedText);
  1118. module.set.value(selectedValue);
  1119. settings.onChange.call(element, value, selectedText, $selectedItem);
  1120. }
  1121. }
  1122. },
  1123. remove: {
  1124. active: function() {
  1125. $module.removeClass(className.active);
  1126. },
  1127. visible: function() {
  1128. $module.removeClass(className.visible);
  1129. },
  1130. activeItem: function() {
  1131. $item.removeClass(className.active);
  1132. },
  1133. filteredItem: function() {
  1134. $item.removeClass(className.filtered);
  1135. },
  1136. searchTerm: function() {
  1137. $search.val('');
  1138. },
  1139. selectedItem: function() {
  1140. $item.removeClass(className.selected);
  1141. },
  1142. tabbable: function() {
  1143. if( module.is.searchable() ) {
  1144. module.debug('Searchable dropdown initialized');
  1145. $search
  1146. .attr('tabindex', '-1')
  1147. ;
  1148. $menu
  1149. .attr('tabindex', '-1')
  1150. ;
  1151. }
  1152. else {
  1153. module.debug('Simple selection dropdown initialized');
  1154. $module
  1155. .attr('tabindex', '-1')
  1156. ;
  1157. $menu
  1158. .attr('tabindex', '-1')
  1159. ;
  1160. }
  1161. }
  1162. },
  1163. is: {
  1164. active: function() {
  1165. return $module.hasClass(className.active);
  1166. },
  1167. alreadySetup: function() {
  1168. return ($module.is('select') && $module.parent(selector.dropdown).length > 0);
  1169. },
  1170. animating: function($subMenu) {
  1171. return ($subMenu)
  1172. ? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating')
  1173. : $menu.is(':animated') || $menu.transition && $menu.transition('is animating')
  1174. ;
  1175. },
  1176. allFiltered: function() {
  1177. return ($item.filter('.' + className.filtered).length === $item.length);
  1178. },
  1179. hidden: function($subMenu) {
  1180. return ($subMenu)
  1181. ? $subMenu.is(':hidden')
  1182. : $menu.is(':hidden')
  1183. ;
  1184. },
  1185. selectMutation: function(mutations) {
  1186. var
  1187. selectChanged = false
  1188. ;
  1189. $.each(mutations, function(index, mutation) {
  1190. if(mutation.target && $(mutation.target).is('select')) {
  1191. selectChanged = true;
  1192. return true;
  1193. }
  1194. });
  1195. return selectChanged;
  1196. },
  1197. search: function() {
  1198. return $module.hasClass(className.search);
  1199. },
  1200. searchable: function() {
  1201. return ($search.length > 0);
  1202. },
  1203. searchSelection: function() {
  1204. return ( module.is.searchable() && $search.parent().is($module) );
  1205. },
  1206. selection: function() {
  1207. return $module.hasClass(className.selection);
  1208. },
  1209. upward: function() {
  1210. return $module.hasClass(className.upward);
  1211. },
  1212. visible: function($subMenu) {
  1213. return ($subMenu)
  1214. ? $subMenu.is(':visible')
  1215. : $menu.is(':visible')
  1216. ;
  1217. }
  1218. },
  1219. can: {
  1220. click: function() {
  1221. return (hasTouch || settings.on == 'click');
  1222. },
  1223. show: function() {
  1224. return !$module.hasClass(className.disabled);
  1225. }
  1226. },
  1227. animate: {
  1228. show: function(callback, $subMenu) {
  1229. var
  1230. $currentMenu = $subMenu || $menu,
  1231. start = ($subMenu)
  1232. ? function() {}
  1233. : function() {
  1234. module.hideSubMenus();
  1235. module.hideOthers();
  1236. module.set.active();
  1237. }
  1238. ;
  1239. callback = $.isFunction(callback)
  1240. ? callback
  1241. : function(){}
  1242. ;
  1243. module.set.scrollPosition(module.get.activeItem(), true);
  1244. module.verbose('Doing menu show animation', $currentMenu);
  1245. if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
  1246. if(settings.transition == 'auto') {
  1247. settings.transition = module.is.upward()
  1248. ? 'slide up'
  1249. : 'slide down'
  1250. ;
  1251. module.verbose('Automatically determining animation based on animation direction', settings.transition);
  1252. }
  1253. if(settings.transition == 'none') {
  1254. callback.call(element);
  1255. }
  1256. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  1257. $currentMenu
  1258. .transition({
  1259. animation : settings.transition + ' in',
  1260. debug : settings.debug,
  1261. verbose : settings.verbose,
  1262. duration : settings.duration,
  1263. queue : true,
  1264. onStart : start,
  1265. onComplete : function() {
  1266. callback.call(element);
  1267. }
  1268. })
  1269. ;
  1270. }
  1271. else if(settings.transition == 'slide down') {
  1272. start();
  1273. $currentMenu
  1274. .hide()
  1275. .clearQueue()
  1276. .children()
  1277. .clearQueue()
  1278. .css('opacity', 0)
  1279. .delay(50)
  1280. .animate({
  1281. opacity : 1
  1282. }, settings.duration, 'easeOutQuad', module.event.resetStyle)
  1283. .end()
  1284. .slideDown(100, 'easeOutQuad', function() {
  1285. module.event.resetStyle.call(this);
  1286. callback.call(element);
  1287. })
  1288. ;
  1289. }
  1290. else if(settings.transition == 'fade') {
  1291. start();
  1292. $currentMenu
  1293. .hide()
  1294. .clearQueue()
  1295. .fadeIn(settings.duration, function() {
  1296. module.event.resetStyle.call(this);
  1297. callback.call(element);
  1298. })
  1299. ;
  1300. }
  1301. else {
  1302. module.error(error.transition, settings.transition);
  1303. }
  1304. }
  1305. },
  1306. hide: function(callback, $subMenu) {
  1307. var
  1308. $currentMenu = $subMenu || $menu,
  1309. duration = ($subMenu)
  1310. ? (settings.duration * 0.9)
  1311. : settings.duration,
  1312. start = ($subMenu)
  1313. ? function() {}
  1314. : function() {
  1315. if( module.can.click() ) {
  1316. module.unbind.intent();
  1317. }
  1318. module.focusSearch();
  1319. module.remove.active();
  1320. }
  1321. ;
  1322. callback = $.isFunction(callback)
  1323. ? callback
  1324. : function(){}
  1325. ;
  1326. if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
  1327. module.verbose('Doing menu hide animation', $currentMenu);
  1328. if(settings.transition == 'auto') {
  1329. settings.transition = module.is.upward()
  1330. ? 'slide up'
  1331. : 'slide down'
  1332. ;
  1333. }
  1334. $input.trigger('blur');
  1335. if(settings.transition == 'none') {
  1336. callback.call(element);
  1337. }
  1338. else if($.fn.transition !== undefined && $module.transition('is supported')) {
  1339. $currentMenu
  1340. .transition({
  1341. animation : settings.transition + ' out',
  1342. duration : settings.duration,
  1343. debug : settings.debug,
  1344. verbose : settings.verbose,
  1345. queue : true,
  1346. onStart : start,
  1347. onComplete : function() {
  1348. callback.call(element);
  1349. }
  1350. })
  1351. ;
  1352. }
  1353. else if(settings.transition == 'slide down') {
  1354. start();
  1355. $currentMenu
  1356. .show()
  1357. .clearQueue()
  1358. .children()
  1359. .clearQueue()
  1360. .css('opacity', 1)
  1361. .animate({
  1362. opacity : 0
  1363. }, 100, 'easeOutQuad', module.event.resetStyle)
  1364. .end()
  1365. .delay(50)
  1366. .slideUp(100, 'easeOutQuad', function() {
  1367. module.event.resetStyle.call(this);
  1368. callback.call(element);
  1369. })
  1370. ;
  1371. }
  1372. else if(settings.transition == 'fade') {
  1373. start();
  1374. $currentMenu
  1375. .show()
  1376. .clearQueue()
  1377. .fadeOut(150, function() {
  1378. module.event.resetStyle.call(this);
  1379. callback.call(element);
  1380. })
  1381. ;
  1382. }
  1383. else {
  1384. module.error(error.transition);
  1385. }
  1386. }
  1387. }
  1388. },
  1389. delay: {
  1390. show: function() {
  1391. module.verbose('Delaying show event to ensure user intent');
  1392. clearTimeout(module.timer);
  1393. module.timer = setTimeout(module.show, settings.delay.show);
  1394. },
  1395. hide: function() {
  1396. module.verbose('Delaying hide event to ensure user intent');
  1397. clearTimeout(module.timer);
  1398. module.timer = setTimeout(module.hide, settings.delay.hide);
  1399. }
  1400. },
  1401. escape: {
  1402. regExp: function(text) {
  1403. text = String(text);
  1404. return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
  1405. }
  1406. },
  1407. setting: function(name, value) {
  1408. module.debug('Changing setting', name, value);
  1409. if( $.isPlainObject(name) ) {
  1410. $.extend(true, settings, name);
  1411. }
  1412. else if(value !== undefined) {
  1413. settings[name] = value;
  1414. }
  1415. else {
  1416. return settings[name];
  1417. }
  1418. },
  1419. internal: function(name, value) {
  1420. if( $.isPlainObject(name) ) {
  1421. $.extend(true, module, name);
  1422. }
  1423. else if(value !== undefined) {
  1424. module[name] = value;
  1425. }
  1426. else {
  1427. return module[name];
  1428. }
  1429. },
  1430. debug: function() {
  1431. if(settings.debug) {
  1432. if(settings.performance) {
  1433. module.performance.log(arguments);
  1434. }
  1435. else {
  1436. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1437. module.debug.apply(console, arguments);
  1438. }
  1439. }
  1440. },
  1441. verbose: function() {
  1442. if(settings.verbose && settings.debug) {
  1443. if(settings.performance) {
  1444. module.performance.log(arguments);
  1445. }
  1446. else {
  1447. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  1448. module.verbose.apply(console, arguments);
  1449. }
  1450. }
  1451. },
  1452. error: function() {
  1453. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  1454. module.error.apply(console, arguments);
  1455. },
  1456. performance: {
  1457. log: function(message) {
  1458. var
  1459. currentTime,
  1460. executionTime,
  1461. previousTime
  1462. ;
  1463. if(settings.performance) {
  1464. currentTime = new Date().getTime();
  1465. previousTime = time || currentTime;
  1466. executionTime = currentTime - previousTime;
  1467. time = currentTime;
  1468. performance.push({
  1469. 'Name' : message[0],
  1470. 'Arguments' : [].slice.call(message, 1) || '',
  1471. 'Element' : element,
  1472. 'Execution Time' : executionTime
  1473. });
  1474. }
  1475. clearTimeout(module.performance.timer);
  1476. module.performance.timer = setTimeout(module.performance.display, 100);
  1477. },
  1478. display: function() {
  1479. var
  1480. title = settings.name + ':',
  1481. totalTime = 0
  1482. ;
  1483. time = false;
  1484. clearTimeout(module.performance.timer);
  1485. $.each(performance, function(index, data) {
  1486. totalTime += data['Execution Time'];
  1487. });
  1488. title += ' ' + totalTime + 'ms';
  1489. if(moduleSelector) {
  1490. title += ' \'' + moduleSelector + '\'';
  1491. }
  1492. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  1493. console.groupCollapsed(title);
  1494. if(console.table) {
  1495. console.table(performance);
  1496. }
  1497. else {
  1498. $.each(performance, function(index, data) {
  1499. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  1500. });
  1501. }
  1502. console.groupEnd();
  1503. }
  1504. performance = [];
  1505. }
  1506. },
  1507. invoke: function(query, passedArguments, context) {
  1508. var
  1509. object = instance,
  1510. maxDepth,
  1511. found,
  1512. response
  1513. ;
  1514. passedArguments = passedArguments || queryArguments;
  1515. context = element || context;
  1516. if(typeof query == 'string' && object !== undefined) {
  1517. query = query.split(/[\. ]/);
  1518. maxDepth = query.length - 1;
  1519. $.each(query, function(depth, value) {
  1520. var camelCaseValue = (depth != maxDepth)
  1521. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  1522. : query
  1523. ;
  1524. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  1525. object = object[camelCaseValue];
  1526. }
  1527. else if( object[camelCaseValue] !== undefined ) {
  1528. found = object[camelCaseValue];
  1529. return false;
  1530. }
  1531. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  1532. object = object[value];
  1533. }
  1534. else if( object[value] !== undefined ) {
  1535. found = object[value];
  1536. return false;
  1537. }
  1538. else {
  1539. module.error(error.method, query);
  1540. return false;
  1541. }
  1542. });
  1543. }
  1544. if ( $.isFunction( found ) ) {
  1545. response = found.apply(context, passedArguments);
  1546. }
  1547. else if(found !== undefined) {
  1548. response = found;
  1549. }
  1550. if($.isArray(returnedValue)) {
  1551. returnedValue.push(response);
  1552. }
  1553. else if(returnedValue !== undefined) {
  1554. returnedValue = [returnedValue, response];
  1555. }
  1556. else if(response !== undefined) {
  1557. returnedValue = response;
  1558. }
  1559. return found;
  1560. }
  1561. };
  1562. if(methodInvoked) {
  1563. if(instance === undefined) {
  1564. module.initialize();
  1565. }
  1566. module.invoke(query);
  1567. }
  1568. else {
  1569. if(instance !== undefined) {
  1570. instance.invoke('destroy');
  1571. }
  1572. module.initialize();
  1573. }
  1574. })
  1575. ;
  1576. return (returnedValue !== undefined)
  1577. ? returnedValue
  1578. : this
  1579. ;
  1580. };
  1581. $.fn.dropdown.settings = {
  1582. debug : false,
  1583. verbose : true,
  1584. performance : true,
  1585. on : 'click',
  1586. action : 'activate',
  1587. allowTab : true,
  1588. fullTextSearch : false,
  1589. preserveHTML : true,
  1590. sortSelect : false,
  1591. allowCategorySelection : false,
  1592. delay : {
  1593. hide : 300,
  1594. show : 200,
  1595. search : 50,
  1596. touch : 50
  1597. },
  1598. forceSelection: true,
  1599. transition : 'auto',
  1600. duration : 250,
  1601. /* Callbacks */
  1602. onNoResults : function(searchTerm){},
  1603. onChange : function(value, text){},
  1604. onShow : function(){},
  1605. onHide : function(){},
  1606. /* Component */
  1607. name : 'Dropdown',
  1608. namespace : 'dropdown',
  1609. error : {
  1610. action : 'You called a dropdown action that was not defined',
  1611. alreadySetup : 'Once a select has been initialized behaviors must be called on the created ui dropdown',
  1612. method : 'The method you called is not defined.',
  1613. transition : 'The requested transition was not found'
  1614. },
  1615. metadata: {
  1616. defaultText : 'defaultText',
  1617. defaultValue : 'defaultValue',
  1618. placeholderText : 'placeholderText',
  1619. text : 'text',
  1620. value : 'value'
  1621. },
  1622. selector : {
  1623. dropdown : '.ui.dropdown',
  1624. input : '> input[type="hidden"], > select',
  1625. item : '.item',
  1626. menu : '.menu',
  1627. menuIcon : '.dropdown.icon',
  1628. search : '> input.search, .menu > .search > input, .menu > input.search',
  1629. text : '> .text:not(.icon)'
  1630. },
  1631. className : {
  1632. active : 'active',
  1633. animating : 'animating',
  1634. disabled : 'disabled',
  1635. dropdown : 'ui dropdown',
  1636. filtered : 'filtered',
  1637. loading : 'loading',
  1638. menu : 'menu',
  1639. placeholder : 'default',
  1640. search : 'search',
  1641. selected : 'selected',
  1642. selection : 'selection',
  1643. upward : 'upward',
  1644. visible : 'visible'
  1645. }
  1646. };
  1647. /* Templates */
  1648. $.fn.dropdown.settings.templates = {
  1649. menu: function(select) {
  1650. var
  1651. placeholder = select.placeholder || false,
  1652. values = select.values || {},
  1653. html = ''
  1654. ;
  1655. $.each(select.values, function(index, option) {
  1656. html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>';
  1657. });
  1658. return html;
  1659. },
  1660. dropdown: function(select) {
  1661. var
  1662. placeholder = select.placeholder || false,
  1663. values = select.values || {},
  1664. html = ''
  1665. ;
  1666. html += '<i class="dropdown icon"></i>';
  1667. if(select.placeholder) {
  1668. html += '<div class="default text">' + placeholder + '</div>';
  1669. }
  1670. else {
  1671. html += '<div class="text"></div>';
  1672. }
  1673. html += '<div class="menu">';
  1674. $.each(select.values, function(index, option) {
  1675. html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>';
  1676. });
  1677. html += '</div>';
  1678. return html;
  1679. }
  1680. };
  1681. /* Dependencies */
  1682. $.extend( $.easing, {
  1683. easeOutQuad: function (x, t, b, c, d) {
  1684. return -c *(t/=d)*(t-2) + b;
  1685. },
  1686. });
  1687. })( jQuery, window , document );