Khi một sự kiện 'mờ' xảy ra, làm thế nào tôi có thể tìm ra tiêu điểm phần tử nào đã đi * đến *?


186

Giả sử tôi đính kèm một blurchức năng vào hộp nhập HTML như thế này:

<input id="myInput" onblur="function() { ... }"></input>

Có cách nào để lấy ID của phần tử gây ra blursự kiện này (phần tử được nhấp) bên trong hàm không? Làm sao?

Ví dụ: giả sử tôi có một khoảng như thế này:

<span id="mySpan">Hello World</span>

Nếu tôi nhấp vào nhịp ngay sau khi phần tử đầu vào có tiêu điểm, phần tử đầu vào sẽ mất tiêu điểm. Làm thế nào để chức năng biết rằng nó đã mySpanđược nhấp?

PS: Nếu sự kiện onclick của nhịp sẽ xảy ra trước sự kiện onblur của phần tử đầu vào, vấn đề của tôi sẽ được giải quyết, bởi vì tôi có thể đặt một số giá trị trạng thái cho biết một phần tử cụ thể đã được nhấp.

PPS: Bối cảnh của vấn đề này là tôi muốn kích hoạt điều khiển bộ tự động AJAX bên ngoài (từ một phần tử có thể nhấp) để hiển thị các đề xuất của nó, mà không có các đề xuất biến mất ngay lập tức vì blursự kiện trên phần tử đầu vào. Vì vậy, tôi muốn kiểm tra blurchức năng nếu một yếu tố cụ thể đã được nhấp và nếu có, hãy bỏ qua sự kiện mờ.


Đây là một câu hỏi thú vị mà tôi muốn thấy lý do đằng sau - tức là tại sao bạn làm điều này? Bối cảnh là gì?
Raul

Rahul và roosteronacid, tôi đã cập nhật câu hỏi như một phản ứng với ý kiến ​​của bạn (PPS).
Michiel Borkent

1
Vì thông tin này hơi cũ, hãy xem tại đây để biết câu trả lời mới hơn: stackoverflow.com/questions/7096120/ Kẻ
Jonathan M

Câu trả lời:


86

Hmm ... Trong Firefox, bạn có thể sử dụng explicitOriginalTargetđể kéo phần tử được nhấp vào. Tôi dự kiến ​​sẽ toElementlàm tương tự cho IE, nhưng nó dường như không hoạt động ... Tuy nhiên, bạn có thể lấy phần tử mới được tập trung từ tài liệu:

function showBlur(ev)
{
   var target = ev.explicitOriginalTarget||document.activeElement;
   document.getElementById("focused").value = 
      target ? target.id||target.tagName||target : '';
}

...

<button id="btn1" onblur="showBlur(event)">Button 1</button>
<button id="btn2" onblur="showBlur(event)">Button 2</button>
<button id="btn3" onblur="showBlur(event)">Button 3</button>
<input id="focused" type="text" disabled="disabled" />

Nên biết trước: Kỹ thuật này không không làm việc cho tập trung những thay đổi gây ra bởi tabbing thông qua các lĩnh vực với bàn phím, và không làm việc ở tất cả trong Chrome hoặc Safari. Các vấn đề lớn với việc sử dụng activeElement(trừ trong IE) là nó không được liên tục cập nhật cho đến khi sau khi các blursự kiện đã được xử lý, và có thể không có giá trị hiệu lực ở tất cả trong chế biến! Điều này có thể được giảm thiểu bằng một biến thể về kỹ thuật mà Michiel đã kết thúc bằng cách sử dụng :

function showBlur(ev)
{
  // Use timeout to delay examination of activeElement until after blur/focus 
  // events have been processed.
  setTimeout(function()
  {
    var target = document.activeElement;
    document.getElementById("focused").value = 
      target ? target.id||target.tagName||target : '';
  }, 1);
}

Điều này sẽ hoạt động trong hầu hết các trình duyệt hiện đại (đã được thử nghiệm trong Chrome, IE và Firefox), với lời cảnh báo rằng Chrome không đặt trọng tâm vào các nút được nhấp (so với được gắn thẻ).


