Sử dụng jQuery để kiểm tra xem đầu vào có tập trung không


561

Trên trang đầu của trang web tôi đang xây dựng, một số người <div>sử dụng lớp :hovergiả CSS để thêm đường viền khi chuột ở trên chúng. Một trong những cái <div>chứa một <form>cái, sử dụng jQuery, sẽ giữ đường viền nếu một đầu vào bên trong nó có tiêu điểm. Điều này hoạt động hoàn hảo ngoại trừ IE6 không hỗ trợ :hovertrên bất kỳ yếu tố nào ngoài <a>s. Vì vậy, đối với trình duyệt này, chúng tôi chỉ sử dụng jQuery để bắt chước CSS :hoverbằng $(#element).hover()phương thức này. Vấn đề duy nhất là, bây giờ jQuery xử lý cả biểu mẫu focus() hover() khi đầu vào có tiêu điểm thì người dùng di chuyển chuột vào và ra, đường viền sẽ biến mất.

Tôi đã nghĩ rằng chúng ta có thể sử dụng một số loại điều kiện để ngăn chặn hành vi này. Ví dụ: nếu chúng tôi đã thử nghiệm trên chuột nếu bất kỳ đầu vào nào có tiêu điểm, chúng tôi có thể ngăn chặn đường viền đi. AFAIK, không có :focusbộ chọn trong jQuery, vì vậy tôi không chắc làm thế nào để thực hiện điều này. Có ý kiến ​​gì không?


1
bạn có thể cố gắng đun sôi nó xuống một vài câu về những gì được yêu cầu, và những gì tôi đang xảy ra?
mkoryak

Tôi nghĩ rằng bạn cần xem xét việc nắm bắt các sự kiện tập trung và làm mờ ( docs.jquery.com/Events/f Focusdocs.jquery.com/Events/blur )
Wolfr

Tôi đã đăng câu trả lời cho câu hỏi liên quan "Có 'trọng tâm' trong JavaScript (hoặc jQuery) không?" . Tôi đã nâng cao [cách tiếp cận cletus được trích dẫn bởi gnarf] (# 2684561).
luiggitama

Câu trả lời:


928

jQuery 1.6+

jQuery đã thêm một :focusbộ chọn để chúng ta không còn cần phải tự thêm nó nữa. Chỉ dùng$("..").is(":focus")

jQuery 1.5 trở xuống

Chỉnh sửa: Khi thời gian thay đổi, chúng tôi tìm thấy các phương pháp tốt hơn để kiểm tra trọng tâm, yêu thích mới là ý chính này từ Ben Alman :

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

Trích dẫn từ Mathias Bynens tại đây :

Lưu ý rằng (elem.type || elem.href)thử nghiệm đã được thêm vào để lọc ra các kết quả dương tính giả như cơ thể. Bằng cách này, chúng tôi đảm bảo lọc ra tất cả các yếu tố ngoại trừ điều khiển biểu mẫu và siêu liên kết.

Bạn đang xác định một bộ chọn mới. Xem Plugin / Authoring . Sau đó, bạn có thể làm:

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

hoặc là:

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

Bất kỳ jQuery

Nếu bạn chỉ muốn tìm ra yếu tố nào có trọng tâm, bạn có thể sử dụng

$(document.activeElement)

Nếu bạn không chắc chắn phiên bản sẽ là 1.6 hoặc thấp hơn, bạn có thể thêm :focusbộ chọn nếu thiếu:

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

4
Điều này có thể gây ra dương tính giả. Xem stackoverflow.com/questions/967096/ khăn để biết thêm thông tin (cảm ơn Ben Alman và Diego Perini).
Mathias Bynens

@Mathias Bynens - Cảm ơn bạn đã cập nhật (rất mong được chỉnh sửa cộng đồng wiki này trả lời btw!)
gnarf

Còn khi bạn cần nó để hoạt động với cả 1.5- và 1.6 thì sao? Tôi không muốn ghi đè bộ chọn tiêu điểm của jQuery. Một cái gì đó như thế if (!jQuery.expr[':'].focus) { /* gist from Ben Alman */ }nào?
Betamos

@betamos - Chính xác là đúng ... Tôi sẽ thêm một cái gì đó vào câu trả lời để phản ánh điều đó.
gnarf

2
@Alex - Vui lòng cung cấp trường hợp thử nghiệm giảm trên jsFiddle cho thấy sự cố, vì theo như tôi có thể nói, không có lý do gì điều này không hoạt động trên các yếu tố "động". Tôi gọi shenanigans ...
gnarf

46

CSS:

.focus {
    border-color:red;
}

JQuery:

  $(document).ready(function() {

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

22

Đây là một câu trả lời mạnh mẽ hơn câu trả lời hiện được chấp nhận:

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

Lưu ý rằng (elem.type || elem.href)thử nghiệm đã được thêm vào để lọc ra dương tính giả như thế nào body. Bằng cách này, chúng tôi đảm bảo lọc ra tất cả các yếu tố ngoại trừ điều khiển biểu mẫu và siêu liên kết.

(Lấy từ ý chính này của Ben Alman .)


13

Cập nhật tháng 4 năm 2015

Vì câu hỏi này đã xuất hiện được một thời gian và một số quy ước mới đã được đưa ra, tôi cảm thấy rằng tôi nên đề cập đến .livephương pháp này đã bị khấu hao.

Ở vị trí của nó, .onphương pháp hiện đã được giới thiệu.

Tài liệu của họ khá hữu ích trong việc giải thích cách thức hoạt động của nó;

Phương thức .on () gắn các trình xử lý sự kiện vào tập hợp các phần tử hiện được chọn trong đối tượng jQuery. Kể từ jQuery 1.7, phương thức .on () cung cấp tất cả các chức năng cần thiết để đính kèm các trình xử lý sự kiện. Để được trợ giúp chuyển đổi từ các phương thức sự kiện jQuery cũ hơn, hãy xem .bind (), .delegate () và .live ().

Vì vậy, để bạn nhắm mục tiêu sự kiện 'tập trung đầu vào', bạn có thể sử dụng điều này trong một tập lệnh. Cái gì đó như:

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

Điều này khá mạnh mẽ và thậm chí cho phép bạn sử dụng phím TAB.


2

Tôi không hoàn toàn chắc chắn những gì bạn theo đuổi nhưng điều này nghe có vẻ như có thể đạt được bằng cách lưu trữ trạng thái của các phần tử đầu vào (hoặc div?) Làm biến:

$('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;
        });
});

Đây là những gì tôi cố gắng làm, nhưng tôi đã sử dụng một lớp CSS tùy ý thay vì một biến javascript toàn cầu.
bloudermilk

Tôi đã sử dụng một biến thể của điều này. Không cần plugin jQuery mới. Điều đó làm cho tôi một người cắm trại hạnh phúc!
Ngày Dennis ngày

1

Một cách khác để sử dụng các lớp để đánh dấu trạng thái của một phần tử là chức năng lưu trữ dữ liệu nội bộ .

PS: Bạn có thể lưu trữ booleans và bất cứ điều gì bạn muốn bằng cách sử dụng data()chức năng. Nó không chỉ là về chuỗi :)

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

