ใช้ jQuery เพื่อทดสอบว่าอินพุตมีโฟกัสหรือไม่


561

ในหน้าแรกของเว็บไซต์ที่ฉันกำลังสร้างหลายแห่ง<div>ใช้ CSS :hoverหลอกคลาสเพื่อเพิ่มเส้นขอบเมื่อเมาส์อยู่เหนือพวกเขา หนึ่งในนั้น<div>ประกอบด้วย a <form>ซึ่งใช้ jQuery จะเก็บขอบไว้หากอินพุตภายในนั้นมีโฟกัส มันทำงานได้อย่างสมบูรณ์ยกเว้นว่า IE6 ไม่รองรับ:hoverองค์ประกอบอื่นที่ไม่ใช่<a>s ดังนั้นสำหรับเบราว์เซอร์นี้เราเท่านั้นที่ใช้ jQuery เพื่อเลียนแบบ CSS :hoverโดยใช้$(#element).hover()เมธอด ปัญหาเดียวคือตอนนี้ที่ jQuery จัดการทั้งแบบฟอร์มfocus() และ hover()เมื่ออินพุตมีการโฟกัสผู้ใช้จะย้ายเมาส์เข้าและออกเส้นขอบจะหายไป

ฉันคิดว่าเราสามารถใช้เงื่อนไขบางอย่างเพื่อหยุดพฤติกรรมนี้ ตัวอย่างเช่นหากเราทดสอบโดยใช้เมาส์หากอินพุตใด ๆ มีโฟกัสเราสามารถหยุดเส้นขอบไม่ให้หายไปได้ AFAIK ไม่มี:focusตัวเลือกใน jQuery ดังนั้นฉันไม่แน่ใจว่าจะทำให้สิ่งนี้เกิดขึ้นได้อย่างไร ความคิดใด ๆ


1
คุณลองต้มให้น้อยลงในประโยคสองสามประโยคของสิ่งที่จำเป็นและสิ่งที่ฉันเกิดขึ้นได้อย่างไร
mkoryak

ฉันคิดว่าคุณต้องมองหาการจับโฟกัสและเบลอกิจกรรม ( docs.jquery.com/Events/focusและdocs.jquery.com/Events/blur )
Wolfr

ฉันโพสต์คำตอบสำหรับคำถามที่เกี่ยวข้อง"มี" มีโฟกัส "ใน JavaScript (หรือ jQuery) หรือไม่" . ฉันได้ปรับปรุง [วิธี cletus อ้างโดย gnarf] (# 2684561)
luiggitama

คำตอบ:


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

ยกมาจาก 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 );

4
สิ่งนี้อาจทำให้เกิดผลบวกปลอม ดูstackoverflow.com/questions/967096/…สำหรับข้อมูลเพิ่มเติม (ขอบคุณ Ben Alman และ Diego Perini)
Mathias Bynens

@Mathias Bynens - ขอบคุณสำหรับการอัปเดต (คุณมีมากกว่ายินดีที่จะแก้ไขชุมชนนี้ wiki คำตอบ btw!)
gnarf

แล้วเมื่อคุณต้องการใช้งานกับทั้ง 1.5 และ 1.6 ล่ะ ฉันไม่ต้องการแทนที่ตัวเลือกการโฟกัสของ jQuery สิ่งที่ชอบif (!jQuery.expr[':'].focus) { /* gist from Ben Alman */ }?
Betamos

@betamos - ถูกต้อง ... ฉันจะเพิ่มบางอย่างลงในคำตอบเพื่อสะท้อนถึงสิ่งนั้น
แคระ

2
@Alex - โปรดให้กรณีทดสอบลดลงใน jsFiddle แสดงปัญหาเพราะเท่าที่ฉันสามารถบอกได้มีเหตุผลที่ไม่ควรใช้องค์ประกอบ "แบบไดนามิก" ฉันเรียก shenanigans ...
แคระ

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ด้วยวิธีนี้เราตรวจสอบให้แน่ใจว่าได้กรององค์ประกอบทั้งหมดยกเว้นตัวควบคุมฟอร์มและไฮเปอร์ลิงก์แล้ว

(นำมาจากส่วนสำคัญนี้โดยBen Alman )


13

อัปเดตเมษายน 2558

เนื่องจากคำถามนี้ได้ผ่านไประยะหนึ่งแล้วและมีการประชุมใหม่ ๆ เข้ามาฉันรู้สึกว่าฉันควรพูดถึง.liveวิธีการที่ได้รับการคิดค่าเสื่อมราคา

ในสถานที่ที่.onวิธีการได้รับการแนะนำในขณะนี้

เอกสารของพวกเขาค่อนข้างมีประโยชน์ในการอธิบายวิธีการทำงาน

วิธีการ. on () แนบตัวจัดการเหตุการณ์กับชุดองค์ประกอบที่เลือกในปัจจุบันในวัตถุ jQuery ตั้งแต่ jQuery 1.7 เมธอด. on () จัดเตรียมการทำงานทั้งหมดที่จำเป็นสำหรับการแนบตัวจัดการเหตุการณ์ สำหรับความช่วยเหลือในการแปลงจากวิธีเหตุการณ์ jQuery ที่เก่ากว่าดู. ผูก (), .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 โดยพลการแทนตัวแปรจาวาสคริปต์ทั่วโลก
bloudermilk

ฉันใช้รูปแบบของสิ่งนี้ ไม่จำเป็นต้องใช้ปลั๊กอิน jQuery ใหม่ นั่นทำให้ฉันเป็นนักไปพักแรมที่มีความสุข!
Dennis Day

1

อีกทางเลือกหนึ่งในการใช้คลาสเพื่อทำเครื่องหมายสถานะขององค์ประกอบคือฟังก์ชันการทำงานของที่เก็บข้อมูลภายในฟังก์ชั่นการจัดเก็บข้อมูล

PS: คุณสามารถเก็บบูลีนและสิ่งที่คุณต้องการโดยใช้data()ฟังก์ชั่น มันไม่ได้เกี่ยวกับสตริง :)

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

