防止在焦点事件之后点击

4
当用户点击输入框时,将执行两个连续的事件:focusclickfocus总是首先执行并显示通知。但是,紧接在focus之后立即运行的click会隐藏通知。只有在输入框未聚焦且两个事件连续执行时才会出现此问题。
我正在寻找一种干净的解决方案,可以帮助我实现此功能(不需要任何超时或奇怪的黑客技巧)。 HTML:
<label for="example">Example input: </label>
<input type="text" id="example" name="example" />
<p id="notice" class="hide">This text could show when focus, hide when blur and toggle show/hide when click.</p>

JavaScript:

$('#example').on('focus', _onFocus)
             .on('blur', _onBlur)
             .on('click', _onClick);

function _onFocus(e) {  
    console.log('focus');

    e.preventDefault();
    e.stopPropagation();
    e.stopImmediatePropagation();

    $('#notice').removeClass('hide');
}

function _onClick(e) {
   console.log('click');
   $('#notice').toggleClass('hide');
}

function _onBlur(e) {
    console.log('blur');
    $('#notice').addClass('hide');
}

UPDATED Fiddle is here:


这是你想要的吗?http://jsfiddle.net/3Bev4/11/ - Abhitalks
为什么你在_onFocus和_onBlur事件中不使用addClass()和removeClass()的组合呢?在单击事件中切换类真的必要吗? - Suraj Kumar
@abhitalks 不行。点击应该自己切换显示/隐藏。 - Artem Fitiskin
@SurajKumar 是的,这是必要的。这只是一个简单的例子,在实际代码中还有其他使用它的原因。 - Artem Fitiskin
@ArtemFitiskin:更新了代码片段并添加为答案。 - Abhitalks
5个回答

3

我认为你把切换按钮搞混了。不需要防止事件传播等操作。只需在 click 触发时检查通知是否已可见。

演示:http://jsfiddle.net/3Bev4/13/

代码

var $notice = $('#notice'); // cache the notice

function _onFocus(e) {  
    console.log('focus');
    $notice.removeClass('hide'); // on focus show it
}

function _onClick(e) {
   console.log('click');
    if ($notice.is('hidden')) { // on click check if already visible
       $notice.removeClass('hide'); // if not then show it
    }
}

function _onBlur(e) {
    console.log('blur');
    $notice.addClass('hide'); // on blur hide it
}

希望能帮到你。
更新:根据问题提出者对单击切换的澄清:
只需将焦点事件缓存到状态变量中,然后基于该状态显示通知或切换类。
演示2:http://jsfiddle.net/3Bev4/19/ 更新代码:
var $notice = $('#notice'), isfocus = false; 

function _onFocus(e) {  
    isFocus = true; // cache the state of focus
    $notice.removeClass('hide');
}

function _onClick(e) {
    if (isFocus) { // if focus was fired, show/hide based on visibility
        if ($notice.is('hidden')) { $notice.removeClass('hide'); }
        isFocus = false; // reset the cached state for future
    } else {
        $notice.toggleClass('hide'); // toggle if there is only click while focussed
    }
}

更新2:基于原始问题提出的观察,建议在选项卡聚焦后的第一次点击时进行以下操作:

仔细考虑后,您是否可以仅绑定mousedownmouseup而不是click? 这将不会触发焦点。

演示3:http://jsfiddle.net/3Bev4/24/

更新后的代码:

$('#example').on('focus', _onFocus)
             .on('blur', _onBlur)
             .on('mousedown', _onClick);

var $notice = $('#notice');
function _onFocus(e) { $notice.removeClass('hide'); }
function _onClick(e) { $notice.toggleClass('hide'); }
function _onBlur(e) { $notice.addClass('hide'); }

这对你来说可行吗?


谢谢,但是你的解决方案中点击无法作为切换器工作。请看我的fiddle并尝试多次点击一个字段。 - Artem Fitiskin
1
@ArtemFitiskin:好的,现在我明白你想表达什么了。已经更新了答案。 - Abhitalks
另外,我有一个使用setTimeout的想法,但这不是一个清晰的解决方案。_onFocus --> isFocus = true; setTimeout(function () { isFocus = false }, 500); - Artem Fitiskin
1
@ArtemFitiskin:再次更新了答案。你能否只绑定mousedown或mouseup而不是click?这样就不会触发焦点了。演示:http://jsfiddle.net/3Bev4/21/ - Abhitalks
谢谢@Abhitalks,这对我帮助很大。我不知道mousedown不会触发焦点! - nathancahill
显示剩余5条评论

2

设置一个变量来表示"焦点"似乎可以解决问题:http://jsfiddle.net/3Bev4/9/

Javascript:

$('#example').on('focus', _onFocus)
    .on('click', _onClick)
    .on('blur', _onBlur);
focus = false;

function _onFocus(e) {
    console.log('focus');
    $('#notice').removeClass('hide');

    e.preventDefault();
    e.stopPropagation();
    e.stopImmediatePropagation();
    focus = true;
}

function _onClick(e) {
    console.log('click');
    if (!focus) {
        $('#notice').toggleClass('hide');
    } else {
        focus = false;
    }
}

function _onBlur(e) {
    console.log('blur');
    $('#notice').addClass('hide');
}

我完全理解这个方法,但是如果你使用Tab键选择字段(注意显示正确),然后单击它,你会到达_onClick的else语句(什么也不会发生,必须隐藏)。 - Artem Fitiskin
+1 @Rob。很抱歉我没有早点注意到你的答案,直到OP要求我才看到。否则我就不会首先尝试了! - Abhitalks

0
如果你想在失去焦点时隐藏通知,那么肯定需要这样做:
function _onBlur(e) {
    console.log('blur');
    $('#notice').addClass('hide'); // Add the hidden class, not remove it
}

在 fiddle 中这样做似乎解决了问题。


0

你可以使用许多jQuery方法来代替添加或移动类:

更新:添加参数以处理单击函数 http://jsfiddle.net/3Bev4/23/

var showNotice = false;
$('#example').focus(function(){
     $('#notice').show();
     showNotice = true;
}).click(function(){
    if(showNotice){                
         $('#notice').show();
        showNotice = false;
    }else{
         showNotice = true;
        $('#notice').hide();
    }


}).blur(function(){
     $('#notice').hide(); 
});

如果您使用Tab键选择字段(无需单击即可聚焦),则您的解决方案将无法正常工作(聚焦而不单击不会显示通知)。 - Artem Fitiskin
添加一个参数,以便我们可以处理点击函数。 - Hank X

0

你写的代码是正确的,除了你需要将 $('#notice').removeClass('hide'); 替换为 $('#notice').addClass('hide');

因为在 onBlur 事件中你想要隐藏它,所以添加 hide 类,而不是移除 "hide" 类。

我希望这就是你犯的错误。 如果我错了,请纠正我,因为我不太懂 JQuery,我只知道 JavaScript。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接