jQuery:在表单输入框获得焦点时显示div,在失去焦点时隐藏div(附注)

19

我可以使用以下代码实现当输入框获得/失去焦点时,显示/隐藏一个隐藏的

元素:

  $('#example').focus(function() {
    $('div.example').css('display','block');
  }).blur(function() {
    $('div.example').fadeOut('medium');
  });
问题是我想要
在用户与该div内部进行交互(例如,在
中单击或高亮文本等操作)时仍然可见。 但是,当输入不处于焦点状态且鼠标与
内部的元素交互时,
会淡出。

<p>
<label for="example">Text:</label>
<input id="example" name="example" type="text" maxlength="100" />
<div class="example">Some text...<br /><br />More text...</div>
</p>

当用户单击输入框和/或div.example外部时,我如何使div.example消失? 我尝试使用focusin / focusout来检查<p>的焦点,但也不起作用。

div.example是否直接通过jQuery位于输入字段#example下方? 做这件事的代码如下:

var fieldExample = $('#example');
$('div.example').css("position","absolute");
$('div.example').css("left", fieldExample.offset().left);
$('div.example').css("top", fieldExample.offset().top + fieldExample.outerHeight());

如果这个问题之前已经被问过,请原谅我,但是我所看到的众多显示/隐藏div的问题并没有涵盖这个。感谢您的建议。:)

4个回答

30

如果你在文档上跟踪focusin事件,因为focusin会冒泡,所以你可以判断新聚焦的元素是否是“外部”的,如果是,则可以对其进行处理。这种方法适用于单击和按Tab键。

$('#example').focus(function() {
    var div = $('div.example').show();
    $(document).bind('focusin.example click.example',function(e) {
        if ($(e.target).closest('.example, #example').length) return;
        $(document).unbind('.example');
        div.fadeOut('medium');
    });
});
$('div.example').hide();​

更新了代码,使用focusin和click事件来决定是否隐藏div.example。我使用命名空间事件,这样我就可以调用unbind('.example')来取消绑定它们两个。

示例:http://jsfiddle.net/9XmVT/11/

附注:将你的CSS定位代码更改为只调用一次css方法。

$('div.example').css({
    "position":"absolute",
    "left": fieldExample.offset().left,
    "top": fieldExample.offset().top + fieldExample.outerHeight()
});

使用绝对定位的div的示例:http://jsfiddle.net/9XmVT/14/

更新

Ben Alman 刚刚更新了他的 clickoutside 事件,并将其转换为处理许多“外部”事件。 http://benalman.com/projects/jquery-outside-events-plugin/

这样可以让您执行以下操作:

$('#example').focus(function() {
    $('div.example').show().bind('focusoutside clickoutside',function(e) {
        $(this).unbind('focusoutside clickoutside').fadeOut('medium');
    });
});
$('div.example').hide();

嗨Peter,不幸的是,div仍然消失了。当您单击或选择该div中的文本时,我希望它保持可见状态。直到用户明确单击其他地方,div才应该消失。感谢您在这里的帮助。谢谢 :) - Lyon
@Lyon 你说得对。我刚刚更新了我的答案,提供了一种适合你的方法。 - PetersenDidIt
谢谢Peter。非常感谢你在这方面给予的帮助。我一直在绞尽脑汁,试图弄清楚如何做到这一点。是否也可以这样做,当用户点击其他地方,例如页面上的文本或页面背景时(例如,输入/ div不再处于焦点状态),div.example也会消失?目前,只有当我点击下一个输入时,它才会消失。非常感谢。我一直在尝试适应您的代码来实现它,但无济于事 :( - Lyon
@Lyon 更新了答案来处理点击和切换选项卡,应该解决了点击文本而未隐藏的问题。 - PetersenDidIt
@Lyon Ben Alman刚刚更新了他的clickoutside事件插件,以处理不仅仅是在外面单击的情况。http://benalman.com/projects/jquery-outside-events-plugin/ 这可能是你感兴趣的东西。 - PetersenDidIt
如果有人需要多个输入+隐藏的div,我在Stack Exchange Code Review上提出了问题: https://codereview.stackexchange.com/questions/212253/on-form-inputs-focus-show-div-hide-div-on-blur-for-multiple-inputs-and-hidden#212254+1 @P - Kerry7777

2

1
你可以使用计时器来引入轻微的延迟,如果在字段上有焦点或单击div,则停止计时器:
var timer = false ;
$('#example').focus(function() {
    if (timer)
        clearTimeout(timer);
    $('div.example').css('display','block');

  }).blur(function() {

    if (timer)
        clearTimeout(timer);

    timer = setTimeout(function(){
            $('div.example').fadeOut('medium');
        },500);

  });

$('div.example').click(function(){
    if (timer)
        clearTimeout(timer);
})

并没有真正解决问题,只是延迟了问题的出现。 - PetersenDidIt

1

解决这个问题的一个纯JavaScript方法是与包装器结合使用relatedTarget。由于relatedTarget的工作方式,您的div.example需要可聚焦才能与relatedTarget一起使用。但是,因为div元素默认情况下不可聚焦,所以您需要通过向元素添加tabindex="0"tabindex="-1"属性来使div.example变得可聚焦。您可以阅读MDN tabindex文档中两者之间的区别。

运行以下代码以查看其实际效果。我已将红色边框添加到div.example元素以更好地呈现。

const wrapper = document.getElementById("wrapper");
const toggle = document.querySelector("#example");
const target = document.querySelector("div.example");

toggle.addEventListener("focus", () => {
  target.style.display = "";
});

wrapper.addEventListener("focusout", (event) => {
  if (wrapper.contains(event.relatedTarget)) {
    return;
  }
  target.style.display = "none";
});
<div id="wrapper">
  <label for="example">Text:</label>
  <input id="example" name="example" type="text" maxlength="100" />
  <div class="example" tabindex="0" style="border: 1px solid red;">Some text...<br />More text...</div>
</div>


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