jQuery blur should not fire if div is clicked/focused

只谈情不闲聊 提交于 2019-11-30 17:03:34

问题


I have a standard text input that has a blur event. The blur event should fire when anything in the document is clicked (other than the input AND <div id='show-anyways'></div>).

My problem is that I don't know how to add the <div id='show-anyways'></div> to negate the blur event function.

Hopefully I have explained myself well enough, I know it's kinda a weird situation. Please let me know if you need more info.


回答1:


Use the event target to determine what is clicked. Following will track all clicks on document and not trigger blur() if element is the DIV or the Input.

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

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

It will not trigger on elements that have any preventPropogation set up.




回答2:


UPDATE: had to completely rewrite my solution. The blur event handler is attached to the event that loses focus: if it was similar to mouseout event, we could know which element will get the focus, but there's no such luck. So we have to resort capturing .click events instead - and trigger some function based on it, instead of listening to blur events.

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

Here's a fiddle to play with. Sorry for that confusion caused by my original answer. (




回答3:


There are a few things missing from the other solutions. The most important is that you need to check if the input is focused before calling your blur event. The other thing is that a blur event is called not only if you click somewhere else: you can also call it when you go to another tab in your browser or if you hit tab or shift + tab to go to the next/previous input. Finally, you need to consider using the jQuery function closest() when you check if the target element is an exception of your blur event (it can be the child of your exception).

So, I came up with this jQuery prototype function:

$.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>

Tested in Chrome and IE11. Feel free to comment if you need more explanation.




回答4:


could try adding some logic like?

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

});

this basically fires when the blur occurs, it checks what was clicked/targed and if it happens to be the show-anyways then it will return false and stop doing anything. but if its not show-anyways then it can do your blur event?

untested, but is this what you mean?



来源:https://stackoverflow.com/questions/11173509/jquery-blur-should-not-fire-if-div-is-clicked-focused

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!