Лучший способ найти «следующий» элемент ввода формы в jQuery? - PullRequest
38 голосов
/ 14 ноября 2008

С помощью jQuery, как лучше всего найти следующий элемент формы на странице, начиная с произвольного элемента? Когда я говорю элемент формы, я имею в виду <input>, <select>, <button> или <textarea>.

В следующих примерах элемент с идентификатором «this» является произвольной отправной точкой, а элемент с идентификатором «next» - тем, который я хочу найти. Один и тот же ответ должен работать для всех примеров.

Пример 1:

<ul>
 <li><input type="text" /></li>
 <li><input id="this" type="text" /></li>
</ul>

<ul>
 <li><input id="next" type="text" /></li>
</ul>

<button></button>

Пример 2:

<ul>
 <li><input id="this" type="text" /></li>
</ul>

<button id="next"></button>

Пример 3:

<input id="this" type="text" />
<input id="next" type="text" />

Пример 4:

<div>
  <input id="this" type="text" />
  <input type="hidden" />
  <div>
    <table>
      <tr><td></td><td><input id="next" type="text" /></td></tr>
    </table>
  </div>
  <button></button>
</div>

РЕДАКТИРОВАТЬ: два ответа, представленные до сих пор, оба требуют записи порядкового номера для всех элементов ввода на странице. Как я упоминал в комментариях к одному из них, это то, что я уже делаю, и я бы предпочел иметь решение только для чтения, поскольку это будет происходить внутри плагина.

Ответы [ 12 ]

52 голосов
/ 15 ноября 2008

престижность,

А как насчет использования .index?

например, $(':input:eq(' + ($(':input').index(this) + 1) + ')');

13 голосов
/ 19 июля 2010

redsquare абсолютно прав и отличное решение, которое я также использовал в одном из моих проектов.

Я просто хотел указать на то, что ему не хватает скобок, поскольку текущее решение объединяет индекс с 1 вместо их сложения вместе.

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

$(":input:eq(" + ($(":input").index(this) + 1) + ")");

Извините за двойной пост, но я не смог найти способ прокомментировать его пост ...

10 голосов
/ 14 декабря 2011

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

function nextOnTabIndex(element) {
      var fields = $($('form')
                    .find('a[href], button, input, select, textarea')
                    .filter(':visible').filter('a, :enabled')
                    .toArray()
                    .sort(function(a, b) {
                      return ((a.tabIndex > 0) ? a.tabIndex : 1000) - ((b.tabIndex > 0) ? b.tabIndex : 1000);
                    }));


      return fields.eq((fields.index(element) + 1) % fields.length);
    }

