Фокус Следующий Элемент В Индексе Вкладки



Я пытаюсь переместить фокус на следующий элемент в последовательности вкладок на основе текущего элемента, который имеет фокус. До сих пор я ничего не нашел в своих поисках.



function OnFocusOut()
{
var currentElement = $get(currentElementId); // ID set by OnFocusIn

currentElementId = "";
currentElement.nextElementByTabIndex.focus();
}


конечно nextElementByTabIndex является ключевой частью для этой работы. Как найти следующий элемент в последовательности вкладок? Решение должно быть основано на использовании JScript, а не что-то вроде JQuery.

692   12  

12 ответов:

без jquery: Прежде всего, на ваших закладочных элементах добавьте class="tabable" Это позволит нам выбрать их позже. (Не забывайте о"."префикс селектора класса в коде ниже)

var lastTabIndex = 10;
function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFOcusIn
    var curIndex = currentElement.tabIndex; //get current elements tab index
    if(curIndex == lastTabIndex) { //if we are on the last tabindex, go back to the beginning
        curIndex = 0;
    }
    var tabbables = document.querySelectorAll(".tabable"); //get all tabable elements
    for(var i=0; i<tabbables.length; i++) { //loop through each element
        if(tabbables[i].tabIndex == (curIndex+1)) { //check the tabindex to see if it's the element we want
            tabbables[i].focus(); //if it's the one we want, focus it and exit the loop
            break;
        }
    }
}

я никогда не реализовывал это, но я изучил подобную проблему, и вот что я хотел бы попробовать.

попробуй сначала

во-первых, я хотел бы посмотреть, если бы вы могли просто огонь a keypress событие для клавиши Tab на элементе, который в настоящее время имеет фокус. Там может быть другой способ сделать это для разных браузеров.

если это не сработает, вам придется работать усерднее...

ссылаясь на реализацию jQuery, вы обязательно:

  1. слушайте Tab и Shift + Tab
  2. знать, какие элементы табуляции
  3. понять, как работает порядок вкладок

1. Слушайте Tab и Shift + Tab

прослушивание Tab и Shift + Tab, вероятно, хорошо освещены в другом месте в интернете, поэтому я пропущу эту часть.

2. Знайте, какие элементы табулируются

знание того, какие элементы являются вкладками, сложнее. В принципе, элемент является вкладка-возможность, если она фокусируется и не имеет атрибута tabindex="-1" set. Итак, мы должны спросить, какие элементы являются фокусируемыми. Следующие элементы являются фокусируемыми:

  • input,select,textarea,button и object элементы, которые не отключаются.
  • a и area элементы, которые имеют href или иметь числовое значение tabindex set.
  • любой элемент, который имеет числовое значение tabindex набор.

кроме того, элемент фокусируется только в том случае, если:

  • ни один из его предков display: none.
  • вычисленное значение visibility и visible. Это означает, что ближайший предок должен иметь visibility set должен иметь значение visible. Если ни один предок не имеет visibility установить, то вычисленное значение visible.

подробнее в другом ответ переполнения стека.

3. Поймите, как работает порядок вкладок

порядок табуляции элементов в документе контролируется . Если значение не установлено,tabindex эффективно 0.

The tabindex заказ на документ есть: 1, 2, 3, ..., 0.

изначально, когда body элемент (или нет элемента) имеет фокус, первый элемент в порядке табуляции является самым низким ненулевым tabindex. Если несколько элементов имеют то же самое tabindex, затем вы идете в порядке документа пока вы не достигнете последнего элемента с этим tabindex. Затем вы переходите к следующему самому низкому tabindex и процесс продолжается. Наконец, закончите с этими элементами с нулем (или пустым) tabindex.

Я создал простой плагин jQuery что делает именно это. Он использует ':селектор tabbable' пользовательского интерфейса jQuery, чтобы найти следующий tabbable элемент и выбрать его.

пример использования:

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){
    $.tabNext();
    return false;
});

вот что я строю для этой цели:

        focusNextElement: function () {
            //add all elements we want to include in our selection
            var focussableElements = 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])';
            if (document.activeElement && document.activeElement.form) {
                var focussable = Array.prototype.filter.call(document.activeElement.form.querySelectorAll(focussableElements),
                function (element) {
                    //check for visibility while always include the current activeElement 
                    return element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement
                });
                var index = focussable.indexOf(document.activeElement);
                if(index > -1) {
                   var nextElement = focussable[index + 1] || focussable[0];
                   nextElement.focus();
                }                    
            }
        }

характеристики:

  • настраиваемый набор фокусируемых элементов
  • jQuery не требуется
  • работает во всех современных браузерах
  • быстрый и легкий

