เมื่อมีเหตุการณ์ 'เบลอ' เกิดขึ้นฉันจะทราบได้อย่างไรว่าองค์ประกอบโฟกัสไปที่ * ถึง *


187

สมมติว่าฉันแนบblurฟังก์ชั่นกับช่องใส่ HTML เช่นนี้

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

มีวิธีรับ ID ขององค์ประกอบที่ทำให้เกิดblurเหตุการณ์ไฟ (องค์ประกอบที่ถูกคลิก) ภายในฟังก์ชันหรือไม่ อย่างไร?

ตัวอย่างเช่นสมมติว่าฉันมีช่วงเช่นนี้:

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

หากฉันคลิกที่ระยะห่างหลังจากองค์ประกอบอินพุตมีโฟกัสองค์ประกอบอินพุตจะสูญเสียโฟกัส ฟังก์ชั่นรู้ได้อย่างไรว่ามันmySpanถูกคลิกแล้ว?

PS: หากเหตุการณ์ onclick ของช่วงจะเกิดขึ้นก่อนที่เหตุการณ์ onblur ขององค์ประกอบอินพุตปัญหาของฉันจะได้รับการแก้ไขเพราะฉันสามารถตั้งค่าสถานะบางอย่างที่ระบุว่ามีการคลิกองค์ประกอบเฉพาะ

PPS: พื้นหลังของปัญหานี้คือฉันต้องการทริกเกอร์การควบคุมอัตโนมัติ AJAX จากภายนอก (จากองค์ประกอบที่คลิกได้) เพื่อแสดงคำแนะนำโดยไม่มีข้อเสนอแนะหายไปทันทีเนื่องจากblurเหตุการณ์ในองค์ประกอบอินพุต ดังนั้นฉันต้องการตรวจสอบblurฟังก์ชั่นหากมีการคลิกองค์ประกอบเฉพาะอย่างใดอย่างหนึ่งและหากเป็นเช่นนั้นให้ข้ามเหตุการณ์เบลอ


นี่เป็นคำถามที่น่าสนใจที่ฉันชอบที่จะเห็นเหตุผลอยู่เบื้องหลัง - นั่นคือเหตุผลที่คุณทำเช่นนี้? บริบทคืออะไร
ราหุล

Rahul และ roosteronacid ฉันได้อัปเดตคำถามเป็นการตอบสนองต่อความคิดเห็นของคุณ (PPS)
Michiel Borkent

1
เนื่องจากข้อมูลนี้ค่อนข้างเก่าดูที่นี่สำหรับคำตอบที่ใหม่กว่า: stackoverflow.com/questions/7096120//
Jonathan M

คำตอบ:


86

อืม ... ใน Firefox คุณสามารถใช้explicitOriginalTargetเพื่อดึงองค์ประกอบที่ถูกคลิก ฉันคาดว่าtoElementจะทำเช่นเดียวกันสำหรับ IE แต่ดูเหมือนจะไม่ทำงาน ... อย่างไรก็ตามคุณสามารถดึงองค์ประกอบที่มุ่งเน้นใหม่จากเอกสาร:

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" />

Caveat:เทคนิคนี้ใช้ไม่ได้กับการเปลี่ยนแปลงโฟกัสที่เกิดจากการแท็บผ่านฟิลด์ด้วยแป้นพิมพ์และไม่สามารถใช้งานได้ใน Chrome หรือ Safari ปัญหาใหญ่กับการใช้activeElement(ยกเว้นใน IE) ก็คือว่ามันจะไม่มีการปรับปรุงอย่างต่อเนื่องจนกระทั่งหลังจากblurเหตุการณ์ได้รับการประมวลผลและอาจจะไม่มีค่าที่ถูกต้องที่ทุกคนในระหว่างการประมวลผล! สิ่งนี้สามารถลดลงได้ด้วยการเปลี่ยนแปลงของเทคนิค Michiel โดยใช้ :

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

