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.

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