1
Tôi đã tìm kiếm một cái gì đó giống như tường minh rõ ràng trong một thời gian dài. Làm thế nào bạn phát hiện ra nó?
Kev

3
Kiểm tra đối tượng sự kiện trong FireBug. FWIW, thuộc tính dành riêng cho Mozilla và được ghi lại trên MDC: developer.mozilla.org/en/DOM/event.explicitOrigenTarget
Shog9

2
Điều này không hoạt động (hoặc ngừng hoạt động?) Trong Firefox 3.6 và Safari 4.0.3 trong Windows.
Chetan S

1
@Jonathan: tài sản có sẵn, nhưng không được cập nhật khi blursự kiện này nổ ra. Tôi đã cập nhật câu trả lời với các chi tiết. Bạn đã thử sử dụng activeE bổ sung cho điều này trong Chrome hoặc Firefox chưa? Nó cung cấp cho bạn phần tử bị mờ ...
Shog9

1
Trên thực tế không hoạt động trên FF 31: tường minh rõ ràng Mục tiêu hiển thị mục tiêu mờ hiện tại, document.activeEuity là null trên sự kiện mờ.
Adrian Maire

75

Câu trả lời năm 2015 : theo UI Events , bạn có thể sử dụng thuộc relatedTargettính của sự kiện:

Được sử dụng để xác định thứ cấp EventTargetliên quan đến sự kiện Tập trung, tùy thuộc vào loại sự kiện.

Đối với blursự kiện,

relatedTarget: mục tiêu nhận sự kiện tập trung.

Thí dụ:

function blurListener(event) {
  event.target.className = 'blurred';
  if(event.relatedTarget)
    event.relatedTarget.className = 'focused';
}
[].forEach.call(document.querySelectorAll('input'), function(el) {
  el.addEventListener('blur', blurListener, false);
});
.blurred { background: orange }
.focused { background: lime }
<p>Blurred elements will become orange.</p>
<p>Focused elements should become lime.</p>
<input /><input /><input />

Lưu ý Firefox sẽ không hỗ trợ relatedTargetcho đến phiên bản 48 ( lỗi 962251 , MDN ).


Firefox không có hỗ trợ, nhưng có một vé: bugzilla.mozilla.org/show_orms.cgi?id=687787
sandstrom

3
Bây giờ nó có. Xem ở đây .
rplaurindo

yêu cộng đồng mạng, bây giờ mọi thứ đã dễ dàng hơn rất nhiều ^ _ ^
am05mhz

6
Giải pháp tuyệt vời. Thật không may, relatedTargetsẽ trở lại nullnếu tiêu điểm nhận mục tiêu không phải là một yếu tố đầu vào.
Pedro Hoehl Carvalho

5
Nếu nhận phần tử tiêu điểm không phải là phần tử đầu vào, hãy thêm một tabIndex="0"thuộc tính cho nó và nó sẽ hoạt động
Dany

19

Cuối cùng tôi đã giải quyết nó bằng một khoảng thời gian chờ đợi cho sự kiện onblur (nhờ lời khuyên của một người bạn không phải là StackOverflow):

<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input>
<span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>

Hoạt động cả trong FF và IE.


9
Đây có được coi là thực hành xấu trong thế giới javascript btw?
Michiel Borkent

1
bài cũ nhưng tôi có cùng một câu hỏi. bất kể, đó là điều duy nhất dường như hoàn thành công việc trên nhiều trình duyệt.
joshs

câu trả lời này đã giúp tôi TON bằng cách giải quyết một số vấn đề khác ... Cảm ơn Michael!
Alex

@MichielBorkent đây là một triển khai tồi vì nó không phải là sự kiện. Bạn chờ đợi một khoảng thời gian nhất định và chỉ hy vọng rằng nó đã đủ dài. Bạn càng chờ đợi lâu thì bạn càng an toàn, nhưng cũng sẽ lãng phí thời gian hơn nếu bạn không cần phải chờ đợi quá lâu. Có thể ai đó đang ở trên một thiết bị thực sự cũ / chậm và thời gian chờ này là không đủ. Thật không may, tôi ở đây vì các sự kiện không cung cấp cho tôi những gì tôi cần để xác định xem iframe có được nhấp vào trong FireFox hay không, nhưng nó hoạt động cho tất cả các trình duyệt khác. Tôi rất muốn sử dụng phương pháp này ngay cả khi nó là một thực hành tồi.
CTS_AE

