选项卡无法进入选定状态,直到被点击两次(第一次)

时间:2022-08-26 09:05:34

This has been happening for a long time since I have been working with jQuery UI Tabs, as seen on http://eq4.net/hive/ - upon first loading the page (or after adding a tab for that matter).

这已经发生了很长一段时间以来我一直在使用jQuery UI选项卡,如http://eq4.net/hive/上所见 - 首次加载页面时(或者在添加选项卡之后)。

After clicking once, the load and show events get triggered, but no content loads into the panel, and the currently selected tab index is set to -1 (none) and the tabs all fall out of selected state.

单击一次后,将触发加载和显示事件,但没有内容加载到面板中,并且当前选定的选项卡索引设置为-1(无),并且选项卡全部脱离选定状态。

Then if you click again, everything operates as you would expect, until you add a tab.

然后,如果再次单击,则所有操作都会按预期运行,直到您添加选项卡。

Can someone point me in the right direction so I can begin to debug this quirk? There is nothing in my code which should have any effect on tab selection, most of it is updating other aspects of the UI which seems to happen correctly.

有人能指出我正确的方向,所以我可以开始调试这个怪癖吗?我的代码中没有任何内容可以对选项卡选择产生任何影响,大部分内容都是更新UI的其他方面,这似乎是正确发生的。

I am using jQuery UI 1.8.20 and jQuery 1.7.2 - thank you

我正在使用jQuery UI 1.8.20和jQuery 1.7.2 - 谢谢

4 个解决方案

#1


0  

Confirm the behaviour you report and can only suggest a workaround by which, after a tab is added, the previously selected tab is automatically re-selected twice. The first select will be the buggy ineffective one and the second will actually reselect the tab (and its associated panel).

确认您报告的行为,并且只能建议一种解决方法,在添加选项卡后,将自动重新选择以前选择的选项卡两次。第一个选择将是错误无效的选项,第二个将实际重新选择选项卡(及其相关的面板)。

Something along the following lines maybe :

以下几行可能是:

$(function(){

    ...

    var selectedTab = null;

    $(selector).tabs({
          ...
          select: function(event, ui) {
              //Keep `selectedTab` up to date to remember the selected tab
              selectedTab = ui.tab; //or ui.index?
          }
          add: function(event, ui) {
               //Here re-select selectedTab twice (if not null).
               //Probably easier to use selectedTab.trigger('click') than the tabs' .select() method, (which requires the selector to be known).
          }
    });
});

It's difficult to see how to handle the special case where no tab has yet been selected (ie. selectedTab === null).

很难看出如何处理尚未选择制表符的特殊情况(即selectedTab === null)。

This would be a nasty, inefficient fudge (and not recommended with ajax mode) but would save having to hack the plugin (which, if easily fixable, would have been fixed).

这将是一个讨厌,低效的软糖(并不建议使用ajax模式),但可以节省不得不破解插件(如果容易修复,将修复)。

#2


0  

Turns out it was the fx option causing this behavior, I will venture to guess the event bubbler didn't bubble right.

原来是导致这种行为的fx选项,我冒昧地猜测事件起泡器没有冒泡。

upon removing:

fx: {
     opacity: 'toggle',
    duration: 100
}