суть ответа заключается в поиске следующего элемента:

  function findNextTabStop(el) {
    var universe = document.querySelectorAll('input, button, select, textarea, a[href]');
    var list = Array.prototype.filter.call(universe, function(item) {return item.tabIndex >= "0"});
    var index = list.indexOf(el);
    return list[index + 1] || list[0];
  }

использование:

var nextEl = findNextTabStop(element);
nextEl.focus();

обратите внимание, что я не забочусь о приоритизации tabIndex.

Как упоминалось в комментарии выше, я не думаю, что какие-либо браузеры предоставляют информацию о порядке табуляции. Здесь упрощенное приближение того, что браузер делает, чтобы получить следующий элемент в порядке табуляции:

var allowedTags = {input: true, textarea: true, button: true};

var walker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT,
  {
    acceptNode: function(node)
    {
      if (node.localName in allowedTags)
        return NodeFilter.FILTER_ACCEPT;
      else
        NodeFilter.FILTER_SKIP;
    }
  },
  false
);
walker.currentNode = currentElement;
if (!walker.nextNode())
{
  // Restart search from the start of the document
  walker.currentNode = walker.root;
  walker.nextNode();
}
if (walker.currentNode && walker.currentNode != walker.root)
  walker.currentNode.focus();

это только рассматривает некоторые теги и игнорирует

кажется, что вы можете проверить tabIndex свойство элемента, чтобы определить, является ли он фокусируемым. Элемент, который не является фокусируемым, имеет tabindex из "-1".

тогда вам просто нужно знать правила для табуляции:

  • tabIndex="1" имеет самый высокий приоритет.
  • tabIndex="2" имеет следующий наивысший приоритет.
  • tabIndex="3" следующий, и так далее.
  • tabIndex="0" (или tabbable по умолчанию) имеет самый низкий приоритет.
  • tabIndex="-1" (или не табулируется по умолчанию)не действует как табуляция.
  • для двух элементов, имеющих одинаковый tabIndex, тот, который появляется первым в DOM, имеет более высокий приоритет.

вот пример того, как построить список табуляторов, в последовательности, используя чистый Javascript:

function getTabStops(o, a, el) {
    // Check if this element is a tab stop
    if (el.tabIndex > 0) {
        if (o[el.tabIndex]) {
            o[el.tabIndex].push(el);
        } else {
            o[el.tabIndex] = [el];
        }
    } else if (el.tabIndex === 0) {
        // Tab index "0" comes last so we accumulate it seperately
        a.push(el);
    }
    // Check if children are tab stops
    for (var i = 0, l = el.children.length; i < l; i++) {
        getTabStops(o, a, el.children[i]);
    }
}

var o = [],
    a = [],
    stops = [],
    active = document.activeElement;

getTabStops(o, a, document.body);

// Use simple loops for maximum browser support
for (var i = 0, l = o.length; i < l; i++) {
    if (o[i]) {
        for (var j = 0, m = o[i].length; j < m; j++) {
            stops.push(o[i][j]);
        }
    }
}
for (var i = 0, l = a.length; i < l; i++) {
    stops.push(a[i]);
}

мы сначала идем по DOM, собирая все табуляции в последовательности с их индексом. Затем мы собираем окончательный список. Заметить это мы добавляем элементы с tabIndex="0" в самом конце списка, после пользования с tabIndex на 1, 2, 3, и т. д.

для полностью рабочего примера, где вы можете использовать вкладку с помощью клавиши "enter", проверьте это скрипка.

вы указали свои собственные значения tabIndex для каждого элемента, который вы хотите прокрутить? если да, то вы можете попробовать это:

var lasTabIndex = 10; //Set this to the highest tabIndex you have
function OnFocusOut()
{
    var currentElement = $get(currentElementId); // ID set by OnFocusIn 

    var curIndex = $(currentElement).attr('tabindex'); //get the tab index of the current element
    if(curIndex == lastTabIndex) { //if we are on the last tabindex, go back to the beginning
        curIndex = 0;
    }
    $('[tabindex=' + (curIndex + 1) + ']').focus(); //set focus on the element that has a tab index one greater than the current tab index
}

вы используете jquery, верно?

надеюсь, что это полезно.

<input size="2" tabindex="1" id="one"
  maxlength="2" onkeyup="toUnicode(this)" />

<input size="2" tabindex="2" id="two"
  maxlength="2" onkeyup="toUnicode(this)" />

<input size="2" tabindex="3" id="three"
 maxlength="2" onkeyup="toUnicode(this)" />

тогда используйте простой javascript

