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.

898 lines
30 KiB

  1. /*!
  2. * # Semantic UI 2.1.6 - Tab
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2015 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.tab = function(parameters) {
  14. var
  15. // use window context if none specified
  16. $allModules = $.isFunction(this)
  17. ? $(window)
  18. : $(this),
  19. moduleSelector = $allModules.selector || '',
  20. time = new Date().getTime(),
  21. performance = [],
  22. query = arguments[0],
  23. methodInvoked = (typeof query == 'string'),
  24. queryArguments = [].slice.call(arguments, 1),
  25. initializedHistory = false,
  26. returnedValue
  27. ;
  28. $allModules
  29. .each(function() {
  30. var
  31. settings = ( $.isPlainObject(parameters) )
  32. ? $.extend(true, {}, $.fn.tab.settings, parameters)
  33. : $.extend({}, $.fn.tab.settings),
  34. className = settings.className,
  35. metadata = settings.metadata,
  36. selector = settings.selector,
  37. error = settings.error,
  38. eventNamespace = '.' + settings.namespace,
  39. moduleNamespace = 'module-' + settings.namespace,
  40. $module = $(this),
  41. $context,
  42. $tabs,
  43. cache = {},
  44. firstLoad = true,
  45. recursionDepth = 0,
  46. element = this,
  47. instance = $module.data(moduleNamespace),
  48. activeTabPath,
  49. parameterArray,
  50. module,
  51. historyEvent
  52. ;
  53. module = {
  54. initialize: function() {
  55. module.debug('Initializing tab menu item', $module);
  56. module.fix.callbacks();
  57. module.determineTabs();
  58. module.debug('Determining tabs', settings.context, $tabs);
  59. // set up automatic routing
  60. if(settings.auto) {
  61. module.set.auto();
  62. }
  63. module.bind.events();
  64. if(settings.history && !initializedHistory) {
  65. module.initializeHistory();
  66. initializedHistory = true;
  67. }
  68. module.instantiate();
  69. },
  70. instantiate: function () {
  71. module.verbose('Storing instance of module', module);
  72. instance = module;
  73. $module
  74. .data(moduleNamespace, module)
  75. ;
  76. },
  77. destroy: function() {
  78. module.debug('Destroying tabs', $module);
  79. $module
  80. .removeData(moduleNamespace)
  81. .off(eventNamespace)
  82. ;
  83. },
  84. bind: {
  85. events: function() {
  86. // if using $.tab don't add events
  87. if( !$.isWindow( element ) ) {
  88. module.debug('Attaching tab activation events to element', $module);
  89. $module
  90. .on('click' + eventNamespace, module.event.click)
  91. ;
  92. }
  93. }
  94. },
  95. determineTabs: function() {
  96. var
  97. $reference
  98. ;
  99. // determine tab context
  100. if(settings.context === 'parent') {
  101. if($module.closest(selector.ui).length > 0) {
  102. $reference = $module.closest(selector.ui);
  103. module.verbose('Using closest UI element as parent', $reference);
  104. }
  105. else {
  106. $reference = $module;
  107. }
  108. $context = $reference.parent();
  109. module.verbose('Determined parent element for creating context', $context);
  110. }
  111. else if(settings.context) {
  112. $context = $(settings.context);
  113. module.verbose('Using selector for tab context', settings.context, $context);
  114. }
  115. else {
  116. $context = $('body');
  117. }
  118. // find tabs
  119. if(settings.childrenOnly) {
  120. $tabs = $context.children(selector.tabs);
  121. module.debug('Searching tab context children for tabs', $context, $tabs);
  122. }
  123. else {
  124. $tabs = $context.find(selector.tabs);
  125. module.debug('Searching tab context for tabs', $context, $tabs);
  126. }
  127. },
  128. fix: {
  129. callbacks: function() {
  130. if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) {
  131. if(parameters.onTabLoad) {
  132. parameters.onLoad = parameters.onTabLoad;
  133. delete parameters.onTabLoad;
  134. module.error(error.legacyLoad, parameters.onLoad);
  135. }
  136. if(parameters.onTabInit) {
  137. parameters.onFirstLoad = parameters.onTabInit;
  138. delete parameters.onTabInit;
  139. module.error(error.legacyInit, parameters.onFirstLoad);
  140. }
  141. settings = $.extend(true, {}, $.fn.tab.settings, parameters);
  142. }
  143. }
  144. },
  145. initializeHistory: function() {
  146. module.debug('Initializing page state');
  147. if( $.address === undefined ) {
  148. module.error(error.state);
  149. return false;
  150. }
  151. else {
  152. if(settings.historyType == 'state') {
  153. module.debug('Using HTML5 to manage state');
  154. if(settings.path !== false) {
  155. $.address
  156. .history(true)
  157. .state(settings.path)
  158. ;
  159. }
  160. else {
  161. module.error(error.path);
  162. return false;
  163. }
  164. }
  165. $.address
  166. .bind('change', module.event.history.change)
  167. ;
  168. }
  169. },
  170. event: {
  171. click: function(event) {
  172. var
  173. tabPath = $(this).data(metadata.tab)
  174. ;
  175. if(tabPath !== undefined) {
  176. if(settings.history) {
  177. module.verbose('Updating page state', event);
  178. $.address.value(tabPath);
  179. }
  180. else {
  181. module.verbose('Changing tab', event);
  182. module.changeTab(tabPath);
  183. }
  184. event.preventDefault();
  185. }
  186. else {
  187. module.debug('No tab specified');
  188. }
  189. },
  190. history: {
  191. change: function(event) {
  192. var
  193. tabPath = event.pathNames.join('/') || module.get.initialPath(),
  194. pageTitle = settings.templates.determineTitle(tabPath) || false
  195. ;
  196. module.performance.display();
  197. module.debug('History change event', tabPath, event);
  198. historyEvent = event;
  199. if(tabPath !== undefined) {
  200. module.changeTab(tabPath);
  201. }
  202. if(pageTitle) {
  203. $.address.title(pageTitle);
  204. }
  205. }
  206. }
  207. },
  208. refresh: function() {
  209. if(activeTabPath) {
  210. module.debug('Refreshing tab', activeTabPath);
  211. module.changeTab(activeTabPath);
  212. }
  213. },
  214. cache: {
  215. read: function(cacheKey) {
  216. return (cacheKey !== undefined)
  217. ? cache[cacheKey]
  218. : false
  219. ;
  220. },
  221. add: function(cacheKey, content) {
  222. cacheKey = cacheKey || activeTabPath;
  223. module.debug('Adding cached content for', cacheKey);
  224. cache[cacheKey] = content;
  225. },
  226. remove: function(cacheKey) {
  227. cacheKey = cacheKey || activeTabPath;
  228. module.debug('Removing cached content for', cacheKey);
  229. delete cache[cacheKey];
  230. }
  231. },
  232. set: {
  233. auto: function() {
  234. var
  235. url = (typeof settings.path == 'string')
  236. ? settings.path.replace(/\/$/, '') + '/{$tab}'
  237. : '/{$tab}'
  238. ;
  239. module.verbose('Setting up automatic tab retrieval from server', url);
  240. if($.isPlainObject(settings.apiSettings)) {
  241. settings.apiSettings.url = url;
  242. }
  243. else {
  244. settings.apiSettings = {
  245. url: url
  246. };
  247. }
  248. },
  249. loading: function(tabPath) {
  250. var
  251. $tab = module.get.tabElement(tabPath),
  252. isLoading = $tab.hasClass(className.loading)
  253. ;
  254. if(!isLoading) {
  255. module.verbose('Setting loading state for', $tab);
  256. $tab
  257. .addClass(className.loading)
  258. .siblings($tabs)
  259. .removeClass(className.active + ' ' + className.loading)
  260. ;
  261. if($tab.length > 0) {
  262. settings.onRequest.call($tab[0], tabPath);
  263. }
  264. }
  265. },
  266. state: function(state) {
  267. $.address.value(state);
  268. }
  269. },
  270. changeTab: function(tabPath) {
  271. var
  272. pushStateAvailable = (window.history && window.history.pushState),
  273. shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad),
  274. remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ),
  275. // only add default path if not remote content
  276. pathArray = (remoteContent && !shouldIgnoreLoad)
  277. ? module.utilities.pathToArray(tabPath)
  278. : module.get.defaultPathArray(tabPath)
  279. ;
  280. tabPath = module.utilities.arrayToPath(pathArray);
  281. $.each(pathArray, function(index, tab) {
  282. var
  283. currentPathArray = pathArray.slice(0, index + 1),
  284. currentPath = module.utilities.arrayToPath(currentPathArray),
  285. isTab = module.is.tab(currentPath),
  286. isLastIndex = (index + 1 == pathArray.length),
  287. $tab = module.get.tabElement(currentPath),
  288. $anchor,
  289. nextPathArray,
  290. nextPath,
  291. isLastTab
  292. ;
  293. module.verbose('Looking for tab', tab);
  294. if(isTab) {
  295. module.verbose('Tab was found', tab);
  296. // scope up
  297. activeTabPath = currentPath;
  298. parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
  299. if(isLastIndex) {
  300. isLastTab = true;
  301. }
  302. else {
  303. nextPathArray = pathArray.slice(0, index + 2);
  304. nextPath = module.utilities.arrayToPath(nextPathArray);
  305. isLastTab = ( !module.is.tab(nextPath) );
  306. if(isLastTab) {
  307. module.verbose('Tab parameters found', nextPathArray);
  308. }
  309. }
  310. if(isLastTab && remoteContent) {
  311. if(!shouldIgnoreLoad) {
  312. module.activate.navigation(currentPath);
  313. module.fetch.content(currentPath, tabPath);
  314. }
  315. else {
  316. module.debug('Ignoring remote content on first tab load', currentPath);
  317. firstLoad = false;
  318. module.cache.add(tabPath, $tab.html());
  319. module.activate.all(currentPath);
  320. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  321. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  322. }
  323. return false;
  324. }
  325. else {
  326. module.debug('Opened local tab', currentPath);
  327. module.activate.all(currentPath);
  328. if( !module.cache.read(currentPath) ) {
  329. module.cache.add(currentPath, true);
  330. module.debug('First time tab loaded calling tab init');
  331. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  332. }
  333. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  334. }
  335. }
  336. else if(tabPath.search('/') == -1 && tabPath !== '') {
  337. // look for in page anchor
  338. $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
  339. currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
  340. $tab = module.get.tabElement(currentPath);
  341. // if anchor exists use parent tab
  342. if($anchor && $anchor.length > 0 && currentPath) {
  343. module.debug('Anchor link used, opening parent tab', $tab, $anchor);
  344. if( !$tab.hasClass(className.active) ) {
  345. setTimeout(function() {
  346. module.scrollTo($anchor);
  347. }, 0);
  348. }
  349. module.activate.all(currentPath);
  350. if( !module.cache.read(currentPath) ) {
  351. module.cache.add(currentPath, true);
  352. module.debug('First time tab loaded calling tab init');
  353. settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  354. }
  355. settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
  356. return false;
  357. }
  358. }
  359. else {
  360. module.error(error.missingTab, $module, $context, currentPath);
  361. return false;
  362. }
  363. });
  364. },
  365. scrollTo: function($element) {
  366. var
  367. scrollOffset = ($element && $element.length > 0)
  368. ? $element.offset().top
  369. : false
  370. ;
  371. if(scrollOffset !== false) {
  372. module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
  373. $(document).scrollTop(scrollOffset);
  374. }
  375. },
  376. update: {
  377. content: function(tabPath, html, evaluateScripts) {
  378. var
  379. $tab = module.get.tabElement(tabPath),
  380. tab = $tab[0]
  381. ;
  382. evaluateScripts = (evaluateScripts !== undefined)
  383. ? evaluateScripts
  384. : settings.evaluateScripts
  385. ;
  386. if(evaluateScripts) {
  387. module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
  388. $tab.html(html);
  389. }
  390. else {
  391. module.debug('Updating HTML', tabPath, html);
  392. tab.innerHTML = html;
  393. }
  394. }
  395. },
  396. fetch: {
  397. content: function(tabPath, fullTabPath) {
  398. var
  399. $tab = module.get.tabElement(tabPath),
  400. apiSettings = {
  401. dataType : 'html',
  402. encodeParameters : false,
  403. on : 'now',
  404. cache : settings.alwaysRefresh,
  405. headers : {
  406. 'X-Remote': true
  407. },
  408. onSuccess : function(response) {
  409. module.cache.add(fullTabPath, response);
  410. module.update.content(tabPath, response);
  411. if(tabPath == activeTabPath) {
  412. module.debug('Content loaded', tabPath);
  413. module.activate.tab(tabPath);
  414. }
  415. else {
  416. module.debug('Content loaded in background', tabPath);
  417. }
  418. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  419. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  420. },
  421. urlData: {
  422. tab: fullTabPath
  423. }
  424. },
  425. request = $tab.api('get request') || false,
  426. existingRequest = ( request && request.state() === 'pending' ),
  427. requestSettings,
  428. cachedContent
  429. ;
  430. fullTabPath = fullTabPath || tabPath;
  431. cachedContent = module.cache.read(fullTabPath);
  432. if(settings.cache && cachedContent) {
  433. module.activate.tab(tabPath);
  434. module.debug('Adding cached content', fullTabPath);
  435. if(settings.evaluateScripts == 'once') {
  436. module.update.content(tabPath, cachedContent, false);
  437. }
  438. else {
  439. module.update.content(tabPath, cachedContent);
  440. }
  441. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  442. }
  443. else if(existingRequest) {
  444. module.set.loading(tabPath);
  445. module.debug('Content is already loading', fullTabPath);
  446. }
  447. else if($.api !== undefined) {
  448. requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
  449. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  450. module.set.loading(tabPath);
  451. $tab.api(requestSettings);
  452. }
  453. else {
  454. module.error(error.api);
  455. }
  456. }
  457. },
  458. activate: {
  459. all: function(tabPath) {
  460. module.activate.tab(tabPath);
  461. module.activate.navigation(tabPath);
  462. },
  463. tab: function(tabPath) {
  464. var
  465. $tab = module.get.tabElement(tabPath),
  466. isActive = $tab.hasClass(className.active)
  467. ;
  468. module.verbose('Showing tab content for', $tab);
  469. if(!isActive) {
  470. $tab
  471. .addClass(className.active)
  472. .siblings($tabs)
  473. .removeClass(className.active + ' ' + className.loading)
  474. ;
  475. if($tab.length > 0) {
  476. settings.onVisible.call($tab[0], tabPath);
  477. }
  478. }
  479. },
  480. navigation: function(tabPath) {
  481. var
  482. $navigation = module.get.navElement(tabPath),
  483. isActive = $navigation.hasClass(className.active)
  484. ;
  485. module.verbose('Activating tab navigation for', $navigation, tabPath);
  486. if(!isActive) {
  487. $navigation
  488. .addClass(className.active)
  489. .siblings($allModules)
  490. .removeClass(className.active + ' ' + className.loading)
  491. ;
  492. }
  493. }
  494. },
  495. deactivate: {
  496. all: function() {
  497. module.deactivate.navigation();
  498. module.deactivate.tabs();
  499. },
  500. navigation: function() {
  501. $allModules
  502. .removeClass(className.active)
  503. ;
  504. },
  505. tabs: function() {
  506. $tabs
  507. .removeClass(className.active + ' ' + className.loading)
  508. ;
  509. }
  510. },
  511. is: {
  512. tab: function(tabName) {
  513. return (tabName !== undefined)
  514. ? ( module.get.tabElement(tabName).length > 0 )
  515. : false
  516. ;
  517. }
  518. },
  519. get: {
  520. initialPath: function() {
  521. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  522. },
  523. path: function() {
  524. return $.address.value();
  525. },
  526. // adds default tabs to tab path
  527. defaultPathArray: function(tabPath) {
  528. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  529. },
  530. defaultPath: function(tabPath) {
  531. var
  532. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0),
  533. defaultTab = $defaultNav.data(metadata.tab) || false
  534. ;
  535. if( defaultTab ) {
  536. module.debug('Found default tab', defaultTab);
  537. if(recursionDepth < settings.maxDepth) {
  538. recursionDepth++;
  539. return module.get.defaultPath(defaultTab);
  540. }
  541. module.error(error.recursion);
  542. }
  543. else {
  544. module.debug('No default tabs found for', tabPath, $tabs);
  545. }
  546. recursionDepth = 0;
  547. return tabPath;
  548. },
  549. navElement: function(tabPath) {
  550. tabPath = tabPath || activeTabPath;
  551. return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  552. },
  553. tabElement: function(tabPath) {
  554. var
  555. $fullPathTab,
  556. $simplePathTab,
  557. tabPathArray,
  558. lastTab
  559. ;
  560. tabPath = tabPath || activeTabPath;
  561. tabPathArray = module.utilities.pathToArray(tabPath);
  562. lastTab = module.utilities.last(tabPathArray);
  563. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  564. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]');
  565. return ($fullPathTab.length > 0)
  566. ? $fullPathTab
  567. : $simplePathTab
  568. ;
  569. },
  570. tab: function() {
  571. return activeTabPath;
  572. }
  573. },
  574. utilities: {
  575. filterArray: function(keepArray, removeArray) {
  576. return $.grep(keepArray, function(keepValue) {
  577. return ( $.inArray(keepValue, removeArray) == -1);
  578. });
  579. },
  580. last: function(array) {
  581. return $.isArray(array)
  582. ? array[ array.length - 1]
  583. : false
  584. ;
  585. },
  586. pathToArray: function(pathName) {
  587. if(pathName === undefined) {
  588. pathName = activeTabPath;
  589. }
  590. return typeof pathName == 'string'
  591. ? pathName.split('/')
  592. : [pathName]
  593. ;
  594. },
  595. arrayToPath: function(pathArray) {
  596. return $.isArray(pathArray)
  597. ? pathArray.join('/')
  598. : false
  599. ;
  600. }
  601. },
  602. setting: function(name, value) {
  603. module.debug('Changing setting', name, value);
  604. if( $.isPlainObject(name) ) {
  605. $.extend(true, settings, name);
  606. }
  607. else if(value !== undefined) {
  608. settings[name] = value;
  609. }
  610. else {
  611. return settings[name];
  612. }
  613. },
  614. internal: function(name, value) {
  615. if( $.isPlainObject(name) ) {
  616. $.extend(true, module, name);
  617. }
  618. else if(value !== undefined) {
  619. module[name] = value;
  620. }
  621. else {
  622. return module[name];
  623. }
  624. },
  625. debug: function() {
  626. if(settings.debug) {
  627. if(settings.performance) {
  628. module.performance.log(arguments);
  629. }
  630. else {
  631. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  632. module.debug.apply(console, arguments);
  633. }
  634. }
  635. },
  636. verbose: function() {
  637. if(settings.verbose && settings.debug) {
  638. if(settings.performance) {
  639. module.performance.log(arguments);
  640. }
  641. else {
  642. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  643. module.verbose.apply(console, arguments);
  644. }
  645. }
  646. },
  647. error: function() {
  648. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  649. module.error.apply(console, arguments);
  650. },
  651. performance: {
  652. log: function(message) {
  653. var
  654. currentTime,
  655. executionTime,
  656. previousTime
  657. ;
  658. if(settings.performance) {
  659. currentTime = new Date().getTime();
  660. previousTime = time || currentTime;
  661. executionTime = currentTime - previousTime;
  662. time = currentTime;
  663. performance.push({
  664. 'Name' : message[0],
  665. 'Arguments' : [].slice.call(message, 1) || '',
  666. 'Element' : element,
  667. 'Execution Time' : executionTime
  668. });
  669. }
  670. clearTimeout(module.performance.timer);
  671. module.performance.timer = setTimeout(module.performance.display, 500);
  672. },
  673. display: function() {
  674. var
  675. title = settings.name + ':',
  676. totalTime = 0
  677. ;
  678. time = false;
  679. clearTimeout(module.performance.timer);
  680. $.each(performance, function(index, data) {
  681. totalTime += data['Execution Time'];
  682. });
  683. title += ' ' + totalTime + 'ms';
  684. if(moduleSelector) {
  685. title += ' \'' + moduleSelector + '\'';
  686. }
  687. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  688. console.groupCollapsed(title);
  689. if(console.table) {
  690. console.table(performance);
  691. }
  692. else {
  693. $.each(performance, function(index, data) {
  694. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  695. });
  696. }
  697. console.groupEnd();
  698. }
  699. performance = [];
  700. }
  701. },
  702. invoke: function(query, passedArguments, context) {
  703. var
  704. object = instance,
  705. maxDepth,
  706. found,
  707. response
  708. ;
  709. passedArguments = passedArguments || queryArguments;
  710. context = element || context;
  711. if(typeof query == 'string' && object !== undefined) {
  712. query = query.split(/[\. ]/);
  713. maxDepth = query.length - 1;
  714. $.each(query, function(depth, value) {
  715. var camelCaseValue = (depth != maxDepth)
  716. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  717. : query
  718. ;
  719. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  720. object = object[camelCaseValue];
  721. }
  722. else if( object[camelCaseValue] !== undefined ) {
  723. found = object[camelCaseValue];
  724. return false;
  725. }
  726. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  727. object = object[value];
  728. }
  729. else if( object[value] !== undefined ) {
  730. found = object[value];
  731. return false;
  732. }
  733. else {
  734. module.error(error.method, query);
  735. return false;
  736. }
  737. });
  738. }
  739. if ( $.isFunction( found ) ) {
  740. response = found.apply(context, passedArguments);
  741. }
  742. else if(found !== undefined) {
  743. response = found;
  744. }
  745. if($.isArray(returnedValue)) {
  746. returnedValue.push(response);
  747. }
  748. else if(returnedValue !== undefined) {
  749. returnedValue = [returnedValue, response];
  750. }
  751. else if(response !== undefined) {
  752. returnedValue = response;
  753. }
  754. return found;
  755. }
  756. };
  757. if(methodInvoked) {
  758. if(instance === undefined) {
  759. module.initialize();
  760. }
  761. module.invoke(query);
  762. }
  763. else {
  764. if(instance !== undefined) {
  765. instance.invoke('destroy');
  766. }
  767. module.initialize();
  768. }
  769. })
  770. ;
  771. return (returnedValue !== undefined)
  772. ? returnedValue
  773. : this
  774. ;
  775. };
  776. // shortcut for tabbed content with no defined navigation
  777. $.tab = function() {
  778. $(window).tab.apply(this, arguments);
  779. };
  780. $.fn.tab.settings = {
  781. name : 'Tab',
  782. namespace : 'tab',
  783. debug : false,
  784. verbose : false,
  785. performance : true,
  786. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  787. history : false, // use browser history
  788. historyType : 'hash', // #/ or html5 state
  789. path : false, // base path of url
  790. context : false, // specify a context that tabs must appear inside
  791. childrenOnly : false, // use only tabs that are children of context
  792. maxDepth : 25, // max depth a tab can be nested
  793. alwaysRefresh : false, // load tab content new every tab click
  794. cache : true, // cache the content requests to pull locally
  795. ignoreFirstLoad : false, // don't load remote content on first load
  796. apiSettings : false, // settings for api call
  797. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  798. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  799. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  800. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  801. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  802. templates : {
  803. determineTitle: function(tabArray) {} // returns page title for path
  804. },
  805. error: {
  806. api : 'You attempted to load content without API module',
  807. method : 'The method you called is not defined',
  808. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  809. noContent : 'The tab you specified is missing a content url.',
  810. path : 'History enabled, but no path was specified',
  811. recursion : 'Max recursive depth reached',
  812. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  813. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  814. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  815. },
  816. metadata : {
  817. tab : 'tab',
  818. loaded : 'loaded',
  819. promise: 'promise'
  820. },
  821. className : {
  822. loading : 'loading',
  823. active : 'active'
  824. },
  825. selector : {
  826. tabs : '.ui.tab',
  827. ui : '.ui'
  828. }
  829. };
  830. })( jQuery, window, document );