2012-06-23 20 views
5

Tengo una entrada de texto estándar que tiene un evento de desenfoque. El evento desenfoque debe activarse cuando se hace clic en cualquier elemento del documento (que no sea la entrada AND <div id='show-anyways'></div>).jQuery blur no debería activarse si se hace clic/se enfoca en

Mi problema es que no sé cómo agregar el <div id='show-anyways'></div> para anular la función de evento de desenfoque.

Afortunadamente me he explicado lo suficiente, sé que es una situación un poco extraña. por favor déjeme saber si usted necesita mas información.

+2

muestra lo que has codificado hasta ahora, por favor. –

+1

Necesitaría 'e.preventDefault',' e.stopPropagation', o determinar en qué se hizo clic y detener el burbujeo antes de que llegue al objetivo. El error de diseño que siento es que tienes un controlador de eventos borrosos en el DOM? ¿Lo entiendo bien? –

Respuesta

10

usar el objetivo de eventos para determinar lo que se ha hecho clic. Después hará un seguimiento de todos los clics en documento y no provocar el desenfoque() si el elemento es el DIV o la entrada.

var $input=$('#MY-Input-ID'); 

$(document).click(function(evt){ 
    var $tgt=$(evt.target); 
    if(!$tgt.is('#show-anyways') && !$tgt.is($input)){ 
     $input.blur() 
    } 
}) 

No se disparará en los elementos que tiene una configuración preventPropogation.

+0

De hecho tuve que terminar usando $ (document) .click para mi solución ya que el evento input.blur original no se activaría si se ingresara la secuencia click/focus -> # show-anyways -> document.click. Por lo tanto, el evento entre # show-anyways y document.click no desencadenaría el evento input.blur ... – sadmicrowave

+2

Nota: una buena forma de comprobar si hay un clic dentro de un div y todos sus hijos es agregar '&&! $ tgt.is ($ ('*', $ ('# show-anyways'))) 'a las sentencias condicionales dentro de la función de clic arriba. – garromark

+0

@garromark que solo comprueba los descendientes del elemento ... '$ tgt.closest ('# show-allways'). Length' comprobará los descendientes y el elemento .. no estoy seguro de por qué no usé ese – charlietfl

0

¿Podría intentar agregar algo de lógica como?

$('input').blur(function(e){ 
var tester = e.target; 
if ($(tester).attr('id') == 'show-anyways'){ 
return false; 
} 
else { 
// do something? 
} 

}); 

esto básicamente se activa cuando se produce la falta de definición, se comprueba lo que se ha hecho clic/Targed y si pasa a ser el espectáculo de todos modos luego volverá falso y dejar de hacer nada. pero si no se muestra, de todos modos, ¿puede hacer su evento de desenfoque?

no probado, pero ¿es esto lo que quieres decir?

+2

esto es exactamente lo que quiero decir, pero e.getget devuelve 'entrada' para mí en el evento borroso ... así que no puedo llegar a cuál es tu solución ... – sadmicrowave

+0

lo encontró: el constructo en el evento es originalEvent.explicitOriginalTarget – sadmicrowave

+0

Sadly originalEvent.explicitOriginalTarget is Gecko only. – Yogh

1

ACTUALIZACIÓN: tuve que reescribir completamente mi solución. El controlador de eventos blur se adjunta al evento que pierde el foco: si era similar al evento mouseout, podríamos saber qué elemento obtendrá el foco, pero no hay tal suerte. Así que tenemos que recurrir a la captura de eventos .click en su lugar, y activar alguna función basada en él, en lugar de escuchar eventos blur.

var inputIsBlurred = function() { 
    console.log('Run away!!!'); 
}; 
$(document).click(function(e){ 
    var $target = $(e.target); 
    console.log($target); 
    if ($target.is('#some_input') // fired by an input - no special effects 
     || $target.is('#show-anyways') // fired by 'show-anyways' div 
     || $target.parents('#show-anyways').length > 0 // ... or its children 
) { 
     return true; // move along, nothing to do here 
    } 
    inputIsBlurred(); 
});​ 

