2009-03-31 18 views
21

Chciałbym, aby przeglądarka działała tak, jakby użytkownik nacisnął klawisz Tab, gdy coś kliknie. W obsługi click Próbowałem następujących sposobów:Symulowanie naciśnięcia klawisza przy użyciu JavaScriptu

var event = document.createEvent('KeyboardEvent'); 
event.initKeyEvent("keypress", true, true, null, false, false, false, false, 9, 0); 
this.input.focus()[0].dispatchEvent(event); 

i jQuery:

this.input.focus().trigger({ type : 'keypress', which : 9 }); 

... co ja zajmowałem się od here.

Pierwsze podejście wydaje się najlepszym rozwiązaniem, ale nie działa. Jeśli zmienię dwa ostatnie parametry na 98, 98, to w polu wejściowym wpisuje się "b". Ale 9, 0 i 9, 9 (dawny które wziąłem bezpośrednio z witryny internetowej MDC) zarówno daj mi te błędy w Firebug pod FF3:

Permission denied to get property XULElement.popupOpen 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to get property XULElement.overrideValue 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to get property XULElement.selectedIndex 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to set property XULElement.selectedIndex 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Słyszałem takie (bez jasnej definicji "takie") zdarzenia są "niezaufane", co może wyjaśniać te błędy.

Drugie podejście powoduje, że każda wartość, którą umieszczam jako zdarzenie, która ma być przekazana jako zdarzenie. Która, ale bez skutku (nawet jeśli używam 98 zamiast 9, nie ma "b" jest wpisane w polu.) Jeśli Próbuję ustawić parametr event.data w obiekcie, który przekazuję, który kończy się niezdefiniowanym po wywołaniu zdarzenia. Poniżej znajduje się kod, którego używam do wyświetlenia:

$('#hi').keypress(function(e) { 
    console.log(e); 
}); 

Jakieś inne pomysły?

+0

Czego chcesz się powołać? Czy próbujesz przenieść je do następnego wejścia? – hunter

+0

Tak. Ale następne "wejście" niekoniecznie musi być elementem wejściowym lub innym elementem o naturalnej tabulacji. Nie jest również koniecznie nienaturalnie tabulatorowany (tj. $ ("[Tabindex]")). Fizycznie naciskająca zakładka (lub shift + zakładka) robi dokładnie to, czego chcę ... – Kev

+0

Dzięki za to. Interesuje mnie tylko pierwszy przykładowy kod twojego pytania, który naprawdę pomógł :) –

Odpowiedz

4

Rozwiązaniem, z którego skorzystałem, jest stworzenie "fokusowego" diva (z tabindex = -1 - może mieć fokus, ale początkowo nie można go zakładać) po obu stronach obszaru, w którym chcesz ręcznie zarządzać fokusami. Następnie umieściłem słuchacza z bąbelkami prawdziwymi dla skupienia i rozmycia na całym obszarze. Kiedy fokus pojawia się na danym obszarze, wartości tabindeksu zostają zmienione na -1, a gdy pojawia się jakieś rozmycie, zostają one zmienione na 0. Oznacza to, że podczas skupienia się w tym obszarze można go ukryć i przesunąć poprawnie kończy się na innych elementach strony lub elementach interfejsu użytkownika przeglądarki, ale jak tylko się tam skupisz, osoby kradnące ogniskowanie stają się tablikowalne, a przy ogniskowaniu ustawiają prawidłowo obszar ręczny i kierują skupienie na element na jego końcu, tak jakbyś kliknął na jednym końcu lub drugim obszarze ręcznym.

1

Właściwie, wydaje mi się, że istnieje sposób, nawet jeśli jest to poważna PITA. Mogę się upewnić, że każdy element, nawet jeśli naturalnie jest tab-stop, ma Xtabindex, w jakiś sposób we właściwej kolejności, mimo że będę wchodził do widżetów innych ludzi, a więc używając jQuery, aby dodać je po fakcie, zamiast być w stanie określić go bezpośrednio w kodzie HTML lub innym początkowym kodzie budynku. Wtedy cała moja forma będzie miała rzeczywisty tabindex. Podczas gdy ma fokus, będzie absorbował naciśnięcia klawiszy, a jeśli są to tabulatory lub shift + zakładka, przenieś fałszywą fokus na podstawie Xtabindex. Jeśli przycisk zostanie naciśnięty na ostatnim (lub przesunięciu + pierwszym elemencie) w formularzu, nie będzie pochłaniał naciśnięcia klawisza, dzięki czemu przeglądarka prawidłowo ustawi ostrość na innych stronach lub elementach interfejsu przeglądarki poza formularzem za pomocą klawiatury.

Mogę tylko zgadywać, jakie niezamierzone skutki uboczne zostaną wprowadzone w tym podejściu.

W rzeczywistości nie jest to nawet rozwiązanie, ponieważ nadal nie mogę sfałszować zakładki na ostatnim elemencie, który go używa.

+0

http: // list .whatwg.org/htdig.cgi/whatwg-whatwg.org/2008-December/017980.html przedstawił interesujący punkt: "Ale co jeśli agent użytkownika nie robi rzeczy przy użyciu cyklu, ale zamiast tego korzysta z zarządzania kierunkowym ogniskowaniem , jak wiele telefonów? " – Kev

3

To rozwiązanie Kiedyś na naszym webapp dla dwóch formantów niestandardowych, kalendarz pop-up i selektor ciężaru jednostki pop-up/wartość (klikając pola tekstowego wyskakuje div z dwóch wybiera)

function tab_focus(elem) 
    var fields = elem.form.getElements() 
    for(var i=0;i<fields.length;i++) { 
    if(fields[i].id == elem.id){ 
     for(i=i+1;i<fields.length;i++){ 
     if(fields[i].type != 'hidden'){ 
      fields[i].focus() 
      return  
     } 
     } 
     break; 
    } 
    } 
    elem.form.focusFirstElement(); 
} 

Używa to frameworka Prototype i oczekuje, że jego elementem będzie element rozszerzony (np. $ ('Thing_id')).

Otrzymuje formę, do której należy element, i przechodzi przez elementy formularza, aż znajdzie się.

Następnie szuka pierwszego elementu, który nie jest ukryty, i przekazuje mu fokus.

Jeśli w formularzu nie ma elementów, przenosi fokus do pierwszego elementu formularza. Zamiast tego mogłem znaleźć następny formularz na stronie przez document.forms, ale większość naszych stron używa jednego formularza.

+0

Chodzi o to, że niektóre z moich możliwych do ustawienia elementów interfejsu użytkownika nie są elementami formularza, ponieważ są to niestandardowe widgety. – Kev

+1

Dla użytkowników jquery zamień pierwszy wiersz tej funkcji na: var fields = $ ('form') [0]; Aby zapętlić elementy formularza. – eniac

0

Myślę, że te błędy pochodzą z autouzupełniania. Możesz być w stanie je wyłączyć poprzez ustawienie, zanim wywołania zdarzenia, atrybut autouzupełnianie na „off”

setAttribute('autocomplete','off') 
1

stworzyłem simple jQuery plugin który nie rozwiązuje tego problemu. Korzysta z selektora jQuery do ": tabbable", aby znaleźć następny element "tabbable" i wybiera go.

Przykład użycia:

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