it-swarm.com.de

Bester Weg, um "nächste" Form-Eingabeelement in jQuery zu finden?

Wie kann man mit jQuery das nächste Formularelement auf der Seite finden, beginnend mit einem beliebigen Element? Wenn ich Formularelement sage, meine ich <input>, <select>, <button> oder <textarea>.

In den folgenden Beispielen ist das Element mit der ID "this" der beliebige Startpunkt, und das Element mit der ID "Next" ist das Element, das ich finden möchte. Die gleiche Antwort sollte für alle Beispiele funktionieren.

Beispiel 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>

Beispiel 2

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

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

Beispiel 3:

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

Beispiel 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>

BEARBEITEN: Bei den beiden bisher gegebenen Antworten müssen alle Eingangselemente der Seite mit einer Folgenummer versehen werden. Wie ich bereits in den Kommentaren eines von ihnen erwähnt habe, mache ich das schon so, und ich würde eine schreibgeschützte Lösung vorziehen, da dies in einem Plugin geschieht.

37
kodos

kudos,

Was ist mit der Verwendung von .index?

z.B. $(':input:eq(' + ($(':input').index(this) + 1) + ')');

51
redsquare

redsquare ist absolut richtig und auch eine großartige Lösung, die ich auch in einem meiner Projekte verwendet habe.

Ich wollte nur darauf hinweisen, dass ihm einige Klammern fehlen, da die aktuelle Lösung den Index mit 1 verkettet, anstatt sie zusammenzumachen.

Die korrigierte Lösung würde also so aussehen:

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

Tut mir leid wegen des Doppelpostens, aber ich habe keinen Weg gefunden, seinen Beitrag zu kommentieren ...

13
reSPAWNed

Diese Lösung erfordert keine Indizes und spielt auch gut mit tabindex - mit anderen Worten, Sie erhalten genau das Element, das der Browser Ihnen auf der Registerkarte geben würde, ohne zusätzlichen Aufwand.

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);
    }

Es funktioniert, indem Sie alle tabellierbaren Felder im Formular (wie in http://www.w3.org/TR/html5/editing.html#focus-management ) erlaubt, und dann die Felder nach ( http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute ), um das nächste zu ermittelnde Element zu ermitteln. Sobald dies der Fall ist, prüft es, wo sich das übergebene Feld in diesem Array befindet, und gibt das nächste Element zurück.

Ein paar Dinge zu beachten:

  • es scheint, dass jQuery sort () für ein jQuery-Objekt unterstützt, aber ich kannit nicht explizit in der Dokumentation finden. Daher rufe ich toArray () auf und ändere dann das Array in ein jQuery-Objekt. 
  • Es gibt andere Felder, für die das Register zulässig ist, aber ich habe sie ausgelassen, da sie keine Standardformularfelder sind.

Der zum Testen verwendete Code lautete (mit 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>
10
Jai

Nachdem ich jeden Code ausprobiert hatte (und Probleme mit den Browsern hatte), fand ich einen Code, der in den Top-Browsern funktioniert. Die vorherigen Routinen konnten aufgrund einiger seltsamer Probleme nicht verwendet werden.

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

Hoffe das hilft jemand anderem. Genießen.

7
Jeff Mathews

Sie können jedem Formularelement eine ID (oder einen eindeutigen Klassennamen) geben, die es als Formularelement identifiziert und ihm einen Index gibt. Zum Beispiel:

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

Wenn Sie dann vom ersten Element zum zweiten Element wechseln möchten, können Sie Folgendes tun:

//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);

Dies hat den Vorteil, dass Sie jedes Element als nächstes markieren können, unabhängig von Ort und Typ. Sie können auch die Reihenfolge Ihrer Durchquerung steuern. Wenn Sie also aus irgendeinem Grund ein Element überspringen und später darauf zurückkommen möchten, können Sie dies auch tun.

2
jckeyes

Sie können dies tun, um eine vollständige Liste der Formularelemente zu erhalten, nach denen Sie suchen:

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

Dann sollte es leicht sein, das nächste Element zu finden:

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
alexmeia

Oder Sie können das html-Attribut 'tabindex' verwenden. Wenn ein Benutzer ein Formular umblättert, wird tabindex = "i" bis tabindex = "i + 1" verwendet. Sie können jQuery verwenden, um das Attribut sehr einfach abzurufen. Wäre für einen Nizza Rückfall für Benutzer ohne Javascript aktiviert, auch.

1
Chris Serra

Ich habe eine Funktion entwickelt, die die Arbeit erledigt, ohne Indizes explizit zu definieren:

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];
            }
        }
    }
}

Und hier ist ein Arbeitsbeispiel. Die Formular-Tags dienen der Konsistenz. Alles, was Sie wirklich brauchen, ist ein gemeinsames Elternteil, und Sie können sogar den Body-Tag als Elternteil verwenden (mit einer geringfügigen Änderung der Funktion).

Fügen Sie diese in eine Datei ein und öffnen Sie sie mit Firefox/Firebug. Sie werden sehen, dass das richtige Element für alle Ihre Beispiele zurückgegeben wird:

<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
enobrev
var elementSelector = "input:visible,textarea:visible";
var nextSibling = $(elementSelector )[$(elementSelector ).index() + 1];
//$(nextSibling).focus(); possible action

Ich denke nur, dass die obige Lösung einfacher ist, oder Sie können alles in einer Zeile hinzufügen, wenn Sie möchten :-)

var nextSibling = $("input:visible,textarea:visible")[$("input:visible,textarea:visible").index() + 1];
0
NicoJuicy

Alle Lösungen, die index (oder nextAll) verwenden, funktionieren nur, wenn alle Formulareingaben gleichgeordnet sind, z. innerhalb desselben <div>-Blocks. Das Folgende wird umgangen, indem ein Array von IDs aller sichtbaren, nicht lesbaren Eingaben auf der Seite erstellt und der erste nach dem aktuellen Steuerelement ausgewählt wird.

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

Die Verwendung der Kartenfunktion macht sie etwas prägnanter als Lösungen, die Iteratoren verwenden. 

0
PiersB

Sie können das jQuery-Feld-Plugin verwenden, mit dem Sie dies tun können.

0
Anton Kuzmin

Das hat gut für mich funktioniert und verborgene Eingaben werden übersprungen:

input_el.nextAll( 'input:visible:first' ).focus();
0
Jay Haase