jQuery UI Tabs插件无法处理2层标签

我正在处理一个使用jQuery UI选项卡以结构化方式显示用户生成的数据的旧项目。系统不限制用户可以创建的选项卡的数量(但通常第二层中大约有30个),而jQuery UI Tabs仅包装这些选项卡,这看起来非常不专业。

jQuery UI Tabs插件无法处理2层标签

我偶然发现了Paul Blundell于2014年推出的精美插件OverflowTabs(这是他的JSFiddle:http://jsfiddle.net/o1wLbtj4/,),但是不幸的是,我无法使其在我的2个选项卡层中都能正常工作。我正在使用jQuery 1.10.2和jQuery UI 1.10.4。

jQuery UI Tabs插件无法处理2层标签

我做了一个简化的JSFiddle,它显示了我要执行的操作:打开一个对话框窗口,其中包含2层选项卡中的数据。当标签过多时,两个层次都应将溢出的标签推入菜单,单击该菜单可打开一个下拉菜单,但此刻(在具有名称的层次上)仅显示最后一个标签,并且下拉按钮不起作用并显示为0:http://jsfiddle.net/megahra/6s2xwgec/18/

据我所知,该插件正确地从第一层中删除了选项卡,并将它们添加到溢出div(_hidetab函数)中,但是由于某些原因,后来被覆盖了。我怀疑该插件无法正确处理第二层,但我不知道在哪里解决。

如果有人能指出正确的方向,我将不胜感激!

编辑:
多亏了Twisty的帮助,该插件现在可用于多个选项卡级别,并且我修复了一些错误。
这是正在工作的JSFiddle: https://jsfiddle.net/megahra/uexr4qfw/289/
-已知错误:初始化时,此插件不适用于带有style="display: none"的div中的选项卡。

$.widget("ui.tabs",$.ui.tabs,{
  options: {
    overflowTabs: false,tabPadding: 25,containerPadding: 0,dropdownSize: 50
  },_create: function() {
    this._super("_create");
    this.tabsWidth = 0;
    this.containerWidth = 0;
    this.overflowTabsId = "id" + this._createUniqueId();

    $(this.element).addClass(this.overflowTabsId);

    if (!this.options.overflowTabs)
      return;

    // update the tabs
    this.updateOverflowTabs();

    // Detect a window resize and check the tabs again
    var that = this;
    var el = this.element;

    $(window).resize(function() {
      // Add a slight delay after resize,to fix Maximise issue.
      setTimeout(function() {
        that.updateOverflowTabs();
      },150);
    });

    // Detect dropdown click
    $(el).on("click",'> .overflow-selector',function(e) {
      $('> .ui-tabs-overflow',el).toggleclass('hide');

      $overflowTabs = $('.ui-tabs-overflow').not($('> .ui-tabs-overflow',el));

      //if there is more than the currently clicked one,close all others
      if($overflowTabs) {
        $overflowTabs.toggleclass('hide',true);
        }
    });

    //Detect tab click
    $('li a').on("click",function(e) {
        //close dropdown if open
        $('> .ui-tabs-overflow',el).toggleclass('hide',true);
        //ToDo: apply overflowTabs plugin to content of new tab (if it contains tabs)

    });
  },refresh: function() {
    this._super("refresh");
    this.updateOverflowTabs();
  },updateOverflowTabs: function() {
    var failsafe = 0;
    this._calculateWidths();
    var el = this.element;

    // Loop until tabsWidth is less than the containerWidth
    while (this.tabsWidth > this.containerWidth -10 && failsafe < 30) {
      this._hidetab();
      this._calculateWidths();
      failsafe++;
    }

    // Finish now if there are no tabs in the overflow list
    if ($('> .ui-tabs-overflow li',el).length === 0)
      return;

    // Reset
    failsafe = 0;

    // Get the first tab in the overflow list
    var next = this._nextTab();

    // Loop until we cannot fit any more tabs
    while (next.totalSize < this.containerWidth && $('> .ui-tabs-overflow li',el).length > 0 && failsafe < 30) {
      this._showTab(next.tab);
      this._calculateWidths();
      next = this._nextTab();
      failsafe++;
    }

    $('> .overflow-selector .total',el).html($('> .ui-tabs-overflow li',el).length);
  },_calculateWidths: function() {
    var width = 0;
    $(this.element).find('> .ui-tabs-nav > li').each(function() {
      width += $(this).outerWidth(true);
    });
    this.tabsWidth = width;
    this.containerWidth = $(this.element).parent().width() - this.options.containerPadding - this.options.dropdownSize;
  },_hidetab: function() {
    if (!$(this.element).find('> .ui-tabs-overflow').length) {
      $(this.element).find('> .ui-tabs-nav').after('<ul class="ui-tabs-overflow hide"></ul>');
      $(this.element).find('> .ui-tabs-overflow').after('<div class="overflow-selector">&#8595 <span class="total">0</span></div>');
      //calculate position of overflow-selector relativ to tab row (overflow-selector is 15px high)
      let topOffset = ($(this.element).find('> .ui-tabs-nav').innerHeight() * 0.48) - 12;
      $(this.element).find('> .overflow-selector').css('top',topOffset);
    }
    var lastTab = $('> .ui-tabs-nav li',this.element).last();
    lastTab.prependTo($('> .ui-tabs-overflow',this.element));
  },_showTab: function(tab) {
    tab.appendTo($('> .ui-tabs-nav',this.element));

    // Check to see if overflow list is now empty
    if ($(this.element).find('> .ui-tabs-overflow li').size() == 0) {
      $(this.element).find('> .ui-tabs-overflow').remove();
      $(this.element).find('> .overflow-selector').remove();
    }
  },_nextTab: function() {
    var result = {};
    var firstTab = $(this.element).find('> .ui-tabs-overflow li').first();
    result.tab = firstTab;
    result.totalSize = this.tabsWidth + this._textWidth(firstTab) + this.options.tabPadding;
    return result;
  },_textWidth: function(element) {
    var self = $(element),children = self.children(),calculator = $('<span style="display: inline-block;" />'),width;

    children.wrap(calculator);
    width = children.parent().width();
    children.unwrap();

    return width;
  },_createUniqueId: function() {
    // Math.random should be unique because of its seeding algorithm.
    // Convert it to base 36 (numbers + letters),and grab the first 9 characters
    // after the decimal.
    return '_' + Math.random().toString(36).substr(2,9);
    }
});
zhanglun0909 回答:jQuery UI Tabs插件无法处理2层标签

发现了一些旧代码用法,只是做了一些小的清理。我发现了几个问题。

工作示例:https://jsfiddle.net/Twisty/tbvasj1g/

  1. 点击事件非常贪婪,并且隐藏了不需要隐藏的列表项
  2. 添加/删除类是预切换方法。更新为使用.toggleClass()
  3. .size()已折旧为length

      

    注意:此方法已在jQuery 3.0中删除。请改用.length属性。   .size()方法在功能上等效于.length属性;但是,.length属性是首选的,因为它没有函数调用的开销。

  4. $(this.element).find(selector)替换为简写$(selector,this.element)

  5. .total更新从计算功能移到了更新功能。循环结束时,有些东西将其重置为0。不知道是什么。在那里进行更新只是没有意义,所以我将其移至现在可以使用。

小部件工厂

$.widget("ui.tabs",$.ui.tabs,{
  options: {
    overflowTabs: false,tabPadding: 25,containerPadding: 0,dropdownSize: 50
  },_create: function() {
    this._super("_create");
    this.tabsWidth = 0;
    this.containerWidth = 0;
    if (!this.options.overflowTabs)
      return;

    // update the tabs
    this.updateOverflowTabs();

    // Detect a window resize and check the tabs again
    var that = this;
    var el = this.element;

    $(window).resize(function() {
      // Add a slight delay after resize,to fix Maximise issue.
      setTimeout(function() {
        that.updateOverflowTabs();
      },150);
    });

    // Detect dropdown click
    $(".tabStructure").on("click",".overflow-selector",function(e) {
      $('.ui-tabs-overflow',el).toggleClass('hide');
    });
  },refresh: function() {
    this._super("refresh");
    this.updateOverflowTabs();
  },updateOverflowTabs: function() {
    var failsafe = 0;
    this._calculateWidths();
    var el = this.element;
    console.log("cWidth",this.containerWidth);

    // Loop until tabsWidth is less than the containerWidth
    while (this.tabsWidth > this.containerWidth && failsafe < 30) {
      //debugger;
      this._hideTab();
      this._calculateWidths();
      failsafe++;
    }

    // Finish now if there are no tabs in the overflow list
    if ($('.ui-tabs-overflow li',el).length === 0)
      return;

    // Reset
    failsafe = 0;

    // Get the first tab in the overflow list
    var next = this._nextTab();

    // Loop until we cannot fit any more tabs
    while (next.totalSize < this.containerWidth && $('.ui-tabs-overflow li',el).length > 0 && failsafe < 30) {
      this._showTab(next.tab);
      this._calculateWidths();
      next = this._nextTab();
      failsafe++;
    }

    $('.overflow-selector .total',el).html($('.ui-tabs-overflow li',el).length);
  },_calculateWidths: function() {
    var width = 0;
    $(this.element).find('.ui-tabs-nav > li').each(function() {
      width += $(this).outerWidth(true);
      //debugger;
    });
    this.tabsWidth = width;
    this.containerWidth = $(this.element).parent().width() - this.options.containerPadding - this.options.dropdownSize;
  },_hideTab: function() {
    if (!$('.ui-tabs-overflow').length) {
      $(this.element).find('.ui-tabs-nav').after('<ul class="ui-tabs-overflow hide"></ul>');
      $(this.element).find('.ui-tabs-overflow').after('<div class="overflow-selector">&#8595 <span class="total">0</span></div>');
    }
    var lastTab = $(this.element).find('.ui-tabs-nav li').last();
    lastTab.appendTo($(this.element).find('.ui-tabs-overflow'));
  },_showTab: function(tab) {
    tab.appendTo($(this.element).find('.ui-tabs-nav'));

    // Check to see if overflow list is now empty
    if ($(this.element).find('.ui-tabs-overflow li').size() == 0) {
      $(this.element).find('.ui-tabs-overflow').remove();
      $(this.element).find('.overflow-selector').remove();
    }
  },_nextTab: function() {
    var result = {};
    var firstTab = $(this.element).find('.ui-tabs-overflow li').first();
    result.tab = firstTab;
    result.totalSize = this.tabsWidth + this._textWidth(firstTab) + this.options.tabPadding;
    return result;
  },_textWidth: function(element) {
    var self = $(element),children = self.children(),calculator = $('<span style="display: inline-block;" />'),width;

    children.wrap(calculator);
    width = children.parent().width();
    children.unwrap();

    return width;
  }
});

$(function() {
  $("#rowDialog").dialog({
    title: 'Test modal',closeOnEscape: false,minHeight: 'auto',width: '600px',modal: true,resizable: true,buttons: [{
      // Close button
      text: 'Close',click: function() {
        $(this).dialog('close')
      },}]
  });

  $(".tabStructure").tabs({
    overflowTabs: true
  });
});

总体上不支持此解决方案。我建议分页。如果其他选项卡中没有内容或内容很多,则下拉列表将被剪切。另外,如果您从下拉菜单中选择一个选项卡,该选项卡将被隐藏,并且您也无法知道正在查看的选项卡,因为它们都不是可视指示器。

本文链接:https://www.f2er.com/3151505.html

大家都在问