1
Câu hỏi này khá cũ, nó quay trở lại năm 2008. Trong khi đó, có thể có những cách tiếp cận tốt hơn. Bạn có thể thử câu trả lời năm 2015 không?
Michiel Borkent

16

Có thể sử dụng sự kiện mousedown của tài liệu thay vì mờ:

$(document).mousedown(function(){
  if ($(event.target).attr("id") == "mySpan") {
    // some process
  }
});

8

Các thể hiện loại FocusEventrelatedTargetthuộc tính, tuy nhiên, lên đến phiên bản 47 của FF, cụ thể, thuộc tính này trả về null, từ 48 đã hoạt động.

Bạn có thể xem thêm ở đây .


2

Tôi cũng đang cố gắng làm cho Autocompleter bỏ qua việc làm mờ nếu một phần tử cụ thể được nhấp và có một giải pháp hoạt động, nhưng chỉ dành cho Firefox do tường minh rõ ràng

Autocompleter.Base.prototype.onBlur = Autocompleter.Base.prototype.onBlur.wrap( 
        function(origfunc, ev) {
            if ($(this.options.ignoreBlurEventElement)) {
                var newTargetElement = (ev.explicitOriginalTarget.nodeType == 3 ? ev.explicitOriginalTarget.parentNode : ev.explicitOriginalTarget);
                if (!newTargetElement.descendantOf($(this.options.ignoreBlurEventElement))) {
                    return origfunc(ev);
                }
            }
        }
    );

Mã này bao bọc mặc định phương thức Autocompleter trên mặc định và kiểm tra xem các tham số ignBlurEventEuity được đặt. nếu được đặt, nó sẽ kiểm tra mọi lúc để xem phần tử được nhấp có bỏ quaBlurEventEuity hay không. Nếu đúng như vậy, Autocompleter không cal onBlur, nếu không nó gọi làBlur. Vấn đề duy nhất với điều này là nó chỉ hoạt động trong Firefox vì thuộc tính tường minh rõ ràng là đặc trưng của Mozilla. Bây giờ tôi đang cố gắng tìm một cách khác so với sử dụng tường thuật rõ ràng. Giải pháp bạn đã đề cập yêu cầu bạn thêm hành vi onclick bằng tay vào thành phần. Nếu tôi không thể quản lý để giải quyết vấn đề rõ ràng. Nguồn gốc, tôi đoán tôi sẽ làm theo giải pháp của bạn.


2

Bạn có thể đảo ngược những gì bạn đang kiểm tra và khi nào? Đó là nếu bạn nhớ lại những gì đã được làm mờ lần trước:

<input id="myInput" onblur="lastBlurred=this;"></input>

và sau đó trong onClick cho nhịp của bạn, hãy gọi hàm () với cả hai đối tượng:

<span id="mySpan" onClick="function(lastBlurred, this);">Hello World</span>

Hàm của bạn sau đó có thể quyết định có kích hoạt điều khiển Ajax.AutoCompleter hay không. Hàm có đối tượng được nhấp đối tượng mờ. OnBlur đã xảy ra rồi nên nó sẽ không làm cho các đề xuất biến mất.


1

Sử dụng một cái gì đó như thế này:

var myVar = null;

Và sau đó bên trong chức năng của bạn:

myVar = fldID;

Và sau đó:

setTimeout(setFocus,1000)

Và sau đó:

function setFocus(){ document.getElementById(fldID).focus(); }

Mã cuối cùng:

<html>
<head>
    <script type="text/javascript">
        function somefunction(){
            var myVar = null;

            myVar = document.getElementById('myInput');

            if(myVar.value=='')
                setTimeout(setFocusOnJobTitle,1000);
            else
                myVar.value='Success';
        }
        function setFocusOnJobTitle(){
            document.getElementById('myInput').focus();
        }
    </script>
</head>
<body>
<label id="jobTitleId" for="myInput">Job Title</label>
<input id="myInput" onblur="somefunction();"></input>
</body>
</html>

1