Он работает, собирая все поля с вкладками в форме (как это разрешено http://www.w3.org/TR/html5/editing.html#focus-management),, а затем сортируя поля на основе (http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute)), чтобы найти следующий элемент для табуляции. он смотрит на то, где переданное поле находится в этом массиве, и возвращает следующий элемент.

Несколько замечаний:

  • jQuery поддерживает sort () для объекта jQuery, но я не могу найти это явно в документации, следовательно, вызывая toArray (), а затем переупаковка массива в объекте jQuery.
  • Есть и другие поля, которые все в порядке, но я оставил их, поскольку они не являются стандартными поля формы.

Код, который я использовал для проверки этого, был (используя jQuery 1.7):

<script>
  $(function() {
    $('a[href], button, input, select, textarea').click(function() {
      console.log(nextOnTabIndex($(this)).attr('name'));
    })
  });
</script>

<form>
  <input type='text' name='a'/>
  <input type='text' name='b' tabindex='1' />
  <a>Hello</a>
  <input type='text' name='c'/>
  <textarea name='d' tabindex='2'></textarea>
  <input id='submit' type='submit' name='e' tabindex='1' />
</form>
7 голосов
/ 26 сентября 2013

Попробовав каждый код, который я смог найти (и возникли проблемы между браузерами), я нашел тот, который работает в лучших браузерах. Не удалось использовать предыдущие подпрограммы из-за некоторых странных проблем.

$(document.body).keydown(function(event) {
    if(event.keyCode == 13 ) {
        $(":input")[$(":input").index(document.activeElement) + 1].focus();
        return false;
    }
});

Надеюсь, это поможет кому-то еще. Наслаждайтесь.

2 голосов
/ 15 ноября 2008

Вы можете сделать это, чтобы получить полный список элементов формы, которые вы ищете:

var yourFormFields = $("yourForm").find('button,input,textarea,select');

Тогда, должно быть легко найти следующий элемент:

var index = yourFormFields.index( this ); // the index of your current element in the list. if the current element is not in the list, index = -1

if ( index > -1 && ( index + 1 ) < yourFormFields.length ) { 

                    var nextElement = yourFormFields.eq( index + 1 );

                    }
2 голосов
/ 14 ноября 2008

Вы можете присвоить каждому элементу формы идентификатор (или уникальное имя класса), который идентифицирует его как элемент формы, а также дает ему индекс. Например:

<div>
    <input id="FormElement_0" type="text" />
    <input id="FormElement_1" type="text" />
<div>

Затем, если вы хотите перейти от первого элемента ко второму, вы можете сделать что-то вроде этого:

//I'm assuming "this" is referring to the first input

//grab the id
var id = $(this).attr('id');

//get the index from the id and increment it
var index = parseInt(id.split('_')[0], 10);
index++;

//grab the element witht that index
var next = $('#FormElement_' + index);

Преимущество этого заключается в том, что вы можете пометить любой элемент следующим, независимо от его местоположения или типа. Вы также можете контролировать порядок своего обхода. Поэтому, если по какой-либо причине вы хотите пропустить элемент и вернуться к нему позже, вы можете сделать это тоже.

1 голос
/ 15 ноября 2008

Я придумал функцию, которая выполняет работу без явного определения индексов:

function nextInput(form, id) {
    var aInputs = $('#' + form).find(':input[type!=hidden]');
    for (var i in aInputs) {
        if ($(aInputs[i]).attr('id') == id) {
            if (typeof(aInputs[parseInt(i) + 1]) != 'undefined') {
                return aInputs[parseInt(i) + 1];
            }
        }
    }
}

А вот рабочий пример. Теги формы предназначены для согласованности. Все, что вам действительно нужно, это общий родительский элемент, и он может просто использовать тег body в качестве родительского (с небольшим изменением функции).

Вставьте это в файл и откройте с помощью firefox / firebug, и вы увидите, что он возвращает правильный элемент для всех ваших примеров:

<html>
  <head>
    <script src="http://www.google.com/jsapi"></script>
    <script>
      function nextInput(form, id) {
        var aInputs = $('#' + form).find(':input[type!=hidden]');
        for (var i in aInputs) {
          if ($(aInputs[i]).attr('id') == id) {
            if (typeof(aInputs[parseInt(i) + 1]) != 'undefined') {
              return aInputs[parseInt(i) + 1];
            }
          }
        }
      }

      google.load("jquery", "1.2.6");
      google.setOnLoadCallback(function() {
        console.log(nextInput('myform1', 'this1'));
        console.log(nextInput('myform2', 'this2'));
        console.log(nextInput('myform3', 'this3'));
        console.log(nextInput('myform4', 'this4'));
      });
    </script>
  </head>
  <body>
    <form id="myform1">
      <ul>
         <li><input type="text" /></li>
         <li><input id="this1" type="text" /></li>
      </ul>
      <ul>
        <li><input id="next1" type="text" /></li>
      </ul>
    </form>

    <form id="myform2">
      <ul>
         <li><input type="text" /></li>
         <li><input id="this2" type="text" /></li>
      </ul>
      <ul>
        <li><input id="next2" type="text" /></li>
      </ul>
    </form>

    <form id="myform3">
      <input id="this3" type="text" />
      <input id="next3" type="text" />
    </form>

    <form id="myform4">
      <div>
        <input id="this4" type="text" />
        <input type="hidden" />
        <div>
        <table>
          <tr><td></td><td><input id="next4" type="text" /></td></tr>
        </table>
        </div>
        <button></button>
      </div>
    </form>
  </body>
</html>
1 голос
/ 14 ноября 2008

Или вы можете использовать html-атрибут 'tabindex', который используется, когда пользователь перемещается по форме, переходя от tabindex = "i" к tabindex = "i + 1". Вы можете использовать jQuery, чтобы получить атрибут очень легко. Также было бы неплохо вернуться к пользователям без включенного JavaScript.

0 голосов
/ 25 июня 2014

Все решения, использующие индекс (или nextAll), будут работать только в том случае, если все входные данные формы являются братьями и сестрами, например в том же блоке <div>. Следующая процедура позволяет обойти это путем создания массива идентификаторов всех видимых, не доступных только для чтения входных данных на странице и выбирает первый после текущего элемента управления, округляя, если текущий элемент управления является последним на странице.

ids = $(":input:visible:not([readonly])").map(function () { return this.id });
nextId = ids[($.inArray($(this).attr("id"), ids) + 1) % ids.length];
$("#" + nextId).focus();

Использование функции map делает ее несколько более краткой, чем решения с использованием итераторов.

0 голосов
/ 20 февраля 2014

Это хорошо сработало для меня и правильно пропускает скрытые вводы:

input_el.nextAll( 'input:visible:first' ).focus();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...