如何配置 Featherlight 以支持模态中的 tabindex?

How can I configure Featherlight to support tabindex within the modal?

我的表单(look at the demo fiddle here,我还在下面粘贴了一些代码)似乎不支持 Featherlight 模态中的 tabindex。

我认为这是因为 this part of Featherlight here

如何在模式中显示表单并让用户按 TAB 键跳转到下一个字段?

看来我需要在 Featherlight 库中添加 hack,但我不想这样做。

谢谢!


<div style="display: none;">
  <div id="modal">
    My form NEEDS to support tabindex. If Featherlight is going to set tabindex to -1 for anything (even temporarily), it should only be for elements that aren't inside the modal.
    <div class="mainInputWrapper">
      <input type="text" name="fullname" placeholder="Your Name" required id="firstname" /><span class="forValidationDisplay"></span>
    </div>
    <div class="mainInputWrapper">
      <input type="email" name="email" placeholder="Your Best Email Address*" required id="email" /><span class="forValidationDisplay"></span>
    </div>
    <button>
      Submit
    </button>
  </div>
</div>
<a class="role-element leadstyle-link" href="#" data-featherlight="#modal">Click here if you're interested</a>

为什么 featherlight 中的 buttons 会保持 tabbable 而 input.

却不是

我会修复错误。

对此感到抱歉。

我找到了一种覆盖 Featherlight 并避免编辑其源代码的方法。

    $.featherlight._callbackChain.beforeOpen = function (event) {
        //
        //By overriding this function, I can prevent the messing up of tabindex values done by: https://github.com/noelboss/featherlight/blob/master/src/featherlight.js#L559            
    };
    $.featherlight._callbackChain.afterClose = function (event) {
        //See note above in $.featherlight._callbackChain.beforeOpen
    };
    $.featherlight.defaults.afterContent = function (event) {
        var firstInput = $('.featherlight-content #firstname');
        console.log('Considering whether to focus on input depending on window size...', $(window).width(), $(window).height(), firstInput);
        if (Math.min($(window).width(), $(window).height()) > 736) {//if the smallest dimension of the device is larger than iPhone6+
            console.log('yes, focus');
            firstInput.attr('autofocus', true);
        }
    };

以防万一,@Ryan 代码的最后一条语句不是必需的。

我在源代码的末尾添加了这个(因为在我的情况下我不介意编辑源代码)并且它起作用了:

$.featherlight._callbackChain.beforeOpen = function (event) {
        //
        //By overriding this function, I can prevent the messing up of tabindex values done by: https://github.com/noelboss/featherlight/blob/master/src/featherlight.js#L559
};
$.featherlight._callbackChain.afterClose = function (event) {
    //See note above in $.featherlight._callbackChain.beforeOpen
};

我对 tabindex=-1 问题的解决方法:

        afterContent: function(event) {
            $j('.featherlight-content input').each(function(index){
                if(index == 1) {
                    $j(this).prop('autofocus',true);
                }
                $j(this).prop('tabindex',index);
            });
        }

我使用一个小的 jquery 函数来修复 tabIndex :

$.fn.fixTabIndex = function(){

    // We don't modify tabindex or focus for hidden inputs
    this.find('input[type!="hidden"]').each(function(i, e){

        var $this = $(this);

        // Focus on first input with data-focus attribute
        if($this.data('focus')){
            $this.focus();
        }

        // Set tabindex with current index plus a random number (default 100)
        $this.prop('tabindex', 100 + i);
    });

    return this; // chainable methods
};

应该将 data-focus="true" 添加到所需的输入中。

用法:

    $(featherlight-selector).featherlight({
        targetAttr: 'href',
        afterContent: function(){
            $(form-selector)fixTabIndex();
        }
    });

也许有更好的方法 select 形成...

不幸的是,接受的答案破坏了禁用滚动功能。

Luis Paulo Lohmann 的回答更好,恕我直言。这是它的一个稍微改进的版本:

afterContent: function () {
    $('.featherlight-content').find('a, input[type!="hidden"], select, textarea, iframe, button:not(.featherlight-close), iframe, [contentEditable=true]').each(function (index) {
        if (index === 0) {
            $(this).prop('autofocus', true);
        }
        $(this).prop('tabindex', 0);
    });
}

改进:

感谢@Ryan 为我指明了正确的方向。我让这个以 definitely-a-hack 的方式工作。我没有重置 featherlight 中的内容,而是更新了原始的 .not 以忽略 featherlight 实例中包含的任何内容。这给我留下了以下内容。这里肯定有一些不是最佳实践的位可以使用一些工作,比如临时实例和等待内容更新的超时,但我现在没有更多时间处理它。

这是基于对第二个 .not 进行更改的来源。它保持模态外没有制表符,没有滚动,并且 return 到原始焦点。

$.featherlight._callbackChain.beforeOpen = function (_super, event) {
  $(document.documentElement).addClass('with-featherlight');

  // Remember focus:
  this._previouslyActive = document.activeElement;

  // Disable tabbing outside the current instance:
  // See 
  // Starting point 
  // Updates here. Don't give the tabindex to elements within the currently open featherlight container.
  // This wasn't working with the current state of the content. The intended content is not yet in the instance,
  // the timeout forces its hand.
  var tempInstance = this.$instance.get(0);
  setTimeout(function() {
    this._$previouslyTabbable = $("a, input, select, textarea, iframe, button, iframe, [contentEditable=true]")
      .not('[tabindex]')
      .not(function (index, element) {
        return $.contains(tempInstance, element)
      });

    this._$previouslyWithTabIndex = $('[tabindex]').not('[tabindex="-1"]');
    this._previousWithTabIndices = this._$previouslyWithTabIndex.map(function (_i, elem) {
      return $(elem).attr('tabindex');
    });

    this._$previouslyWithTabIndex.add(this._$previouslyTabbable).attr('tabindex', -1);
  }.bind(this), 100);

  if (document.activeElement.blur) {
    document.activeElement.blur();
  }
  return _super(event);
};