Tôi nghĩ rằng nó không phải là sở hữu, với IE bạn có thể thử sử dụng window.event.toElement, nhưng nó không hoạt động với firefox!


Không hoạt động với Chrome hoặc Safari. Có lẽ sẽ không hoạt động với các phiên bản IE mới tương thích với các tiêu chuẩn hơn.
robocat

1

Như đã lưu ý trong câu trả lời này , bạn có thể kiểm tra giá trị của document.activeElement. documentlà một biến toàn cục, vì vậy bạn không cần phải thực hiện bất kỳ phép thuật nào để sử dụng nó trong trình xử lý onBlur của mình:

function myOnBlur(e) {
  if(document.activeElement ===
       document.getElementById('elementToCheckForFocus')) {
    // Focus went where we expected!
    // ...
  }
}

1
  • document.activeEuity có thể là nút cha (ví dụ nút cơ thể vì nó đang trong giai đoạn tạm thời chuyển từ mục tiêu sang mục tiêu khác), vì vậy không thể sử dụng phạm vi của bạn
  • ev.explicitOrigenTarget không phải lúc nào cũng có giá trị

Vì vậy, cách tốt nhất là sử dụng onclick trên sự kiện cơ thể để hiểu gián tiếp nút của bạn (event.target) bị mờ


1

Hoạt động trong Google Chrome v66.x, Mozilla v59.x và Microsoft Edge ... Giải pháp với jQuery.

Tôi kiểm tra trong Internet Explorer 9 và không được hỗ trợ.

$("#YourElement").blur(function(e){
     var InputTarget =  $(e.relatedTarget).attr("id"); // GET ID Element
     console.log(InputTarget);
     if(target == "YourId") { // If you want validate or make a action to specfic element
          ... // your code
     }
});

Nhận xét thử nghiệm của bạn trong các phiên bản thám hiểm internet khác.


0

Chỉnh sửa: Một cách khó khăn để làm điều đó là tạo một biến theo dõi sự tập trung cho mọi yếu tố bạn quan tâm. Vì vậy, nếu bạn quan tâm rằng 'myInput' bị mất tiêu điểm, hãy đặt một biến thành tiêu điểm.

<script type="text/javascript">
   var lastFocusedElement;
</script>
<input id="myInput" onFocus="lastFocusedElement=this;" />

Câu trả lời gốc: Bạn có thể truyền 'cái này' cho hàm.

<input id="myInput" onblur="function(this){
   var theId = this.id; // will be 'myInput'
}" />

điều này không trả lời câu hỏi, hy vọng tôi đã làm cho nó rõ ràng hơn với ví dụ bổ sung
Michiel Borkent

0

Tôi đề nghị sử dụng các biến toàn cục Blurfrom và Blurto. Sau đó, định cấu hình tất cả các yếu tố bạn quan tâm để gán vị trí của chúng trong DOM cho biến mờ khi chúng mất tiêu điểm. Ngoài ra, định cấu hình chúng sao cho việc lấy tiêu điểm đặt biến mờ thành vị trí của chúng trong DOM. Sau đó, bạn có thể sử dụng một chức năng khác hoàn toàn để phân tích dữ liệu mờ và làm mờ dữ liệu.


Đó gần như là giải pháp, nhưng trong trình xử lý sự kiện onblur tôi đã cần phải biết mục nào đã được nhấp, do đó, thời gian chờ trên onblur đã làm điều đó cho tôi.
Michiel Borkent

0

xin lưu ý rằng giải pháp với tường minh rõ ràng không có tác dụng đối với các bước nhảy từ đầu vào văn bản đến đầu vào văn bản.

hãy thử thay thế các nút bằng các kiểu nhập văn bản sau và bạn sẽ thấy sự khác biệt:

<input id="btn1" onblur="showBlur(event)" value="text1">
<input id="btn2" onblur="showBlur(event)" value="text2">
<input id="btn3" onblur="showBlur(event)" value="text3">

0

Tôi đã chơi với tính năng tương tự và phát hiện ra rằng FF, IE, Chrome và Opera có khả năng cung cấp yếu tố nguồn của một sự kiện. Tôi chưa thử Safari nhưng tôi đoán nó có thể có thứ gì đó tương tự.

