| @@ 17657-18598 (lines=942) @@ | ||
| 17654 | * |
|
| 17655 | */ |
|
| 17656 | ||
| 17657 | ;(function ($, window, document, undefined) { |
|
| 17658 | ||
| 17659 | "use strict"; |
|
| 17660 | ||
| 17661 | window = (typeof window != 'undefined' && window.Math == Math) |
|
| 17662 | ? window |
|
| 17663 | : (typeof self != 'undefined' && self.Math == Math) |
|
| 17664 | ? self |
|
| 17665 | : Function('return this')() |
|
| 17666 | ; |
|
| 17667 | ||
| 17668 | $.fn.tab = function(parameters) { |
|
| 17669 | ||
| 17670 | var |
|
| 17671 | // use window context if none specified |
|
| 17672 | $allModules = $.isFunction(this) |
|
| 17673 | ? $(window) |
|
| 17674 | : $(this), |
|
| 17675 | ||
| 17676 | moduleSelector = $allModules.selector || '', |
|
| 17677 | time = new Date().getTime(), |
|
| 17678 | performance = [], |
|
| 17679 | ||
| 17680 | query = arguments[0], |
|
| 17681 | methodInvoked = (typeof query == 'string'), |
|
| 17682 | queryArguments = [].slice.call(arguments, 1), |
|
| 17683 | ||
| 17684 | initializedHistory = false, |
|
| 17685 | returnedValue |
|
| 17686 | ; |
|
| 17687 | ||
| 17688 | $allModules |
|
| 17689 | .each(function() { |
|
| 17690 | var |
|
| 17691 | ||
| 17692 | settings = ( $.isPlainObject(parameters) ) |
|
| 17693 | ? $.extend(true, {}, $.fn.tab.settings, parameters) |
|
| 17694 | : $.extend({}, $.fn.tab.settings), |
|
| 17695 | ||
| 17696 | className = settings.className, |
|
| 17697 | metadata = settings.metadata, |
|
| 17698 | selector = settings.selector, |
|
| 17699 | error = settings.error, |
|
| 17700 | ||
| 17701 | eventNamespace = '.' + settings.namespace, |
|
| 17702 | moduleNamespace = 'module-' + settings.namespace, |
|
| 17703 | ||
| 17704 | $module = $(this), |
|
| 17705 | $context, |
|
| 17706 | $tabs, |
|
| 17707 | ||
| 17708 | cache = {}, |
|
| 17709 | firstLoad = true, |
|
| 17710 | recursionDepth = 0, |
|
| 17711 | element = this, |
|
| 17712 | instance = $module.data(moduleNamespace), |
|
| 17713 | ||
| 17714 | activeTabPath, |
|
| 17715 | parameterArray, |
|
| 17716 | module, |
|
| 17717 | ||
| 17718 | historyEvent |
|
| 17719 | ||
| 17720 | ; |
|
| 17721 | ||
| 17722 | module = { |
|
| 17723 | ||
| 17724 | initialize: function() { |
|
| 17725 | module.debug('Initializing tab menu item', $module); |
|
| 17726 | module.fix.callbacks(); |
|
| 17727 | module.determineTabs(); |
|
| 17728 | ||
| 17729 | module.debug('Determining tabs', settings.context, $tabs); |
|
| 17730 | // set up automatic routing |
|
| 17731 | if(settings.auto) { |
|
| 17732 | module.set.auto(); |
|
| 17733 | } |
|
| 17734 | module.bind.events(); |
|
| 17735 | ||
| 17736 | if(settings.history && !initializedHistory) { |
|
| 17737 | module.initializeHistory(); |
|
| 17738 | initializedHistory = true; |
|
| 17739 | } |
|
| 17740 | ||
| 17741 | module.instantiate(); |
|
| 17742 | }, |
|
| 17743 | ||
| 17744 | instantiate: function () { |
|
| 17745 | module.verbose('Storing instance of module', module); |
|
| 17746 | instance = module; |
|
| 17747 | $module |
|
| 17748 | .data(moduleNamespace, module) |
|
| 17749 | ; |
|
| 17750 | }, |
|
| 17751 | ||
| 17752 | destroy: function() { |
|
| 17753 | module.debug('Destroying tabs', $module); |
|
| 17754 | $module |
|
| 17755 | .removeData(moduleNamespace) |
|
| 17756 | .off(eventNamespace) |
|
| 17757 | ; |
|
| 17758 | }, |
|
| 17759 | ||
| 17760 | bind: { |
|
| 17761 | events: function() { |
|
| 17762 | // if using $.tab don't add events |
|
| 17763 | if( !$.isWindow( element ) ) { |
|
| 17764 | module.debug('Attaching tab activation events to element', $module); |
|
| 17765 | $module |
|
| 17766 | .on('click' + eventNamespace, module.event.click) |
|
| 17767 | ; |
|
| 17768 | } |
|
| 17769 | } |
|
| 17770 | }, |
|
| 17771 | ||
| 17772 | determineTabs: function() { |
|
| 17773 | var |
|
| 17774 | $reference |
|
| 17775 | ; |
|
| 17776 | ||
| 17777 | // determine tab context |
|
| 17778 | if(settings.context === 'parent') { |
|
| 17779 | if($module.closest(selector.ui).length > 0) { |
|
| 17780 | $reference = $module.closest(selector.ui); |
|
| 17781 | module.verbose('Using closest UI element as parent', $reference); |
|
| 17782 | } |
|
| 17783 | else { |
|
| 17784 | $reference = $module; |
|
| 17785 | } |
|
| 17786 | $context = $reference.parent(); |
|
| 17787 | module.verbose('Determined parent element for creating context', $context); |
|
| 17788 | } |
|
| 17789 | else if(settings.context) { |
|
| 17790 | $context = $(settings.context); |
|
| 17791 | module.verbose('Using selector for tab context', settings.context, $context); |
|
| 17792 | } |
|
| 17793 | else { |
|
| 17794 | $context = $('body'); |
|
| 17795 | } |
|
| 17796 | // find tabs |
|
| 17797 | if(settings.childrenOnly) { |
|
| 17798 | $tabs = $context.children(selector.tabs); |
|
| 17799 | module.debug('Searching tab context children for tabs', $context, $tabs); |
|
| 17800 | } |
|
| 17801 | else { |
|
| 17802 | $tabs = $context.find(selector.tabs); |
|
| 17803 | module.debug('Searching tab context for tabs', $context, $tabs); |
|
| 17804 | } |
|
| 17805 | }, |
|
| 17806 | ||
| 17807 | fix: { |
|
| 17808 | callbacks: function() { |
|
| 17809 | if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) { |
|
| 17810 | if(parameters.onTabLoad) { |
|
| 17811 | parameters.onLoad = parameters.onTabLoad; |
|
| 17812 | delete parameters.onTabLoad; |
|
| 17813 | module.error(error.legacyLoad, parameters.onLoad); |
|
| 17814 | } |
|
| 17815 | if(parameters.onTabInit) { |
|
| 17816 | parameters.onFirstLoad = parameters.onTabInit; |
|
| 17817 | delete parameters.onTabInit; |
|
| 17818 | module.error(error.legacyInit, parameters.onFirstLoad); |
|
| 17819 | } |
|
| 17820 | settings = $.extend(true, {}, $.fn.tab.settings, parameters); |
|
| 17821 | } |
|
| 17822 | } |
|
| 17823 | }, |
|
| 17824 | ||
| 17825 | initializeHistory: function() { |
|
| 17826 | module.debug('Initializing page state'); |
|
| 17827 | if( $.address === undefined ) { |
|
| 17828 | module.error(error.state); |
|
| 17829 | return false; |
|
| 17830 | } |
|
| 17831 | else { |
|
| 17832 | if(settings.historyType == 'state') { |
|
| 17833 | module.debug('Using HTML5 to manage state'); |
|
| 17834 | if(settings.path !== false) { |
|
| 17835 | $.address |
|
| 17836 | .history(true) |
|
| 17837 | .state(settings.path) |
|
| 17838 | ; |
|
| 17839 | } |
|
| 17840 | else { |
|
| 17841 | module.error(error.path); |
|
| 17842 | return false; |
|
| 17843 | } |
|
| 17844 | } |
|
| 17845 | $.address |
|
| 17846 | .bind('change', module.event.history.change) |
|
| 17847 | ; |
|
| 17848 | } |
|
| 17849 | }, |
|
| 17850 | ||
| 17851 | event: { |
|
| 17852 | click: function(event) { |
|
| 17853 | var |
|
| 17854 | tabPath = $(this).data(metadata.tab) |
|
| 17855 | ; |
|
| 17856 | if(tabPath !== undefined) { |
|
| 17857 | if(settings.history) { |
|
| 17858 | module.verbose('Updating page state', event); |
|
| 17859 | $.address.value(tabPath); |
|
| 17860 | } |
|
| 17861 | else { |
|
| 17862 | module.verbose('Changing tab', event); |
|
| 17863 | module.changeTab(tabPath); |
|
| 17864 | } |
|
| 17865 | event.preventDefault(); |
|
| 17866 | } |
|
| 17867 | else { |
|
| 17868 | module.debug('No tab specified'); |
|
| 17869 | } |
|
| 17870 | }, |
|
| 17871 | history: { |
|
| 17872 | change: function(event) { |
|
| 17873 | var |
|
| 17874 | tabPath = event.pathNames.join('/') || module.get.initialPath(), |
|
| 17875 | pageTitle = settings.templates.determineTitle(tabPath) || false |
|
| 17876 | ; |
|
| 17877 | module.performance.display(); |
|
| 17878 | module.debug('History change event', tabPath, event); |
|
| 17879 | historyEvent = event; |
|
| 17880 | if(tabPath !== undefined) { |
|
| 17881 | module.changeTab(tabPath); |
|
| 17882 | } |
|
| 17883 | if(pageTitle) { |
|
| 17884 | $.address.title(pageTitle); |
|
| 17885 | } |
|
| 17886 | } |
|
| 17887 | } |
|
| 17888 | }, |
|
| 17889 | ||
| 17890 | refresh: function() { |
|
| 17891 | if(activeTabPath) { |
|
| 17892 | module.debug('Refreshing tab', activeTabPath); |
|
| 17893 | module.changeTab(activeTabPath); |
|
| 17894 | } |
|
| 17895 | }, |
|
| 17896 | ||
| 17897 | cache: { |
|
| 17898 | ||
| 17899 | read: function(cacheKey) { |
|
| 17900 | return (cacheKey !== undefined) |
|
| 17901 | ? cache[cacheKey] |
|
| 17902 | : false |
|
| 17903 | ; |
|
| 17904 | }, |
|
| 17905 | add: function(cacheKey, content) { |
|
| 17906 | cacheKey = cacheKey || activeTabPath; |
|
| 17907 | module.debug('Adding cached content for', cacheKey); |
|
| 17908 | cache[cacheKey] = content; |
|
| 17909 | }, |
|
| 17910 | remove: function(cacheKey) { |
|
| 17911 | cacheKey = cacheKey || activeTabPath; |
|
| 17912 | module.debug('Removing cached content for', cacheKey); |
|
| 17913 | delete cache[cacheKey]; |
|
| 17914 | } |
|
| 17915 | }, |
|
| 17916 | ||
| 17917 | set: { |
|
| 17918 | auto: function() { |
|
| 17919 | var |
|
| 17920 | url = (typeof settings.path == 'string') |
|
| 17921 | ? settings.path.replace(/\/$/, '') + '/{$tab}' |
|
| 17922 | : '/{$tab}' |
|
| 17923 | ; |
|
| 17924 | module.verbose('Setting up automatic tab retrieval from server', url); |
|
| 17925 | if($.isPlainObject(settings.apiSettings)) { |
|
| 17926 | settings.apiSettings.url = url; |
|
| 17927 | } |
|
| 17928 | else { |
|
| 17929 | settings.apiSettings = { |
|
| 17930 | url: url |
|
| 17931 | }; |
|
| 17932 | } |
|
| 17933 | }, |
|
| 17934 | loading: function(tabPath) { |
|
| 17935 | var |
|
| 17936 | $tab = module.get.tabElement(tabPath), |
|
| 17937 | isLoading = $tab.hasClass(className.loading) |
|
| 17938 | ; |
|
| 17939 | if(!isLoading) { |
|
| 17940 | module.verbose('Setting loading state for', $tab); |
|
| 17941 | $tab |
|
| 17942 | .addClass(className.loading) |
|
| 17943 | .siblings($tabs) |
|
| 17944 | .removeClass(className.active + ' ' + className.loading) |
|
| 17945 | ; |
|
| 17946 | if($tab.length > 0) { |
|
| 17947 | settings.onRequest.call($tab[0], tabPath); |
|
| 17948 | } |
|
| 17949 | } |
|
| 17950 | }, |
|
| 17951 | state: function(state) { |
|
| 17952 | $.address.value(state); |
|
| 17953 | } |
|
| 17954 | }, |
|
| 17955 | ||
| 17956 | changeTab: function(tabPath) { |
|
| 17957 | var |
|
| 17958 | pushStateAvailable = (window.history && window.history.pushState), |
|
| 17959 | shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad), |
|
| 17960 | remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ), |
|
| 17961 | // only add default path if not remote content |
|
| 17962 | pathArray = (remoteContent && !shouldIgnoreLoad) |
|
| 17963 | ? module.utilities.pathToArray(tabPath) |
|
| 17964 | : module.get.defaultPathArray(tabPath) |
|
| 17965 | ; |
|
| 17966 | tabPath = module.utilities.arrayToPath(pathArray); |
|
| 17967 | $.each(pathArray, function(index, tab) { |
|
| 17968 | var |
|
| 17969 | currentPathArray = pathArray.slice(0, index + 1), |
|
| 17970 | currentPath = module.utilities.arrayToPath(currentPathArray), |
|
| 17971 | ||
| 17972 | isTab = module.is.tab(currentPath), |
|
| 17973 | isLastIndex = (index + 1 == pathArray.length), |
|
| 17974 | ||
| 17975 | $tab = module.get.tabElement(currentPath), |
|
| 17976 | $anchor, |
|
| 17977 | nextPathArray, |
|
| 17978 | nextPath, |
|
| 17979 | isLastTab |
|
| 17980 | ; |
|
| 17981 | module.verbose('Looking for tab', tab); |
|
| 17982 | if(isTab) { |
|
| 17983 | module.verbose('Tab was found', tab); |
|
| 17984 | // scope up |
|
| 17985 | activeTabPath = currentPath; |
|
| 17986 | parameterArray = module.utilities.filterArray(pathArray, currentPathArray); |
|
| 17987 | ||
| 17988 | if(isLastIndex) { |
|
| 17989 | isLastTab = true; |
|
| 17990 | } |
|
| 17991 | else { |
|
| 17992 | nextPathArray = pathArray.slice(0, index + 2); |
|
| 17993 | nextPath = module.utilities.arrayToPath(nextPathArray); |
|
| 17994 | isLastTab = ( !module.is.tab(nextPath) ); |
|
| 17995 | if(isLastTab) { |
|
| 17996 | module.verbose('Tab parameters found', nextPathArray); |
|
| 17997 | } |
|
| 17998 | } |
|
| 17999 | if(isLastTab && remoteContent) { |
|
| 18000 | if(!shouldIgnoreLoad) { |
|
| 18001 | module.activate.navigation(currentPath); |
|
| 18002 | module.fetch.content(currentPath, tabPath); |
|
| 18003 | } |
|
| 18004 | else { |
|
| 18005 | module.debug('Ignoring remote content on first tab load', currentPath); |
|
| 18006 | firstLoad = false; |
|
| 18007 | module.cache.add(tabPath, $tab.html()); |
|
| 18008 | module.activate.all(currentPath); |
|
| 18009 | settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 18010 | settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 18011 | } |
|
| 18012 | return false; |
|
| 18013 | } |
|
| 18014 | else { |
|
| 18015 | module.debug('Opened local tab', currentPath); |
|
| 18016 | module.activate.all(currentPath); |
|
| 18017 | if( !module.cache.read(currentPath) ) { |
|
| 18018 | module.cache.add(currentPath, true); |
|
| 18019 | module.debug('First time tab loaded calling tab init'); |
|
| 18020 | settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 18021 | } |
|
| 18022 | settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 18023 | } |
|
| 18024 | ||
| 18025 | } |
|
| 18026 | else if(tabPath.search('/') == -1 && tabPath !== '') { |
|
| 18027 | // look for in page anchor |
|
| 18028 | $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]'); |
|
| 18029 | currentPath = $anchor.closest('[data-tab]').data(metadata.tab); |
|
| 18030 | $tab = module.get.tabElement(currentPath); |
|
| 18031 | // if anchor exists use parent tab |
|
| 18032 | if($anchor && $anchor.length > 0 && currentPath) { |
|
| 18033 | module.debug('Anchor link used, opening parent tab', $tab, $anchor); |
|
| 18034 | if( !$tab.hasClass(className.active) ) { |
|
| 18035 | setTimeout(function() { |
|
| 18036 | module.scrollTo($anchor); |
|
| 18037 | }, 0); |
|
| 18038 | } |
|
| 18039 | module.activate.all(currentPath); |
|
| 18040 | if( !module.cache.read(currentPath) ) { |
|
| 18041 | module.cache.add(currentPath, true); |
|
| 18042 | module.debug('First time tab loaded calling tab init'); |
|
| 18043 | settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 18044 | } |
|
| 18045 | settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 18046 | return false; |
|
| 18047 | } |
|
| 18048 | } |
|
| 18049 | else { |
|
| 18050 | module.error(error.missingTab, $module, $context, currentPath); |
|
| 18051 | return false; |
|
| 18052 | } |
|
| 18053 | }); |
|
| 18054 | }, |
|
| 18055 | ||
| 18056 | scrollTo: function($element) { |
|
| 18057 | var |
|
| 18058 | scrollOffset = ($element && $element.length > 0) |
|
| 18059 | ? $element.offset().top |
|
| 18060 | : false |
|
| 18061 | ; |
|
| 18062 | if(scrollOffset !== false) { |
|
| 18063 | module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element); |
|
| 18064 | $(document).scrollTop(scrollOffset); |
|
| 18065 | } |
|
| 18066 | }, |
|
| 18067 | ||
| 18068 | update: { |
|
| 18069 | content: function(tabPath, html, evaluateScripts) { |
|
| 18070 | var |
|
| 18071 | $tab = module.get.tabElement(tabPath), |
|
| 18072 | tab = $tab[0] |
|
| 18073 | ; |
|
| 18074 | evaluateScripts = (evaluateScripts !== undefined) |
|
| 18075 | ? evaluateScripts |
|
| 18076 | : settings.evaluateScripts |
|
| 18077 | ; |
|
| 18078 | if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') { |
|
| 18079 | $tab |
|
| 18080 | .empty() |
|
| 18081 | .append($(html).clone(true)) |
|
| 18082 | ; |
|
| 18083 | } |
|
| 18084 | else { |
|
| 18085 | if(evaluateScripts) { |
|
| 18086 | module.debug('Updating HTML and evaluating inline scripts', tabPath, html); |
|
| 18087 | $tab.html(html); |
|
| 18088 | } |
|
| 18089 | else { |
|
| 18090 | module.debug('Updating HTML', tabPath, html); |
|
| 18091 | tab.innerHTML = html; |
|
| 18092 | } |
|
| 18093 | } |
|
| 18094 | } |
|
| 18095 | }, |
|
| 18096 | ||
| 18097 | fetch: { |
|
| 18098 | ||
| 18099 | content: function(tabPath, fullTabPath) { |
|
| 18100 | var |
|
| 18101 | $tab = module.get.tabElement(tabPath), |
|
| 18102 | apiSettings = { |
|
| 18103 | dataType : 'html', |
|
| 18104 | encodeParameters : false, |
|
| 18105 | on : 'now', |
|
| 18106 | cache : settings.alwaysRefresh, |
|
| 18107 | headers : { |
|
| 18108 | 'X-Remote': true |
|
| 18109 | }, |
|
| 18110 | onSuccess : function(response) { |
|
| 18111 | if(settings.cacheType == 'response') { |
|
| 18112 | module.cache.add(fullTabPath, response); |
|
| 18113 | } |
|
| 18114 | module.update.content(tabPath, response); |
|
| 18115 | if(tabPath == activeTabPath) { |
|
| 18116 | module.debug('Content loaded', tabPath); |
|
| 18117 | module.activate.tab(tabPath); |
|
| 18118 | } |
|
| 18119 | else { |
|
| 18120 | module.debug('Content loaded in background', tabPath); |
|
| 18121 | } |
|
| 18122 | settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent); |
|
| 18123 | settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent); |
|
| 18124 | ||
| 18125 | if(settings.loadOnce) { |
|
| 18126 | module.cache.add(fullTabPath, true); |
|
| 18127 | } |
|
| 18128 | else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) { |
|
| 18129 | setTimeout(function() { |
|
| 18130 | var |
|
| 18131 | $clone = $tab.children().clone(true) |
|
| 18132 | ; |
|
| 18133 | $clone = $clone.not('script'); |
|
| 18134 | module.cache.add(fullTabPath, $clone); |
|
| 18135 | }, 0); |
|
| 18136 | } |
|
| 18137 | else { |
|
| 18138 | module.cache.add(fullTabPath, $tab.html()); |
|
| 18139 | } |
|
| 18140 | }, |
|
| 18141 | urlData: { |
|
| 18142 | tab: fullTabPath |
|
| 18143 | } |
|
| 18144 | }, |
|
| 18145 | request = $tab.api('get request') || false, |
|
| 18146 | existingRequest = ( request && request.state() === 'pending' ), |
|
| 18147 | requestSettings, |
|
| 18148 | cachedContent |
|
| 18149 | ; |
|
| 18150 | ||
| 18151 | fullTabPath = fullTabPath || tabPath; |
|
| 18152 | cachedContent = module.cache.read(fullTabPath); |
|
| 18153 | ||
| 18154 | ||
| 18155 | if(settings.cache && cachedContent) { |
|
| 18156 | module.activate.tab(tabPath); |
|
| 18157 | module.debug('Adding cached content', fullTabPath); |
|
| 18158 | if(!settings.loadOnce) { |
|
| 18159 | if(settings.evaluateScripts == 'once') { |
|
| 18160 | module.update.content(tabPath, cachedContent, false); |
|
| 18161 | } |
|
| 18162 | else { |
|
| 18163 | module.update.content(tabPath, cachedContent); |
|
| 18164 | } |
|
| 18165 | } |
|
| 18166 | settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent); |
|
| 18167 | } |
|
| 18168 | else if(existingRequest) { |
|
| 18169 | module.set.loading(tabPath); |
|
| 18170 | module.debug('Content is already loading', fullTabPath); |
|
| 18171 | } |
|
| 18172 | else if($.api !== undefined) { |
|
| 18173 | requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings); |
|
| 18174 | module.debug('Retrieving remote content', fullTabPath, requestSettings); |
|
| 18175 | module.set.loading(tabPath); |
|
| 18176 | $tab.api(requestSettings); |
|
| 18177 | } |
|
| 18178 | else { |
|
| 18179 | module.error(error.api); |
|
| 18180 | } |
|
| 18181 | } |
|
| 18182 | }, |
|
| 18183 | ||
| 18184 | activate: { |
|
| 18185 | all: function(tabPath) { |
|
| 18186 | module.activate.tab(tabPath); |
|
| 18187 | module.activate.navigation(tabPath); |
|
| 18188 | }, |
|
| 18189 | tab: function(tabPath) { |
|
| 18190 | var |
|
| 18191 | $tab = module.get.tabElement(tabPath), |
|
| 18192 | $deactiveTabs = (settings.deactivate == 'siblings') |
|
| 18193 | ? $tab.siblings($tabs) |
|
| 18194 | : $tabs.not($tab), |
|
| 18195 | isActive = $tab.hasClass(className.active) |
|
| 18196 | ; |
|
| 18197 | module.verbose('Showing tab content for', $tab); |
|
| 18198 | if(!isActive) { |
|
| 18199 | $tab |
|
| 18200 | .addClass(className.active) |
|
| 18201 | ; |
|
| 18202 | $deactiveTabs |
|
| 18203 | .removeClass(className.active + ' ' + className.loading) |
|
| 18204 | ; |
|
| 18205 | if($tab.length > 0) { |
|
| 18206 | settings.onVisible.call($tab[0], tabPath); |
|
| 18207 | } |
|
| 18208 | } |
|
| 18209 | }, |
|
| 18210 | navigation: function(tabPath) { |
|
| 18211 | var |
|
| 18212 | $navigation = module.get.navElement(tabPath), |
|
| 18213 | $deactiveNavigation = (settings.deactivate == 'siblings') |
|
| 18214 | ? $navigation.siblings($allModules) |
|
| 18215 | : $allModules.not($navigation), |
|
| 18216 | isActive = $navigation.hasClass(className.active) |
|
| 18217 | ; |
|
| 18218 | module.verbose('Activating tab navigation for', $navigation, tabPath); |
|
| 18219 | if(!isActive) { |
|
| 18220 | $navigation |
|
| 18221 | .addClass(className.active) |
|
| 18222 | ; |
|
| 18223 | $deactiveNavigation |
|
| 18224 | .removeClass(className.active + ' ' + className.loading) |
|
| 18225 | ; |
|
| 18226 | } |
|
| 18227 | } |
|
| 18228 | }, |
|
| 18229 | ||
| 18230 | deactivate: { |
|
| 18231 | all: function() { |
|
| 18232 | module.deactivate.navigation(); |
|
| 18233 | module.deactivate.tabs(); |
|
| 18234 | }, |
|
| 18235 | navigation: function() { |
|
| 18236 | $allModules |
|
| 18237 | .removeClass(className.active) |
|
| 18238 | ; |
|
| 18239 | }, |
|
| 18240 | tabs: function() { |
|
| 18241 | $tabs |
|
| 18242 | .removeClass(className.active + ' ' + className.loading) |
|
| 18243 | ; |
|
| 18244 | } |
|
| 18245 | }, |
|
| 18246 | ||
| 18247 | is: { |
|
| 18248 | tab: function(tabName) { |
|
| 18249 | return (tabName !== undefined) |
|
| 18250 | ? ( module.get.tabElement(tabName).length > 0 ) |
|
| 18251 | : false |
|
| 18252 | ; |
|
| 18253 | } |
|
| 18254 | }, |
|
| 18255 | ||
| 18256 | get: { |
|
| 18257 | initialPath: function() { |
|
| 18258 | return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab); |
|
| 18259 | }, |
|
| 18260 | path: function() { |
|
| 18261 | return $.address.value(); |
|
| 18262 | }, |
|
| 18263 | // adds default tabs to tab path |
|
| 18264 | defaultPathArray: function(tabPath) { |
|
| 18265 | return module.utilities.pathToArray( module.get.defaultPath(tabPath) ); |
|
| 18266 | }, |
|
| 18267 | defaultPath: function(tabPath) { |
|
| 18268 | var |
|
| 18269 | $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0), |
|
| 18270 | defaultTab = $defaultNav.data(metadata.tab) || false |
|
| 18271 | ; |
|
| 18272 | if( defaultTab ) { |
|
| 18273 | module.debug('Found default tab', defaultTab); |
|
| 18274 | if(recursionDepth < settings.maxDepth) { |
|
| 18275 | recursionDepth++; |
|
| 18276 | return module.get.defaultPath(defaultTab); |
|
| 18277 | } |
|
| 18278 | module.error(error.recursion); |
|
| 18279 | } |
|
| 18280 | else { |
|
| 18281 | module.debug('No default tabs found for', tabPath, $tabs); |
|
| 18282 | } |
|
| 18283 | recursionDepth = 0; |
|
| 18284 | return tabPath; |
|
| 18285 | }, |
|
| 18286 | navElement: function(tabPath) { |
|
| 18287 | tabPath = tabPath || activeTabPath; |
|
| 18288 | return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); |
|
| 18289 | }, |
|
| 18290 | tabElement: function(tabPath) { |
|
| 18291 | var |
|
| 18292 | $fullPathTab, |
|
| 18293 | $simplePathTab, |
|
| 18294 | tabPathArray, |
|
| 18295 | lastTab |
|
| 18296 | ; |
|
| 18297 | tabPath = tabPath || activeTabPath; |
|
| 18298 | tabPathArray = module.utilities.pathToArray(tabPath); |
|
| 18299 | lastTab = module.utilities.last(tabPathArray); |
|
| 18300 | $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); |
|
| 18301 | $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]'); |
|
| 18302 | return ($fullPathTab.length > 0) |
|
| 18303 | ? $fullPathTab |
|
| 18304 | : $simplePathTab |
|
| 18305 | ; |
|
| 18306 | }, |
|
| 18307 | tab: function() { |
|
| 18308 | return activeTabPath; |
|
| 18309 | } |
|
| 18310 | }, |
|
| 18311 | ||
| 18312 | utilities: { |
|
| 18313 | filterArray: function(keepArray, removeArray) { |
|
| 18314 | return $.grep(keepArray, function(keepValue) { |
|
| 18315 | return ( $.inArray(keepValue, removeArray) == -1); |
|
| 18316 | }); |
|
| 18317 | }, |
|
| 18318 | last: function(array) { |
|
| 18319 | return $.isArray(array) |
|
| 18320 | ? array[ array.length - 1] |
|
| 18321 | : false |
|
| 18322 | ; |
|
| 18323 | }, |
|
| 18324 | pathToArray: function(pathName) { |
|
| 18325 | if(pathName === undefined) { |
|
| 18326 | pathName = activeTabPath; |
|
| 18327 | } |
|
| 18328 | return typeof pathName == 'string' |
|
| 18329 | ? pathName.split('/') |
|
| 18330 | : [pathName] |
|
| 18331 | ; |
|
| 18332 | }, |
|
| 18333 | arrayToPath: function(pathArray) { |
|
| 18334 | return $.isArray(pathArray) |
|
| 18335 | ? pathArray.join('/') |
|
| 18336 | : false |
|
| 18337 | ; |
|
| 18338 | } |
|
| 18339 | }, |
|
| 18340 | ||
| 18341 | setting: function(name, value) { |
|
| 18342 | module.debug('Changing setting', name, value); |
|
| 18343 | if( $.isPlainObject(name) ) { |
|
| 18344 | $.extend(true, settings, name); |
|
| 18345 | } |
|
| 18346 | else if(value !== undefined) { |
|
| 18347 | if($.isPlainObject(settings[name])) { |
|
| 18348 | $.extend(true, settings[name], value); |
|
| 18349 | } |
|
| 18350 | else { |
|
| 18351 | settings[name] = value; |
|
| 18352 | } |
|
| 18353 | } |
|
| 18354 | else { |
|
| 18355 | return settings[name]; |
|
| 18356 | } |
|
| 18357 | }, |
|
| 18358 | internal: function(name, value) { |
|
| 18359 | if( $.isPlainObject(name) ) { |
|
| 18360 | $.extend(true, module, name); |
|
| 18361 | } |
|
| 18362 | else if(value !== undefined) { |
|
| 18363 | module[name] = value; |
|
| 18364 | } |
|
| 18365 | else { |
|
| 18366 | return module[name]; |
|
| 18367 | } |
|
| 18368 | }, |
|
| 18369 | debug: function() { |
|
| 18370 | if(!settings.silent && settings.debug) { |
|
| 18371 | if(settings.performance) { |
|
| 18372 | module.performance.log(arguments); |
|
| 18373 | } |
|
| 18374 | else { |
|
| 18375 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
| 18376 | module.debug.apply(console, arguments); |
|
| 18377 | } |
|
| 18378 | } |
|
| 18379 | }, |
|
| 18380 | verbose: function() { |
|
| 18381 | if(!settings.silent && settings.verbose && settings.debug) { |
|
| 18382 | if(settings.performance) { |
|
| 18383 | module.performance.log(arguments); |
|
| 18384 | } |
|
| 18385 | else { |
|
| 18386 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
| 18387 | module.verbose.apply(console, arguments); |
|
| 18388 | } |
|
| 18389 | } |
|
| 18390 | }, |
|
| 18391 | error: function() { |
|
| 18392 | if(!settings.silent) { |
|
| 18393 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
|
| 18394 | module.error.apply(console, arguments); |
|
| 18395 | } |
|
| 18396 | }, |
|
| 18397 | performance: { |
|
| 18398 | log: function(message) { |
|
| 18399 | var |
|
| 18400 | currentTime, |
|
| 18401 | executionTime, |
|
| 18402 | previousTime |
|
| 18403 | ; |
|
| 18404 | if(settings.performance) { |
|
| 18405 | currentTime = new Date().getTime(); |
|
| 18406 | previousTime = time || currentTime; |
|
| 18407 | executionTime = currentTime - previousTime; |
|
| 18408 | time = currentTime; |
|
| 18409 | performance.push({ |
|
| 18410 | 'Name' : message[0], |
|
| 18411 | 'Arguments' : [].slice.call(message, 1) || '', |
|
| 18412 | 'Element' : element, |
|
| 18413 | 'Execution Time' : executionTime |
|
| 18414 | }); |
|
| 18415 | } |
|
| 18416 | clearTimeout(module.performance.timer); |
|
| 18417 | module.performance.timer = setTimeout(module.performance.display, 500); |
|
| 18418 | }, |
|
| 18419 | display: function() { |
|
| 18420 | var |
|
| 18421 | title = settings.name + ':', |
|
| 18422 | totalTime = 0 |
|
| 18423 | ; |
|
| 18424 | time = false; |
|
| 18425 | clearTimeout(module.performance.timer); |
|
| 18426 | $.each(performance, function(index, data) { |
|
| 18427 | totalTime += data['Execution Time']; |
|
| 18428 | }); |
|
| 18429 | title += ' ' + totalTime + 'ms'; |
|
| 18430 | if(moduleSelector) { |
|
| 18431 | title += ' \'' + moduleSelector + '\''; |
|
| 18432 | } |
|
| 18433 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
|
| 18434 | console.groupCollapsed(title); |
|
| 18435 | if(console.table) { |
|
| 18436 | console.table(performance); |
|
| 18437 | } |
|
| 18438 | else { |
|
| 18439 | $.each(performance, function(index, data) { |
|
| 18440 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
|
| 18441 | }); |
|
| 18442 | } |
|
| 18443 | console.groupEnd(); |
|
| 18444 | } |
|
| 18445 | performance = []; |
|
| 18446 | } |
|
| 18447 | }, |
|
| 18448 | invoke: function(query, passedArguments, context) { |
|
| 18449 | var |
|
| 18450 | object = instance, |
|
| 18451 | maxDepth, |
|
| 18452 | found, |
|
| 18453 | response |
|
| 18454 | ; |
|
| 18455 | passedArguments = passedArguments || queryArguments; |
|
| 18456 | context = element || context; |
|
| 18457 | if(typeof query == 'string' && object !== undefined) { |
|
| 18458 | query = query.split(/[\. ]/); |
|
| 18459 | maxDepth = query.length - 1; |
|
| 18460 | $.each(query, function(depth, value) { |
|
| 18461 | var camelCaseValue = (depth != maxDepth) |
|
| 18462 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
|
| 18463 | : query |
|
| 18464 | ; |
|
| 18465 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
|
| 18466 | object = object[camelCaseValue]; |
|
| 18467 | } |
|
| 18468 | else if( object[camelCaseValue] !== undefined ) { |
|
| 18469 | found = object[camelCaseValue]; |
|
| 18470 | return false; |
|
| 18471 | } |
|
| 18472 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
|
| 18473 | object = object[value]; |
|
| 18474 | } |
|
| 18475 | else if( object[value] !== undefined ) { |
|
| 18476 | found = object[value]; |
|
| 18477 | return false; |
|
| 18478 | } |
|
| 18479 | else { |
|
| 18480 | module.error(error.method, query); |
|
| 18481 | return false; |
|
| 18482 | } |
|
| 18483 | }); |
|
| 18484 | } |
|
| 18485 | if ( $.isFunction( found ) ) { |
|
| 18486 | response = found.apply(context, passedArguments); |
|
| 18487 | } |
|
| 18488 | else if(found !== undefined) { |
|
| 18489 | response = found; |
|
| 18490 | } |
|
| 18491 | if($.isArray(returnedValue)) { |
|
| 18492 | returnedValue.push(response); |
|
| 18493 | } |
|
| 18494 | else if(returnedValue !== undefined) { |
|
| 18495 | returnedValue = [returnedValue, response]; |
|
| 18496 | } |
|
| 18497 | else if(response !== undefined) { |
|
| 18498 | returnedValue = response; |
|
| 18499 | } |
|
| 18500 | return found; |
|
| 18501 | } |
|
| 18502 | }; |
|
| 18503 | if(methodInvoked) { |
|
| 18504 | if(instance === undefined) { |
|
| 18505 | module.initialize(); |
|
| 18506 | } |
|
| 18507 | module.invoke(query); |
|
| 18508 | } |
|
| 18509 | else { |
|
| 18510 | if(instance !== undefined) { |
|
| 18511 | instance.invoke('destroy'); |
|
| 18512 | } |
|
| 18513 | module.initialize(); |
|
| 18514 | } |
|
| 18515 | }) |
|
| 18516 | ; |
|
| 18517 | return (returnedValue !== undefined) |
|
| 18518 | ? returnedValue |
|
| 18519 | : this |
|
| 18520 | ; |
|
| 18521 | ||
| 18522 | }; |
|
| 18523 | ||
| 18524 | // shortcut for tabbed content with no defined navigation |
|
| 18525 | $.tab = function() { |
|
| 18526 | $(window).tab.apply(this, arguments); |
|
| 18527 | }; |
|
| 18528 | ||
| 18529 | $.fn.tab.settings = { |
|
| 18530 | ||
| 18531 | name : 'Tab', |
|
| 18532 | namespace : 'tab', |
|
| 18533 | ||
| 18534 | silent : false, |
|
| 18535 | debug : false, |
|
| 18536 | verbose : false, |
|
| 18537 | performance : true, |
|
| 18538 | ||
| 18539 | auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers |
|
| 18540 | history : false, // use browser history |
|
| 18541 | historyType : 'hash', // #/ or html5 state |
|
| 18542 | path : false, // base path of url |
|
| 18543 | ||
| 18544 | context : false, // specify a context that tabs must appear inside |
|
| 18545 | childrenOnly : false, // use only tabs that are children of context |
|
| 18546 | maxDepth : 25, // max depth a tab can be nested |
|
| 18547 | ||
| 18548 | deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together |
|
| 18549 | ||
| 18550 | alwaysRefresh : false, // load tab content new every tab click |
|
| 18551 | cache : true, // cache the content requests to pull locally |
|
| 18552 | loadOnce : false, // Whether tab data should only be loaded once when using remote content |
|
| 18553 | cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute |
|
| 18554 | ignoreFirstLoad : false, // don't load remote content on first load |
|
| 18555 | ||
| 18556 | apiSettings : false, // settings for api call |
|
| 18557 | evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content |
|
| 18558 | ||
| 18559 | onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded |
|
| 18560 | onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load |
|
| 18561 | onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible |
|
| 18562 | onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content |
|
| 18563 | ||
| 18564 | templates : { |
|
| 18565 | determineTitle: function(tabArray) {} // returns page title for path |
|
| 18566 | }, |
|
| 18567 | ||
| 18568 | error: { |
|
| 18569 | api : 'You attempted to load content without API module', |
|
| 18570 | method : 'The method you called is not defined', |
|
| 18571 | missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.', |
|
| 18572 | noContent : 'The tab you specified is missing a content url.', |
|
| 18573 | path : 'History enabled, but no path was specified', |
|
| 18574 | recursion : 'Max recursive depth reached', |
|
| 18575 | legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.', |
|
| 18576 | legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code', |
|
| 18577 | state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>' |
|
| 18578 | }, |
|
| 18579 | ||
| 18580 | metadata : { |
|
| 18581 | tab : 'tab', |
|
| 18582 | loaded : 'loaded', |
|
| 18583 | promise: 'promise' |
|
| 18584 | }, |
|
| 18585 | ||
| 18586 | className : { |
|
| 18587 | loading : 'loading', |
|
| 18588 | active : 'active' |
|
| 18589 | }, |
|
| 18590 | ||
| 18591 | selector : { |
|
| 18592 | tabs : '.ui.tab', |
|
| 18593 | ui : '.ui' |
|
| 18594 | } |
|
| 18595 | ||
| 18596 | }; |
|
| 18597 | ||
| 18598 | })( jQuery, window, document ); |
|
| 18599 | ||
| 18600 | /*! |
|
| 18601 | * # Semantic UI 2.2.11 - Transition |
|
| @@ 11-952 (lines=942) @@ | ||
| 8 | * |
|
| 9 | */ |
|
| 10 | ||
| 11 | ;(function ($, window, document, undefined) { |
|
| 12 | ||
| 13 | "use strict"; |
|
| 14 | ||
| 15 | window = (typeof window != 'undefined' && window.Math == Math) |
|
| 16 | ? window |
|
| 17 | : (typeof self != 'undefined' && self.Math == Math) |
|
| 18 | ? self |
|
| 19 | : Function('return this')() |
|
| 20 | ; |
|
| 21 | ||
| 22 | $.fn.tab = function(parameters) { |
|
| 23 | ||
| 24 | var |
|
| 25 | // use window context if none specified |
|
| 26 | $allModules = $.isFunction(this) |
|
| 27 | ? $(window) |
|
| 28 | : $(this), |
|
| 29 | ||
| 30 | moduleSelector = $allModules.selector || '', |
|
| 31 | time = new Date().getTime(), |
|
| 32 | performance = [], |
|
| 33 | ||
| 34 | query = arguments[0], |
|
| 35 | methodInvoked = (typeof query == 'string'), |
|
| 36 | queryArguments = [].slice.call(arguments, 1), |
|
| 37 | ||
| 38 | initializedHistory = false, |
|
| 39 | returnedValue |
|
| 40 | ; |
|
| 41 | ||
| 42 | $allModules |
|
| 43 | .each(function() { |
|
| 44 | var |
|
| 45 | ||
| 46 | settings = ( $.isPlainObject(parameters) ) |
|
| 47 | ? $.extend(true, {}, $.fn.tab.settings, parameters) |
|
| 48 | : $.extend({}, $.fn.tab.settings), |
|
| 49 | ||
| 50 | className = settings.className, |
|
| 51 | metadata = settings.metadata, |
|
| 52 | selector = settings.selector, |
|
| 53 | error = settings.error, |
|
| 54 | ||
| 55 | eventNamespace = '.' + settings.namespace, |
|
| 56 | moduleNamespace = 'module-' + settings.namespace, |
|
| 57 | ||
| 58 | $module = $(this), |
|
| 59 | $context, |
|
| 60 | $tabs, |
|
| 61 | ||
| 62 | cache = {}, |
|
| 63 | firstLoad = true, |
|
| 64 | recursionDepth = 0, |
|
| 65 | element = this, |
|
| 66 | instance = $module.data(moduleNamespace), |
|
| 67 | ||
| 68 | activeTabPath, |
|
| 69 | parameterArray, |
|
| 70 | module, |
|
| 71 | ||
| 72 | historyEvent |
|
| 73 | ||
| 74 | ; |
|
| 75 | ||
| 76 | module = { |
|
| 77 | ||
| 78 | initialize: function() { |
|
| 79 | module.debug('Initializing tab menu item', $module); |
|
| 80 | module.fix.callbacks(); |
|
| 81 | module.determineTabs(); |
|
| 82 | ||
| 83 | module.debug('Determining tabs', settings.context, $tabs); |
|
| 84 | // set up automatic routing |
|
| 85 | if(settings.auto) { |
|
| 86 | module.set.auto(); |
|
| 87 | } |
|
| 88 | module.bind.events(); |
|
| 89 | ||
| 90 | if(settings.history && !initializedHistory) { |
|
| 91 | module.initializeHistory(); |
|
| 92 | initializedHistory = true; |
|
| 93 | } |
|
| 94 | ||
| 95 | module.instantiate(); |
|
| 96 | }, |
|
| 97 | ||
| 98 | instantiate: function () { |
|
| 99 | module.verbose('Storing instance of module', module); |
|
| 100 | instance = module; |
|
| 101 | $module |
|
| 102 | .data(moduleNamespace, module) |
|
| 103 | ; |
|
| 104 | }, |
|
| 105 | ||
| 106 | destroy: function() { |
|
| 107 | module.debug('Destroying tabs', $module); |
|
| 108 | $module |
|
| 109 | .removeData(moduleNamespace) |
|
| 110 | .off(eventNamespace) |
|
| 111 | ; |
|
| 112 | }, |
|
| 113 | ||
| 114 | bind: { |
|
| 115 | events: function() { |
|
| 116 | // if using $.tab don't add events |
|
| 117 | if( !$.isWindow( element ) ) { |
|
| 118 | module.debug('Attaching tab activation events to element', $module); |
|
| 119 | $module |
|
| 120 | .on('click' + eventNamespace, module.event.click) |
|
| 121 | ; |
|
| 122 | } |
|
| 123 | } |
|
| 124 | }, |
|
| 125 | ||
| 126 | determineTabs: function() { |
|
| 127 | var |
|
| 128 | $reference |
|
| 129 | ; |
|
| 130 | ||
| 131 | // determine tab context |
|
| 132 | if(settings.context === 'parent') { |
|
| 133 | if($module.closest(selector.ui).length > 0) { |
|
| 134 | $reference = $module.closest(selector.ui); |
|
| 135 | module.verbose('Using closest UI element as parent', $reference); |
|
| 136 | } |
|
| 137 | else { |
|
| 138 | $reference = $module; |
|
| 139 | } |
|
| 140 | $context = $reference.parent(); |
|
| 141 | module.verbose('Determined parent element for creating context', $context); |
|
| 142 | } |
|
| 143 | else if(settings.context) { |
|
| 144 | $context = $(settings.context); |
|
| 145 | module.verbose('Using selector for tab context', settings.context, $context); |
|
| 146 | } |
|
| 147 | else { |
|
| 148 | $context = $('body'); |
|
| 149 | } |
|
| 150 | // find tabs |
|
| 151 | if(settings.childrenOnly) { |
|
| 152 | $tabs = $context.children(selector.tabs); |
|
| 153 | module.debug('Searching tab context children for tabs', $context, $tabs); |
|
| 154 | } |
|
| 155 | else { |
|
| 156 | $tabs = $context.find(selector.tabs); |
|
| 157 | module.debug('Searching tab context for tabs', $context, $tabs); |
|
| 158 | } |
|
| 159 | }, |
|
| 160 | ||
| 161 | fix: { |
|
| 162 | callbacks: function() { |
|
| 163 | if( $.isPlainObject(parameters) && (parameters.onTabLoad || parameters.onTabInit) ) { |
|
| 164 | if(parameters.onTabLoad) { |
|
| 165 | parameters.onLoad = parameters.onTabLoad; |
|
| 166 | delete parameters.onTabLoad; |
|
| 167 | module.error(error.legacyLoad, parameters.onLoad); |
|
| 168 | } |
|
| 169 | if(parameters.onTabInit) { |
|
| 170 | parameters.onFirstLoad = parameters.onTabInit; |
|
| 171 | delete parameters.onTabInit; |
|
| 172 | module.error(error.legacyInit, parameters.onFirstLoad); |
|
| 173 | } |
|
| 174 | settings = $.extend(true, {}, $.fn.tab.settings, parameters); |
|
| 175 | } |
|
| 176 | } |
|
| 177 | }, |
|
| 178 | ||
| 179 | initializeHistory: function() { |
|
| 180 | module.debug('Initializing page state'); |
|
| 181 | if( $.address === undefined ) { |
|
| 182 | module.error(error.state); |
|
| 183 | return false; |
|
| 184 | } |
|
| 185 | else { |
|
| 186 | if(settings.historyType == 'state') { |
|
| 187 | module.debug('Using HTML5 to manage state'); |
|
| 188 | if(settings.path !== false) { |
|
| 189 | $.address |
|
| 190 | .history(true) |
|
| 191 | .state(settings.path) |
|
| 192 | ; |
|
| 193 | } |
|
| 194 | else { |
|
| 195 | module.error(error.path); |
|
| 196 | return false; |
|
| 197 | } |
|
| 198 | } |
|
| 199 | $.address |
|
| 200 | .bind('change', module.event.history.change) |
|
| 201 | ; |
|
| 202 | } |
|
| 203 | }, |
|
| 204 | ||
| 205 | event: { |
|
| 206 | click: function(event) { |
|
| 207 | var |
|
| 208 | tabPath = $(this).data(metadata.tab) |
|
| 209 | ; |
|
| 210 | if(tabPath !== undefined) { |
|
| 211 | if(settings.history) { |
|
| 212 | module.verbose('Updating page state', event); |
|
| 213 | $.address.value(tabPath); |
|
| 214 | } |
|
| 215 | else { |
|
| 216 | module.verbose('Changing tab', event); |
|
| 217 | module.changeTab(tabPath); |
|
| 218 | } |
|
| 219 | event.preventDefault(); |
|
| 220 | } |
|
| 221 | else { |
|
| 222 | module.debug('No tab specified'); |
|
| 223 | } |
|
| 224 | }, |
|
| 225 | history: { |
|
| 226 | change: function(event) { |
|
| 227 | var |
|
| 228 | tabPath = event.pathNames.join('/') || module.get.initialPath(), |
|
| 229 | pageTitle = settings.templates.determineTitle(tabPath) || false |
|
| 230 | ; |
|
| 231 | module.performance.display(); |
|
| 232 | module.debug('History change event', tabPath, event); |
|
| 233 | historyEvent = event; |
|
| 234 | if(tabPath !== undefined) { |
|
| 235 | module.changeTab(tabPath); |
|
| 236 | } |
|
| 237 | if(pageTitle) { |
|
| 238 | $.address.title(pageTitle); |
|
| 239 | } |
|
| 240 | } |
|
| 241 | } |
|
| 242 | }, |
|
| 243 | ||
| 244 | refresh: function() { |
|
| 245 | if(activeTabPath) { |
|
| 246 | module.debug('Refreshing tab', activeTabPath); |
|
| 247 | module.changeTab(activeTabPath); |
|
| 248 | } |
|
| 249 | }, |
|
| 250 | ||
| 251 | cache: { |
|
| 252 | ||
| 253 | read: function(cacheKey) { |
|
| 254 | return (cacheKey !== undefined) |
|
| 255 | ? cache[cacheKey] |
|
| 256 | : false |
|
| 257 | ; |
|
| 258 | }, |
|
| 259 | add: function(cacheKey, content) { |
|
| 260 | cacheKey = cacheKey || activeTabPath; |
|
| 261 | module.debug('Adding cached content for', cacheKey); |
|
| 262 | cache[cacheKey] = content; |
|
| 263 | }, |
|
| 264 | remove: function(cacheKey) { |
|
| 265 | cacheKey = cacheKey || activeTabPath; |
|
| 266 | module.debug('Removing cached content for', cacheKey); |
|
| 267 | delete cache[cacheKey]; |
|
| 268 | } |
|
| 269 | }, |
|
| 270 | ||
| 271 | set: { |
|
| 272 | auto: function() { |
|
| 273 | var |
|
| 274 | url = (typeof settings.path == 'string') |
|
| 275 | ? settings.path.replace(/\/$/, '') + '/{$tab}' |
|
| 276 | : '/{$tab}' |
|
| 277 | ; |
|
| 278 | module.verbose('Setting up automatic tab retrieval from server', url); |
|
| 279 | if($.isPlainObject(settings.apiSettings)) { |
|
| 280 | settings.apiSettings.url = url; |
|
| 281 | } |
|
| 282 | else { |
|
| 283 | settings.apiSettings = { |
|
| 284 | url: url |
|
| 285 | }; |
|
| 286 | } |
|
| 287 | }, |
|
| 288 | loading: function(tabPath) { |
|
| 289 | var |
|
| 290 | $tab = module.get.tabElement(tabPath), |
|
| 291 | isLoading = $tab.hasClass(className.loading) |
|
| 292 | ; |
|
| 293 | if(!isLoading) { |
|
| 294 | module.verbose('Setting loading state for', $tab); |
|
| 295 | $tab |
|
| 296 | .addClass(className.loading) |
|
| 297 | .siblings($tabs) |
|
| 298 | .removeClass(className.active + ' ' + className.loading) |
|
| 299 | ; |
|
| 300 | if($tab.length > 0) { |
|
| 301 | settings.onRequest.call($tab[0], tabPath); |
|
| 302 | } |
|
| 303 | } |
|
| 304 | }, |
|
| 305 | state: function(state) { |
|
| 306 | $.address.value(state); |
|
| 307 | } |
|
| 308 | }, |
|
| 309 | ||
| 310 | changeTab: function(tabPath) { |
|
| 311 | var |
|
| 312 | pushStateAvailable = (window.history && window.history.pushState), |
|
| 313 | shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad), |
|
| 314 | remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ), |
|
| 315 | // only add default path if not remote content |
|
| 316 | pathArray = (remoteContent && !shouldIgnoreLoad) |
|
| 317 | ? module.utilities.pathToArray(tabPath) |
|
| 318 | : module.get.defaultPathArray(tabPath) |
|
| 319 | ; |
|
| 320 | tabPath = module.utilities.arrayToPath(pathArray); |
|
| 321 | $.each(pathArray, function(index, tab) { |
|
| 322 | var |
|
| 323 | currentPathArray = pathArray.slice(0, index + 1), |
|
| 324 | currentPath = module.utilities.arrayToPath(currentPathArray), |
|
| 325 | ||
| 326 | isTab = module.is.tab(currentPath), |
|
| 327 | isLastIndex = (index + 1 == pathArray.length), |
|
| 328 | ||
| 329 | $tab = module.get.tabElement(currentPath), |
|
| 330 | $anchor, |
|
| 331 | nextPathArray, |
|
| 332 | nextPath, |
|
| 333 | isLastTab |
|
| 334 | ; |
|
| 335 | module.verbose('Looking for tab', tab); |
|
| 336 | if(isTab) { |
|
| 337 | module.verbose('Tab was found', tab); |
|
| 338 | // scope up |
|
| 339 | activeTabPath = currentPath; |
|
| 340 | parameterArray = module.utilities.filterArray(pathArray, currentPathArray); |
|
| 341 | ||
| 342 | if(isLastIndex) { |
|
| 343 | isLastTab = true; |
|
| 344 | } |
|
| 345 | else { |
|
| 346 | nextPathArray = pathArray.slice(0, index + 2); |
|
| 347 | nextPath = module.utilities.arrayToPath(nextPathArray); |
|
| 348 | isLastTab = ( !module.is.tab(nextPath) ); |
|
| 349 | if(isLastTab) { |
|
| 350 | module.verbose('Tab parameters found', nextPathArray); |
|
| 351 | } |
|
| 352 | } |
|
| 353 | if(isLastTab && remoteContent) { |
|
| 354 | if(!shouldIgnoreLoad) { |
|
| 355 | module.activate.navigation(currentPath); |
|
| 356 | module.fetch.content(currentPath, tabPath); |
|
| 357 | } |
|
| 358 | else { |
|
| 359 | module.debug('Ignoring remote content on first tab load', currentPath); |
|
| 360 | firstLoad = false; |
|
| 361 | module.cache.add(tabPath, $tab.html()); |
|
| 362 | module.activate.all(currentPath); |
|
| 363 | settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 364 | settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 365 | } |
|
| 366 | return false; |
|
| 367 | } |
|
| 368 | else { |
|
| 369 | module.debug('Opened local tab', currentPath); |
|
| 370 | module.activate.all(currentPath); |
|
| 371 | if( !module.cache.read(currentPath) ) { |
|
| 372 | module.cache.add(currentPath, true); |
|
| 373 | module.debug('First time tab loaded calling tab init'); |
|
| 374 | settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 375 | } |
|
| 376 | settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 377 | } |
|
| 378 | ||
| 379 | } |
|
| 380 | else if(tabPath.search('/') == -1 && tabPath !== '') { |
|
| 381 | // look for in page anchor |
|
| 382 | $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]'); |
|
| 383 | currentPath = $anchor.closest('[data-tab]').data(metadata.tab); |
|
| 384 | $tab = module.get.tabElement(currentPath); |
|
| 385 | // if anchor exists use parent tab |
|
| 386 | if($anchor && $anchor.length > 0 && currentPath) { |
|
| 387 | module.debug('Anchor link used, opening parent tab', $tab, $anchor); |
|
| 388 | if( !$tab.hasClass(className.active) ) { |
|
| 389 | setTimeout(function() { |
|
| 390 | module.scrollTo($anchor); |
|
| 391 | }, 0); |
|
| 392 | } |
|
| 393 | module.activate.all(currentPath); |
|
| 394 | if( !module.cache.read(currentPath) ) { |
|
| 395 | module.cache.add(currentPath, true); |
|
| 396 | module.debug('First time tab loaded calling tab init'); |
|
| 397 | settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 398 | } |
|
| 399 | settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent); |
|
| 400 | return false; |
|
| 401 | } |
|
| 402 | } |
|
| 403 | else { |
|
| 404 | module.error(error.missingTab, $module, $context, currentPath); |
|
| 405 | return false; |
|
| 406 | } |
|
| 407 | }); |
|
| 408 | }, |
|
| 409 | ||
| 410 | scrollTo: function($element) { |
|
| 411 | var |
|
| 412 | scrollOffset = ($element && $element.length > 0) |
|
| 413 | ? $element.offset().top |
|
| 414 | : false |
|
| 415 | ; |
|
| 416 | if(scrollOffset !== false) { |
|
| 417 | module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element); |
|
| 418 | $(document).scrollTop(scrollOffset); |
|
| 419 | } |
|
| 420 | }, |
|
| 421 | ||
| 422 | update: { |
|
| 423 | content: function(tabPath, html, evaluateScripts) { |
|
| 424 | var |
|
| 425 | $tab = module.get.tabElement(tabPath), |
|
| 426 | tab = $tab[0] |
|
| 427 | ; |
|
| 428 | evaluateScripts = (evaluateScripts !== undefined) |
|
| 429 | ? evaluateScripts |
|
| 430 | : settings.evaluateScripts |
|
| 431 | ; |
|
| 432 | if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && typeof html !== 'string') { |
|
| 433 | $tab |
|
| 434 | .empty() |
|
| 435 | .append($(html).clone(true)) |
|
| 436 | ; |
|
| 437 | } |
|
| 438 | else { |
|
| 439 | if(evaluateScripts) { |
|
| 440 | module.debug('Updating HTML and evaluating inline scripts', tabPath, html); |
|
| 441 | $tab.html(html); |
|
| 442 | } |
|
| 443 | else { |
|
| 444 | module.debug('Updating HTML', tabPath, html); |
|
| 445 | tab.innerHTML = html; |
|
| 446 | } |
|
| 447 | } |
|
| 448 | } |
|
| 449 | }, |
|
| 450 | ||
| 451 | fetch: { |
|
| 452 | ||
| 453 | content: function(tabPath, fullTabPath) { |
|
| 454 | var |
|
| 455 | $tab = module.get.tabElement(tabPath), |
|
| 456 | apiSettings = { |
|
| 457 | dataType : 'html', |
|
| 458 | encodeParameters : false, |
|
| 459 | on : 'now', |
|
| 460 | cache : settings.alwaysRefresh, |
|
| 461 | headers : { |
|
| 462 | 'X-Remote': true |
|
| 463 | }, |
|
| 464 | onSuccess : function(response) { |
|
| 465 | if(settings.cacheType == 'response') { |
|
| 466 | module.cache.add(fullTabPath, response); |
|
| 467 | } |
|
| 468 | module.update.content(tabPath, response); |
|
| 469 | if(tabPath == activeTabPath) { |
|
| 470 | module.debug('Content loaded', tabPath); |
|
| 471 | module.activate.tab(tabPath); |
|
| 472 | } |
|
| 473 | else { |
|
| 474 | module.debug('Content loaded in background', tabPath); |
|
| 475 | } |
|
| 476 | settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent); |
|
| 477 | settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent); |
|
| 478 | ||
| 479 | if(settings.loadOnce) { |
|
| 480 | module.cache.add(fullTabPath, true); |
|
| 481 | } |
|
| 482 | else if(typeof settings.cacheType == 'string' && settings.cacheType.toLowerCase() == 'dom' && $tab.children().length > 0) { |
|
| 483 | setTimeout(function() { |
|
| 484 | var |
|
| 485 | $clone = $tab.children().clone(true) |
|
| 486 | ; |
|
| 487 | $clone = $clone.not('script'); |
|
| 488 | module.cache.add(fullTabPath, $clone); |
|
| 489 | }, 0); |
|
| 490 | } |
|
| 491 | else { |
|
| 492 | module.cache.add(fullTabPath, $tab.html()); |
|
| 493 | } |
|
| 494 | }, |
|
| 495 | urlData: { |
|
| 496 | tab: fullTabPath |
|
| 497 | } |
|
| 498 | }, |
|
| 499 | request = $tab.api('get request') || false, |
|
| 500 | existingRequest = ( request && request.state() === 'pending' ), |
|
| 501 | requestSettings, |
|
| 502 | cachedContent |
|
| 503 | ; |
|
| 504 | ||
| 505 | fullTabPath = fullTabPath || tabPath; |
|
| 506 | cachedContent = module.cache.read(fullTabPath); |
|
| 507 | ||
| 508 | ||
| 509 | if(settings.cache && cachedContent) { |
|
| 510 | module.activate.tab(tabPath); |
|
| 511 | module.debug('Adding cached content', fullTabPath); |
|
| 512 | if(!settings.loadOnce) { |
|
| 513 | if(settings.evaluateScripts == 'once') { |
|
| 514 | module.update.content(tabPath, cachedContent, false); |
|
| 515 | } |
|
| 516 | else { |
|
| 517 | module.update.content(tabPath, cachedContent); |
|
| 518 | } |
|
| 519 | } |
|
| 520 | settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent); |
|
| 521 | } |
|
| 522 | else if(existingRequest) { |
|
| 523 | module.set.loading(tabPath); |
|
| 524 | module.debug('Content is already loading', fullTabPath); |
|
| 525 | } |
|
| 526 | else if($.api !== undefined) { |
|
| 527 | requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings); |
|
| 528 | module.debug('Retrieving remote content', fullTabPath, requestSettings); |
|
| 529 | module.set.loading(tabPath); |
|
| 530 | $tab.api(requestSettings); |
|
| 531 | } |
|
| 532 | else { |
|
| 533 | module.error(error.api); |
|
| 534 | } |
|
| 535 | } |
|
| 536 | }, |
|
| 537 | ||
| 538 | activate: { |
|
| 539 | all: function(tabPath) { |
|
| 540 | module.activate.tab(tabPath); |
|
| 541 | module.activate.navigation(tabPath); |
|
| 542 | }, |
|
| 543 | tab: function(tabPath) { |
|
| 544 | var |
|
| 545 | $tab = module.get.tabElement(tabPath), |
|
| 546 | $deactiveTabs = (settings.deactivate == 'siblings') |
|
| 547 | ? $tab.siblings($tabs) |
|
| 548 | : $tabs.not($tab), |
|
| 549 | isActive = $tab.hasClass(className.active) |
|
| 550 | ; |
|
| 551 | module.verbose('Showing tab content for', $tab); |
|
| 552 | if(!isActive) { |
|
| 553 | $tab |
|
| 554 | .addClass(className.active) |
|
| 555 | ; |
|
| 556 | $deactiveTabs |
|
| 557 | .removeClass(className.active + ' ' + className.loading) |
|
| 558 | ; |
|
| 559 | if($tab.length > 0) { |
|
| 560 | settings.onVisible.call($tab[0], tabPath); |
|
| 561 | } |
|
| 562 | } |
|
| 563 | }, |
|
| 564 | navigation: function(tabPath) { |
|
| 565 | var |
|
| 566 | $navigation = module.get.navElement(tabPath), |
|
| 567 | $deactiveNavigation = (settings.deactivate == 'siblings') |
|
| 568 | ? $navigation.siblings($allModules) |
|
| 569 | : $allModules.not($navigation), |
|
| 570 | isActive = $navigation.hasClass(className.active) |
|
| 571 | ; |
|
| 572 | module.verbose('Activating tab navigation for', $navigation, tabPath); |
|
| 573 | if(!isActive) { |
|
| 574 | $navigation |
|
| 575 | .addClass(className.active) |
|
| 576 | ; |
|
| 577 | $deactiveNavigation |
|
| 578 | .removeClass(className.active + ' ' + className.loading) |
|
| 579 | ; |
|
| 580 | } |
|
| 581 | } |
|
| 582 | }, |
|
| 583 | ||
| 584 | deactivate: { |
|
| 585 | all: function() { |
|
| 586 | module.deactivate.navigation(); |
|
| 587 | module.deactivate.tabs(); |
|
| 588 | }, |
|
| 589 | navigation: function() { |
|
| 590 | $allModules |
|
| 591 | .removeClass(className.active) |
|
| 592 | ; |
|
| 593 | }, |
|
| 594 | tabs: function() { |
|
| 595 | $tabs |
|
| 596 | .removeClass(className.active + ' ' + className.loading) |
|
| 597 | ; |
|
| 598 | } |
|
| 599 | }, |
|
| 600 | ||
| 601 | is: { |
|
| 602 | tab: function(tabName) { |
|
| 603 | return (tabName !== undefined) |
|
| 604 | ? ( module.get.tabElement(tabName).length > 0 ) |
|
| 605 | : false |
|
| 606 | ; |
|
| 607 | } |
|
| 608 | }, |
|
| 609 | ||
| 610 | get: { |
|
| 611 | initialPath: function() { |
|
| 612 | return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab); |
|
| 613 | }, |
|
| 614 | path: function() { |
|
| 615 | return $.address.value(); |
|
| 616 | }, |
|
| 617 | // adds default tabs to tab path |
|
| 618 | defaultPathArray: function(tabPath) { |
|
| 619 | return module.utilities.pathToArray( module.get.defaultPath(tabPath) ); |
|
| 620 | }, |
|
| 621 | defaultPath: function(tabPath) { |
|
| 622 | var |
|
| 623 | $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0), |
|
| 624 | defaultTab = $defaultNav.data(metadata.tab) || false |
|
| 625 | ; |
|
| 626 | if( defaultTab ) { |
|
| 627 | module.debug('Found default tab', defaultTab); |
|
| 628 | if(recursionDepth < settings.maxDepth) { |
|
| 629 | recursionDepth++; |
|
| 630 | return module.get.defaultPath(defaultTab); |
|
| 631 | } |
|
| 632 | module.error(error.recursion); |
|
| 633 | } |
|
| 634 | else { |
|
| 635 | module.debug('No default tabs found for', tabPath, $tabs); |
|
| 636 | } |
|
| 637 | recursionDepth = 0; |
|
| 638 | return tabPath; |
|
| 639 | }, |
|
| 640 | navElement: function(tabPath) { |
|
| 641 | tabPath = tabPath || activeTabPath; |
|
| 642 | return $allModules.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); |
|
| 643 | }, |
|
| 644 | tabElement: function(tabPath) { |
|
| 645 | var |
|
| 646 | $fullPathTab, |
|
| 647 | $simplePathTab, |
|
| 648 | tabPathArray, |
|
| 649 | lastTab |
|
| 650 | ; |
|
| 651 | tabPath = tabPath || activeTabPath; |
|
| 652 | tabPathArray = module.utilities.pathToArray(tabPath); |
|
| 653 | lastTab = module.utilities.last(tabPathArray); |
|
| 654 | $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); |
|
| 655 | $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]'); |
|
| 656 | return ($fullPathTab.length > 0) |
|
| 657 | ? $fullPathTab |
|
| 658 | : $simplePathTab |
|
| 659 | ; |
|
| 660 | }, |
|
| 661 | tab: function() { |
|
| 662 | return activeTabPath; |
|
| 663 | } |
|
| 664 | }, |
|
| 665 | ||
| 666 | utilities: { |
|
| 667 | filterArray: function(keepArray, removeArray) { |
|
| 668 | return $.grep(keepArray, function(keepValue) { |
|
| 669 | return ( $.inArray(keepValue, removeArray) == -1); |
|
| 670 | }); |
|
| 671 | }, |
|
| 672 | last: function(array) { |
|
| 673 | return $.isArray(array) |
|
| 674 | ? array[ array.length - 1] |
|
| 675 | : false |
|
| 676 | ; |
|
| 677 | }, |
|
| 678 | pathToArray: function(pathName) { |
|
| 679 | if(pathName === undefined) { |
|
| 680 | pathName = activeTabPath; |
|
| 681 | } |
|
| 682 | return typeof pathName == 'string' |
|
| 683 | ? pathName.split('/') |
|
| 684 | : [pathName] |
|
| 685 | ; |
|
| 686 | }, |
|
| 687 | arrayToPath: function(pathArray) { |
|
| 688 | return $.isArray(pathArray) |
|
| 689 | ? pathArray.join('/') |
|
| 690 | : false |
|
| 691 | ; |
|
| 692 | } |
|
| 693 | }, |
|
| 694 | ||
| 695 | setting: function(name, value) { |
|
| 696 | module.debug('Changing setting', name, value); |
|
| 697 | if( $.isPlainObject(name) ) { |
|
| 698 | $.extend(true, settings, name); |
|
| 699 | } |
|
| 700 | else if(value !== undefined) { |
|
| 701 | if($.isPlainObject(settings[name])) { |
|
| 702 | $.extend(true, settings[name], value); |
|
| 703 | } |
|
| 704 | else { |
|
| 705 | settings[name] = value; |
|
| 706 | } |
|
| 707 | } |
|
| 708 | else { |
|
| 709 | return settings[name]; |
|
| 710 | } |
|
| 711 | }, |
|
| 712 | internal: function(name, value) { |
|
| 713 | if( $.isPlainObject(name) ) { |
|
| 714 | $.extend(true, module, name); |
|
| 715 | } |
|
| 716 | else if(value !== undefined) { |
|
| 717 | module[name] = value; |
|
| 718 | } |
|
| 719 | else { |
|
| 720 | return module[name]; |
|
| 721 | } |
|
| 722 | }, |
|
| 723 | debug: function() { |
|
| 724 | if(!settings.silent && settings.debug) { |
|
| 725 | if(settings.performance) { |
|
| 726 | module.performance.log(arguments); |
|
| 727 | } |
|
| 728 | else { |
|
| 729 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
| 730 | module.debug.apply(console, arguments); |
|
| 731 | } |
|
| 732 | } |
|
| 733 | }, |
|
| 734 | verbose: function() { |
|
| 735 | if(!settings.silent && settings.verbose && settings.debug) { |
|
| 736 | if(settings.performance) { |
|
| 737 | module.performance.log(arguments); |
|
| 738 | } |
|
| 739 | else { |
|
| 740 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
| 741 | module.verbose.apply(console, arguments); |
|
| 742 | } |
|
| 743 | } |
|
| 744 | }, |
|
| 745 | error: function() { |
|
| 746 | if(!settings.silent) { |
|
| 747 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
|
| 748 | module.error.apply(console, arguments); |
|
| 749 | } |
|
| 750 | }, |
|
| 751 | performance: { |
|
| 752 | log: function(message) { |
|
| 753 | var |
|
| 754 | currentTime, |
|
| 755 | executionTime, |
|
| 756 | previousTime |
|
| 757 | ; |
|
| 758 | if(settings.performance) { |
|
| 759 | currentTime = new Date().getTime(); |
|
| 760 | previousTime = time || currentTime; |
|
| 761 | executionTime = currentTime - previousTime; |
|
| 762 | time = currentTime; |
|
| 763 | performance.push({ |
|
| 764 | 'Name' : message[0], |
|
| 765 | 'Arguments' : [].slice.call(message, 1) || '', |
|
| 766 | 'Element' : element, |
|
| 767 | 'Execution Time' : executionTime |
|
| 768 | }); |
|
| 769 | } |
|
| 770 | clearTimeout(module.performance.timer); |
|
| 771 | module.performance.timer = setTimeout(module.performance.display, 500); |
|
| 772 | }, |
|
| 773 | display: function() { |
|
| 774 | var |
|
| 775 | title = settings.name + ':', |
|
| 776 | totalTime = 0 |
|
| 777 | ; |
|
| 778 | time = false; |
|
| 779 | clearTimeout(module.performance.timer); |
|
| 780 | $.each(performance, function(index, data) { |
|
| 781 | totalTime += data['Execution Time']; |
|
| 782 | }); |
|
| 783 | title += ' ' + totalTime + 'ms'; |
|
| 784 | if(moduleSelector) { |
|
| 785 | title += ' \'' + moduleSelector + '\''; |
|
| 786 | } |
|
| 787 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
|
| 788 | console.groupCollapsed(title); |
|
| 789 | if(console.table) { |
|
| 790 | console.table(performance); |
|
| 791 | } |
|
| 792 | else { |
|
| 793 | $.each(performance, function(index, data) { |
|
| 794 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
|
| 795 | }); |
|
| 796 | } |
|
| 797 | console.groupEnd(); |
|
| 798 | } |
|
| 799 | performance = []; |
|
| 800 | } |
|
| 801 | }, |
|
| 802 | invoke: function(query, passedArguments, context) { |
|
| 803 | var |
|
| 804 | object = instance, |
|
| 805 | maxDepth, |
|
| 806 | found, |
|
| 807 | response |
|
| 808 | ; |
|
| 809 | passedArguments = passedArguments || queryArguments; |
|
| 810 | context = element || context; |
|
| 811 | if(typeof query == 'string' && object !== undefined) { |
|
| 812 | query = query.split(/[\. ]/); |
|
| 813 | maxDepth = query.length - 1; |
|
| 814 | $.each(query, function(depth, value) { |
|
| 815 | var camelCaseValue = (depth != maxDepth) |
|
| 816 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
|
| 817 | : query |
|
| 818 | ; |
|
| 819 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
|
| 820 | object = object[camelCaseValue]; |
|
| 821 | } |
|
| 822 | else if( object[camelCaseValue] !== undefined ) { |
|
| 823 | found = object[camelCaseValue]; |
|
| 824 | return false; |
|
| 825 | } |
|
| 826 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
|
| 827 | object = object[value]; |
|
| 828 | } |
|
| 829 | else if( object[value] !== undefined ) { |
|
| 830 | found = object[value]; |
|
| 831 | return false; |
|
| 832 | } |
|
| 833 | else { |
|
| 834 | module.error(error.method, query); |
|
| 835 | return false; |
|
| 836 | } |
|
| 837 | }); |
|
| 838 | } |
|
| 839 | if ( $.isFunction( found ) ) { |
|
| 840 | response = found.apply(context, passedArguments); |
|
| 841 | } |
|
| 842 | else if(found !== undefined) { |
|
| 843 | response = found; |
|
| 844 | } |
|
| 845 | if($.isArray(returnedValue)) { |
|
| 846 | returnedValue.push(response); |
|
| 847 | } |
|
| 848 | else if(returnedValue !== undefined) { |
|
| 849 | returnedValue = [returnedValue, response]; |
|
| 850 | } |
|
| 851 | else if(response !== undefined) { |
|
| 852 | returnedValue = response; |
|
| 853 | } |
|
| 854 | return found; |
|
| 855 | } |
|
| 856 | }; |
|
| 857 | if(methodInvoked) { |
|
| 858 | if(instance === undefined) { |
|
| 859 | module.initialize(); |
|
| 860 | } |
|
| 861 | module.invoke(query); |
|
| 862 | } |
|
| 863 | else { |
|
| 864 | if(instance !== undefined) { |
|
| 865 | instance.invoke('destroy'); |
|
| 866 | } |
|
| 867 | module.initialize(); |
|
| 868 | } |
|
| 869 | }) |
|
| 870 | ; |
|
| 871 | return (returnedValue !== undefined) |
|
| 872 | ? returnedValue |
|
| 873 | : this |
|
| 874 | ; |
|
| 875 | ||
| 876 | }; |
|
| 877 | ||
| 878 | // shortcut for tabbed content with no defined navigation |
|
| 879 | $.tab = function() { |
|
| 880 | $(window).tab.apply(this, arguments); |
|
| 881 | }; |
|
| 882 | ||
| 883 | $.fn.tab.settings = { |
|
| 884 | ||
| 885 | name : 'Tab', |
|
| 886 | namespace : 'tab', |
|
| 887 | ||
| 888 | silent : false, |
|
| 889 | debug : false, |
|
| 890 | verbose : false, |
|
| 891 | performance : true, |
|
| 892 | ||
| 893 | auto : false, // uses pjax style endpoints fetching content from same url with remote-content headers |
|
| 894 | history : false, // use browser history |
|
| 895 | historyType : 'hash', // #/ or html5 state |
|
| 896 | path : false, // base path of url |
|
| 897 | ||
| 898 | context : false, // specify a context that tabs must appear inside |
|
| 899 | childrenOnly : false, // use only tabs that are children of context |
|
| 900 | maxDepth : 25, // max depth a tab can be nested |
|
| 901 | ||
| 902 | deactivate : 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together |
|
| 903 | ||
| 904 | alwaysRefresh : false, // load tab content new every tab click |
|
| 905 | cache : true, // cache the content requests to pull locally |
|
| 906 | loadOnce : false, // Whether tab data should only be loaded once when using remote content |
|
| 907 | cacheType : 'response', // Whether to cache exact response, or to html cache contents after scripts execute |
|
| 908 | ignoreFirstLoad : false, // don't load remote content on first load |
|
| 909 | ||
| 910 | apiSettings : false, // settings for api call |
|
| 911 | evaluateScripts : 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content |
|
| 912 | ||
| 913 | onFirstLoad : function(tabPath, parameterArray, historyEvent) {}, // called first time loaded |
|
| 914 | onLoad : function(tabPath, parameterArray, historyEvent) {}, // called on every load |
|
| 915 | onVisible : function(tabPath, parameterArray, historyEvent) {}, // called every time tab visible |
|
| 916 | onRequest : function(tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content |
|
| 917 | ||
| 918 | templates : { |
|
| 919 | determineTitle: function(tabArray) {} // returns page title for path |
|
| 920 | }, |
|
| 921 | ||
| 922 | error: { |
|
| 923 | api : 'You attempted to load content without API module', |
|
| 924 | method : 'The method you called is not defined', |
|
| 925 | missingTab : 'Activated tab cannot be found. Tabs are case-sensitive.', |
|
| 926 | noContent : 'The tab you specified is missing a content url.', |
|
| 927 | path : 'History enabled, but no path was specified', |
|
| 928 | recursion : 'Max recursive depth reached', |
|
| 929 | legacyInit : 'onTabInit has been renamed to onFirstLoad in 2.0, please adjust your code.', |
|
| 930 | legacyLoad : 'onTabLoad has been renamed to onLoad in 2.0. Please adjust your code', |
|
| 931 | state : 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>' |
|
| 932 | }, |
|
| 933 | ||
| 934 | metadata : { |
|
| 935 | tab : 'tab', |
|
| 936 | loaded : 'loaded', |
|
| 937 | promise: 'promise' |
|
| 938 | }, |
|
| 939 | ||
| 940 | className : { |
|
| 941 | loading : 'loading', |
|
| 942 | active : 'active' |
|
| 943 | }, |
|
| 944 | ||
| 945 | selector : { |
|
| 946 | tabs : '.ui.tab', |
|
| 947 | ui : '.ui' |
|
| 948 | } |
|
| 949 | ||
| 950 | }; |
|
| 951 | ||
| 952 | })( jQuery, window, document ); |
|
| 953 | ||