Utilizzo di jQuery per verificare se un input ha lo stato attivo


561

Sulla prima pagina di un sito che sto costruendo, molti <div>usano la :hoverpseudo-classe CSS per aggiungere un bordo quando il mouse è su di essi. Una delle <div>s contiene una <form>che, usando jQuery, manterrà il bordo se un input al suo interno ha lo stato attivo. Funziona perfettamente, tranne per il fatto che IE6 non supporta :hoverelementi diversi da <a>s. Quindi, solo per questo browser stiamo usando jQuery per imitare CSS :hoverusando il $(#element).hover()metodo L'unico problema è che ora jQuery gestisce sia il modulo focus() che hover() , quando un input ha lo stato attivo, l'utente sposta il mouse dentro e fuori, il bordo scompare.

Stavo pensando che potremmo usare una sorta di condizionale per fermare questo comportamento. Ad esempio, se testassimo al passaggio del mouse se qualcuno degli input fosse attivo, potremmo impedire che il bordo vada via. AFAIK, non esiste un :focusselettore in jQuery, quindi non sono sicuro di come farlo. Qualche idea?


1
puoi provare a ridurlo a poche frasi su ciò che è richiesto e cosa sto accadendo?
mkoryak,

Penso che tu debba cercare di catturare l'attenzione e sfocare gli eventi ( docs.jquery.com/Events/focus e docs.jquery.com/Events/blur )
Wolfr,

Ho pubblicato una risposta sulla domanda correlata "Esiste un 'has focus' in JavaScript (o jQuery)?" . Ho migliorato [approccio cletus citato da gnarf] (# 2684561).
luiggitama,

Risposte:


928

jQuery 1.6+

jQuery ha aggiunto un :focusselettore, quindi non è più necessario aggiungerlo da soli. Basta usare$("..").is(":focus")

jQuery 1.5 e precedenti

Modifica: man mano che i tempi cambiano, troviamo metodi migliori per testare l'attenzione, il nuovo preferito è questo riassunto di Ben Alman :

jQuery.expr[':'].focus = function( elem ) {
  return elem === document.activeElement && ( elem.type || elem.href );
};

Citato da Mathias Bynens qui :

Si noti che il (elem.type || elem.href)test è stato aggiunto per filtrare i falsi positivi come il corpo. In questo modo, ci assicuriamo di filtrare tutti gli elementi tranne i controlli dei moduli e i collegamenti ipertestuali.

Stai definendo un nuovo selettore. Vedi Plugin / Authoring . Quindi puoi fare:

if ($("...").is(":focus")) {
  ...
}

o:

$("input:focus").doStuff();

Qualsiasi jQuery

Se vuoi solo capire quale elemento ha il focus, puoi usare

$(document.activeElement)

Se non sei sicuro che la versione sarà 1.6 o precedente, puoi aggiungere il :focusselettore se manca:

(function ( $ ) {
    var filters = $.expr[":"];
    if ( !filters.focus ) { 
        filters.focus = function( elem ) {
           return elem === document.activeElement && ( elem.type || elem.href );
        };
    }
})( jQuery );

4
Ciò può causare falsi positivi. Vedi stackoverflow.com/questions/967096/… per maggiori informazioni (grazie a Ben Alman e Diego Perini).
Mathias Bynens,

@Mathias Bynens - Grazie per l'aggiornamento (sei più che benvenuto a modificare questa risposta della wiki della community tra l'altro!)
Gnarf

E quando ne hai bisogno per funzionare sia con 1.5 che con 1.6? Non voglio ignorare il selettore di messa a fuoco di jQuery. Qualcosa del genere if (!jQuery.expr[':'].focus) { /* gist from Ben Alman */ }?
Betamos,

@betamos - Esatto ... Aggiungerò qualcosa nella risposta per riflettere questo.
gnarf,

2
@Alex - Fornisci un test case ridotto su jsFiddle che mostra il problema, perché, per quanto ne so, non c'è motivo per cui non dovrebbe funzionare su elementi "dinamici". Chiamo shenanigans ...
gnarf

46

CSS:

.focus {
    border-color:red;
}

JQuery:

  $(document).ready(function() {

    $('input').blur(function() {
        $('input').removeClass("focus");
      })
      .focus(function() {
        $(this).addClass("focus")
      });
  });

22

Ecco una risposta più solida di quella attualmente accettata:

jQuery.expr[':'].focus = function(elem) {
  return elem === document.activeElement && (elem.type || elem.href);
};

Si noti che il (elem.type || elem.href)test è stato aggiunto per filtrare i falsi positivi come body. In questo modo, ci assicuriamo di filtrare tutti gli elementi tranne i controlli dei moduli e i collegamenti ipertestuali.

(Tratto da questa idea di Ben Alman .)


13

Aggiornamento di aprile 2015

Poiché questa domanda è in corso da un po 'di tempo, e alcune nuove convenzioni sono entrate in gioco, sento che dovrei menzionare che il .livemetodo è stato deprezzato.

Al suo posto, il .onmetodo è stato ora introdotto.

La loro documentazione è abbastanza utile per spiegare come funziona;

Il metodo .on () collega i gestori di eventi all'insieme di elementi attualmente selezionato nell'oggetto jQuery. A partire da jQuery 1.7, il metodo .on () fornisce tutte le funzionalità necessarie per collegare i gestori di eventi. Per assistenza nella conversione da metodi di eventi jQuery precedenti, consultare .bind (), .delegate () e .live ().

Pertanto, per poter indirizzare l'evento "input focalizzato", è possibile utilizzarlo in uno script. Qualcosa di simile a:

$('input').on("focus", function(){
   //do some stuff
});

Questo è abbastanza robusto e ti permette anche di usare anche il tasto TAB.


2

Non sono del tutto sicuro di ciò che stai cercando, ma sembra che possa essere ottenuto memorizzando lo stato degli elementi di input (o div?) Come variabile:

$('div').each(function(){

    var childInputHasFocus = false;

    $(this).hover(function(){
        if (childInputHasFocus) {
            // do something
        } else { }
    }, function() {
        if (childInputHasFocus) {
            // do something
        } else { }
    });

    $('input', this)
        .focus(function(){
            childInputHasFocus = true;
        })
        .blur(function(){
            childInputHasFocus = false;
        });
});

Questo è quello che ho finito per fare, ma ho usato una classe CSS arbitraria piuttosto che una variabile javascript globale.
Bloudermilk,

Ho usato una variante di questo. Non è necessario alcun nuovo plug-in jQuery. Questo mi rende un camper felice!
Dennis Day

1

Un'alternativa all'utilizzo delle classi per contrassegnare lo stato di un elemento è la funzionalità interna dell'archivio dati .

PS: sei in grado di archiviare i booleani e tutto ciò che desideri utilizzando la data()funzione. Non si tratta solo di stringhe :)