$('#Form').keyup(function (e) {
    var ctrl = null;
    if (e.originalEvent.explicitOriginalTarget) { // FF
        ctrl = e.originalEvent.explicitOriginalTarget;
    }
    else if (e.originalEvent.srcElement) { // IE, Chrome and Opera
        ctrl = e.originalEvent.srcElement;
    }
    //...
});

Điều này hoạt động tốt tại sao downvote? chỉ cần xóa bản gốcEvent!
fekiri malek

0

Tôi không thích sử dụng thời gian chờ khi mã hóa javascript vì vậy tôi sẽ làm theo cách ngược lại với Michiel Borkent. (Không thử mã phía sau nhưng bạn nên lấy ý tưởng).

<input id="myInput" onblur="blured = this.id;"></input>
<span onfocus = "sortOfCallback(this.id)" id="mySpan">Hello World</span>

Trong đầu có gì đó như thế

<head>
    <script type="text/javascript">
        function sortOfCallback(id){
            bluredElement = document.getElementById(blured);
            // Do whatever you want on the blured element with the id of the focus element


        }

    </script>
</head>

0

Bạn có thể sửa IE bằng:

 event.currentTarget.firstChild.ownerDocument.activeElement

Nó trông giống như "tường minh rõ ràng" cho FF.

Antoine và J


0

Tôi đã viết một giải pháp thay thế làm thế nào để làm cho bất kỳ yếu tố nào có thể tập trung và "mờ".

Nó dựa trên việc tạo ra một yếu tố như contentEditable và ẩn trực quan nó và vô hiệu hóa chế độ chỉnh sửa:

el.addEventListener("keydown", function(e) {
  e.preventDefault();
  e.stopPropagation();
});

el.addEventListener("blur", cbBlur);
el.contentEditable = true;

BẢN GIỚI THIỆU

Lưu ý: Đã thử nghiệm trong Chrome, Firefox và Safari (OS X). Không chắc chắn về IE.


Liên quan: Tôi đang tìm kiếm một giải pháp cho VueJs, vì vậy đối với những người quan tâm / tò mò về cách triển khai chức năng đó bằng chỉ thị Vue Focusable, vui lòng xem qua .


-2

Cách này:

<script type="text/javascript">
    function yourFunction(element) {
        alert(element);
    }
</script>
<input id="myinput" onblur="yourFunction(this)">

Hoặc nếu bạn đính kèm trình nghe qua JavaScript (jQuery trong ví dụ này):

var input = $('#myinput').blur(function() {
    alert(this);
});

Chỉnh sửa : xin lỗi. Tôi đọc sai câu hỏi.


3
Nếu bạn biết rằng đây không phải là câu trả lời cho câu hỏi và bạn đã đọc sai nó, thì vui lòng cập nhật nó cho phù hợp hoặc xóa nó.
TJ

-2


Tôi nghĩ nó có thể dễ dàng thông qua jquery bằng cách chuyển tham chiếu của trường gây ra sự kiện onblur trong "này".
Ví dụ

<input type="text" id="text1" onblur="showMessageOnOnblur(this)">

function showMessageOnOnblur(field){
    alert($(field).attr("id"));
}

Cảm ơn
Monika


-2

Bạn có thể làm cho nó như thế này:

<script type="text/javascript">
function myFunction(thisElement) 
{
    document.getElementByName(thisElement)[0];
}
</script>
<input type="text" name="txtInput1" onBlur="myFunction(this.name)"/>

-2

Tôi chỉ thấy các bản hack trong câu trả lời, nhưng thực sự có một giải pháp dựng sẵn rất dễ sử dụng: Về cơ bản, bạn có thể nắm bắt được phần tử tiêu điểm như thế này:

const focusedElement = document.activeElement

https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeEuity


Ít nhất trong trường hợp của tôi, điều này không hoạt động vì activeEuity là phần thân, nếu tôi kiểm tra điều này trên kết xuất / đánh dấu tiếp theo thì nó được đặt chính xác. Nhưng có vẻ như giải pháp của shog9 là giải pháp thích hợp duy nhất vì nó đảm bảo rằng một đánh dấu đã được đưa ra.
Mathijs
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.