Jak ustawić fokus na pierwszy element wejściowy w formularzu HTML niezależnie od identyfikatora?

84

Czy istnieje prosty sposób na ustawienie fokusu (kursora wejściowego) strony internetowej na pierwszym elemencie wejściowym (pole tekstowe, lista rozwijana, ...) podczas ładowania strony bez znajomości identyfikatora elementu?

Chciałbym zaimplementować go jako wspólny skrypt dla wszystkich moich stron / formularzy mojej aplikacji internetowej.

splattne
źródło
7
UWAGA: jeśli formularz jest umieszczony na stronie w sposób, w jaki użytkownik musi przewinąć stronę w dół, aby zobaczyć formularz, ustawienie fokusu automatycznie przewinie stronę w dół, tak jak zrobiłby to kotwica. Nie jest to zbyt dobre, ponieważ użytkownik trafiający na taką stronę zobaczyłby ją natychmiast przewiniętą w dół do pozycji formularza. Testowałem na Safari i FF (IE7 nie przewija strony).
Marco Demaio
@Marco_Demaio Moja aplikacja internetowa jest zbudowana w taki sposób, że każda strona ma swoje pola wprowadzania w górnej części okna.
splattne
3
co się stanie, jeśli użytkownik zmieni rozmiar okna przeglądarki na mniejszą niż 768 pikseli. Strona przewinie się do miejsca, w którym ustawiłeś fokus. Zresztą chciałem Cię tylko ostrzec na wypadek, gdybyś nie wiedział o tak drobnym problemie, ja też o tym nie wiedziałem przed wykonaniem testów.
Marco Demaio

Odpowiedzi:

96

Możesz także wypróbować metodę opartą na jQuery:

$(document).ready(function() {
    $('form:first *:input[type!=hidden]:first').focus();
});
Marko Dumic
źródło
To działa! Zaczynam integrować jQuery w mojej aplikacji internetowej. Więc myślę, że będę się trzymał tego podejścia! Wielkie dzięki, Marko!
splattne
3
Co się stanie, jeśli w takim przypadku pierwszy formularz na stronie zostanie ukryty? A może pierwszy element formularza jest ukryty za pomocą CSS? Z pewnością to się nie powiedzie. Oczywiście jestem pedantyczny, ale tak właśnie się toczę.
James Hughes,
W moim przypadku (używając ASP.NET) mam tylko JEDEN formularz, który nigdy nie jest ukryty. Więc to działa dla mnie.
splattne
@Jame Hughes, możesz napisać to jako funkcję i wywołać ją, kiedy jej potrzebujesz, i możesz zrobić wyjątki. To rozwiązanie naprawdę mi pomogło.
Luci,
to nie działa dla mnie z jakiegoś powodu. czy nie powinienem widzieć kursora.
Chris,
136

Chociaż to nie odpowiada na pytanie (wymagające wspólnego skryptu), pomyślałem, że dla innych może być przydatne, aby wiedzieć, że HTML5 wprowadza atrybut „autofocus”:

<form>
  <input type="text" name="username" autofocus>
  <input type="password" name="password">
  <input type="submit" value="Login">
</form>

Zanurz się w HTML5 , aby uzyskać więcej informacji.

Jacob Stanley
źródło
2
autofokus to nazwa atrybutu. A co z jego wartością? Coś jak autofokus = prawda nie jest potrzebne? Co to znaczy nie ustawiać żadnej wartości?
Geek
4
W HTML5 niektóre atrybuty nie muszą mieć wartości, „zaznaczone” to kolejny atrybut, w którym tak jest. Uważam, że gdy wartość zostanie pominięta, oznacza to, że jest ona taka sama jak nazwa (np. Autofocus = "autofocus" i zaznaczone = "zaznaczone").
Jacob Stanley
Moja aplikacja Spring psuje się, gdy próbuję użyć autofocusbez wartości spring:form. autofocus="autofocus"działa jednak dobrze. Dzięki, @Jacob.
Siergiej Tachenov
2
@Geek Atrybut autofocus, jak wiele innych, jest logicznym typem atrybutu. Dlatego jest używany tylko w sposób deklaratywny, a nie przez przypisywanie mu wartości. Więcej szczegółów można znaleźć w specyfikacji w3c: w3.org/TR/html5/infrastructure.html#boolean-attribute
n1kkou
35
document.forms[0].elements[0].focus();

Można to udoskonalić za pomocą pętli do np. nie skupiać się na niektórych typach pól, polach wyłączonych i tak dalej. Lepiej może być dodanie class = "autofocus" do pola, które faktycznie robisz Kupię skoncentrowane i pętli nad formami [I] .elements [J] szukających tego className.

W każdym razie: robienie tego na każdej stronie zwykle nie jest dobrym pomysłem. Kiedy skupisz się na wejściu, użytkownik traci możliwość np. przewiń stronę z klawiatury. Jeśli jest to nieoczekiwane, może to być denerwujące, więc automatyczne ustawianie ostrości tylko wtedy, gdy masz pewność, że użycie pola formularza będzie tym, co chce zrobić użytkownik. to znaczy. jeśli jesteś Google.

bobince
źródło
3
Powinna być poprawna, ponieważ pytanie nie ma tagu jquery.
Kalle H. Väravas
@ KalleH.Väravas nie, powinien zostać odrzucony, ponieważ przyjmuje założenia, których nigdzie nie można znaleźć, np. istnieje co najmniej jeden formularz. Generalnie to nie działa.
9ilsdx 9rvj 0lo
18