Và sau đó chỉ là vấn đề truy cập trạng thái của các yếu tố.



1

Bạn đã nghĩ về việc sử dụng mouseOvermouseOut để mô phỏng điều này. Đồng thời nhìn vào mouseNhậpmouseLeave


Đó thực chất là những gì tôi đang làm với hover của jQuery. Bạn cung cấp hai chức năng, một cho chuột vào và một cho chuột ra.
bloudermilk

0

Theo dõi cả hai trạng thái (lơ lửng, tập trung) dưới dạng cờ đúng / sai và bất cứ khi nào một thay đổi, hãy chạy một chức năng loại bỏ đường viền nếu cả hai đều sai, nếu không thì hiển thị đường viền.

Vì vậy: bộ onf Focus tập trung = true, bộ onblur tập trung = false. bộ onmouseover hovered = true, bộ onmouseout hovered = false. Sau mỗi sự kiện này chạy một chức năng thêm / xóa đường viền.


0

Theo tôi biết, bạn không thể hỏi trình duyệt nếu bất kỳ đầu vào nào trên màn hình có tiêu điểm, bạn phải thiết lập một số loại theo dõi tiêu điểm.

Tôi thường có một biến gọi là "noF Focus" và đặt nó thành true. Sau đó, tôi thêm một sự kiện tập trung vào tất cả các đầu vào làm cho noF Focus sai. Sau đó, tôi thêm một sự kiện mờ cho tất cả các đầu vào đặt noF Focus trở lại đúng.