แล้วมันเป็นเพียงเรื่องของการเข้าถึงสถานะขององค์ประกอบ



1

คุณมีความคิดเกี่ยวกับการใช้mouseOverและmouseOutเพื่อจำลองสิ่งนี้ ดูที่mouseEnterและmouseLeave ด้วย


นั่นคือสิ่งที่ฉันกำลังทำกับโฮเวอร์ของ jQuery คุณจัดหาฟังก์ชั่นสองอย่างหนึ่งอันสำหรับเม้าส์และเม้าส์หนึ่งเม้าส์
bloudermilk

0

ติดตามสถานะทั้งสอง (โฮเวอร์, โฟกัส) เป็นแฟล็กจริง / เท็จและเมื่อใดก็ตามที่มีการเปลี่ยนแปลงให้เรียกใช้ฟังก์ชันที่ลบเส้นขอบหากทั้งสองเป็นเท็จมิฉะนั้นจะแสดงเส้นขอบ

ดังนั้น: onfocus sets focus = true, onblur ตั้งค่า focus = false onmouseover sets hovered = true, onmouseout sets hovered = false หลังจากแต่ละเหตุการณ์เหล่านี้เรียกใช้ฟังก์ชันที่เพิ่ม / ลบเส้นขอบ


0

เท่าที่ฉันรู้คุณไม่สามารถถามเบราว์เซอร์ว่าอินพุตใด ๆ บนหน้าจอมีโฟกัสคุณต้องตั้งค่าการติดตามโฟกัส

ฉันมักจะมีตัวแปรที่เรียกว่า "noFocus" และตั้งค่าเป็นจริง จากนั้นฉันเพิ่มเหตุการณ์การโฟกัสไปยังอินพุตทั้งหมดที่ทำให้ไม่มีการโฟกัสเป็นเท็จ จากนั้นฉันเพิ่มเหตุการณ์ความพร่ามัวให้กับอินพุตทั้งหมดที่ตั้งค่า noFocus กลับไปเป็นจริง

ฉันมีคลาส MooTools ที่จัดการสิ่งนี้ได้อย่างง่ายดายฉันแน่ใจว่าคุณสามารถสร้างปลั๊กอิน jquery เพื่อทำสิ่งเดียวกันได้

