Ketika peristiwa 'blur' terjadi, bagaimana saya bisa mengetahui fokus elemen mana yang pergi * ke *?

187

Misalkan saya melampirkan blurfungsi ke kotak input HTML seperti ini:

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

Apakah ada cara untuk mendapatkan ID elemen yang menyebabkan blurperistiwa tersebut memunculkan (elemen yang diklik) di dalam fungsi? Bagaimana?

Sebagai contoh, misalkan saya memiliki rentang seperti ini:

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

Jika saya mengklik rentang tepat setelah elemen input memiliki fokus, elemen input akan kehilangan fokusnya. Bagaimana fungsi tahu bahwa itu mySpanyang diklik?

PS: Jika peristiwa onclick dari rentang akan terjadi sebelum peristiwa onblur dari elemen input masalah saya akan diselesaikan, karena saya dapat mengatur beberapa nilai status yang menunjukkan elemen tertentu telah diklik.

PPS: Latar belakang masalah ini adalah bahwa saya ingin memicu kontrol autocompleter AJAX secara eksternal (dari elemen yang dapat diklik) untuk menampilkan sarannya, tanpa saran menghilang segera karena blurperistiwa pada elemen input. Jadi saya ingin memeriksa blurfungsi jika satu elemen tertentu telah diklik, dan jika demikian, abaikan acara blur.

Michiel Borkent
sumber
Ini adalah pertanyaan menarik yang ingin saya lihat alasannya - yaitu mengapa Anda melakukan ini? Apa konteksnya?
Rahul
Rahul dan roosteronacid, saya memperbarui pertanyaan sebagai reaksi atas komentar Anda (PPS).
Michiel Borkent
1
Karena info ini agak lama, lihat di sini untuk jawaban yang lebih baru: stackoverflow.com/questions/7096120/…
Jonathan M

Jawaban:

86

Hmm ... Di Firefox, Anda bisa menggunakan explicitOriginalTargetuntuk menarik elemen yang diklik. Saya berharap toElementuntuk melakukan hal yang sama untuk IE, tetapi tampaknya tidak berfungsi ... Namun, Anda dapat menarik elemen yang baru difokuskan dari dokumen:

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

Peringatan: Teknik ini tidak berfungsi untuk perubahan fokus yang disebabkan oleh tab melalui bidang dengan keyboard, dan tidak berfungsi sama sekali di Chrome atau Safari. Masalah besar dengan menggunakan activeElement(kecuali di IE) adalah bahwa hal itu tidak konsisten diperbarui sampai setelah itu bluracara telah diproses, dan mungkin tidak memiliki nilai yang valid sama sekali selama pengolahan! Ini dapat dikurangi dengan variasi pada teknik Michiel akhirnya menggunakan :

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

Ini harus berfungsi di sebagian besar browser modern (diuji di Chrome, IE, dan Firefox), dengan peringatan bahwa Chrome tidak menetapkan fokus pada tombol yang diklik (vs. ditabrakkan ke).

Shog9
sumber
1
Saya telah mencari sesuatu seperti eksplisitOriginalTarget untuk waktu yang lama. Bagaimana Anda menemukannya?
Kev
3
Memeriksa objek acara di FireBug. FWIW, properti ini khusus untuk Mozilla, dan didokumentasikan di MDC: developer.mozilla.org/en/DOM/event.explicitOriginalTarget
Shog9
2
Ini tidak berfungsi (atau berhenti berfungsi?) Di Firefox 3.6 dan Safari 4.0.3 di Windows.
Chetan S
1
@ Jonathan: properti tersedia, tetapi tidak diperbarui ketika bluracara kebakaran. Saya telah memperbarui jawabannya dengan detail. Sudahkah Anda mencoba menggunakan activeElement untuk ini di Chrome atau Firefox? Ini memberi Anda elemen yang kabur ...
Shog9
1
Sebenarnya tidak bekerja pada FF 31: eksplisitOriginalTarget menunjukkan target blur saat ini, document.activeElement adalah nol pada acara blur.
Adrian Maire
75

Jawaban 2015 : menurut Acara UI , Anda dapat menggunakan relatedTargetproperti acara:

Digunakan untuk mengidentifikasi sekunder yang EventTargetterkait dengan acara Fokus, tergantung pada jenis acara.

Untuk bluracara,

relatedTarget: target acara menerima fokus.

Contoh:

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

Catatan Firefox tidak akan mendukung relatedTargethingga versi 48 ( bug 962251 , MDN ).

Oriol
sumber
Firefox tidak memiliki dukungan, tetapi ada tiket: bugzilla.mozilla.org/show_bug.cgi?id=687787
sandstrom
3
Sekarang sudah. Lihat di sini .
rplaurindo
cintai komunitas web, sekarang semuanya jauh lebih mudah ^ _ ^
am05mhz
6
Solusi bagus Sayangnya, relatedTargetakan kembali nulljika target yang menerima fokus bukan elemen input.
Pedro Hoehl Carvalho
5
Jika menerima elemen fokus bukan elemen input, tambahkan tabIndex="0"atribut ke dalamnya dan itu akan berfungsi
Dany
19