Aquí está a fiddle para jugar. Perdón por la confusión causada por mi respuesta original. (

1

Faltan algunas cosas de las otras soluciones. Lo más importante es que debe verificar si la entrada está enfocada antes de llamar a su evento de desenfoque. La otra cosa es que un evento borroso se llama no solo si hace clic en otro lugar: también puede llamarlo cuando vaya a otra pestaña en su navegador o si marca tab o shift + tab para ir a la entrada siguiente/anterior. Finalmente, debe considerar utilizar la función jQuery closest() cuando comprueba si el elemento de destino es una excepción de su evento de desenfoque (puede ser el elemento secundario de su excepción).

Por lo tanto, se me ocurrió con esta función prototipo jQuery:

$.fn.extend({ 
 

 
    blurIfNot : function(options, handler) 
 
    { 
 
     var defaults = 
 
     { 
 
      except : [], 
 
      maxParent : null // A DOM element within which 
 
          // a matching element may be found 
 
     }; 
 
     var opt = $.extend({}, defaults, options); 
 
     var time = new Date().getTime(); 
 
     
 
     this.each(function() 
 
     { 
 
      var thisInp = $(this); 
 
      thisInp[0].blurIfNot = {}; 
 
      time += 1000000000000; 
 
      
 
      var except = opt.except; 
 
      
 
      if ($.isFunction(opt.except)) 
 
      { except = opt.except.call(thisInp[0]); } 
 
      
 
      function fire_blur_event(_tar, evt, mousedown) 
 
      { 
 
       var proceed = true; 
 
       
 
       for (var i in except) 
 
       { 
 
        if (_tar.is(thisInp) || 
 
        _tar.closest(except[i], opt.maxParent).length) 
 
        { 
 
         proceed = false; 
 
         break; 
 
        } 
 
       } 
 
       if (proceed) 
 
       { 
 
        thisInp[0].blurIfNot.focus = false; 
 
        handler.call(thisInp[0], evt); 
 
       } 
 
       else if (mousedown) 
 
       { 
 
        $('html').one('mouseup', function(e) 
 
        { 
 
         thisInp[0].focus(); 
 
        }); 
 
       } 
 
      } 
 
      
 
      if (!thisInp[0].blurIfNot.isset) 
 
      { 
 
       $('html').mousedown(function(e) 
 
       { 
 
        if (thisInp[0].blurIfNot.focus) 
 
        { 
 
         var tar = $(e.target); 
 
         
 
         if (!tar.is('input')) 
 
         { fire_blur_event(tar, e, true); } 
 
        } 
 
       }); 
 
       
 
       $(window).blur(function(e) 
 
       { 
 
        if (thisInp[0].blurIfNot.focus) 
 
        { 
 
         thisInp[0].blurIfNot.focus = false; 
 
         handler.call(thisInp[0], e); 
 
        } 
 
       }); 
 
      } 
 
      else 
 
      { // to be able to update the input event if you have 
 
       // created new inputs dynamically 
 
       $('input').off('focus.blufIfNot' + time); 
 
      } 
 
      
 
      $('input').on('focus.blurIfNot' + time, function(e) 
 
      { 
 
       var tar = $(e.target); 
 
       
 
       if (tar[0] == thisInp[0]) 
 
       { thisInp[0].blurIfNot.focus = true; } 
 
       
 
       else if (thisInp[0].blurIfNot.focus) 
 
       { fire_blur_event(tar, e); } 
 
      }); 
 
      
 
      thisInp[0].blurIfNot.isset = true; 
 
     }); 
 
     return this; 
 
    } 
 
}); 
 

 
$('#input_blur_if_not').blurIfNot(
 
{ 
 
    except : [ 
 
     $('.autocomplete'), $('.question') 
 
    ], 
 
    // You can also define the elements with a function: 
 
    // except : function() 
 
    // { 
 
    //  return [ $(this).parent().find('.autocomplete') ]; 
 
    // }, 
 
    maxParent : $('#parent')[0] // optional 
 
}, 
 
function(e) 
 
{ 
 
    var rand = Math.random(); 
 
    
 
    $('#test').css('padding', rand * 100 + "px"). 
 
    html(rand + " blur !"); 
 
});
.autocomplete { 
 
    background: #eee; 
 
} 
 
.autocomplete, input { 
 
    width: 200px; 
 
    padding: 3px; 
 
    border: 1px solid #555; 
 
} 
 
.question { 
 
    display:inline-block; 
 
    border-radius:50%; 
 
    background:#137dba; 
 
    color:#fff; 
 
    font-weight:bold; 
 
    padding:2px 7px; 
 
    cursor:pointer; 
 
} 
 
#test { 
 
    position:absolute; 
 
    top:0; 
 
    left:260px; 
 
    color:red; 
 
    font-weight:bold; 
 
    padding:10px 0; 
 
    vertical-align:bottom; 
 
}
<script src="http://code.jquery.com/jquery-latest.js"></script> 
 

 
<div id="parent"> 
 
    
 
    <input value="an input" /> 
 
    <br><br> 
 
    <input id="input_blur_if_not" value="input with autocomplete menu" /> 
 
    
 
    <div class="question">?</div> 
 
    <div class="autocomplete"> 
 
     <div>option 1</div> 
 
     <div>option 2</div> 
 
    </div> 
 
    <br> 
 
    <input value="another input" /> 
 
    <div id="test"></div> 
 
    
 
</div>

Probado en Chrome y EI11. Siéntase libre de comentar si necesita más explicación.

+0

muy completo . Gracias por tomarse el tiempo para probar y publicar esto. – sadmicrowave

Cuestiones relacionadas