123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- // Generated by CoffeeScript 2.0.0-beta4
- (function() {
- // ------------------------------------------------------------------------
- // 變數與常數設置
- // ------------------------------------------------------------------------
- // 模組名稱。
- var Attribute, ClassName, EVENT_NAMESPACE, Error, Event, MODULE_NAMESPACE, Metadata, NAME, Selector, Settings;
- NAME = 'tab';
- // 模組事件鍵名。
- EVENT_NAMESPACE = `.${NAME}`;
- // 模組命名空間。
- MODULE_NAMESPACE = `module-${NAME}`;
- // 模組設定。
- Settings = {
- // 消音所有提示,甚至是錯誤訊息。
- silent: false,
- // 顯示除錯訊息。
- debug: true,
- // 監聽 DOM 結構異動並自動重整快取。
- observeChanges: true,
- // 當分頁第一次開啟時所會呼叫的回呼函式。
- onFirstLoad: (tabName) => {},
- // 當分頁被開啟時所會呼叫的回呼函式。
- onLoad: (tabName) => {},
- // 是否要紀錄分頁籤的開關歷程至瀏覽器的上下頁歷程中。
- history: true
- };
- // 中繼資料名稱。
- Metadata = {
- LOADED: 'loaded'
- };
- // 事件名稱。
- Event = {
- FIRSTLOAD: `firstload${EVENT_NAMESPACE}`,
- LOAD: `load${EVENT_NAMESPACE}`,
- CLICK: `click${EVENT_NAMESPACE}`,
- HASHCHANGE: `hashchange${EVENT_NAMESPACE}`,
- POPSTATE: `popstate${EVENT_NAMESPACE}`
- };
- // 標籤名稱。
- Attribute = {
- GROUP: 'data-tab-group',
- TAB: 'data-tab'
- };
- // 樣式名稱。
- ClassName = {
- ACTIVE: 'active',
- TAB: 'tab'
- };
- // 選擇器名稱。
- Selector = {
- TAB: (name) => {
- return `.tab[${Attribute.TAB}='${name}']`;
- },
- ANY_TAB: '.tab[data-tab]',
- ACTIVE_TAB: '.active.tab[data-tab]',
- HIDDEN_TAB: '.tab[data-tab]:not(.active)',
- MENU: '.menu',
- MENU_ITEM: (name) => {
- return `.menu .item[${Attribute.TAB}='${name}']`;
- },
- ITEM: '.item'
- };
- // 錯誤訊息。
- Error = {};
- // ------------------------------------------------------------------------
- // 模組註冊
- // ------------------------------------------------------------------------
- ts.register({NAME, MODULE_NAMESPACE, Error, Settings}, ({$allModules, $this, element, debug, settings, index}) => {
- var module, separator;
- // ------------------------------------------------------------------------
- // 區域變數
- // ------------------------------------------------------------------------
- separator = ',';
- // ------------------------------------------------------------------------
- // 模組定義
- // ------------------------------------------------------------------------
- return module = {
- change: {
- tab: (name, recursive = true, update = true) => {
- var $item, $tab, i, len, path, paths;
- name = module.decode(name);
- paths = recursive ? ts(Selector.TAB(name)).tab('get paths') : [name];
- for (i = 0, len = paths.length; i < len; i++) {
- path = paths[i];
- $item = ts(Selector.MENU_ITEM(path));
- $tab = ts(Selector.TAB(path));
- $tab.tab('set active');
- $item.tab('set active').tab('hide others');
- if ($item.tab('not loaded')) {
- $item.trigger(Event.FIRSTLOAD, $tab.get(), path).tab('set loaded', true);
- }
- $item.trigger(Event.LOAD, $tab.get(), path);
- }
- if (update) {
- module.update.hash();
- }
- return $allModules;
- }
- },
- hide: {
- others: () => {
- var $items;
- $items = module.get.relative.$items();
- $items.tab('set hidden');
- return $items.each(function() {
- return ts(this).tab('get $tab').tab('set hidden');
- });
- }
- },
- get: {
- name: () => {
- return $this.attr(Attribute.TAB);
- },
- paths: () => {
- var $parent, paths;
- paths = [];
- $parent = $this;
- while ($parent.length !== 0) {
- paths.push($parent.tab('get name'));
- $parent = $parent.tab('get parent $tab');
- }
- return paths;
- },
- active: {
- $tab: () => {
- return ts(Selector.ACTIVE_TAB);
- }
- },
- relative: {
- $items: () => {
- return $this.closest(Selector.MENU).find(Selector.ITEM).not($this);
- }
- },
- parent: {
- $tab: $this.parent().closest(Selector.ANY_TAB)
- },
- tab: () => {
- return module.get.$tab().get();
- },
- $tab: () => {
- return ts(Selector.TAB(module.get.name()));
- },
- path: () => {
- return module.get.paths().join(separator);
- },
- hash: () => {
- var hash;
- hash = window.location.hash;
- if (hash) {
- return module.decode(hash.slice(1));
- } else {
- return '';
- }
- }
- },
- decode: (uri) => {
- return decodeURIComponent(uri);
- },
- has: {
- hash: () => {
- return !!window.location.hash;
- },
- parent: {
- tab: () => {
- return $this.parent().closest(Selector.ANY_TAB).length !== 0;
- }
- },
- hidden: {
- parent: () => {
- return $this.closest(Selector.HIDDEN_TAB).length !== 0;
- }
- },
- active: {
- children: () => {
- return $this.find(Selector.ACTIVE_TAB).length !== 0;
- }
- }
- },
- set: {
- loaded: (bool) => {
- return $this.data(Metadata.LOADED, bool);
- },
- hidden: () => {
- return $this.removeClass(ClassName.ACTIVE);
- },
- active: () => {
- return $this.addClass(ClassName.ACTIVE);
- }
- },
- is: {
- active: () => {
- return $this.hasClass(ClassName.ACTIVE);
- },
- tab: () => {
- return $this.hasClass(ClassName.TAB);
- },
- loaded: () => {
- return $this.data(Metadata.LOADED) === true;
- }
- },
- not: {
- loaded: () => {
- return !module.is.loaded();
- }
- },
- apply: {
- hash: () => {
- return setTimeout(function() {
- var hash;
- if (!module.has.hash()) {
- return;
- }
- hash = module.get.hash();
- if (module.same.hash(hash)) {
- return;
- }
- return hash.split(separator).forEach((value) => {
- return module.change.tab(value, true, false);
- });
- }, 0);
- }
- },
- update: {
- hash: () => {
- var hash;
- hash = [];
- module.get.active.$tab().each(function() {
- var $tab;
- $tab = ts(this);
- if ($tab.tab('has hidden parent')) {
- return;
- }
- if ($tab.tab('has active children')) {
- return;
- }
- return hash.push($tab.tab('get name'));
- });
- hash = `#${hash.join(separator)}`;
- if (settings.history) {
- return history.pushState(null, null, hash);
- } else {
- return history.replaceState(null, null, hash);
- }
- }
- },
- same: {
- hash: (hash) => {
- var same;
- same = true;
- hash.split(separator).forEach((value) => {
- if (!same) {
- return;
- }
- if (ts(Selector.TAB(value)).tab('has hidden parent')) {
- return same = false;
- }
- });
- return same;
- }
- },
- bind: {
- events: () => {
- $this.on(Event.CLICK, () => {
- if (module.is.active()) {
- return;
- }
- return module.change.tab(module.get.name(), false);
- });
- $this.on(Event.FIRSTLOAD, (event, context, name) => {
- debug('發生 FIRSTLOAD 事件', context, name);
- return settings.onFirstLoad.call(context, event, name);
- });
- $this.on(Event.LOAD, (event, context, name) => {
- debug('發生 LOAD 事件', context, name);
- return settings.onLoad.call(context, event, name);
- });
- $this.attr('href', 'javascript:void(0)');
- if (!settings.history) {
- return;
- }
- return ts(window).off(Event.POPSTATE).on(Event.POPSTATE, () => {
- debug('發生 POPSTATE 事件', window);
- return module.apply.hash();
- });
- }
- },
- // ------------------------------------------------------------------------
- // 基礎方法
- // ------------------------------------------------------------------------
- initialize: () => {
- debug('初始化分頁籤', element);
- if (module.is.tab()) {
- return;
- }
- module.bind.events();
- return module.apply.hash();
- },
- instantiate: () => {
- return debug('實例化分頁籤', element);
- },
- refresh: () => {
- return $allModules;
- },
- destroy: () => {
- debug('摧毀分頁籤', element);
- $this.removeData(MODULE_NAMESPACE).off(EVENT_NAMESPACE);
- return $allModules;
- }
- };
- });
- }).call(this);
|