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.

896 lines
30 KiB

  1. /*!
  2. * # Semantic UI 2.0.0 - 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 dont 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('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. on : 'now',
  403. cache : 'local',
  404. onSuccess : function(response) {
  405. module.cache.add(fullTabPath, response);
  406. module.update.content(tabPath, response);
  407. if(tabPath == activeTabPath) {
  408. module.debug('Content loaded', tabPath);
  409. module.activate.tab(tabPath);
  410. }
  411. else {
  412. module.debug('Content loaded in background', tabPath);
  413. }
  414. settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  415. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  416. },
  417. urlData: {
  418. tab: fullTabPath
  419. }
  420. },
  421. request = $tab.api('get request') || false,
  422. existingRequest = ( request && request.state() === 'pending' ),
  423. requestSettings,
  424. cachedContent
  425. ;
  426. fullTabPath = fullTabPath || tabPath;
  427. cachedContent = module.cache.read(fullTabPath);
  428. if(settings.cache && cachedContent) {
  429. module.activate.tab(tabPath);
  430. module.debug('Adding cached content', fullTabPath);
  431. if(settings.evaluateScripts == 'once') {
  432. module.update.content(tabPath, cachedContent, false);
  433. }
  434. else {
  435. module.update.content(tabPath, cachedContent);
  436. }
  437. settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
  438. }
  439. else if(existingRequest) {
  440. module.set.loading(tabPath);
  441. module.debug('Content is already loading', fullTabPath);
  442. }
  443. else if($.api !== undefined) {
  444. requestSettings = $.extend(true, {
  445. headers: {
  446. 'X-Remote': true
  447. }
  448. }, settings.apiSettings, apiSettings);
  449. module.debug('Retrieving remote content', fullTabPath, requestSettings);
  450. $tab.api(requestSettings);
  451. }
  452. else {
  453. module.error(error.api);
  454. }
  455. }
  456. },
  457. activate: {
  458. all: function(tabPath) {
  459. module.activate.tab(tabPath);
  460. module.activate.navigation(tabPath);
  461. },
  462. tab: function(tabPath) {
  463. var
  464. $tab = module.get.tabElement(tabPath),
  465. isActive = $tab.hasClass(className.active)
  466. ;
  467. module.verbose('Showing tab content for', $tab);
  468. if(!isActive) {
  469. $tab
  470. .addClass(className.active)
  471. .siblings($tabs)
  472. .removeClass(className.active + ' ' + className.loading)
  473. ;
  474. if($tab.length > 0) {
  475. settings.onVisible.call($tab[0], tabPath);
  476. }
  477. }
  478. },
  479. navigation: function(tabPath) {
  480. var
  481. $navigation = module.get.navElement(tabPath),
  482. isActive = $navigation.hasClass(className.active)
  483. ;
  484. module.verbose('Activating tab navigation for', $navigation, tabPath);
  485. if(!isActive) {
  486. $navigation
  487. .addClass(className.active)
  488. .siblings($allModules)
  489. .removeClass(className.active + ' ' + className.loading)
  490. ;
  491. }
  492. }
  493. },
  494. deactivate: {
  495. all: function() {
  496. module.deactivate.navigation();
  497. module.deactivate.tabs();
  498. },
  499. navigation: function() {
  500. $allModules
  501. .removeClass(className.active)
  502. ;
  503. },
  504. tabs: function() {
  505. $tabs
  506. .removeClass(className.active + ' ' + className.loading)
  507. ;
  508. }
  509. },
  510. is: {
  511. tab: function(tabName) {
  512. return (tabName !== undefined)
  513. ? ( module.get.tabElement(tabName).length > 0 )
  514. : false
  515. ;
  516. }
  517. },
  518. get: {
  519. initialPath: function() {
  520. return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
  521. },
  522. path: function() {
  523. return $.address.value();
  524. },
  525. // adds default tabs to tab path
  526. defaultPathArray: function(tabPath) {
  527. return module.utilities.pathToArray( module.get.defaultPath(tabPath) );
  528. },
  529. defaultPath: function(tabPath) {
  530. var
  531. $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0),
  532. defaultTab = $defaultNav.data(metadata.tab) || false
  533. ;
  534. if( defaultTab ) {
  535. module.debug('Found default tab', defaultTab);
  536. if(recursionDepth < settings.maxDepth) {
  537. recursionDepth++;
  538. return module.get.defaultPath(defaultTab);
  539. }
  540. module.error(error.recursion);
  541. }
  542. else {
  543. module.debug('No default tabs found for', tabPath, $tabs);
  544. }
  545. recursionDepth = 0;
  546. return tabPath;
  547. },
  548. navElement: function(tabPath) {
  549. tabPath = tabPath || activeTabPath;
  550. return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  551. },
  552. tabElement: function(tabPath) {
  553. var
  554. $fullPathTab,
  555. $simplePathTab,
  556. tabPathArray,
  557. lastTab
  558. ;
  559. tabPath = tabPath || activeTabPath;
  560. tabPathArray = module.utilities.pathToArray(tabPath);
  561. lastTab = module.utilities.last(tabPathArray);
  562. $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]');
  563. $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]');
  564. return ($fullPathTab.length > 0)
  565. ? $fullPathTab
  566. : $simplePathTab
  567. ;
  568. },
  569. tab: function() {
  570. return activeTabPath;
  571. }
  572. },
  573. utilities: {
  574. filterArray: function(keepArray, removeArray) {
  575. return $.grep(keepArray, function(keepValue) {
  576. return ( $.inArray(keepValue, removeArray) == -1);
  577. });
  578. },
  579. last: function(array) {
  580. return $.isArray(array)
  581. ? array[ array.length - 1]
  582. : false
  583. ;
  584. },
  585. pathToArray: function(pathName) {
  586. if(pathName === undefined) {
  587. pathName = activeTabPath;
  588. }
  589. return typeof pathName == 'string'
  590. ? pathName.split('/')
  591. : [pathName]
  592. ;
  593. },
  594. arrayToPath: function(pathArray) {
  595. return $.isArray(pathArray)
  596. ? pathArray.join('/')
  597. : false
  598. ;
  599. }
  600. },
  601. setting: function(name, value) {
  602. module.debug('Changing setting', name, value);
  603. if( $.isPlainObject(name) ) {
  604. $.extend(true, settings, name);
  605. }
  606. else if(value !== undefined) {
  607. settings[name] = value;
  608. }
  609. else {
  610. return settings[name];
  611. }
  612. },
  613. internal: function(name, value) {
  614. if( $.isPlainObject(name) ) {
  615. $.extend(true, module, name);
  616. }
  617. else if(value !== undefined) {
  618. module[name] = value;
  619. }
  620. else {
  621. return module[name];
  622. }
  623. },
  624. debug: function() {
  625. if(settings.debug) {
  626. if(settings.performance) {
  627. module.performance.log(arguments);
  628. }
  629. else {
  630. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  631. module.debug.apply(console, arguments);
  632. }
  633. }
  634. },
  635. verbose: function() {
  636. if(settings.verbose && settings.debug) {
  637. if(settings.performance) {
  638. module.performance.log(arguments);
  639. }
  640. else {
  641. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  642. module.verbose.apply(console, arguments);
  643. }
  644. }
  645. },
  646. error: function() {
  647. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  648. module.error.apply(console, arguments);
  649. },
  650. performance: {
  651. log: function(message) {
  652. var
  653. currentTime,
  654. executionTime,
  655. previousTime
  656. ;
  657. if(settings.performance) {
  658. currentTime = new Date().getTime();
  659. previousTime = time || currentTime;
  660. executionTime = currentTime - previousTime;
  661. time = currentTime;
  662. performance.push({
  663. 'Name' : message[0],
  664. 'Arguments' : [].slice.call(message, 1) || '',
  665. 'Element' : element,
  666. 'Execution Time' : executionTime
  667. });
  668. }
  669. clearTimeout(module.performance.timer);
  670. module.performance.timer = setTimeout(module.performance.display, 500);
  671. },
  672. display: function() {
  673. var
  674. title = settings.name + ':',
  675. totalTime = 0
  676. ;
  677. time = false;
  678. clearTimeout(module.performance.timer);
  679. $.each(performance, function(index, data) {
  680. totalTime += data['Execution Time'];
  681. });
  682. title += ' ' + totalTime + 'ms';
  683. if(moduleSelector) {
  684. title += ' \'' + moduleSelector + '\'';
  685. }
  686. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  687. console.groupCollapsed(title);
  688. if(console.table) {
  689. console.table(performance);
  690. }
  691. else {
  692. $.each(performance, function(index, data) {
  693. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  694. });
  695. }
  696. console.groupEnd();
  697. }
  698. performance = [];
  699. }
  700. },
  701. invoke: function(query, passedArguments, context) {
  702. var
  703. object = instance,
  704. maxDepth,
  705. found,
  706. response
  707. ;
  708. passedArguments = passedArguments || queryArguments;
  709. context = element || context;
  710. if(typeof query == 'string' && object !== undefined) {
  711. query = query.split(/[\. ]/);
  712. maxDepth = query.length - 1;
  713. $.each(query, function(depth, value) {
  714. var camelCaseValue = (depth != maxDepth)
  715. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  716. : query
  717. ;
  718. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  719. object = object[camelCaseValue];
  720. }
  721. else if( object[camelCaseValue] !== undefined ) {
  722. found = object[camelCaseValue];
  723. return false;
  724. }
  725. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  726. object = object[value];
  727. }
  728. else if( object[value] !== undefined ) {
  729. found = object[value];
  730. return false;
  731. }
  732. else {
  733. module.error(error.method, query);
  734. return false;
  735. }
  736. });
  737. }
  738. if ( $.isFunction( found ) ) {
  739. response = found.apply(context, passedArguments);
  740. }
  741. else if(found !== undefined) {
  742. response = found;
  743. }
  744. if($.isArray(returnedValue)) {
  745. returnedValue.push(response);
  746. }
  747. else if(returnedValue !== undefined) {
  748. returnedValue = [returnedValue, response];
  749. }
  750. else if(response !== undefined) {
  751. returnedValue = response;
  752. }
  753. return found;
  754. }
  755. };
  756. if(methodInvoked) {
  757. if(instance === undefined) {
  758. module.initialize();
  759. }
  760. module.invoke(query);
  761. }
  762. else {
  763. if(instance !== undefined) {
  764. instance.invoke('destroy');
  765. }
  766. module.initialize();
  767. }
  768. })
  769. ;
  770. return (returnedValue !== undefined)
  771. ? returnedValue
  772. : this
  773. ;
  774. };
  775. // shortcut for tabbed content with no defined navigation
  776. $.tab = function() {
  777. $(window).tab.apply(this, arguments);
  778. };
  779. $.fn.tab.settings = {
  780. name : 'Tab',
  781. namespace : 'tab',
  782. debug : false,
  783. verbose : false,
  784. performance : true,
  785. auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers
  786. history : false, // use browser history
  787. historyType : 'hash', // #/ or html5 state
  788. path : false, // base path of url
  789. context : false, // specify a context that tabs must appear inside
  790. childrenOnly : false, // use only tabs that are children of context
  791. maxDepth : 25, // max depth a tab can be nested
  792. alwaysRefresh : false, // load tab content new every tab click
  793. cache : true, // cache the content requests to pull locally
  794. ignoreFirstLoad : false, // don't load remote content on first load
  795. apiSettings : false, // settings for api call
  796. evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
  797. onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded
  798. onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load
  799. onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible
  800. onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
  801. templates : {
  802. determineTitle: function(tabArray) {} // returns page title for path
  803. },
  804. error: {
  805. api : 'You attempted to load content without API module',
  806. method : 'The method you called is not defined',
  807. missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.',
  808. noContent : 'The tab you specified is missing a content url.',
  809. path : 'History enabled, but no path was specified',
  810. recursion : 'Max recursive depth reached',
  811. legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.',
  812. legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code',
  813. state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>'
  814. },
  815. metadata : {
  816. tab : 'tab',
  817. loaded : 'loaded',
  818. promise: 'promise'
  819. },
  820. className : {
  821. loading : 'loading',
  822. active : 'active'
  823. },
  824. selector : {
  825. tabs : '.ui.tab',
  826. ui : '.ui'
  827. }
  828. };
  829. })( jQuery, window , document );