Saya menyelesaikannya pada akhirnya dengan batas waktu pada acara onblur (terima kasih atas saran dari teman yang bukan StackOverflow):

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

Bekerja baik di FF dan IE.

Michiel Borkent
sumber
9
Apakah ini dianggap praktik buruk di dunia javascript btw?
Michiel Borkent
1
posting lama tapi saya punya pertanyaan yang sama. bagaimanapun, itu adalah satu-satunya hal yang tampaknya menyelesaikan pekerjaan lintas-browser.
joshs
jawaban ini membantu TON saya dengan menyelesaikan beberapa masalah lain ... Terima kasih Michael!
Alex
@MichielBorkent ini adalah implementasi yang buruk karena tidak didorong oleh peristiwa. Anda menunggu sejumlah waktu tertentu dan hanya berharap itu sudah cukup lama. Semakin lama Anda menunggu, semakin aman Anda, tetapi juga semakin banyak waktu yang Anda buang jika Anda tidak perlu menunggu terlalu lama. Mungkin seseorang menggunakan perangkat yang sangat lama / lambat dan batas waktu ini tidak cukup. Sayangnya saya ada di sini karena acara tersebut tidak memberikan saya apa yang perlu saya tentukan jika iframe diklik di FireFox, namun ia berfungsi untuk semua browser lainnya. Saya sangat tergoda untuk menggunakan metode ini sekarang meskipun itu adalah praktik yang buruk.
CTS_AE
1
Pertanyaan ini cukup lama, kembali ke 2008. Sementara itu mungkin ada pendekatan yang lebih baik. Bisakah Anda mencoba jawaban tahun 2015?
Michiel Borkent
16

Dimungkinkan untuk menggunakan acara dokumen mousedown alih-alih blur:

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

FocusEventInstance type mempunyai relatedTargetatribut, namun, hingga versi 47 dari FF, secara khusus, atribut ini mengembalikan null, dari 48 yang sudah berfungsi.

Anda dapat melihat lebih banyak di sini .

rplaurindo
sumber
2

Saya juga mencoba untuk membuat Autocompleter abaikan blur jika elemen tertentu diklik dan memiliki solusi yang berfungsi, tetapi hanya untuk Firefox karena secara eksplisitOriginalTarget

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

Kode ini membungkus metode onBlur otomatis pada Autocompleter dan memeriksa apakah parameter ignBlurEventElement disetel. jika disetel, ia memeriksa setiap kali untuk melihat apakah elemen yang diklik diabaikanBlurEventElement atau tidak. Jika ya, Autocompleter tidak dapat menggunakanBlur, selain itu ia memanggil onBlur. Satu-satunya masalah dengan ini adalah bahwa ia hanya berfungsi di Firefox karena properti eksplisitOriginalTarget adalah spesifik Mozilla. Sekarang saya mencoba menemukan cara yang berbeda daripada menggunakan eksplisitOriginalTarget. Solusi yang Anda sebutkan mengharuskan Anda untuk menambahkan perilaku onclick secara manual ke elemen. Jika saya tidak dapat mengelola untuk memecahkan masalah eksplisitOriginalTarget, saya kira saya akan mengikuti solusi Anda.

matte
sumber
2

Bisakah Anda membalikkan apa yang Anda periksa dan kapan? Itu jika Anda mengingat apa yang kabur terakhir:

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

dan kemudian di onClick untuk rentang Anda, panggil fungsi () dengan kedua objek:

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

Fungsi Anda kemudian dapat memutuskan apakah akan memicu kontrol Ajax.AutoCompleter atau tidak. Fungsi memiliki objek yang diklik dan objek kabur. OnBlur telah terjadi sehingga tidak akan membuat saran menghilang.

bmb
sumber
1

Gunakan sesuatu seperti ini:

var myVar = null;

Dan kemudian di dalam fungsi Anda:

myVar = fldID;

Lalu:

setTimeout(setFocus,1000)

Lalu:

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

Kode terakhir:

<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>
Vara
sumber
1

saya pikir itu tidak mungkin, dengan IE Anda dapat mencoba menggunakan window.event.toElement, tetapi itu tidak berfungsi dengan firefox!

stefano m
sumber
Tidak bekerja dengan Chrome atau Safari. Mungkin tidak akan berfungsi dengan versi baru IE yang lebih kompatibel dengan standar.
robocat
1

Seperti disebutkan dalam jawaban ini , Anda dapat memeriksa nilainya document.activeElement. documentadalah variabel global, jadi Anda tidak perlu melakukan sihir apa pun untuk menggunakannya di penangan onBlur Anda:

function myOnBlur(e) {
  if(document.activeElement ===
       document.getElementById('elementToCheckForFocus')) {
    // Focus went where we expected!
    // ...
  }
}
Kevin
sumber
1
  • document.activeElement bisa menjadi simpul induk (misalnya simpul tubuh karena sedang dalam fase sementara beralih dari target ke yang lain), sehingga tidak dapat digunakan untuk ruang lingkup Anda
  • ev.explicitOriginalTarget tidak selalu dihargai