Tôi có một lớp MooTools xử lý việc này khá dễ dàng, tôi chắc chắn rằng bạn có thể tạo một plugin jquery để làm điều tương tự.

Khi đã được tạo, bạn có thể kiểm tra noF Focus trước khi thực hiện bất kỳ hoán đổi đường viền nào.



0

Có một plugin để kiểm tra xem một phần tử có được tập trung hay không: http://plugins.jquery.com/project/f Focused

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

1
Tại sao nên sử dụng plugin khi bạn chỉ có thể sử dụng jquery cốt lõi?
Marcy Sutton

1
Bạn đúng rồi. Nhưng tôi đã không biết một giải pháp cho vấn đề này vào 2 năm trước.
Murat Çorlu

0

Tôi đã đặt một sự kiện .live ("tiêu điểm") để chọn () (tô sáng) nội dung của kiểu nhập văn bản để người dùng không phải chọn nó trước khi nhập giá trị mới.

$ (formObj) .select ();

Do sự kỳ quặc giữa các trình duyệt khác nhau, lựa chọn đôi khi sẽ bị thay thế bởi lần nhấp gây ra nó và nó sẽ bỏ chọn nội dung ngay sau khi ủng hộ việc đặt con trỏ trong trường văn bản (hoạt động chủ yếu là ok trong FF nhưng không thành công trong IE)

Tôi nghĩ rằng tôi có thể giải quyết điều này bằng cách đặt một chút chậm trễ vào việc chọn ...

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

Điều này hoạt động tốt và lựa chọn sẽ tiếp tục, nhưng một vấn đề buồn cười nảy sinh .. Nếu bạn chuyển từ trường này sang trường tiếp theo, tiêu điểm sẽ chuyển sang trường tiếp theo trước khi chọn. Vì chọn lấy cắp tiêu điểm, tiêu điểm sẽ quay lại và kích hoạt sự kiện "lấy nét" mới. Điều này đã kết thúc trong một loạt các đầu vào chọn nhảy múa trên khắp màn hình.

Một giải pháp khả thi sẽ là kiểm tra xem trường vẫn tập trung trước khi thực hiện select (), nhưng như đã đề cập, không có cách nào đơn giản để kiểm tra ... Tôi cuối cùng chỉ phân phối với toàn bộ tô sáng tự động, thay vì chuyển những gì nên làm một lệnh jQuery select () gọi vào một hàm lớn với các chương trình con ...


0

Những gì tôi cố gắng làm là tạo ra một lớp tùy ý gọi là .elementhasf Focus, được thêm và xóa trong hàm jQuery Focus (). Khi hàm hover () chạy trên chuột, nó sẽ kiểm tra .elementhasf Focus:

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

Vì vậy, nếu nó không có lớp đó (đọc: không có phần tử nào trong div có tiêu điểm) thì đường viền sẽ bị xóa. Nếu không, không có gì xảy ra.


-2

Đơn giản

 <input type="text" /> 



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

    alert("I am in Focus");

     });
 </script>

Điều đó không cho bạn biết yếu tố nào hiện đang được tập trung. Nó được gọi khi một yếu tố mới được tập trung. Vì vậy, nếu một yếu tố đã có trọng tâm và bạn muốn biết liệu 'cái này' có phải là một phần tử hay không, mã này là vô dụng.
Alexis Wilke
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.