สิ่งนี้จะทำงานได้ในเบราว์เซอร์ที่ทันสมัยที่สุด (ทดสอบใน Chrome, IE และ Firefox) โดยมีข้อแม้ว่า Chrome ไม่ได้ตั้งค่าโฟกัสที่ปุ่มที่คลิก (เทียบกับแท็บเป็น)


1
ฉันได้รับการมองหาบางอย่างเช่นชัดเจนต้นฉบับเป้าหมายเป็นเวลานาน คุณค้นพบมันได้อย่างไร
Kev

3
ตรวจสอบวัตถุเหตุการณ์ใน FireBug FWIW คุณสมบัติเป็น Mozilla เฉพาะและบันทึกไว้ใน MDC: developer.mozilla.org/en/DOM/event.explicitOriginalTarget
Shog9

2
สิ่งนี้ใช้ไม่ได้ (หรือหยุดทำงาน) ใน Firefox 3.6 และ Safari 4.0.3 ใน Windows
Chetan S

1
@Jonathan: คุณสมบัตินี้พร้อมใช้งาน แต่ไม่ได้รับการอัปเดตเมื่อมีblurเหตุการณ์เกิดขึ้น ฉันได้อัพเดตคำตอบพร้อมรายละเอียดแล้ว คุณได้ลองใช้ activeElement สำหรับสิ่งนี้ใน Chrome หรือ Firefox หรือไม่? มันทำให้องค์ประกอบของคุณเบลอ ...
Shog9

1
อันที่จริงไม่ได้ทำงานกับ FF 31: ชัดเจนOriginalTargetแสดงเป้าหมายเบลอปัจจุบัน document.activeElement เป็นโมฆะในเหตุการณ์เบลอ
Adrian Maire

75

คำตอบในปี 2015 : ตามกิจกรรม UIคุณสามารถใช้relatedTargetคุณสมบัติของกิจกรรม:

ใช้เพื่อระบุรองEventTargetที่เกี่ยวข้องกับเหตุการณ์โฟกัสขึ้นอยู่กับประเภทของเหตุการณ์

สำหรับblurกิจกรรม

relatedTarget: เป้าหมายของเหตุการณ์ที่ได้รับโฟกัส

ตัวอย่าง:

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 />

หมายเหตุ Firefox จะไม่รองรับrelatedTargetจนถึงรุ่น 48 ( ข้อผิดพลาด 962251 , MDN )


Firefox ไม่มีการสนับสนุน แต่มีตั๋วคือ: bugzilla.mozilla.org/show_bug.cgi?id=687787
sandstrom

3
ตอนนี้มันมี ดูที่นี่
rplaurindo

รักชุมชนเว็บตอนนี้ทุกอย่างง่ายขึ้น ^ _ ^
am05mhz

6
ทางออกที่ดี น่าเสียดายที่relatedTargetจะกลับมาnullหากเป้าหมายการรับโฟกัสไม่ใช่องค์ประกอบอินพุต
Pedro Hoehl Carvalho

5
หากการรับองค์ประกอบการโฟกัสไม่ใช่องค์ประกอบการป้อนข้อมูลให้เพิ่มแอtabIndex="0"ททริบิวต์นั้นและมันจะใช้ได้
Dany

19

ฉันแก้ไขมันในที่สุดด้วยการหมดเวลาในเหตุการณ์ onblur (ขอบคุณคำแนะนำของเพื่อนที่ไม่ใช่ StackOverflow):

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

ทำงานได้ทั้งใน FF และ IE


9
นี่ถือว่าเป็นการปฏิบัติที่ไม่ดีใน javascript world btw หรือไม่
Michiel Borkent

1
โพสต์เก่า แต่ฉันมีคำถามเดียวกัน ไม่ว่าจะเป็นสิ่งเดียวที่ดูเหมือนจะทำให้งานเสร็จข้ามเบราว์เซอร์
joshs