tabs now load as they should. I will explore exactly what does (and doesn't) happen when using the fx option and report back.

标签现在加载它们应该。我将详细探讨使用fx选项并报告时会发生什么(和不会发生)。

#3


0  

try putting this

试试这个

      $( "#pages" ).tabs().find( ".ui-tabs-nav" ).sortable({ 
              axis: "x",   sort: function(event, ui) {
                        },

in Document.Ready

      $(document).ready(function () {
            $( "#pages" ).tabs().find( ".ui-tabs-nav" ).sortable({
                axis: "x",
                sort: function(event, ui) {

            },
      });

#4


0  

With credit to Google, it is apparent that there are several issues to do with jQuery UI tabs' .add() method, however the following process seems (unsurprisingly?) to be thoroughly reliable:

有了Google的信誉,显然有几个问题与jQuery UI标签'.add()方法有关,但是以下过程似乎(不出所料?)是完全可靠的:

  • call .tabs('destroy')
  • append a new tab (ie. a new li node), "manually"
  • 附加一个新标签(即一个新的li节点),“手动”

  • re-initialize .tabs()

On the surface, this is quite simple to achieve though in practice there are a few hoops to jump through in the development of generalized working code - chiefly:

从表面上看,这很容易实现,但在实践中,在开发通用工作代码时会有一些窍门 - 主要是:

  • the need to preserve the native .add() method's ability to insert tabs at any index, not just at the end
  • 需要保留原生.add()方法在任何索引处插入制表符的能力,而不仅仅是在最后

  • the need to maintain track of the currently selected tab and to re-select it after re-initialization
  • 需要保持跟踪当前选定的选项卡,并在重新初始化后重新选择它

  • the need to ensure that the full range of UI's .tabs() options remains available.
  • 需要确保所有UI的.tabs()选项仍然可用。

Great, a chance to write something challenging!

太棒了,有机会写出具有挑战性的东西!

After playing with the code for a while, I came to the conclusion that a "feeder" (more conventionally an "adapter") pattern was more appropriate (and simpler) than a patch or monkey-patch for the UI tabs plugin itself and after several iterations I came up with a lightweight jQuery plugin to do the job :

在使用代码一段时间之后,我得出的结论是,“馈送器”(更常规的“适配器”)模式比UI选项卡插件本身以及之后的补丁或猴子补丁更合适(并且更简单)几次迭代我想出了一个轻量级的jQuery插件来完成这项工作:

$.fn['tabsFeeder'] = function(options) {
    this.on('addTab', function(event, url, label, index) {
        var $that = $(this),
            s = $that.data('tabs').options;
        $that.tabs('destroy');
        try {
            var $lis = $that.find('li'),
                n = $lis.length;
            index = Math.max((index === undefined) ? n : index, 0);
            $lis.eq(Math.min(index, n - 1))[(index < n) ? 'before' : 'after']('<li><a href="' + url + '">' + label + '</a></li>');
            if (s.selected !== undefined && index <= s.selected) {
                s.selected += 1;
            }
            throw ('');
        }
        catch (e) {
            $that.tabs(s);
        }
    });

    this.on('current', function(event, callback) {
        $that = $(this);
        if ($that.eq(0).length > 0 && typeof callback === 'function') {
            var ui = {
                'tab': $that.find('li.ui-state-active a'),
                'panel': $that.find('.ui-tabs-panel').not('.ui-tabs-hide'),
                'index': $that.tabs('option', 'selected')
            };
            callback(event, ui);
        }
    });
    this.tabs(options);
};

Trust me, it's lightweight.

相信我,它很轻巧。

With this plugin (and jQuery UI tabs) in place, the bottom line is that we can now:

有了这个插件(和jQuery UI选项卡),底线是我们现在可以:

  • initialize tabs with $('selector').tabsFeeder(options), where options are the standard jQuery UI tabs options - no additions and no omissions
  • 使用$('selector')初始化选项卡。tabsFeeder(options),其中options是标准的jQuery UI选项卡选项 - 没有添加和没有遗漏

  • call $('selector').trigger("addTab", [url, label]); or $('selector').trigger("addTab", [url, label, index]); instead of .tabs("add", url, label) or .tabs("add", url, label, index).
  • 调用$('selector')。trigger(“addTab”,[url,label]);或$('selector')。trigger(“addTab”,[url,label,index]);而不是.tabs(“add”,url,label)或.tabs(“add”,url,label,index)。

And for good measure, I included a current custom event to give access to the currently selected tab (delivered to a callback function as a "ui" object as per tabs native events).

为了更好地衡量,我包含了一个当前的自定义事件来访问当前选定的选项卡(根据选项卡本机事件将其作为“ui”对象传递给回调函数)。

I'm not sure I can thoroughly justify the use of a custom event handlers instead of proper method, except to say that the plugin :

我不确定我是否可以完全证明使用自定义事件处理程序而不是正确的方法,除了说插件:

  • was easier to write
  • 写得更容易

  • is more concise
  • 更简洁

  • doesn't need to write any data of its own to the DOM.
  • 不需要将自己的任何数据写入DOM。

  • method chaining is guaranteed
  • 方法链是有保证的

You can see tabsFeeder in action here

您可以在此处查看tabsFeeder

Shortcomings

Because tabsFeeder relies on reinitializing .tabs(), it is inefficient and probably unsuitable for use with ajax mode as content may need to be re-fetched - but by all means try - performance may be acceptable.

因为tabsFeeder依赖于重新初始化.tabs(),所以效率很低,并且可能不适合与ajax模式一起使用,因为内容可能需要重新获取 - 但无论如何都要尝试 - 性能可能是可以接受的。

The "addTab" event handler uses UI tabs plugin's select event to track the current tab. In order to allow a select callback to be specified in the options, I opted for a compact observer-like pattern in which the firing order is hard-coded as standard callback (if present) followed by the plugin's defaultSelect() (one JavaScript statement). Whereas this seems logical and works fine in the demo, it is not fully explored and I can't guarantee that it will be correct in all applications. It would be possible to allow the order (A-B versus B-A) to be established programmatically, but this would be tedious to code and probably not necessary.

“addTab”事件处理程序使用UI选项卡插件的select事件来跟踪当前选项卡。为了允许在选项中指定选择回调,我选择了一个紧凑的类似观察者的模式,其中触发顺序被硬编码为标准回调(如果存在),然后是插件的defaultSelect()(一个JavaScript语句) )。虽然这看似合乎逻辑且在演示中运行良好,但尚未完全探索,我不能保证它在所有应用程序中都是正确的。可以允许以编程方式建立订单(A-B与B-A),但这对于编码而言可能是乏味的,并且可能不是必需的。

#1


0  

Confirm the behaviour you report and can only suggest a workaround by which, after a tab is added, the previously selected tab is automatically re-selected twice. The first select will be the buggy ineffective one and the second will actually reselect the tab (and its associated panel).

确认您报告的行为,并且只能建议一种解决方法,在添加选项卡后,将自动重新选择以前选择的选项卡两次。第一个选择将是错误无效的选项,第二个将实际重新选择选项卡(及其相关的面板)。

Something along the following lines maybe :

以下几行可能是:

$(function(){

    ...

    var selectedTab = null;

    $(selector).tabs({
          ...
          select: function(event, ui) {
              //Keep `selectedTab` up to date to remember the selected tab
              selectedTab = ui.tab; //or ui.index?
          }
          add: function(event, ui) {
               //Here re-select selectedTab twice (if not null).
               //Probably easier to use selectedTab.trigger('click') than the tabs' .select() method, (which requires the selector to be known).
          }
    });
});

It's difficult to see how to handle the special case where no tab has yet been selected (ie. selectedTab === null).

很难看出如何处理尚未选择制表符的特殊情况(即selectedTab === null)。

This would be a nasty, inefficient fudge (and not recommended with ajax mode) but would save having to hack the plugin (which, if easily fixable, would have been fixed).

这将是一个讨厌,低效的软糖(并不建议使用ajax模式),但可以节省不得不破解插件(如果容易修复,将修复)。

#2


0  

Turns out it was the fx option causing this behavior, I will venture to guess the event bubbler didn't bubble right.

原来是导致这种行为的fx选项,我冒昧地猜测事件起泡器没有冒泡。

upon removing:

fx: {
     opacity: 'toggle',
    duration: 100
}

tabs now load as they should. I will explore exactly what does (and doesn't) happen when using the fx option and report back.

标签现在加载它们应该。我将详细探讨使用fx选项并报告时会发生什么(和不会发生)。

#3


0  

try putting this

试试这个

      $( "#pages" ).tabs().find( ".ui-tabs-nav" ).sortable({ 
              axis: "x",   sort: function(event, ui) {
                        },

in Document.Ready

      $(document).ready(function () {
            $( "#pages" ).tabs().find( ".ui-tabs-nav" ).sortable({
                axis: "x",
                sort: function(event, ui) {

            },
      });

#4


0  

With credit to Google, it is apparent that there are several issues to do with jQuery UI tabs' .add() method, however the following process seems (unsurprisingly?) to be thoroughly reliable:

有了Google的信誉,显然有几个问题与jQuery UI标签'.add()方法有关,但是以下过程似乎(不出所料?)是完全可靠的:

  • call .tabs('destroy')
  • append a new tab (ie. a new li node), "manually"
  • 附加一个新标签(即一个新的li节点),“手动”

  • re-initialize .tabs()

On the surface, this is quite simple to achieve though in practice there are a few hoops to jump through in the development of generalized working code - chiefly:

从表面上看,这很容易实现,但在实践中,在开发通用工作代码时会有一些窍门 - 主要是:

  • the need to preserve the native .add() method's ability to insert tabs at any index, not just at the end
  • 需要保留原生.add()方法在任何索引处插入制表符的能力,而不仅仅是在最后

  • the need to maintain track of the currently selected tab and to re-select it after re-initialization
  • 需要保持跟踪当前选定的选项卡,并在重新初始化后重新选择它

  • the need to ensure that the full range of UI's .tabs() options remains available.
  • 需要确保所有UI的.tabs()选项仍然可用。

Great, a chance to write something challenging!

太棒了,有机会写出具有挑战性的东西!

After playing with the code for a while, I came to the conclusion that a "feeder" (more conventionally an "adapter") pattern was more appropriate (and simpler) than a patch or monkey-patch for the UI tabs plugin itself and after several iterations I came up with a lightweight jQuery plugin to do the job :

在使用代码一段时间之后,我得出的结论是,“馈送器”(更常规的“适配器”)模式比UI选项卡插件本身以及之后的补丁或猴子补丁更合适(并且更简单)几次迭代我想出了一个轻量级的jQuery插件来完成这项工作:

$.fn['tabsFeeder'] = function(options) {
    this.on('addTab', function(event, url, label, index) {
        var $that = $(this),
            s = $that.data('tabs').options;
        $that.tabs('destroy');
        try {
            var $lis = $that.find('li'),
                n = $lis.length;
            index = Math.max((index === undefined) ? n : index, 0);
            $lis.eq(Math.min(index, n - 1))[(index < n) ? 'before' : 'after']('<li><a href="' + url + '">' + label + '</a></li>');
            if (s.selected !== undefined && index <= s.selected) {
                s.selected += 1;
            }
            throw ('');
        }
        catch (e) {
            $that.tabs(s);
        }
    });

    this.on('current', function(event, callback) {
        $that = $(this);
        if ($that.eq(0).length > 0 && typeof callback === 'function') {
            var ui = {
                'tab': $that.find('li.ui-state-active a'),
                'panel': $that.find('.ui-tabs-panel').not('.ui-tabs-hide'),
                'index': $that.tabs('option', 'selected')
            };
            callback(event, ui);
        }
    });
    this.tabs(options);
};

Trust me, it's lightweight.

相信我,它很轻巧。

With this plugin (and jQuery UI tabs) in place, the bottom line is that we can now:

有了这个插件(和jQuery UI选项卡),底线是我们现在可以:

  • initialize tabs with $('selector').tabsFeeder(options), where options are the standard jQuery UI tabs options - no additions and no omissions
  • 使用$('selector')初始化选项卡。tabsFeeder(options),其中options是标准的jQuery UI选项卡选项 - 没有添加和没有遗漏

  • call $('selector').trigger("addTab", [url, label]); or $('selector').trigger("addTab", [url, label, index]); instead of .tabs("add", url, label) or .tabs("add", url, label, index).
  • 调用$('selector')。trigger(“addTab”,[url,label]);或$('selector')。trigger(“addTab”,[url,label,index]);而不是.tabs(“add”,url,label)或.tabs(“add”,url,label,index)。

And for good measure, I included a current custom event to give access to the currently selected tab (delivered to a callback function as a "ui" object as per tabs native events).

为了更好地衡量,我包含了一个当前的自定义事件来访问当前选定的选项卡(根据选项卡本机事件将其作为“ui”对象传递给回调函数)。

I'm not sure I can thoroughly justify the use of a custom event handlers instead of proper method, except to say that the plugin :

我不确定我是否可以完全证明使用自定义事件处理程序而不是正确的方法,除了说插件:

  • was easier to write
  • 写得更容易

  • is more concise
  • 更简洁

  • doesn't need to write any data of its own to the DOM.
  • 不需要将自己的任何数据写入DOM。

  • method chaining is guaranteed
  • 方法链是有保证的

You can see tabsFeeder in action here

您可以在此处查看tabsFeeder

Shortcomings

Because tabsFeeder relies on reinitializing .tabs(), it is inefficient and probably unsuitable for use with ajax mode as content may need to be re-fetched - but by all means try - performance may be acceptable.

因为tabsFeeder依赖于重新初始化.tabs(),所以效率很低,并且可能不适合与ajax模式一起使用,因为内容可能需要重新获取 - 但无论如何都要尝试 - 性能可能是可以接受的。

The "addTab" event handler uses UI tabs plugin's select event to track the current tab. In order to allow a select callback to be specified in the options, I opted for a compact observer-like pattern in which the firing order is hard-coded as standard callback (if present) followed by the plugin's defaultSelect() (one JavaScript statement). Whereas this seems logical and works fine in the demo, it is not fully explored and I can't guarantee that it will be correct in all applications. It would be possible to allow the order (A-B versus B-A) to be established programmatically, but this would be tedious to code and probably not necessary.

“addTab”事件处理程序使用UI选项卡插件的select事件来跟踪当前选项卡。为了允许在选项中指定选择回调,我选择了一个紧凑的类似观察者的模式,其中触发顺序被硬编码为标准回调(如果存在),然后是插件的defaultSelect()(一个JavaScript语句) )。虽然这看似合乎逻辑且在演示中运行良好,但尚未完全探索,我不能保证它在所有应用程序中都是正确的。可以允许以编程方式建立订单(A-B与B-A),但这对于编码而言可能是乏味的,并且可能不是必需的。