2013-08-15 12 views
5

EDIT: Vedere la mia risposta qui sotto: https://stackoverflow.com/a/25953721/674863IE click sul bambino non mette a fuoco genitore, genitore ha tabindex = 0

Demo: http://jsfiddle.net/fergal_doyle/anXM3/1/

Ho un div con tabindex = 0, e un div bambino con una larghezza fissa. Quando clicco sul div child, mi aspetto che il div esterno ottenga la messa a fuoco. Funziona perfettamente con Firefox e Chrome e funziona solo con Internet Explorer (da 7 a 10) quando il div child non ha alcuna larghezza applicata.

Con una larghezza, facendo clic sul div bambino (bianco) non si concentra su quello esterno, e se quello esterno in precedenza aveva messa a fuoco, facendo clic sul bambino l'esterno si sfoca, che è un dolore per quello che voglio fare.

HTML:

<div tabindex="0" id="test"> 
    <div>Click</div> 
</div> 

CSS:

div { 
    border:1px solid #000; 
    padding:20px; 
    background-color:red; 
} 
div div { 
    padding:8px; 
    background-color:#FFF; 
    cursor:default; 
    width:200px; 
} 

JS:

var $div = $("#test"), 
    $inner = $("#test > div"); 

$div.on("blur", function (e) { 
    console.log("blur"); 
}) 
    .on("focus", function (e) { 
    console.log("focus") 
}); 
+0

ben peggiore delle ipotesi, si può sempre definire un codice per IE solo per aggirare il problema – Huangism

risposta

6

Intercettare eventi e utilizzare JS per impostare lo stato attivo ha causato più problemi.

Alla fine ho capito che l'utilizzo di tag "normali" come div o span fa sì che IE si comporti in modo errato. Ma usa qualcosa come var o qualsiasi tag personalizzato e IE inizia a comportarsi come un browser appropriato.

vedi esempio aggiornate: http://jsfiddle.net/fergal_doyle/anXM3/16/

HTML:

<div tabindex="0" id="test"> 
    <var class="iesux">Works</var> 
    <foo class="iesux">Works</foo> 
    <div class="iesux">Doesn't work in IE</div> 
    <span class="iesux">Doesn't work in IE</span> 
</div> 

CSS:

div { 
    border:1px solid #000; 
    padding:20px; 
    background-color:red; 
} 
.iesux { 
    border:1px solid #000; 
    display:block; 
    padding:8px; 
    background-color:#FFF; 
    cursor:default; 
    width:200px; 
} 

JS:

document.createElement("foo"); 

var $div = $("#test"); 

$div.on("blur", function (e) { 
    console.log("blur"); 
}) 
    .on("focus", function (e) { 
    console.log("focus") 
}); 
+1

Grazie mille per questa soluzione ... Mi sono preso da fare per scrivere una complicata logica di simulazione di eventi, ma semplicemente scambiare un div per un altro elemento risolve tutto per me. –

5

Hai provato ad aggiungere:

$inner.click(function() { 
    $div.focus(); 
}); 

e per evitare che il div esterno per sfocare dopo un focus utilizzare e.stopPropagation()

UPDATE: Dal momento che l'evento click dopo la blur ho usato l'evento Mousedown, perché spara prima blur.

PS: Non dimenticare di gestire gli eventi di tastiera keydown se si vuole anche di raggiungere sbavature sparati dalla tastiera.

http://jsfiddle.net/ouadie/x4nAX/

+0

ho fatto, ma mi dà un "doppio tap". Ad esempio, fare clic sul rosso, quindi fare clic sul bianco. Ottieni "focus", "blur", "focus". e.stopPropagation() non sembra fare ciò che dovrebbe. – Fergal

+0

Ok, ho appena aggiornato il 'jsfiddle' puoi controllare ora? Poiché l'evento "click" si attiva dopo la sfocatura, ho usato l'evento "Mousedown", perché si attiva prima di "blur". – Ouadie

+0

Grazie, buona soluzione con il mouse sul documento. Se aggiorni la tua risposta per riflettere la logica in più, accetterò come risposta. – Fergal

0

Facendo clic su un elemento con tabindex = 0 in IE comporterà l'elemento guadagnando attenzione invisibile. Il modo per ottenere una messa a fuoco visibile è chiamando a fuoco a livello di codice() mentre l'elemento non ha già una messa a fuoco invisibile. Dal fuoco avviene subito dopo mousedown, questo significa che abbiamo bisogno di:

$('#parent').mousedown(function(e){ 
    var parent = $(e.currentTarget) 
    if (!parent.is(':focus')) { 
     parent.focus() 
    } 
}).focus(function(e){ 
    console.log('focused') 
}).blur(function(e){ 
    console.log('blurred') 
}) 

