使用jQuery测试输入是否具有焦点


561

在我正在构建的网站的首页上,有几个<div>使用CSS :hover伪类在鼠标悬停在它们上方时添加边框。的其中一个<div>包含<form>,如果其中的输入具有焦点,则使用jQuery使用jQuery保留边框。除IE6不支持s :hover之外<a>的任何其他元素外,此方法均能完美运行。因此,仅对于此浏览器,我们使用jQuery :hover使用该$(#element).hover()方法来模仿CSS 。唯一的问题是,现在jQuery可以处理form focus() hover(),当输入具有焦点时,用户将鼠标移入和移出,边框就会消失。

我当时以为我们可以使用某种条件来停止这种行为。例如,如果我们在鼠标移开时测试了任何输入是否具有焦点,则可以阻止边框消失。AFAIK,:focusjQuery中没有选择器,所以我不确定如何实现。有任何想法吗?


1
您可以尝试将其简化为几句话,以了解所需的内容以及发生的事情吗?
mkoryak

我认为你需要寻找到捕捉的焦点和模糊事件(docs.jquery.com/Events/focusdocs.jquery.com/Events/blur
Wolfr

我在相关问题“ JavaScript(或jQuery)中是否有'具有焦点'的问题上发布了答案。。我已经增强了[narf引用的方法](#2684561)。
luiggitama 2010年

Answers:


928

jQuery 1.6以上

jQuery添加了一个:focus选择器,因此我们不再需要自己添加它。只需使用$("..").is(":focus")

jQuery 1.5及以下

编辑:随着时代的变化,我们发现更好的方法来测试焦点,新的最爱是Ben Alman的要点

jQuery.expr[':'].focus = function( elem ) {
  return elem === document.activeElement && ( elem.type || elem.href );
};

从马蒂亚斯Bynens引用在这里

请注意,(elem.type || elem.href)已添加测试以过滤出诸如身体之类的误报。这样,我们确保过滤掉除表单控件和超链接以外的所有元素。

您正在定义一个新的选择器。请参阅插件/创作。然后,您可以执行以下操作:

if ($("...").is(":focus")) {
  ...
}

要么:

$("input:focus").doStuff();

任何jQuery

如果您只想找出哪个元素具有焦点,则可以使用

$(document.activeElement)

如果不确定版本是否为1.6或更低,则可以添加:focus缺少的选择器:

(function ( $ ) {
    var filters = $.expr[":"];
    if ( !filters.focus ) { 
        filters.focus = function( elem ) {
           return elem === document.activeElement && ( elem.type || elem.href );
        };
    }
})( jQuery );

4
这可能会导致误报。有关更多信息,请参见stackoverflow.com/questions/967096/…(感谢Ben Alman和Diego Perini)。
Mathias Bynens 2011年

@Mathias Bynens-感谢您的更新(我们非常欢迎您编辑此社区Wiki答案!)
gnarf 2011年

当您需要它同时与1.5和1.6一起使用时,该怎么办?我不想覆盖jQuery自己的焦点选择器。像if (!jQuery.expr[':'].focus) { /* gist from Ben Alman */ }什么?
Betamos 2011年

@betamos-完全正确...我会在答案中添加一些内容以反映这一点。
gnarf 2011年

2
@Alex-请在jsFiddle上提供一个简化的测试用例,以显示该问题,因为据我所知,没有理由这不适用于“动态”元素。我称呼
恶作剧

46

CSS:

.focus {
    border-color:red;
}

jQuery的:

  $(document).ready(function() {

    $('input').blur(function() {
        $('input').removeClass("focus");
      })
      .focus(function() {
        $(this).addClass("focus")
      });
  });

22

这是比当前接受的答案更可靠的答案:

jQuery.expr[':'].focus = function(elem) {
  return elem === document.activeElement && (elem.type || elem.href);
};

请注意,(elem.type || elem.href)已添加测试以过滤掉误报率,例如body。这样,我们确保过滤掉除表单控件和超链接以外的所有元素。

(来自这个要点本Alman)。


13

2015年4月更新

由于这个问题已经存在了一段时间,并且一些新的约定开始发挥作用,我觉得我应该提到该.live方法已被贬值。

.on现在已经引入了该方法。

他们的文档对于解释其工作原理非常有用。

.on()方法将事件处理程序附加到jQuery对象中当前选定的元素集。从jQuery 1.7开始,.on()方法提供了附加事件处理程序所需的所有功能。有关从较旧的jQuery事件方法转换的帮助,请参见.bind()、. delegate()和.live()。

因此,为了使您可以针对“以输入为焦点”事件,您可以在脚本中使用它。就像是:

$('input').on("focus", function(){
   //do some stuff
});

这非常健壮,甚至还允许您使用TAB键。


2

我不确定您要做什么,但这听起来可以通过将输入元素(或div?)的状态存储为变量来实现:

$('div').each(function(){

    var childInputHasFocus = false;

    $(this).hover(function(){
        if (childInputHasFocus) {
            // do something
        } else { }
    }, function() {
        if (childInputHasFocus) {
            // do something
        } else { }
    });

    $('input', this)
        .focus(function(){
            childInputHasFocus = true;
        })
        .blur(function(){
            childInputHasFocus = false;
        });
});

这是我的全部工作,但是我使用了一个任意CSS类,而不是一个全局javascript变量。
bloudermilk,2009年

我用了一个变种。不需要新的jQuery插件。那使我成为一个快乐的露营者!
丹尼斯日

1

使用类标记元素状态的一种替代方法是内部数据存储功能

PS:您可以使用该data()函数存储布尔值和任何所需内容。这不仅仅是关于字符串:)

$("...").mouseover(function ()
{
    // store state on element
}).mouseout(function ()
{
    // remove stored state on element
});

然后,只需访问元素的状态即可。



1

您是否考虑过使用mouseOvermouseOut进行模拟。同时查看mouseEntermouseLeave


从本质上讲,这就是我对jQuery悬停所做的事情。您提供两种功能,一种用于鼠标移入,另一种用于鼠标移出。
bloudermilk

0

跟踪两个状态(悬停,集中)为true / false标志,并且每当状态更改时,运行一个函数,如果两个均为false,则删除border,否则显示border。

因此:onfocus集focused = true,onblur集focused = false。onmouseover设置为hovered = true,onmouseout设置为hovered = false。这些事件中的每个事件之后,运行添加/删除边框的函数。


0

据我所知,您不能问浏览器屏幕上的任何输入是否具有焦点,您必须设置某种焦点跟踪。

我通常有一个名为“ noFocus”的变量,并将其设置为true。然后,我向所有输入添加焦点事件,使noFocus变为false。然后,我将模糊事件添加到将noFocus设置为true的所有输入中。

我有一个MooTools类,可以很轻松地处理此问题,我敢肯定您可以创建一个jquery插件来执行此操作。

创建完后,您可以在进行任何边界交换之前检查noFocus。




0

我将.live(“ focus”)事件设置为select()(突出显示)文本输入的内容,以便用户在键入新值之前不必选择它。

$(formObj).select();

由于不同浏览器之间存在怪癖,因此选择有时会被引起选择的点击所取代,并且会在选择后立即取消选择内容,而是将光标放在文本字段中(在FF中通常可以,但在IE中失败)

我以为我可以通过在选择上稍加延迟来解决此问题...

setTimeout(function(){$(formObj).select();},200);

这可以很好地工作,并且选择将继续存在,但是会出现一个有趣的问题。.如果从一个字段切换到另一个字段,则在进行选择之前,焦点将切换到下一个字段。由于select会失去焦点,因此焦点将返回并触发新的“焦点”事件。最终,输入的级联选择在整个屏幕上跳动。

一个可行的解决方案是在执行select()之前检查该字段是否仍具有焦点,但是如上所述,没有简单的方法可以检查...我最终只是放弃了整个自动突出显示功能,而不是转向应该突出显示的内容。一个jQuery select()调用进入一个充满子程序的巨大函数...


0

我最后要做的是创建一个名为.elementhasfocus的任意类,该类在jQuery focus()函数中添加和删除。当hover()函数在鼠标移出时运行时,它将检查.elementhasfocus:

if(!$("#quotebox").is(".boxhasfocus")) $(this).removeClass("box_border");

因此,如果它没有该类(请参阅:div中的任何元素都没有焦点),则边框将被移除。否则,什么也不会发生。


-2

简单

 <input type="text" /> 



 <script>
     $("input").focusin(function() {

    alert("I am in Focus");

     });
 </script>

但这不能告诉您当前是哪个元素。当新元素成为焦点时调用它。因此,如果某个元素已经具有焦点,并且您想知道“ this”是否是该元素,那么此代码将无用。
Alexis Wilke
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.