关闭选项卡以关注上一个选项卡而不是第一个选项卡时如何更改 dojo 内容选项卡焦点?

Posted

技术标签:

【中文标题】关闭选项卡以关注上一个选项卡而不是第一个选项卡时如何更改 dojo 内容选项卡焦点?【英文标题】:How to change dojo content tab focus when closing a tab to focus on previous tab instead of first tab? 【发布时间】:2012-04-09 15:03:31 【问题描述】:

我正在使用DojoDijit Layout 生成类似于Dijit Theme Tester Demo 的内容选项卡窗格。此处的所有选项卡都是可关闭的。

问题是:当我关闭一个选项卡时,它会返回到列表中的第一个选项卡,而不是上一个选项卡(在它旁边可用)。

您可以将其想象为在 Firefox 或 Chrome 中打开一个新选项卡并尝试关闭最后一个选项卡......在关闭选项卡时,它会将焦点更改为上一个选项卡,这是使用选项卡的可预测行为。但是对于dijit.TabContainers,默认情况下它会返回到第一个选项卡而不是前一个选项卡。当您考虑 UI 基础知识时,这是一个严重的缺陷。

我检查了dojo 文档,但没有找到任何提示。知道怎么做吗?

【问题讨论】:

【参考方案1】:

好的,当单击 dijit.layout.ContentPane(选项卡)上的 [X] 按钮时,会生成一个事件 onClosedijit.layout .TabContainer 正在监听这个事件,所以当这个事件发生时,它会执行回调 closeChild() 然后函数 removeChild() 被执行,最后一个是你应该覆盖的。

tabContainer 从 dijit.layout.StackContainer 继承了这两个函数,您应该查看 API 文档。

因此,为了能够修改关闭选项卡的默认行为,您应该覆盖默认功能,在下面的示例中,我这样做了。阅读 cmets 以获取有关在何处添加逻辑的信息。

例如

<script>
    require([
        "dojo/parser",

        "dojo/_base/lang", //this is the one that has the extend function
        "dojo/topic", //this is needed inside the overrided function

        "dijit/layout/TabContainer",
        "dijit/layout/ContentPane", 

        "dojo/domReady!"
    ], function(Parser, lang, topic, tabContainer, contentPane)
        Parser.parse();

        // this will extend the tabContainer class and we will override the method in question
        lang.extend(tabContainer, 

            // this function, i copied it from the dijit.layout.StackContainer class
            removeChild: function(/*dijit._Widget*/ page)

                // for this to work i had to add as first argument the string "startup"
                this.inherited("startup", arguments);

                if(this._started)
                    // also had to call the dojo.topic class in the require statement
                    topic.publish(this.id + "-removeChild", page);  
                

                if(this._descendantsBeingDestroyed) return; 

                if(this.selectedChildWidget === page)
                    this.selectedChildWidget = undefined;
                    if(this._started)
                        var children = this.getChildren();
                        if(children.length)

                            // this is what you want to add your logic
                            // the var children (array) contains a list of all the tabs
                            // the index selects the tab starting from left to right 
                            // left most being the 0 index   

                            this.selectChild(children[0]);
                        
                    
                

                if(this._started)
                    this.layout();
                
            
        );

        // now you can use your modified tabContainer WALAAAAAAA!
        // from here on, normal programmatic tab creation
        var tc = new tabContainer(
            style: "height: 100%; width: 100%;",
        , "tab-container-div-id");

        var cp1 = new contentPane(
            title: "First Tab",
            closable: true
        );
        tc.addChild(cp1);

        var cp2 = new contentPane(
            title: "Second Tab",
            closable: true
        );
        tc.addChild(cp2);

        var cp3 = new contentPane(
            title: "Third Tab",
            selected: true,
            closable: true
        );
        tc.addChild(cp3);

        tc.startup();
    );
</script>

【讨论】:

【参考方案2】:

在 Dojo 1.10 中,恢复到前一个选项卡是 TabContainers 的正常行为(而不是恢复到第一个选项卡)。

据推测,您可以使用dojo/aspect 来获取旧行为(警告:未测试):

require( [ 'dijit/registry', 'dojo/aspect', 'dojo/_base/lang' ],
    function( registry, aspect, lang )
    
        var tabContainer = registry.byId( 'tab_container');
        aspect.before( tabContainer, 'removeChild', lang.hitch( tabContainer, function( page )
        
            if(this.selectedChildWidget === page)
            
                this.selectedChildWidget = undefined;
                if(this._started)
                
                    var children = this.getChildren();
                    this.selectChild( children[0] );
                
            

            return page;
         ) );
    
);

或者,您也可以在标签的ContentPane 上使用onClose 扩展点:

require( [ 'dijit/registry', 'dojo/_base/lang' ],
    function( registry, lang ) 
        newTabPane.onClose = lang.hitch(this, function () 
            // select first
            var tabContainer = registry.byId('tab_container'),
                all_tabs = tabContainer.getChildren();
            tabContainer.selectChild( all_tabs[0] );

            // allow save to go ahead
            return true;
        );
    
);

显然,这两种方法都允许您在关闭的选项卡上选择特定的不同窗格,而不是稍作调整...

【讨论】:

以上是关于关闭选项卡以关注上一个选项卡而不是第一个选项卡时如何更改 dojo 内容选项卡焦点?的主要内容,如果未能解决你的问题,请参考以下文章

移动 Safari - Javascript 打开选项卡而不会失去对当前页面的关注

如何在关闭特定选项卡而不是在 Angular 2 中关闭浏览器时清除本地存储?

我可以在 A 标签上添加一个属性来获取在新选项卡而不是同一窗口中打开的链接吗?

关闭选项卡时如何防止调试器停止

NodeJS:打开新选项卡而不是默认用户浏览器

当使用angular8单击选项卡时,如何使选项卡聚焦在第一个字段上