Jadi cara terbaik adalah menggunakan onclick on body event untuk memahami secara tidak langsung simpul Anda (event.target) tidak jelas


sumber
1

Bekerja di Google Chrome v66.x, Mozilla v59.x dan Microsoft Edge ... Solusi dengan jQuery.

Saya menguji di Internet Explorer 9 dan tidak didukung.

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

Komentari tes Anda dalam versi penjelajah internet lainnya.

LuisEduardox
sumber
0

Sunting: Cara hacky untuk melakukannya adalah dengan membuat variabel yang melacak fokus untuk setiap elemen yang Anda pedulikan. Jadi, jika Anda peduli bahwa 'input saya' kehilangan fokus, atur variabel ke fokus.

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

Jawaban Asli: Anda dapat meneruskan 'ini' ke fungsi.

<input id="myInput" onblur="function(this){
   var theId = this.id; // will be 'myInput'
}" />
brock.holum
sumber
ini tidak menjawab pertanyaan, semoga saya membuatnya lebih jelas dengan contoh tambahan
Michiel Borkent
0

Saya sarankan menggunakan variabel global blurfrom dan blurto. Kemudian, konfigurasikan semua elemen yang Anda pedulikan untuk menetapkan posisinya di DOM ke blurfrom variabel ketika mereka kehilangan fokus. Selain itu, konfigurasikan agar mendapatkan fokus menetapkan blurto variabel ke posisi mereka di DOM. Kemudian, Anda bisa menggunakan fungsi lain sama sekali untuk menganalisis data blurf dan blurto.

stalepretzel
sumber
Ini hampir solusinya, tetapi dalam event handler onblur saya sudah perlu tahu item apa yang telah diklik, jadi timeout pada onblur melakukannya untuk saya.
Michiel Borkent
0

perlu diingat, bahwa solusi dengan eksplisitOriginalTarget tidak berfungsi untuk lompatan input teks ke input teks.

coba ganti tombol dengan input teks berikut dan Anda akan melihat perbedaannya:

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

sumber
0

Saya telah bermain dengan fitur yang sama ini dan menemukan bahwa FF, IE, Chrome dan Opera memiliki kemampuan untuk menyediakan elemen sumber suatu acara. Saya belum menguji Safari, tetapi dugaan saya, mungkin ada yang serupa.

$('#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;
    }
    //...
});
EricDuWeb
sumber
ini berfungsi dengan baik mengapa downvoting? hapus saja originalEvent!
fekiri malek
0

Saya tidak suka menggunakan batas waktu ketika coding javascript jadi saya akan melakukannya dengan cara yang berlawanan dari Michiel Borkent. (Tidak mencoba kode di belakang tetapi Anda harus mendapatkan ide).

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

Di kepala kira-kira seperti itu

<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>
Ronan Quillevere
sumber
0

Anda dapat memperbaiki IE dengan:

 event.currentTarget.firstChild.ownerDocument.activeElement

Sepertinya "eksplisitOriginalTarget" untuk FF.

Antoine And J

Madbean
sumber
0

Saya menulis sebuah solusi alternatif bagaimana membuat elemen apa pun menjadi fokus dan "blurable".

Ini didasarkan pada pembuatan elemen sebagai contentEditabledan menyembunyikannya secara visual dan menonaktifkan mode edit itu sendiri:

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

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

DEMO

Catatan: Diuji di Chrome, Firefox, dan Safari (OS X). Tidak yakin tentang IE.


Terkait: Saya sedang mencari solusi untuk VueJs, jadi bagi mereka yang tertarik / ingin tahu bagaimana menerapkan fungsionalitas tersebut menggunakan arahan Vue Focusable, silakan lihat .

Serhii Matrunchyk
sumber
-2

Cara ini:

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

Atau jika Anda melampirkan pendengar melalui JavaScript (jQuery dalam contoh ini):

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

Edit : maaf. Saya salah membaca pertanyaan.

Armin Ronacher
sumber
3
Jika Anda sadar bahwa ini bukan jawaban untuk pertanyaan dan Anda salah membaca, silakan perbarui atau hapus.
TJ
-2


Saya pikir itu mudah dimungkinkan melalui jquery dengan melewati referensi lapangan yang menyebabkan peristiwa onblur di "ini".
Untuk misalnya

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

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

Terima kasih,
Monika

Monika Sharma
sumber
-2

Anda bisa membuatnya seperti ini:

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

Saya hanya melihat retasan dalam jawaban, tetapi sebenarnya ada solusi bawaan yang sangat mudah digunakan: Pada dasarnya Anda dapat menangkap elemen fokus seperti ini:

const focusedElement = document.activeElement

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

Thomas J.
sumber
Setidaknya dalam kasus saya, ini tidak berfungsi karena activeElement adalah body, jika saya memeriksa ini pada render berikutnya / centang itu sudah diatur dengan benar. Tetapi tampaknya solusi shog9 adalah satu-satunya solusi yang tepat karena memastikan kutu telah berdetak.
Mathijs Segers