sync.tabpane.js

来自「echo3 很炫的ajax框架技术 js 演示demo ajax j2ee 里」· JavaScript 代码 · 共 1,019 行 · 第 1/3 页

JS
1,019
字号
/**
 * Component rendering peer: TabPane
 */
Extras.Sync.TabPane = Core.extend(Echo.Render.ComponentSync, {

    $static: {
        _supportedPartialProperties: ["activeTab", "activeTabIndex"],
        _paneInsets: 0,
        _defaultBorderType: Extras.TabPane.BORDER_TYPE_ADJACENT_TO_TABS,
        _defaultForeground: "#000000",
        _defaultInsets: 2,
        _defaultTabActiveBorder: "1px solid #00004f",
        _defaultTabActiveHeightIncrease: 2,
        _defaultTabAlignment: "top",
        _defaultTabCloseIconTextMargin: 5,
        _defaultTabContentInsets: 0,
        _defaultTabIconTextMargin: 5,
        _defaultTabInactiveBorder: "1px solid #7f7f7f",
        _defaultTabInset: 10,
        _defaultTabInsets: "3px 8px",
        _defaultTabPosition: Extras.TabPane.TAB_POSITION_TOP,
        _defaultTabSpacing: 0,
        
        /**
         * Runnable to manage scrolling animation.
         */
        ScrollRunnable: Core.extend(Core.Web.Scheduler.Runnable, {
        
            repeat: true,
            timeInterval: 20,

            reverse: false,
            distance: 0,
            
            /** Minimum distance to move (in case of click rather than hold */
            clickDistance: 50,
            
            /** Rate to scroll when scroll button held. */
            pixelsPerSecond: 400,
            
            /** Initial scroll position. */
            initialPosition: null,
            
            disposed: false,
            peer: null,
            lastInvokeTime: null,
        
            $construct: function(peer, reverse) {
                this.peer = peer;
                this.reverse = reverse;
                this.initialPosition = peer.scrollPosition;
                this.lastInvokeTime = new Date().getTime();
            },
            
            dispose: function() {
                if (!this.disposed) {
                    Core.Web.Scheduler.remove(this);
                }
                this.disposed = true;
            },
            
            finish: function() {
                if (this.distance < this.clickDistance) {
                    this.distance = this.clickDistance;
                    this.updatePosition();
                }
                this.dispose();
            },
            
            run: function() {
                var time = new Date().getTime();
                this.distance += Math.ceil(this.pixelsPerSecond * (time - this.lastInvokeTime) / 1000);
                this.lastInvokeTime = time;
                this.updatePosition();
            },
            
            updatePosition: function() {
                var position = this.initialPosition + ((this.reverse ? -1 : 1) * this.distance);
                if (!this.peer.setScrollPosition(position)) {
                    this.dispose();
                }
            }
        })
    },
    
    $load: function() {
        Echo.Render.registerPeer("Extras.TabPane", this);
    },
    
    _icons: null,

    /**
     * Primary DIV element.
     * @type Element
     */
    _div: null,

    /**
     * DIV element which contains content.  All child components are rendered within this DIV,
     * only one is allowed to be visibly displayed at a given time.
     * @type Element
     */    
    _contentContainerDiv: null,
    
    /**
     * Element containing tab headers.
     * @type Element
     */
    _headerContainer: null,
    
    /**
     * The renderId of the active tab.
     * @type String
     */
    _activeTabId: null,
    
    /**
     * Scroll previous arrow.
     */
    _previousControlDiv: null,
    
    /**
     * Scroll next arrow.
     */
    _nextControlDiv: null,
    
    /**
     * Array containing <code>Extras.Sync.TabPane.Tab</code> objects represented the displayed tabs.
     * Each index of this array matches the corresponding child component index.
     * @type Array 
     */
    _tabs: null,
    
    /**
     * Combined width of all tabs.
     */
    _totalTabWidth: 0,
    
    /**
     * Flag indicating whether the header size may need to be reconfigured (by invoking configureHeaderSize() in the next
     * renderDisplay() execution.
     */
    _configureHeaderSizeRequired: false,
    
    _scrollRunnable: null,
    
    scrollPosition: 0,
    
    $construct: function() {
        this._tabs = [];
    },
    
    /**
     * Adds a tab and renders it.
     *
     * @param {Echo.Update.ComponentUpdate} update the component update 
     * @param {Extras.Sync.TabPane.Tab} tab the tab to be added 
     * @param index the index at which the tab should be added
     */
    _addTab: function(update, tab, index) {
        if (index == null || index == this._tabs.length) {
            this._tabs.push(tab);
            tab._render(update);
            this._headerTabContainerTr.appendChild(tab._headerTd);
            this._contentContainerDiv.appendChild(tab._contentDiv);
        } else {
            this._tabs.splice(index, 0, tab);
            tab._render(update);
            this._headerTabContainerTr.insertBefore(tab._headerTd, 
                    this._headerTabContainerTr.childNodes[index]);
            this._contentContainerDiv.insertBefore(tab._contentDiv,
                    this._contentContainerDiv.childNodes[index]);
        }
    },

    _configureHeaderSize: function() {
        var height = new Core.Web.Measure.Bounds(this._headerTabContainerDiv).height;
        if (height === 0) {
            // Cannot calculate header size.
            return;
        }
        
        this._configureHeaderSizeRequired = false;
        var borderSize = Echo.Sync.Border.getPixelSize(this._tabActiveBorder);
        
        if (this._tabPosition == Extras.TabPane.TAB_POSITION_BOTTOM) {
            this._contentContainerDiv.style.top = "0";
            this._contentContainerDiv.style.bottom = (height - borderSize) + "px";
        } else {
            this._contentContainerDiv.style.top = (height - borderSize ) + "px";
            this._contentContainerDiv.style.bottom = "0";
        }
        this._contentContainerDiv.style.left = "0";
        this._contentContainerDiv.style.right = "0";

        Core.Web.VirtualPosition.redraw(this._contentContainerDiv);
        Core.Web.VirtualPosition.redraw(this._headerContainerDiv);
        for (var i = 0; i < this._tabs.length; ++i) {
            this._tabs[i]._renderDisplay();
        }
    },
    
    /**
     * Determines the renderId of the active tab child component.
     * This method first queries the component's <code>activeTab</code> property, 
     * and if it is not set, the id is determined by finding the child component at the 
     * index specified by the component's <code>activeTabIndex</code> property.
     *
     * @return the active tab renderId
     * @type String
     */
    _getActiveTabId: function() {
        var activeTabId = this.component.get("activeTab");
        if (!activeTabId) {
            var activeTabIndex = this.component.get("activeTabIndex");
            if (activeTabIndex != null && activeTabIndex < this.component.children.length) {
                activeTabId = this.component.children[activeTabIndex].renderId;
            }
        }
        return activeTabId;
    },

    /**
     * Retrieves the tab instance with the specified tab id.
     * 
     * @param tabId the tab render id
     * @return the tab, or null if no tab is present with the specified id
     * @type Extras.Sync.TabPane.Tab
     */
    _getTabById: function(tabId) {
        for (var i = 0; i < this._tabs.length; ++i) {
            var tab = this._tabs[i];
            if (tab._childComponent.renderId == tabId) {
                return tab;
            }
        }
        return null;
    },
    
    /**
     * Handler for mouse down event on previous/next scroll buttons.
     */
    _processScrollStart: function(e) {
        if (!this.client || !this.client.verifyInput(this.component)) {
            return;
        }
        
        this._scrollRunnable = new Extras.Sync.TabPane.ScrollRunnable(this, e.registeredTarget === this._previousControlDiv);
        Core.Web.Scheduler.add(this._scrollRunnable);
    },
    
    /**
     * Handler for mouse up event on previous/next scroll buttons.
     */
    _processScrollStop: function(e) {
        if (!this._scrollRunnable) {
            return;
        }
        this._scrollRunnable.finish();
        this._scrollRunnable = null;
    },
    
    /**
     * Removes a specific tab.
     *
     * @param {Extras.Sync.TabPane.Tab} tab the tab to remove
     */
    _removeTab: function(tab) {
        var tabIndex = Core.Arrays.indexOf(this._tabs, tab);
        if (tabIndex == -1) {
            return;
        }
        if (tab._childComponent.renderId == this._activeTabId) {
            this._activeTabId = null;
        }
        this._tabs.splice(tabIndex, 1);
        
        Core.Web.DOM.removeNode(tab._headerTd);
        Core.Web.DOM.removeNode(tab._contentDiv);
        
        tab._dispose();
    },
    
    renderAdd: function(update, parentElement) {
        this._icons = { };
        
        // Configure Properties
        this._activeTabId = this._getActiveTabId();
        this._borderType = this.component.render("borderType", Extras.Sync.TabPane._defaultBorderType);
        this._insets = this.component.render("insets", Extras.Sync.TabPane._defaultInsets);
        this._tabActiveBorder = this.component.render("tabActiveBorder", Extras.Sync.TabPane._defaultTabActiveBorder);
        this._tabActiveHeightIncreasePx = Echo.Sync.Extent.toPixels(this.component.render("tabActiveHeightIncrease", 
                Extras.Sync.TabPane._defaultTabActiveHeightIncrease));
        this._tabInactiveBorder = this.component.render("tabInactiveBorder", Extras.Sync.TabPane._defaultTabInactiveBorder);
        this._tabInsetPx = Echo.Sync.Extent.toPixels(this.component.render("tabInset",Extras.Sync.TabPane._defaultTabInset));
        this._tabPosition = this.component.render("tabPosition", Extras.Sync.TabPane._defaultTabPosition);
        this._tabSpacing = this.component.render("tabSpacing", Extras.Sync.TabPane._defaultTabSpacing);
        this._tabCloseEnabled = this.component.render("tabCloseEnabled", false);
        if (this._tabCloseEnabled) {
            this._icons.defaultIcon = this.component.render("tabCloseIcon");
            this._icons.disabledIcon = this.component.render("tabDisabledCloseIcon");
            this._icons.rolloverIcon = this.component.render("tabRolloverCloseIcon");
        }

        // Render Border Insets
        var pixelInsets = Echo.Sync.Insets.toPixels(this._insets);
        if (this._borderType == Extras.TabPane.BORDER_TYPE_SURROUND) {
            // Do nothing, pixelInsets values are correct.
        } else if (this._borderType == Extras.TabPane.BORDER_TYPE_PARALLEL_TO_TABS) {
            pixelInsets.left = pixelInsets.right = 0;
        } else if (this._tabPosition == Extras.TabPane.TAB_POSITION_BOTTOM) {
            pixelInsets.left = pixelInsets.right = pixelInsets.top = 0;
        } else {
            pixelInsets.left = pixelInsets.right = pixelInsets.bottom = 0;
        }

        // Create Main Element
        this._div = document.createElement("div");
        this._div.id = this.component.renderId;
        this._div.style.cssText = "position:absolute;overflow:hidden;top:" + pixelInsets.top + "px;right:" + pixelInsets.right +
                "px;bottom:" + pixelInsets.bottom + "px;left:" + pixelInsets.left + "px;";
                        
        // Render Header Container
        this._headerContainerDiv = document.createElement("div");
        this._headerContainerDiv.style.cssText = "position:absolute;overflow:hidden;z-index:1;" +
                (this._tabPosition == Extras.TabPane.TAB_POSITION_BOTTOM ? "bottom" : "top") + ":0;" +
                "left:" + this._tabInsetPx + "px;right:" + this._tabInsetPx + "px;";
                
        this._headerTabContainerDiv = document.createElement("div");
        
        this._headerTabContainerTable = document.createElement("table");
        this._headerTabContainerTable.style.padding = 0;
        this._headerTabContainerTable.cellPadding = 0;
        this._headerTabContainerTable.cellSpacing = 0;
        var tbody = document.createElement("tbody");
        this._headerTabContainerTr = document.createElement("tr");
        tbody.appendChild(this._headerTabContainerTr);
        this._headerTabContainerTable.appendChild(tbody);
        this._headerTabContainerDiv.appendChild(this._headerTabContainerTable);
        this._headerContainerDiv.appendChild(this._headerTabContainerDiv);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?