คำตอบนี้ช่วย TON ของฉันด้วยการแก้ปัญหาอื่น ๆ ... ขอบคุณ Michael!
อเล็กซ์

@MichielBorkent นี่เป็นการใช้งานที่ไม่ดีเพราะมันไม่ได้เป็นตัวขับเคลื่อนเหตุการณ์ คุณรอเวลาและหวังว่ามันจะนานพอ ยิ่งคุณรอความปลอดภัยนานเท่าไรคุณก็ยิ่งเสียเวลามากขึ้นเท่านั้นหากคุณไม่ต้องรอนาน อาจมีบางคนอยู่ในอุปกรณ์ที่เก่า / ช้ามากและการหมดเวลานี้อาจไม่เพียงพอ น่าเสียดายที่ฉันมาที่นี่เพราะกิจกรรมไม่ได้ให้สิ่งที่ฉันต้องการเพื่อตรวจสอบว่ามีการคลิก iframe ไปที่ใน FireFox หรือไม่ แต่ก็ใช้ได้กับเบราว์เซอร์อื่นทั้งหมด ฉันถูกล่อลวงให้ใช้วิธีนี้ในขณะนี้แม้ว่ามันจะเป็นการปฏิบัติที่ไม่ดี
CTS_AE

1
คำถามนี้ค่อนข้างเก่ามันกลับไปสู่ปี 2008 ในขณะเดียวกันอาจมีวิธีการที่ดีกว่า คุณลองคำตอบปี 2015 ได้ไหม?
Michiel Borkent

16

เป็นไปได้ที่จะใช้เหตุการณ์ mousedown ของเอกสารแทนการเบลอ:

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

8

FocusEventอินสแตนซ์ชนิดมีrelatedTargetแอตทริบิวต์อย่างไรก็ตามถึงเวอร์ชัน 47 ของ FF โดยเฉพาะแอ็ตทริบิวต์นี้จะส่งคืนค่า null จาก 48 ใช้งานได้แล้ว

คุณสามารถที่จะดูรายละเอียดเพิ่มเติมที่นี่


2

ฉันกำลังพยายามทำให้ Autocompleter เพิกเฉยต่อการเบลอถ้าองค์ประกอบที่เฉพาะเจาะจงถูกคลิกและมีวิธีแก้ปัญหาการทำงาน แต่สำหรับ Firefox เท่านั้นเนื่องจากชัดเจนต้นฉบับดั้งเดิมเป้าหมาย

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

รหัสนี้ล้อมรอบวิธีการ onBlur เริ่มต้นของ Autocompleter และตรวจสอบว่ามีการตั้งค่าพารามิเตอร์ที่ละเว้น หากมีการตั้งค่าไว้จะทำการตรวจสอบทุกครั้งเพื่อดูว่าองค์ประกอบที่ถูกคลิกนั้นเป็นละเว้นBlurEventElementหรือไม่ ถ้าเป็นเช่นนั้น Autocompleter จะไม่ calBlur มิฉะนั้นจะเรียกใช้บน Blur ปัญหาเดียวของเรื่องนี้คือมันใช้งานได้เฉพาะใน Firefox เพราะคุณสมบัติชัดเจนต้นฉบับดั้งเดิมเป้าหมายคือ Mozilla เฉพาะ ตอนนี้ฉันกำลังพยายามหาวิธีที่แตกต่างจากการใช้ชัดเจนต้นฉบับเป้าหมาย วิธีการแก้ปัญหาที่คุณกล่าวถึงนั้นคุณต้องเพิ่มพฤติกรรมการคลิกบนองค์ประกอบด้วยตนเอง หากฉันไม่สามารถจัดการเพื่อแก้ไขปัญหาดั้งเดิมอย่างชัดเจนได้ฉันคิดว่าฉันจะทำตามวิธีแก้ปัญหาของคุณ


2

