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

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

评论

您可以尝试将其简化为所需的几句话,以及我正在发生的事情吗?

我认为您需要研究捕获焦点和模糊事件(docs.jquery.com/Events/focus和docs.jquery.com/Events/blur)

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

#1 楼

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


引自Mathias 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 );


评论


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

–玛蒂亚斯·拜恩斯(Mathias Bynens)
2011-3-22在13:01

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

– gnarf
2011年3月22日在21:31

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

–贝塔莫斯
2011年6月3日19:11



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

– gnarf
11年3月3日在20:51

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

– gnarf
2012年6月14日22:14

#2 楼

CSS:

.focus {
    border-color:red;
}


JQuery:

  $(document).ready(function() {

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


#3 楼

与目前接受的答案相比,这是一个更可靠的答案:

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


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

(摘自Ben Alman的本要点。)

#4 楼

2015年4月更新

由于这个问题已经存在了一段时间,并且一些新的约定已经生效,所以我觉得我应该提一下.live方法已经过时了。

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

其文档对解释其工作原理非常有用;


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


为了使您可以定位“以输入为重点”事件,您可以在脚本中使用它。像这样的东西:

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


这非常强大,甚至允许您使用TAB键。

评论


非常好的解决方案,谢谢。使用on(“ focusout”,用于相反的功能

– Barbz_YHOOL
8月19日23:30

#5 楼

我不确定您要做什么,但这听起来可以通过将输入元素(或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
09年6月8日在21:42

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

–丹尼斯日
2010年11月8日在21:06

#6 楼

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

P.S .:可以使用data()函数存储布尔值以及任何所需的内容。这不仅仅是字符串:)

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


然后这就是访问元素状态的问题。

#7 楼

如果有人在乎,现在有更好的方法来捕获焦点,请$(foo).focus(...)

http://api.jquery.com/focus/

#8 楼

您是否考虑过使用mouseOver和mouseOut进行模拟。同时查看mouseEnter和mouseLeave

评论


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

–bloudermilk
09年6月8日在21:30

#9 楼



所以:onfocus将focuss设置为focus = true,onblur集focused = false。 onmouseover设置为hovered = true,onmouseout设置为hovered = false。在每个这些事件之后,运行一个添加/删除边框的函数。

#10 楼

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

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

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

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

#11 楼

没有:focus,但是有:selected
http://docs.jquery.com/Selectors/selected

,但是如果您想根据所选内容更改外观,您可能应该使用模糊事件。

http://docs.jquery.com/Events/blur

#12 楼

有一个插件可以检查元素是否集中:http://plugins.jquery.com/project/focused

$('input').each(function(){
   if ($(this) == $.focused()) {
      $(this).addClass('focused');
   }
})


评论


为什么只使用核心jquery时为什么要使用插件?

– Marcy Sutton
2011-12-16 18:40

你是对的。但是2年前我不知道该问题的解决方案。

– MuratÇorlu
2011-12-17 22:04

#13 楼

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

$(formObj).select();

由于不同浏览器之间的怪癖,选择有时会被引起选择的点击所取代,并且会取消选择紧接着将内容放置在文本字段中(在FF中通常可以正常运行,但在IE中失败)

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

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

这很好用,选择仍然存在,但是出现了一个有趣的问题。 。如果从一个字段切换到另一个字段,则在进行选择之前,焦点将切换到下一个字段。由于select会失去焦点,因此焦点将返回并触发新的“焦点”事件。最终导致一系列输入选择在屏幕上跳动。

可行的解决方案是在执行select()之前检查字段是否仍然具有焦点,但是如上所述,这并不简单检查方式...我最终只是放弃了整个自动突出显示,而不是将应该是单个jQuery select()调用的内容变成了一个载有子例程的巨大函数...

#14 楼

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

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


因此,如果它没有该类(请阅读: div有焦点)边框已删除。否则,什么都不会发生。

#15 楼

简单

 <input type="text" /> 



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

    alert("I am in Focus");

     });
 </script>


评论


但这不能告诉您当前是哪个元素。当新元素成为焦点时调用它。因此,如果某个元素已经具有焦点,并且您想知道“ this”是否是该元素,则此代码是无用的。

– Alexis Wilke
2014年2月1日下午0:46