เมื่อสร้างแล้วคุณสามารถตรวจสอบ noFocus ก่อนทำการสลับขอบใด ๆ



0

มีปลั๊กอินเพื่อตรวจสอบว่าองค์ประกอบเน้นหรือไม่: http://plugins.jquery.com/project/focused

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

1
ทำไมต้องใช้ปลั๊กอินเมื่อคุณสามารถใช้ jQuery หลักได้
Marcy Sutton

1
คุณพูดถูก แต่ฉันไม่รู้วิธีแก้ปัญหาสำหรับปัญหานี้เมื่อ 2 ปีก่อน
Murat Çorlu

0

ฉันมีชุดกิจกรรม. live ("โฟกัส") เพื่อเลือก () (เน้น) เนื้อหาของการป้อนข้อความเพื่อที่ผู้ใช้จะไม่ต้องเลือกก่อนพิมพ์ค่าใหม่

$ (formObj) .Select ();

เนื่องจากนิสัยใจคอระหว่างเบราว์เซอร์ที่แตกต่างกันบางครั้งการเลือกจะถูกแทนที่ด้วยการคลิกที่ทำให้เกิดและมันจะยกเลิกการเลือกเนื้อหาทันทีหลังจากที่วางเคอร์เซอร์ในช่องข้อความ (ทำงานส่วนใหญ่ตกลงใน FF แต่ล้มเหลวใน IE)

ฉันคิดว่าฉันสามารถแก้ปัญหานี้ได้โดยเลือกความล่าช้าเล็กน้อย ...

setTimeout (ฟังก์ชั่น () {$ (formObj) .Select ();}, 200);

สิ่งนี้ทำงานได้ดีและการเลือกจะคงอยู่ แต่ปัญหาตลก ๆ เกิดขึ้น .. หากคุณแท็บจากฟิลด์หนึ่งไปยังฟิลด์ถัดไปโฟกัสจะเปลี่ยนเป็นฟิลด์ถัดไปก่อนที่การเลือกจะเกิดขึ้น ตั้งแต่เลือกขโมยโฟกัสโฟกัสจะย้อนกลับไปและเรียกใช้เหตุการณ์ "โฟกัส" ใหม่ จบลงด้วยการเรียงซ้อนของข้อมูลที่เลือกเต้นทั่วหน้าจอ

วิธีแก้ปัญหาที่สามารถใช้งานได้คือการตรวจสอบว่าเขตข้อมูลนั้นยังคงมีโฟกัสอยู่ก่อนที่จะดำเนินการเลือก () แต่ตามที่กล่าวไว้ไม่มีวิธีง่ายๆในการตรวจสอบ ... ฉันลงเอยด้วยการจ่ายด้วยไฮไลท์อัตโนมัติทั้งหมด jQuery select () เดียวเรียกใช้ฟังก์ชันขนาดใหญ่ที่มีรูทีนย่อย ...


0

สิ่งที่ฉันทำตอนนี้คือการสร้างคลาสโดยพลการที่เรียกว่า. องค์ประกอบการโฟกัสซึ่งถูกเพิ่มและลบออกภายในฟังก์ชัน jQuery focus () เมื่อฟังก์ชันโฮเวอร์ () ทำงานโดยเลื่อนเมาส์ออกจะเป็นการตรวจสอบ. องค์ประกอบการโฟกัส:

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

ดังนั้นหากไม่มีคลาสนั้น (อ่าน: ไม่มีองค์ประกอบภายใน div มีโฟกัส) เส้นขอบจะถูกลบออก มิฉะนั้นจะไม่มีอะไรเกิดขึ้น


-2

ง่าย

 <input type="text" /> 



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

    alert("I am in Focus");

     });
 </script>

ไม่ได้บอกคุณว่าองค์ประกอบใดที่อยู่ในโฟกัส มันถูกเรียกเมื่อองค์ประกอบใหม่ได้รับการโฟกัส ดังนั้นหากองค์ประกอบมีโฟกัสอยู่แล้วและคุณต้องการทราบว่า 'นี่' เป็นองค์ประกอบหรือไม่รหัสนี้ไม่มีประโยชน์
Alexis Wilke
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.