คุณสามารถย้อนกลับสิ่งที่คุณกำลังตรวจสอบและเมื่อ นั่นคือถ้าคุณจำสิ่งที่เบลอครั้งสุดท้าย:

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

และจากนั้นใน onClick สำหรับการขยายของคุณฟังก์ชั่นการโทร () กับวัตถุทั้งสอง:

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

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


1

ใช้สิ่งนี้:

var myVar = null;

จากนั้นภายในฟังก์ชั่นของคุณ:

myVar = fldID;

แล้ว:

setTimeout(setFocus,1000)

แล้ว:

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

รหัสสุดท้าย:

<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

ฉันคิดว่ามันไม่น่าจะเป็นไปได้สำหรับ IE คุณสามารถลองใช้งานwindow.event.toElementได้ แต่มันก็ไม่ได้ผลกับ firefox!


ใช้งานไม่ได้กับ Chrome หรือ Safari อาจไม่ทำงานกับ IE เวอร์ชันใหม่ที่เข้ากันได้กับมาตรฐานมากกว่านี้
robocat

1

ตามที่ระบุไว้ในคำตอบนี้document.activeElementคุณสามารถตรวจสอบค่าของ documentเป็นตัวแปรทั่วโลกดังนั้นคุณไม่จำเป็นต้องใช้เวทมนตร์ใด ๆ เพื่อใช้งานมันในตัวจัดการแบลร์ของคุณ:

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

1
  • document.activeElement อาจเป็นพาเรนต์โหนด (ตัวอย่างเช่นโหนดเนื้อเนื่องจากอยู่ในช่วงการสลับจากเป้าหมายหนึ่งไปเป็นอีกช่วงเวลาชั่วคราว) ดังนั้นจึงไม่สามารถใช้งานได้สำหรับขอบเขตของคุณ
  • ev.explicitOriginalTarget ไม่ได้ให้ความสำคัญเสมอไป

ดังนั้นวิธีที่ดีที่สุดคือการใช้ onclick กับเหตุการณ์ของร่างกายเพื่อทำความเข้าใจทางอ้อมโหนดของคุณ


1

ใช้งานได้ใน Google Chrome v66.x, Mozilla v59.x และ Microsoft Edge ... โซลูชันด้วย jQuery

ฉันทดสอบใน Internet Explorer 9 และไม่รองรับ

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

แสดงความคิดเห็นการทดสอบของคุณในรุ่นอื่น ๆ ของ Internet Explorer


0

แก้ไข: วิธีแฮ็กที่จะทำคือการสร้างตัวแปรที่ติดตามการโฟกัสสำหรับทุกองค์ประกอบที่คุณสนใจ ดังนั้นหากคุณสนใจว่า 'myInput' โฟกัสหายไปให้ตั้งค่าตัวแปรไว้ที่โฟกัส

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

คำตอบเดิม: คุณสามารถส่ง 'นี้' ไปยังฟังก์ชั่น

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

สิ่งนี้ไม่ตอบคำถามหวังว่าฉันจะทำให้ชัดเจนขึ้นด้วยตัวอย่างเพิ่มเติม
Michiel Borkent

0

ฉันขอแนะนำให้ใช้ตัวแปรทั่วโลก blurfrom และ blurto จากนั้นกำหนดค่าองค์ประกอบทั้งหมดที่คุณต้องการกำหนดตำแหน่งใน DOM ให้กับตัวแปร blurfrom เมื่อพวกเขาสูญเสียการโฟกัส นอกจากนี้กำหนดค่าพวกเขาเพื่อให้ได้รับโฟกัสตั้งตัวแปรเบลอไปยังตำแหน่งของพวกเขาใน DOM จากนั้นคุณสามารถใช้ฟังก์ชันอื่นทั้งหมดเพื่อวิเคราะห์ข้อมูล blurfrom และ blurto


มันเกือบจะเป็นทางออก แต่ในตัวจัดการเหตุการณ์ onblur ฉันต้องการทราบแล้วว่ารายการใดที่ถูกคลิกดังนั้นการหมดเวลาของ onblur จึงทำเพื่อฉัน
Michiel Borkent

