2012-06-23 3 views
5

나는 블러 이벤트가있는 표준 텍스트 입력이 있습니다. 문서에서 아무 것도 클릭하지 않으면 (블렌드 이벤트는 입력 AND <div id='show-anyways'></div> 제외) 발생합니다.div를 클릭하거나 초점을 맞추면 jQuery 흐림이 발생하지 않아야합니다.

내 문제는 내가 흐림 이벤트 기능을 부정하는 <div id='show-anyways'></div>를 추가하는 방법을 모른다는 것이다.

는 다행스럽게도 필자는 자신이 충분히 설명했다 나는 좀 이상한 상황을 알고있다. 자세한 정보가 필요하면 알려주십시오.

+2

당신이 지금까지 코딩 한 것을 보여주십시오. –

+1

'e.preventDefault','e.stopPropagation' 중 하나가 필요하거나 클릭 한 것을 판별하고 목표물을 치기 전에 버블 링을 멈추어야합니다. 내가 생각하는 디자인 결함은 DOM에 블러 이벤트 핸들러가 있다는 것입니다. 그 말이 맞습니까? –

답변

10

은 클릭을 결정하기 위해 이벤트 대상을 사용합니다. 수행하면 문서에 모든 클릭을 추적하고 요소는 DIV 또는 입력 인 경우 흐림()을 트리거하지 않습니다.

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

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

을 그것은 요소를 트리거하지 않습니다 그 어떤 preventPropogation가 설정 한.

+0

클릭/포커스 시퀀스가 ​​입력 된 경우 원래 input.blur 이벤트가 발생하지 않기 때문에 사실상 $ (document) .click을 사용하여 끝내야했습니다. -> # show-anyways -> document.click. 그러므로 # show-anyways와 document.click 사이의 이벤트는 input.blur 이벤트를 트리거하지 않습니다 ... – sadmicrowave

+2

참고 : div 및 모든 하위 항목 내에서 클릭을 확인하는 좋은 방법은'&&! $ tgt.is ($ ('*', $ ('# show-anyways')))'를 위의 클릭 함수 내의 조건문에 추가합니다. – garromark

+0

@garromark는 요소의 자손만을 검사합니다 ... '$ tgt.closest ('# show-anyways '). 길이는 하위 항목과 요소를 검사합니다 .. 왜 내가 그 중 하나를 사용하지 않았는지 확실하지 않습니다 – charlietfl

0

과 같은 논리를 추가 할 수 있습니까? 흐림이 발생하면

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

}); 

이 기본적으로는 targed/클릭 된 것을 확인하고는 것을 일어나는 경우 쇼 - 어쨌든 다음은 false를 반환하고 아무것도 중지, 발생합니다. 그러나 그것이 보이지 않는다면 - 어쨌든 당신의 블러 이벤트를 할 수 있습니까?

테스트되지 않았지만 이것이 무슨 뜻입니까?

+2

이것은 정확히 무슨 뜻인가요?하지만 e.target은 blur 이벤트에 대한 'input'을 반환합니다 ... 그래서 당신의 솔루션이 무엇인지를 알 수 없습니다 ... – sadmicrowave

+0

발견 - 이벤트의 구문은 originalEvent.explicitOriginalTarget – sadmicrowave

+0

입니다. 슬프게도 originalEvent.explicitOriginalTarget은 Gecko에만 해당됩니다. – Yogh

1

업데이트 : 내 솔루션을 완전히 다시 써야했습니다. blur 이벤트 핸들러는 포커스를 잃는 이벤트에 첨부됩니다. mouseout 이벤트와 비슷한 경우 포커스를받을 요소를 알 수 있지만 그런 행운은 없습니다. 따라서 blur 이벤트를 청취하는 대신 .click 이벤트를 대신 캡처하여 일부 기능을 트리거해야합니다.

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(); 
});​ 

다음은 a fiddle입니다. 원래의 대답으로 인해 혼란스러워서 죄송합니다. (

1

다른 솔루션에없는 몇 가지가있다. 가장 중요한 당신이 입력하여 흐림 이벤트를 호출하기 전에 초점을 맞추고 있는지 확인해야 할 것입니다. 다른 것은 흐림 이벤트이다 다른 곳을 클릭 할 때뿐만 아니라 브라우저의 다른 탭으로 이동하거나을 누르는 경우에도 호출 할 수 있습니다.또는 shift + tab을 입력하여 다음/이전 입력으로 이동하십시오. 마지막으로 jQuery 함수 closest() 사용을 고려해야합니다. 대상 요소가 블러 이벤트의 예외 (예외의 자식 일 수 있음)인지 확인해야합니다.

그래서,이 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>

가 크롬과 IE11에서 테스트. 더 자세한 설명이 필요하면 언제든지 의견을 말하십시오.

+0

매우 포괄적 인 . 시간을내어 테스트하고 게시 해 주셔서 감사합니다. – sadmicrowave

관련 문제