function toUnicode(elmnt)
{
  var next;
 if (elmnt.value.length==elmnt.maxLength)
{
next=elmnt.tabIndex + 1;
//look for the fields with the next tabIndex
var f = elmnt.form;
for (var i = 0; i < f.elements.length; i++)
{
  if (next<=f.elements[i].tabIndex)
  {
    f.elements[i].focus();
    break;
    }
   }
  }
}

Tabbable это небольшой пакет JS, который дает вам список всех элементов табуляции в разделе Заказ. Таким образом, вы можете найти свой элемент в этом списке, а затем сосредоточиться на следующей записи списка.

пакет правильно обрабатывает сложные крайние случаи, упомянутые в других ответах (например, ни один предок не может быть display: none). И это не зависит от jQuery!

на момент написания этой статьи (версия 1.1.1), он имеет предостережения, что он не поддерживает IE8, и что Ошибки браузера не позволяют ему обрабатывать contenteditable правильно.

Это мой первый пост на SO, поэтому у меня недостаточно репутации, чтобы прокомментировать принятый ответ, но мне пришлось изменить код следующим образом:

export function focusNextElement () {
  //add all elements we want to include in our selection
  const focussableElements = 
    'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled])'
  if (document.activeElement && document.activeElement.form) {
      var focussable = Array.prototype.filter.call(
        document.activeElement.form.querySelectorAll(focussableElements),
      function (element) {
          // if element has tabindex = -1, it is not focussable
          if ( element.hasAttribute('tabindex') && element.tabIndex === -1 ){
            return false
          }
          //check for visibility while always include the current activeElement 
          return (element.offsetWidth > 0 || element.offsetHeight > 0 || 
            element === document.activeElement)
      });
      console.log(focussable)
      var index = focussable.indexOf(document.activeElement);
      if(index > -1) {
         var nextElement = focussable[index + 1] || focussable[0];
         console.log(nextElement)
         nextElement.focus()
      }                    
  }
}

изменение var на константу не является критическим. Главное изменение заключается в том, что мы избавляемся от селектора, который проверяет tabindex != "-1". Затем позже, если элемент имеет атрибут tabindex и он установлен в "-1", мы не считаем его фокусируемым.

причина, по которой мне нужно было изменить это было потому, что при добавлении tabindex= " -1 " к <input>, этот элемент по-прежнему считался фокусируемым, поскольку он соответствует селектору "input[type=text]:not([disabled])". Мое изменение эквивалентно "если мы не отключаем ввод текста, и у нас есть атрибут tabIndex, а значение этого атрибута равно -1, то мы не должны считаться фокусируемыми.

Я считаю, что когда автор принятого ответа отредактировал свой ответ для учета атрибута tabIndex, они не сделали этого правильно. Пожалуйста я знаю, если это не так

вот более полная версия фокусировки на следующем элементе. Он соответствует требованиям спецификации и сортировка списка элементов, правильно используя свойство tabindex. Также обратная переменная определяется, если вы хотите получить предыдущий элемент.

function focusNextElement( reverse, activeElem ) {
  /*check if an element is defined or use activeElement*/
  activeElem = activeElem instanceof HTMLElement ? activeElem : document.activeElement;

  let queryString = [
      'a:not([disabled]):not([tabindex="-1"])',
      'button:not([disabled]):not([tabindex="-1"])',
      'input:not([disabled]):not([tabindex="-1"])',
      'select:not([disabled]):not([tabindex="-1"])',
      '[tabindex]:not([disabled]):not([tabindex="-1"])'
      /* add custom queries here */
    ].join(','),
    queryResult = Array.prototype.filter.call(document.querySelectorAll(queryString), elem => {
      /*check for visibility while always include the current activeElement*/
      return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem === activeElem;
    }),
    indexedList = queryResult.slice().filter(elem => {
      /* filter out all indexes not greater than 0 */
      return elem.tabIndex == 0 || elem.tabIndex == -1 ? false : true;
    }).sort((a, b) => {
      /* sort the array by index from smallest to largest */
      return a.tabIndex != 0 && b.tabIndex != 0 
        ? (a.tabIndex < b.tabIndex ? -1 : b.tabIndex < a.tabIndex ? 1 : 0) 
        : a.tabIndex != 0 ? -1 : b.tabIndex != 0 ? 1 : 0;
    }),
    focusable = [].concat(indexedList, queryResult.filter(elem => {
      /* filter out all indexes above 0 */
      return elem.tabIndex == 0 || elem.tabIndex == -1 ? true : false;
    }));

  /* if reverse is true return the previous focusable element
     if reverse is false return the next focusable element */
  return reverse ? (focusable[focusable.indexOf(activeElem) - 1] || focusable[focusable.length - 1]) 
    : (focusable[focusable.indexOf(activeElem) + 1] || focusable[0]);
}

Comments

    Ничего не найдено.