0

โปรดทราบว่าการแก้ปัญหาอย่างชัดเจนกับ OriginalTarget จะไม่สามารถใช้งานได้กับการข้ามข้อความไปเป็นข้อความ

พยายามแทนที่ปุ่มด้วยอินพุตข้อความต่อไปนี้และคุณจะเห็นความแตกต่าง:

<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

ฉันได้เล่นด้วยคุณสมบัติเดียวกันนี้และพบว่า FF, IE, Chrome และ Opera มีความสามารถในการจัดหาองค์ประกอบที่มาของเหตุการณ์ ฉันไม่ได้ทดสอบ Safari แต่ฉันเดาว่าอาจมีบางอย่างที่คล้ายกัน

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

มันทำงานได้ดีทำไม downvoting? เพียงลบ originalEvent!
fekiri malek

0

ฉันไม่ชอบการหมดเวลาใช้งานเมื่อมีการเข้ารหัสจาวาสคริปต์ดังนั้นฉันจึงทำแบบตรงกันข้ามกับ Michiel Borkent (ไม่ได้ลองใช้โค้ดด้านหลัง แต่คุณควรเข้าใจ)

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

ในหัวบางอย่างเช่นนั้น

<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

คุณสามารถแก้ไข IE ด้วย:

 event.currentTarget.firstChild.ownerDocument.activeElement

ดูเหมือนว่า "ชัดเจนต้นฉบับดั้งเดิมเป้าหมาย" สำหรับ FF

แอนทอนและเจ


0

ฉันเขียนทางเลือกอื่นวิธีทำให้องค์ประกอบใด ๆ สามารถโฟกัสได้และ "เบลอ"

มันขึ้นอยู่กับการสร้างองค์ประกอบcontentEditableและซ่อนสายตาและปิดใช้งานโหมดแก้ไขตัวเอง:

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

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

การสาธิต

หมายเหตุ: ทดสอบใน Chrome, Firefox และ Safari (OS X) ไม่แน่ใจเกี่ยวกับ IE


ที่เกี่ยวข้อง: ผมกำลังหาวิธีแก้ปัญหาสำหรับ VueJs ดังนั้นสำหรับผู้ที่สนใจ / อยากรู้วิธีการใช้ฟังก์ชั่นดังกล่าวโดยใช้ Vue ที่สามารถโฟกัสสั่งโปรดใช้เวลาดู


-2

ทางนี้:

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

หรือถ้าคุณแนบผู้ฟังผ่าน JavaScript (jQuery ในตัวอย่างนี้):

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

แก้ไข : ขอโทษ ฉันอ่านคำถามผิด


3
หากคุณทราบว่านี่ไม่ใช่คำตอบสำหรับคำถามและคุณอ่านผิดโปรดอัปเดตตามนั้นหรือลบออก
TJ

-2


ฉันคิดว่ามันเป็นไปได้อย่างง่ายดายผ่าน jquery โดยผ่านการอ้างอิงของสนามทำให้เกิดเหตุการณ์ onblur ใน "นี้"
สำหรับเช่น

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

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

ขอบคุณ
โมนิก้า


-2

คุณสามารถทำให้เป็นเช่นนี้:

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

-2

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

const focusedElement = document.activeElement

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


อย่างน้อยในกรณีของฉันสิ่งนี้ไม่ทำงานเนื่องจาก activeElement เป็นตัวถ้าฉันตรวจสอบสิ่งนี้ในการเรนเดอร์ / ทำเครื่องหมายถัดไป แต่ดูเหมือนว่าโซลูชันของ shog9 เป็นโซลูชั่นที่เหมาะสมเพียงอย่างเดียวเนื่องจากทำให้แน่ใจว่าเห็บได้รับสัญญาณแล้ว
Mathijs Segers
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.