$("...").mouseover(function ()
{
    // store state on element
}).mouseout(function ()
{
    // remove stored state on element
});

E poi si tratta solo di accedere allo stato degli elementi.



1

Hai pensato di usare mouseOver e mouseOut per simulare questo. Guarda anche mouseEnter e mouseLeave


Questo è essenzialmente quello che sto facendo con il passaggio del mouse di jQuery. Fornisci due funzioni, una per il mouse in entrata e una per il mouse in uscita.
bloudermilk,

0

Tieni traccia di entrambi gli stati (hovered, focalizzato) come flag vero / falso e ogni volta che uno cambia, esegui una funzione che rimuove il bordo se entrambi sono falsi, altrimenti mostra il bordo.

Quindi: onfocus imposta focalizzato = vero, onblur imposta focalizzato = falso. set onmouseover hovered = true, set onmouseout hovered = false. Dopo ognuno di questi eventi, esegui una funzione che aggiunge / rimuove il bordo.


0

Per quanto ne so, non puoi chiedere al browser se qualche input sullo schermo è attivo, devi impostare una sorta di tracciamento dello stato attivo.

Di solito ho una variabile chiamata "noFocus" e la imposto su true. Quindi aggiungo un evento focus a tutti gli input che rendono falso noFocus. Quindi aggiungo un evento di sfocatura a tutti gli input che riportano noFocus su true.

Ho una classe MooTools che lo gestisce abbastanza facilmente, sono sicuro che potresti creare un plugin jquery per fare lo stesso.

Una volta creato, è possibile controllare noFocus prima di eseguire qualsiasi scambio di bordi.




0

Avevo un evento .live ("focus") impostato per selezionare () (evidenziare) il contenuto di un input di testo in modo che l'utente non dovesse selezionarlo prima di digitare un nuovo valore.

$ (FormObj) .Select ();

A causa delle stranezze tra i diversi browser, a volte la selezione veniva sostituita dal clic che lo causava e deselezionava il contenuto subito dopo per posizionare il cursore all'interno del campo di testo (funzionava principalmente bene in FF ma falliva in IE)

Pensavo di poterlo risolvere mettendo un leggero ritardo sulla selezione ...

setTimeout (function () {$ (formObj) .Select ();}, 200);

Funzionava bene e la selezione persisteva, ma sorgeva un problema divertente. Se si passava da un campo all'altro, lo stato attivo passava al campo successivo prima che la selezione avesse luogo. Dal momento che selezionare ruba lo stato attivo, lo stato attivo tornerebbe indietro e innescherebbe un nuovo evento "attivo". Questo è finito in una cascata di selezioni di input che danzavano su tutto lo schermo.

Una soluzione praticabile sarebbe quella di verificare che il campo abbia ancora lo stato attivo prima di eseguire select (), ma come detto, non esiste un modo semplice per verificare ... Ho finito per rinunciare a tutta la selezione automatica, piuttosto che girare ciò che dovrebbe essere una singola chiamata jQuery select () in un'enorme funzione carica di subroutine ...


0

Quello che ho finito per fare è creare una classe arbitraria chiamata .elementhasfocus che viene aggiunta e rimossa all'interno della funzione jQuery focus (). Quando la funzione hover () viene eseguita al passaggio del mouse, verifica la presenza di .elementhasfocus:

if(!$("#quotebox").is(".boxhasfocus")) $(this).removeClass("box_border");

Quindi se non ha quella classe (leggi: nessun elemento all'interno del div ha lo stato attivo) il bordo viene rimosso. Altrimenti, non succede nulla.


-2

Semplice

 <input type="text" /> 



 <script>
     $("input").focusin(function() {

    alert("I am in Focus");

     });
 </script>

Ciò non ti dice quale elemento è attualmente attivo. Viene chiamato quando un nuovo elemento ottiene lo stato attivo. Quindi, se un elemento ha già il focus e vuoi sapere se 'this' è quello, questo codice è inutile.
Alexis Wilke,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.