Najbardziej wszechstronnym wyrażeniem jQuery, które znalazłem działającym, jest (dzięki pomocy tutaj )

$(document).ready(function() {
    $('input:visible:enabled:first').focus();
});
ngeek
źródło
1
Używałem tego, zauważyłem, że działa bardzo wolno w IE, gdy mam dużą liczbę> 1000 pól wyboru w tabeli. Nie wiesz, co z tym zrobić, być może będziesz musiał po prostu zrezygnować ze skupienia się na pierwszym polu wejściowym.
Sam Watkins
5

Musisz także pominąć wszelkie ukryte dane wejściowe.

for (var i = 0; document.forms[0].elements[i].type == 'hidden'; i++);
document.forms[0].elements[i].focus();
Marko Dumic
źródło
Mogę się mylić, ale ta pętla nie ma zdefiniowanego zachowania, jeśli formularze [0] nie mają ukrytych danych wejściowych.
xtofl
Dokładnie. Służy do pomijania wszelkich wiodących ukrytych danych wejściowych. I jest napisane przy założeniu, że w formularzu są pola nieukryte. Mógłbym to również zrobić z jQuery (opublikuję inną odpowiedź), ale nie wspomniałeś, że chcesz, aby jQuery było zaangażowane.
Marko Dumic
1
@MarkoDumic Po co marnować pamięć, jeśli możesz użyć whilewyciągu?
Lucio,
3

Umieszczenie tego kodu na końcu bodytagu automatycznie ustawi pierwszy widoczny, niewidoczny, włączony element na ekranie. Poradzi sobie z większością spraw, które przyjdą mi z krótkim wyprzedzeniem.

<script>
    (function(){
        var forms = document.forms || [];
        for(var i = 0; i < forms.length; i++){
            for(var j = 0; j < forms[i].length; j++){
                if(!forms[i][j].readonly != undefined && forms[i][j].type != "hidden" && forms[i][j].disabled != true && forms[i][j].style.display != 'none'){
                    forms[i][j].focus();
                    return;
                }
            }
        }
    })();
</script>
James Hughes
źródło
1
Jedną rzeczą do rozważenia jest to, że może pasować do elementów, które same nie są ukryte, ale ich przodek jest. Wymagałoby to śledzenia kopii zapasowej DOM i testowania widoczności każdego przodka, co uważam za poważną przesadę w tego rodzaju sytuacjach.
James Hughes
A co z <input type = "text" readonly = "readonly"> Myślę, że powinieneś dodać taki przypadek do swojego kodu. Zwykle ludzie nie chcą skupiać się na polu tekstowym tylko do odczytu. W każdym razie niezły kod i +1 dzięki!
Marco Demaio
Nieprzetestowane, ale zaktualizowałem go o! Formularze [i] [j] .readonly! = Undefined
James Hughes
3

Używam tego:

$("form:first *:input,select,textarea").filter(":not([readonly='readonly']):not([disabled='disabled']):not([type='hidden'])").first().focus();
Robert Brooker
źródło
2

Spowoduje to pobranie pierwszego z widocznych wspólnych danych wejściowych, w tym obszarów tekstowych i pól wyboru. Daje to również pewność, że nie są one ukryte, wyłączone ani tylko do odczytu. dopuszcza również docelowy element div, którego używam w moim oprogramowaniu (tj. pierwsze wejście w tym formularzu).

$("input:visible:enabled:not([readonly]),textarea:visible:enabled:not([readonly]),select:visible:enabled:not([readonly])", 
    target).first().focus();
Dave K.
źródło
1

Dla tych, którzy używają JSF2.2 + i nie mogą przekazać autofokusa jako atrybutu bez wartości, użyj tego:

 p:autofocus="true"

I dodaj go do przestrzeni nazw p (często też używany pt. Cokolwiek chcesz).

<html ... xmlns:p="http://java.sun.com/jsf/passthrough">
feder
źródło
0

Z AngularJS:

angular.element('#Element')[0].focus();
EpokK
źródło
0

Obejmuje to obszary tekstowe i nie obejmuje przycisków opcji

$(document).ready(function() {
    var first_input = $('input[type=text]:visible:enabled:first, textarea:visible:enabled:first')[0];
    if(first_input != undefined){ first_input.focus(); }
});
HectorPerez
źródło
0

Powinieneś móc użyć clientHeight zamiast sprawdzać atrybut display, ponieważ rodzic mógłby ukrywać ten element:

function setFocus() {
    var forms = document.forms || [];
        for (var i = 0; i < forms.length; i++) {
            for (var j = 0; j < forms[i].length; j++) {
            var widget = forms[i][j];
                if ((widget && widget.domNode && widget.domNode.clientHeight > 0) && typeof widget.focus === "function")
                 && (typeof widget.disabled === "undefined" || widget.disabled === false)
                 && (typeof widget.readOnly === "undefined" || widget.readOnly === false)) {
                        widget.focus();
                        break;
                }
            }
        }
    }   
}
thecoolmacdude
źródło
0

Bez bibliotek innych firm użyj czegoś takiego jak

  const inputElements = parentElement.getElementsByTagName('input')
  if (inputChilds.length > 0) {
    inputChilds.item(0).focus();
  }

Upewnij się, że bierzesz pod uwagę wszystkie tagi elementów formularza, wykluczaj ukryte / wyłączone, jak w innych odpowiedziach i tak dalej.

cghislai
źródło
0

bez jquery, np. ze zwykłym javascript:

document.querySelector('form input:not([type=hidden])').focus()

działa na Safari, ale nie Chrome 75 (kwiecień 2019)

localhostdotdev
źródło