Bir 'bulanıklaştırma' olayı meydana geldiğinde, hangi öğe odağının * öğesine * gittiğini nasıl öğrenebilirim?


188

Diyelim ki bir blurBir HTML giriş kutusuna böyle işlev :

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

blurFonksiyonun içinde olayın tetiklenmesine (tıklatılan öğe) neden olan öğenin kimliğini almanın bir yolu var mı ? Nasıl?

Örneğin, şöyle bir yayılma alanım olduğunu varsayalım:

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

Giriş öğesi odağa girdikten hemen sonra aralığı tıklatırsam, giriş öğesi odağını kaybeder. İşlev mySpantıklatıldığını nasıl biliyor ?

Not: Kapağın onclick olayı, giriş öğesinin onblur olayından önce gerçekleşirse, sorunum çözülür, çünkü belirli bir öğenin tıklandığını gösteren bazı durum değerleri ayarlayabilirim.

PPS: Bu sorunun arka planı önerileri göstermek bluriçin giriş öğesindeki olay nedeniyle hemen kaybolmadan harici bir AJAX otomatik tamamlayıcı denetimi (tıklanabilir bir öğeden) tetiklemek istiyorum olmasıdır . Bu nedenle, blurbelirli bir öğenin tıklanıp tıklanmadığını ve bu durumda bulanıklaştırma olayını yoksaydım.


Bu, akıl yürütmeyi görmek istediğim ilginç bir soru - yani bunu neden yapıyorsunuz? Bağlam nedir?
Rahul

Rahul ve roosteronasit, soruyu yorumlarınıza (PPS) tepki olarak güncelledim.
Michiel Borkent

1
Bu bilgi biraz eski olduğundan, daha yeni bir yanıt için buraya bakın: stackoverflow.com/questions/7096120/…
Jonathan M

Yanıtlar:


86

Hmm ... Firefox'ta, explicitOriginalTargettıklanan öğeyi çekmek için kullanabilirsiniz . toElementIE için de aynısını yapmayı bekledim , ancak işe yaramıyor ... Ancak, yeni odaklanmış öğeyi belgeden çekebilirsiniz:

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

Uyarı: Bu teknik geliyor değil odak için çalışma kaynaklanan değişiklikleri sekme klavye ile alanlar arasında ve Chrome veya Safari hiç işi yok. Kullanarak büyük bir sorun activeElement(IE hariç) sürekli güncellenen kadar olmamasıdır sonrablur olay işleme konuldu ve işlem sırasında da hiç geçerli bir değere sahip olabilir! Bu, Michiel'in kullandığı teknikte bir varyasyon ile hafifletilebilir :

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