Se il bambino è in linea o un blocco con nessun set di larghezza, l'effetto è lo stesso che cliccando direttamente sul genitore. Tuttavia, se il bambino è un blocco in linea o un blocco con una larghezza impostata e il genitore ha già messo a fuoco, allora il genitore si sfocherà() subito dopo l'esecuzione dei gestori di mouse. Abbiamo tre diversi modi di procedere, con diversi compromessi.

Un'opzione consiste semplicemente nel sopprimere la sfocatura con preventDefault(); la virtù di questo approccio è che blur() non sparerà mai e focus() non sparerà in modo ridondante, il che ci consente di scrivere una logica diretta nei nostri focalizzatori e sfocati; il vizio di questo approccio è che disabilita la selezione del testo:

$('#child').mousedown(function(e){ 
    e.preventDefault() 
}) 
$('#parent').mousedown(function(e){ 
    var parent = $(e.currentTarget) 
    if (!parent.is(':focus')) { 
     parent.focus() 
    } 
}).focus(function(e){ 
    console.log('focused') 
}).blur(function(e){ 
    console.log('blurred') 
}) 

Se non vogliamo disabilitare la selezione del testo, un'altra opzione è quella di concentrarsi sul padre dal gestore mouseup del bambino; tuttavia, in questo modo il genitore sfocatura e quindi concentrarsi ancora una volta, che ci impedisce di sapere quando una messa a fuoco o sfocatura è "reale" piuttosto che semplicemente una conseguenza transitoria della nostra logica messa a fuoco propagazione:

$('#child').mouseup(function(e){ 
    $(e.currentTarget).closest('[tabindex]').focus() 
}) 
$('#parent').mousedown(function(e){ 
    var parent = $(e.currentTarget) 
    if (!parent.is(':focus')) { 
     parent.focus() 
    } 
}).focus(function(e){ 
    console.log('focused') 
}).blur(function(e){ 
    console.log('blurred') 
}) 

La terza opzione ha le virtù di entrambi gli approcci di cui sopra, ma è il più complicato logicamente:

$('#parent').mousedown(function(e){ 
    var parent = $(e.currentTarget) 
    var parentWasClicked = parent.is(e.target) 
    var parentHasFocus = parent.is(':focus') 
    if (parentWasClicked && !parentHasFocus) { 
     parent.focus() 
    } else if (parentHasFocus && !parentWasClicked) { 
     window.ignoreFocusChanges = true 
    } 
}) 
.mouseup(function(e){ 
    var parent = $(e.currentTarget) 
    if (!parent.is(':focus')) { 
     parent.focus() 
    } 
}) 
.blur(function(e){ 
    if (window.ignoreFocusChanges) { 
     return 
    } 
    console.log('blurred') 
}) 
.focus(function(e){ 
    if (window.ignoreFocusChanges) { 
     window.ignoreFocusChanges = false 
     return 
    } 
    console.log('focused') 
}) 
0

Let root essere la vostra #test div

function prevent_blur_in_subtree = function (event) { 
    if (event.originalEvent && event.target != root.get(0) && $(event.target).closest(root).size() == 1) { 
     $(window).one("mousedown", prevent_blur_in_subtree); 
     event.stopPropagation(); 
     event.preventDefault(); 
     return false; 
    } 
} 
root.bind("click", function() { 
    if (!$(this).is(":focus")) { 
    $(this).trigger("focus"); 
    } 
}) 
.bind("focus", function() { 
    $(window).one("mousedown", prevent_blur_in_subtree); 
}); 

È necessario utilizzare event.stopPropagation() in qualsiasi clic su root, che non dovrebbe forzare l'evento di messa a fuoco.

Questo problema è uno dei maggiori problemi in qualsiasi IE (5-11). Si può vedere che il codice sorgente di IE non è stato pulito dal 1999. Rido quando le persone parlano di "IE 11 è un browser moderno" o "IE 11 si preoccupa degli standard".

-1

Questa domanda è vecchio, ma ho appena imbattuto questa P roblem e la seguente soluzione funziona in IE11 ed è molto più semplice rispetto a qualsiasi altra:

.iesux { 
    border:1px solid #000; 
    display:block; 
    padding:8px; 
    background-color:#FFF; 
    cursor:default; 
    width:200px; 
    pointer-events: none; 
} 

non è supportato in IE < 11, purtroppo, ma se si può farla franca che è di gran lunga il più facile.

http://jsfiddle.net/anXM3/22/

Problemi correlati