Commit ac68a567 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Merge remote-tracking branch 'nick/redesign' into redesign

parents 0911cccc 2eb0e8d6
Loading
Loading
Loading
Loading
+11 −37
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@ Ext.define('Docs.controller.Tabs', {
        {
            ref: 'videoTree',
            selector: '#videotree'
        },
        {
            ref: 'doctabs',
            selector: '#doctabs'
        }
    ],

@@ -59,22 +63,15 @@ Ext.define('Docs.controller.Tabs', {
                afterrender: function(cmp) {
                    this.addTabIconListeners(cmp);
                    this.addTabListeners(cmp);

                    // var prevTabs = Docs.Settings.get('openTabs');
                    // if (prevTabs) {
                    //     prevTabs.each(function(f) {
                    //         this.addTabFromTree(f, this.getClassTree(), true, true);
                    //     }, this);
                    // }
                },
                resize: function() {
                    Ext.getCmp('doctabs').resizeTabs();
                    Ext.getCmp('doctabs').refresh();
                },
                scope: this
            },
            '#tabOverflowMenu menuitem': {
                click: function(cmp) {
                    this.activateTab(cmp.href, true);
                    Docs.History.push(cmp.href);
                },
                scope: this
            }
@@ -88,7 +85,7 @@ Ext.define('Docs.controller.Tabs', {
    addTabFromTree: function(url, tree) {
        var treeRecord = tree.findRecordByUrl(url);
        if (treeRecord && treeRecord.raw) {
            Ext.getCmp('doctabs').addTab({
            this.getDoctabs().addTab({
                href: treeRecord.raw.url,
                text: treeRecord.raw.text,
                iconCls: treeRecord.raw.iconCls
@@ -115,27 +112,9 @@ Ext.define('Docs.controller.Tabs', {

        cmp.el.addListener('click', function(event, el) {
            cmp.justClosed = true;
            var docTab = Ext.get(el).up('.doctab');
            var url = docTab.down('.tabUrl').getAttribute('href');
            // Forget the scrollstate of a tab after closing
            var url = Ext.get(el).up('.doctab').down('.tabUrl').getAttribute('href');
            delete this.scrollState[url];
            var next = Ext.getCmp('doctabs').removeTab(url);
            if (next) {
                Ext.getCmp('doctabs').activateTab(next);
                Docs.History.push(next);
            }
            docTab.dom.removed = true;
            docTab.animate({
                to: { top: 30 }
            }).animate({
                to: { width: 10 },
                listeners: {
                    afteranimate: function() {
                        docTab.remove();
                    },
                    scope: this
                }
            });
            Ext.getCmp('doctabs').removeTab(url);
        }, this, {
            delegate: '.close',
            preventDefault: true
@@ -153,7 +132,7 @@ Ext.define('Docs.controller.Tabs', {
                return;
            }
            var url = Ext.get(el).down('.tabUrl').getAttribute('href');
            this.activateTab(url);
            Docs.History.push(url);
        }, this, {
            delegate: '.doctab'
        });
@@ -164,11 +143,6 @@ Ext.define('Docs.controller.Tabs', {
        });
    },

    activateTab: function(url, activateOverview) {
        Ext.getCmp('doctabs').activateTab(url, activateOverview);
        Docs.History.push(url);
    },

    /**
     * Saves scrollstate of a tab.
     *
+189 −136
Original line number Diff line number Diff line
@@ -9,12 +9,11 @@ Ext.define('Docs.view.Tabs', {

    componentCls: 'doctabs',

    openTabs: [],
    tabBarTabs: [],
    overflowTabs: [],

    tabWidth: 140,
    minTabWidth: 80,
    maxTabWidth: 140,

    tabs: [],
    tabsInBar: [],

    initComponent: function() {
        var tpl = new Ext.XTemplate(
@@ -54,10 +53,8 @@ Ext.define('Docs.view.Tabs', {
        }
    },

    tabQueue: [],

    /**
     * Adds a new tab to the Tab bar
     * Adds a new tab
     *
     * @param {Object} tab
     * @param {String} tab.href URL of the resource
@@ -69,39 +66,114 @@ Ext.define('Docs.view.Tabs', {
     */
    addTab: function(tab, opts) {

        // If there is room add tab
        // If no room, move last tab to overflow menu and update with current tab
        // console.log("Adding tab", tab, opts)

        if (!Ext.Array.contains(this.openTabs, tab.href)) {
        if (!this.hasTab(tab.href)) {

            this.openTabs.push(tab.href);
            Docs.Settings.set('openTabs', this.openTabs);
            this.tabs.push(tab.href);

            if (this.overflowing()) {
                Ext.get('tabOverflow').show();
            } else {
            if (this.roomForNewTab()) {
                this.addTabToBar(tab, opts);
            }
            this.addTabToOverflow(tab, opts);
        }
        this.activateTab(tab.href);
    },

            Ext.getCmp('tabOverflowMenu').add({
                text: tab.text,
                iconCls: tab.iconCls,
                origIcon: tab.iconCls,
                href: tab.href,
                cls: 'x-menu-item-checked' + (this.overflowing() ? ' overflow' : '')
            });
    /**
     * Removes a tab. If the tab to be closed is currently active, activate a neighboring tab.
     *
     * @param {String} url URL of the tab to remove
     */
    removeTab: function(url) {

        if (!this.hasTab(url)) return false;

        if (this.inTabBar(url)) {
            this.removeTabFromBar(url);
        }

        if (opts.activate) {
            this.activateTab(tab.href);
        var idx = Ext.Array.indexOf(this.tabs, url);
        if (idx !== false) {
            Ext.Array.erase(this.tabs, idx, 1);
        }

        this.resizeTabs();
        if (this.activeTab == url) {
            if (this.tabs.length === 0) {
                Docs.App.getController(this.getControllerName(url)).loadIndex();
            }
            else {
                if (idx === this.tabs.length) {
                    idx -= 1;
                }
                this.activateTab(this.tabs[idx]);
            }
        }
    },

    /**
     * Activates a tab
     *
     * @param {String} url URL of tab
     */
    activateTab: function(url) {

        // console.log("Activating", url);

        this.activeTab = url;

        if (!this.inTabBar(url)) {
            this.swapLastTabWith(url);
        }

        Ext.Array.each(Ext.query('.doctab a[class=tabUrl]'), function(d) {
            Ext.get(d).up('.doctab').removeCls(['active', 'highlight']);
        });

        var activeTab = Ext.query('.doctab a[href="' + url + '"]')[0];
        if (activeTab) {
            var docTab = Ext.get(activeTab).up('.doctab');
            docTab.addCls('active');
        }

        this.highlightOverviewTab(url);
    },

    /**
     *  Refreshes tabs and overflow. Useful for window resize event.
     */
    refresh: function() {

    },

    // Private methods

    /**
     * @private
     * Determines if the tab bar has room for a new tab.
     * @return {Boolean} True if tab bar has room for a new tab
     */
    roomForNewTab: function() {
        return this.tabsInBar.length < this.maxTabsInBar();
    },

    /**
     * @private
     * @return {Boolean} True if we are already tracking a tab with the given URL
     */
    hasTab: function(url) {
        return Ext.Array.contains(this.tabs, url);
    },

    /**
     * @private
     * Adds a tab to the tab bar
     */
    addTabToBar: function(tab, opts) {

        this.tabBarTabs.push(tab.url);
        // console.log("Adding tab to bar", tab.href)

        this.tabsInBar.push(tab.href);

        var tpl = Ext.create('Ext.XTemplate',
            '<div class="doctab" style="visibility: hidden">',
@@ -120,160 +192,141 @@ Ext.define('Docs.view.Tabs', {
            docTab.setStyle('width', '10px');
            docTab.setStyle({ visibility: 'visible' });
            docTab.animate({
                to: { width: this.tabWidth - this.tabDelta() }
                to: { width: this.tabWidth() }
            });
        }
        else {
            docTab.setStyle({ visibility: 'visible' });
        }
    },

    /**
     * Returns the width of the Tab Bar
     * @return {Number} Tab bar width
     */
    tabBarWidth: function() {
        return Ext.getCmp('doctabs').getWidth() - 240;
        this.resizeTabs();
    },

    /**
     * Returns the cumulative width of all visible tabs
     * @return {Number} Tabs width
     * @private
     * @return {Boolean} true if the tab is in the tab bar
     */
    totalTabsWidth: function() {
        return this.openTabs.length * this.tabWidth;
    inTabBar: function(url) {
        return Ext.Array.contains(this.tabsInBar, url);
    },

    /**
     * Returns the cumulative width of all visible tabs
     * @return {Number} Tabs width
     * @private
     */
    minTabsWidth: function() {
        return this.openTabs.length * this.minTabWidth;
    },
    removeTabFromBar: function(url) {

    maxVisibleTabs: function() {
        return Math.ceil(this.tabBarWidth() / this.minTabWidth);
    },
        var idx = Ext.Array.indexOf(this.tabsInBar, url);
        Ext.Array.erase(this.tabsInBar, idx, 1);

    /**
     * Returns the width delta to be applied to each tab for them to fit within the tab bar
     * @return {Number} Number of pixels
     */
    tabDelta: function() {
        var docTab = Ext.get(Ext.query('.doctab a[href="' + url + '"]')[0]).up('.doctab');

        var numTabs = this.maxVisibleTabs();
        if (this.openTabs.length < numTabs) numTabs = this.openTabs.length;

        var delta = Math.ceil((this.totalTabsWidth() - this.tabBarWidth()) / this.openTabs.length);
        return (delta < 0) ? 0 : delta;
        docTab.dom.removed = true;
        docTab.animate({
            to: { top: 30 }
        }).animate({
            to: { width: 10 },
            listeners: {
                afteranimate: function() {
                    docTab.remove();
                },

    /**
     * Returns true if the tab bar is overflowing
     */
    overflowing: function() {
        return ((this.openTabs.length - 1) * this.minTabWidth) > this.tabBarWidth();
                scope: this
            }
        });
        this.resizeTabs();
    },

    /**
     * Resizes the tabs
     * @private
     * Adds a tab to the overflow list
     */
    resizeTabs: function() {
    addTabToOverflow: function(tab, opts) {

        clearTimeout(this.resizeTabsTimer);

        if (this.totalTabsWidth() > this.tabBarWidth()) {

            var tabDelta = this.tabDelta();
        var overflow = this.inTabBar(tab.href);
        if (this.tabs.length > this.tabsInBar.length && this.tabsInBar.length == this.maxTabsInBar()) {
            // Add 'overflow' class to last visible tab in overflow dropdown
        }

            Ext.Array.each(Ext.query('.doctab'), function(t){
                var docTab = Ext.get(t);
                if (!docTab.dom.removed && !docTab.hasCls('overview')) {
                    var newWidth = (this.tabWidth - tabDelta) > this.minTabWidth ? (this.tabWidth - tabDelta) : this.minTabWidth;
                    docTab.animate({
                        to: { width: newWidth }
        Ext.getCmp('tabOverflowMenu').add({
            text: tab.text,
            iconCls: tab.iconCls,
            origIcon: tab.iconCls,
            href: tab.href,
            cls: 'x-menu-item-checked' + (overflow ? '' : ' overflow')
        });
                }
            }, this);
        }
    },

    /**
     * Activates a tab
     *
     * @param {String} url URL of the tab to activate
     * @private
     * Swaps the last tab with teh given tab currently in the overflow list
     */
    activateTab: function(url, activateOverview) {
        this.activeTab = Ext.Array.indexOf(this.openTabs, url);
        Ext.Array.each(Ext.query('.doctab a[class=tabUrl]'), function(d) {
            Ext.get(d).up('.doctab').removeCls(['active', 'highlight']);
        });
        var activeTab = Ext.query('.doctab a[href="' + url + '"]')[0];
        if (activeTab) {
            var docTab = Ext.get(activeTab).up('.doctab');
            docTab.addCls('active');
            if (!docTab.hasCls('overview')) {
                activateOverview = true;
            }
        }
        if (activateOverview) {
    swapLastTabWith: function(url) {
        console.log("Swap last tab with", url);
    },

    /**
     * @private
     */
    highlightOverviewTab: function(url) {
        var overviewTab = Ext.query('.doctab.' + this.getControllerName(url).toLowerCase());
        if (overviewTab && overviewTab[0]) {
            Ext.get(overviewTab[0]).addCls('highlight');
        }
        }
    },

        Ext.Array.each(Ext.ComponentQuery.query('#tabOverflowMenu menuitem'), function(menuItem) {
            menuItem.setIconCls(menuItem.href == url ? undefined : menuItem.origIcon);
        });
    /**
     * @private
     * @return {Number} Maximum number of tabs we can fit in the tab bar
     */
    maxTabsInBar: function() {
        return Math.floor(this.tabBarWidth() / this.minTabWidth);
    },

    /**
     * Removes a tab from the tab bar. If the tab to be removed is the current tab,
     * returns url of the tab on the right.
     *
     * @param {String} url URL of the tab to remove
     * @return {String} URL of the tab to activate next, or undefined.
     * @private
     * @return {Number} Width of a tab in the tab bar
     */
    removeTab: function(url) {
        var idx = Ext.Array.indexOf(this.openTabs, url);
        if (idx !== false) {
            Ext.Array.erase(this.openTabs, idx, 1);
            Docs.Settings.set('openTabs', this.openTabs);
            if (this.activeTab > idx) {
                this.activeTab -= 1;
            }
    tabWidth: function() {

            Ext.Array.each(Ext.ComponentQuery.query('#tabOverflowMenu menuitem[href=' + url + ']'), function(menuItem) {
                Ext.getCmp('tabOverflowMenu').remove(menuItem);
            });
        }
        var width = Math.floor(this.tabBarWidth() / this.tabsInBar.length) + 6;

        if (this.resizeTabsTimer) {
            clearTimeout(this.resizeTabsTimer);
        if (width > this.maxTabWidth) {
            return this.maxTabWidth;
        }

        var self = this;
        this.resizeTabsTimer = setTimeout(function(){
            self.resizeTabs();
        }, 1000);

        if (idx === this.activeTab) {
            if (this.openTabs.length === 0) {
                Docs.App.getController(this.getControllerName(url)).loadIndex();
        else if (width < this.minTabWidth) {
            return this.minTabWidth;
        }
        else {
                if (idx === this.openTabs.length) {
                    idx -= 1;
                }
                return this.openTabs[idx];
            return width;
        }
    },

    /**
     * @private
     * @return {Number} Width of the tab bar (not including the static tabs)
     */
    tabBarWidth: function() {
        return this.getWidth() - 265;
    },

    /**
     * @private
     * Resize tabs in the tab bar
     */
    resizeTabs: function() {
        Ext.Array.each(Ext.query('.doctab'), function(t){
            var docTab = Ext.get(t);
            if (!docTab.dom.removed && !docTab.hasCls('overview')) {
                docTab.animate({
                    to: { width: this.tabWidth() }
                });
            }
        return undefined;
        }, this);
    },

    // Determines controller name from URL
    /**
     * @private
     * Determines controller name from a URL
     */
    getControllerName: function(url) {
        if (/#!?\/api/.test(url)) {
            return 'Classes';
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ Ext.define('Docs.view.videos.Index', {
                itemTpl: [
                    '<dd ext:url="#!/video/{id}"><img src="{thumb}"/>',
                        '<div><h4>{title}',
                        '</h4><p>{[values.description.substr(0,100)]}</p></div>',
                        '</h4><p>{[values.description.substr(0,80)]}</p></div>',
                    '</dd>'
                ],
                data: Docs.data.videos