Bu, çoğu modern tarayıcıda (Chrome, IE ve Firefox'ta test edilmiştir) çalışmalı ve Chrome'un tıklanan düğmelere odaklanmamasına dikkat edilmelidir (sekme yerine).


1
Uzun süredir explicitOriginalTarget gibi bir şey arıyordum. Nasıl buldun?
Kev

3
FireBug'daki olay nesnesini inceledi. FWIW, mülk Mozilla'ya özgüdür ve
MDC'de

2
Bu, Firefox 3.6'da ve Windows'ta Safari 4.0.3'te çalışmıyor (veya çalışmayı durdurdu mu?).
Chetan S

1
@Jonathan: Tesis kullanılabilir, ancak bluretkinlik başladığında güncellenmez . Cevabı ayrıntılarla güncelledim. Chrome veya Firefox'ta bunun için activeElement kullanmayı denediniz mi? Size bulanık unsur verir ...
Shog9

1
Aslında FF 31 üzerinde çalışmıyor: explicitOriginalTarget geçerli bulanıklaştırma hedefini gösterir, document.activeElement bulanıklık olayında boştur.
Adrian Maire

76

2015 yanıtı : UI Etkinliklerine göre relatedTarget, etkinliğin özelliğini kullanabilirsiniz :

EventTargetOlayın türüne bağlı olarak, bir Focus olayıyla ilgili ikincil bir tanımlamak için kullanılır .

İçin blurolaylar,

relatedTarget: olay hedefi alan odak.

Misal:

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

Not Firefox, relatedTargetsürüm 48'e kadar desteklenmez ( hata 962251 , MDN ).


Firefox'un desteği yok, ancak bir bilet var: bugzilla.mozilla.org/show_bug.cgi?id=687787
sandstrom

4
Şimdi var. Buraya bakın .
rplaurindo

1
web topluluğunu seviyorum, şimdi her şey çok daha kolay ^ _ ^
am05mhz

7
Harika bir çözüm. Ne yazık ki, hedef alan odak bir giriş öğesi değilse relatedTargetgeri döner null.
Pedro Hoehl Carvalho

6
Odak öğesi almak bir girdi öğesi değilse, tabIndex="0"ona bir özellik ekleyin ve işe yarayacaktır
Dany

19

Sonunda onblur olayında bir zaman aşımı ile çözdüm (StackOverflow olmayan bir arkadaşın tavsiyesi sayesinde):

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

Hem FF hem de IE'de çalışır.


9
Javascript dünya btw bu kötü uygulama olarak kabul edilir mi?
Michiel Borkent

1
eski yazı ama aynı sorum var. ne olursa olsun, iş çapraz tarayıcı yapmak gibi görünüyor tek şey.
joshs

bu cevap başka bir problemi çözerek bir TON'uma yardımcı oldu ... Teşekkürler Michael!
Alex

@MichielBorkent, olay güdümlü olmadığı için bu kötü bir uygulamadır. Belirli bir süre beklersiniz ve yeterince uzun olduğunu umarsınız. Ne kadar uzun süre beklerseniz o kadar uzun süre beklemek zorunda kalmazsanız daha fazla zaman kaybedersiniz. Belki birisi gerçekten eski / yavaş bir cihazdadır ve bu zaman aşımı yeterli değildir. Ne yazık ki buradayım çünkü olaylar bana bir iframe'in FireFox'a tıklanıp tıklanmadığını belirlemek için ihtiyacım olan şeyleri sağlamıyor, ancak diğer tüm tarayıcılar için çalışıyor. Kötü bir uygulama olmasına rağmen şimdi bu yöntemi kullanmak için çok cazipim.
CTS_AE

1
Bu soru oldukça eski, 2008'e kadar uzanıyor. Bu arada daha iyi yaklaşımlar olabilir. 2015 yanıtını deneyebilir misiniz?
Michiel Borkent

16

Bulanıklık yerine belgenin fareyle üzerine gelme olayını kullanmak mümkündür:

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

8

Tür FocusEventörnekleri varrelatedTarget özniteliği vardır, ancak FF'nin 47 sürümüne kadar, özellikle bu öznitelik null değerini döndürür, 48'den zaten çalışır.

Burada daha fazlasını görebilirsiniz .


2

Ayrıca belirli bir öğe tıkladı ve çalışma bir çözüm var, ancak yalnızca Firefox nedeniyle explicitOriginalTarget nedeniyle Autocompleter bulanıklaştırma yoksay yapmaya çalışıyorum

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

Bu kod, Autocompleter öğesinin varsayılan onBlur yöntemini sarar ve ignoreBlurEventElement parametrelerinin ayarlanıp ayarlanmadığını denetler. ayarlanmışsa, tıklanan öğenin ignoreBlurEventElement öğesinin olup olmadığını her seferinde kontrol eder. Eğer öyleyse, Autocompleter onBlur'u çağırmaz, aksi halde onBlur'u çağırır. Bununla ilgili tek sorun, explicitOriginalTarget özelliği Mozilla'ya özgü olduğu için yalnızca Firefox'ta çalışmasıdır. Şimdi explicitOriginalTarget kullanmaktan farklı bir yol bulmaya çalışıyorum. Bahsettiğiniz çözüm, öğeye manuel olarak onclick davranışı eklemenizi gerektirir. ExplicitOriginalTarget sorununu çözemezsem, çözümünüzü takip edeceğim sanırım.


2

Neyi ne zaman kontrol ettiğinizi tersine çevirebilir misiniz? En son neyin bulanık olduğunu hatırlarsanız:

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

ve daha sonra yayınınız için onClick'te, her iki nesneyle birlikte function () işlevini çağırın:

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

Ardından, işleviniz Ajax.AutoCompleter denetiminin tetiklenip tetiklenmeyeceğine karar verebilir. İşlev tıklanan nesneyi ve bulanık nesneyi içerir. OnBlur zaten oldu, bu yüzden önerilerin kaybolmasını sağlamayacak.


1

Bunun gibi bir şey kullanın:

var myVar = null;

Ve sonra fonksiyonunuzun içinde:

myVar = fldID;

Ve sonra:

setTimeout(setFocus,1000)

Ve sonra:

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

Son kod:

<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

Bence possibe değil, IE ile kullanmayı deneyebilirsiniz window.event.toElement, ancak dosfox ile çalışmaz!


Chrome veya Safari ile çalışmaz. Belki IE'nin daha standartlarla uyumlu yeni sürümleriyle çalışmaz.
robocat

1

Bu cevapta belirtildiği gibi , değerini kontrol edebilirsiniz document.activeElement. documentglobal bir değişkendir, bu nedenle onBlur işleyicinizde kullanmak için sihir yapmanız gerekmez:

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

1
  • document.activeElement bir üst düğüm olabilir (örneğin, geçici bir aşamada bir hedeften diğerine geçiş yaptığı için gövde düğümü), bu nedenle kapsamınız için kullanılamaz
  • ev.explicitOriginalTarget her zaman değerlenmez

Bu yüzden en iyi yol, dolaylı olarak düğümünüzü (event.target) bulanıklıkta olduğunu anlamak için onclick body olayını kullanmaktır


1

Google Chrome v66.x, Mozilla v59.x ve Microsoft Edge'de çalışır ... jQuery ile çözüm.

Internet Explorer 9'da test ediyorum ve desteklenmiyor.

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

Testinizi diğer internet explorer sürümlerinde yorumlayın.


0

Düzenleme: Bunu yapmak için hacky bir yol önem verdiğiniz her öğe için odak iz tutan bir değişken oluşturmak olacaktır. Bu nedenle, 'myInput'un odağı kaybettiğini düşünüyorsanız, odakta bir değişken ayarlayın.

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

Orijinal Yanıt: Bu işleve 'this' iletebilirsiniz.

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

bu soruya cevap vermiyor, umarım ek örnekle daha da netleştirdim
Michiel Borkent

0

Ben blurfrom ve blurto genel değişkenlerini kullanmanızı öneririm. Ardından, odak kaybettiklerinde DOM'daki konumlarını değişken bulanıklıktan atamak istediğiniz önemli tüm öğeleri yapılandırın. Ayrıca, yapılandırmak onları çok odak kazanıyor değişken blurto teşkil ettiği kendi DOM'da pozisyon. Ardından, bulanıklaştırma ve bulanıklaştırma verilerini analiz etmek için tamamen başka bir işlev kullanabilirsiniz.


Neredeyse çözüm, ancak onblur olay işleyicisinde zaten hangi öğenin tıklandığını bilmem gerekiyordu, bu yüzden onblur'daki bir zaman aşımı bunu benim için yaptı.
Michiel Borkent

0

explicitOriginalTarget ile çözümün, metin-giriş-metin-giriş sıçramalarında çalışmadığını unutmayın.

düğmeleri aşağıdaki metin girişleriyle değiştirmeyi deneyin ve farkı göreceksiniz:

<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

Aynı özellikle oynuyorum ve FF, IE, Chrome ve Opera'nın bir etkinliğin kaynak öğesini sağlama yeteneğine sahip olduğunu öğrendim. Safari'yi test etmedim ama tahminim buna benzer bir şey olabilir.

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

bu iyi çalışıyor neden downvoting? sadece originalEvent'i kaldırın!
fekiri malek

0

Ben javascript kodlarken zaman aşımı kullanarak sevmiyorum böylece Michiel Borkent ters yolu yapardı. (Arkasındaki kodu deneyin vermedi ama fikir almalısınız).

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

Kafasında böyle bir şey

<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'yi aşağıdakilerle düzeltebilirsiniz:

 event.currentTarget.firstChild.ownerDocument.activeElement

FF için "explicitOriginalTarget" gibi görünüyor.

Antoine ve J


0

Alternatif bir çözüm yazdımHerhangi bir öğenin odaklanabilir ve "mavileştirilebilir" hale getirilmesi .

Bir öğeyi oluşturmaya contentEditableve görsel olarak gizlemeye ve düzenleme modunun kendisini devre dışı bırakmaya dayanır :

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

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

DEMO

Not: Chrome, Firefox ve Safari'de (OS X) test edilmiştir. IE hakkında emin değilim.


İlgili: VueJ'ler için bir çözüm arıyordum, bu yüzden Vue Focusable yönergesini kullanarak böyle bir işlevin nasıl uygulanacağını merak eden / merak edenler için lütfen bir göz atın .


-2

Bu yoldan:

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

Veya dinleyiciyi JavaScript ile eklerseniz (bu örnekte jQuery):

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

Düzenleme : üzgünüm. Soruyu yanlış okudum.


3
Bunun sorunun cevabı olmadığını biliyorsanız ve onu yanlış okuduysanız, lütfen uygun şekilde güncelleyin veya silin.
TJ

-2


"Bu" onblur olayı neden alan referansını geçerek jquery ile kolayca mümkün olduğunu düşünüyorum.
Örneğin;

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

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

Teşekkürler
Monika


-2

Bunu şu şekilde yapabilirsiniz:

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

-2

Cevaplarda sadece saldırıları görüyorum, ancak aslında kullanımı çok kolay olan yerleşik bir çözüm var: Temel olarak odak öğesini şöyle yakalayabilirsiniz:

const focusedElement = document.activeElement

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


En azından benim durumumda, bu activeElement gövdesi olduğu için çalışmıyor, eğer bir sonraki render / tick'de kontrol edersem doğru ayarlanmış. Ama öyle görünüyor ki shog9'un çözümü, bir kene takıldığından emin olduğu için tek uygun çözümdür.
Mathijs Segers
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.