Bir girişin odağı olup olmadığını test etmek için jQuery kullanma


561

Oluşturduğum bir sitenin ön sayfasında, birkaç tane fare üzerlerine geldiğinde kenarlık eklemek <div>için CSS :hoversözde sınıfını kullanıyor. Biri <div>s bir içeriyor <form>içindeki bir giriş odağı varsa sınır tutacak jQuery kullanarak hangi. IE6'nin s :hoverdışında hiçbir öğeyi desteklememesi dışında bu mükemmel çalışır <a>. Yani, bu tarayıcı için sadece yöntemi :hoverkullanarak CSS taklit etmek için jQuery kullanıyoruz $(#element).hover(). Tek sorun şimdi jQuery kolları formu hem yani, focus() ve hover() bir giriş odak vardır, daha sonra kullanıcı giriş ve çıkış fare hareket, sınır kaybolur.

Bu davranışı durdurmak için bir tür koşullu kullanabileceğimizi düşünüyordum. Örneğin, girişlerden herhangi birinin odaklanıp odaklanmadığını fareyle dışarıda test etsek, sınırın kaybolmasını durdurabiliriz. AFAIK, jQuery'de :focusseçici yok , bu yüzden bunu nasıl yapacağımdan emin değilim. Herhangi bir fikir?


1
Bunu neyin gerekli olduğunu ve neler olduğumu birkaç cümleyle kaynatmaya çalışabilir misin?
mkoryak

Odaklama ve bulanıklaştırma olaylarını yakalamaya bakmanız gerektiğini düşünüyorum ( docs.jquery.com/Events/focus ve docs.jquery.com/Events/blur )
Wolfr

Ben ilgili soru üzerine bir cevap yayınlanmıştır "Bir JavaScript (veya jQuery) orada 'odak vardır' mı?" . [Gnarf tarafından belirtilen cletus yaklaşımını] geliştirdim (# 2684561).
luiggitama

Yanıtlar:


928

jQuery 1.6+

jQuery bir :focusseçici ekledi, böylece artık kendimiz eklememiz gerekmiyor. Sadece kullan$("..").is(":focus")

jQuery 1.5 ve altı

Düzenleme: Zaman değiştikçe, odağı test etmek için daha iyi yöntemler buluyoruz, yeni favori Ben Alman'dan bu özü :

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

Alıntı yapan Mathias Bynens burada :

(elem.type || elem.href)Testin vücut gibi yanlış pozitifleri filtrelemek için eklendiğine dikkat edin . Bu şekilde, form denetimleri ve köprüler dışındaki tüm öğeleri filtrelediğimizden emin oluruz.

Yeni bir seçici tanımlıyorsunuz. Bkz. Eklentiler / Yazma . Sonra şunları yapabilirsiniz:

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

veya:

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

Herhangi bir jQuery

Sadece hangi öğenin odaklandığını bulmak istiyorsanız,

$(document.activeElement)

Sürümün 1.6 veya daha düşük olup olmadığından emin değilseniz, :focusseçiciyi eksikse ekleyebilirsiniz :

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

4
Bu yanlış pozitiflere neden olabilir. Daha fazla bilgi için stackoverflow.com/questions/967096/… adresine bakın (Ben Alman ve Diego Perini sayesinde).
Mathias Bynens

@Mathias Bynens - Güncelleme için teşekkürler (bu topluluk wiki cevabını
btw'yi

Hem 1.5 hem de 1.6 ile çalışmak için ne zaman ihtiyacınız var? JQuery'nin kendi odak seçicisini geçersiz kılmak istemiyorum. Gibi bir şey if (!jQuery.expr[':'].focus) { /* gist from Ben Alman */ }?
Betamos

@betamos - Kesinlikle doğru ... Cevabı yansıtmak için bir şeyler ekleyeceğim.
gnarf

2
@Alex - çünkü kadarını söyleyebilirim olduğunca, jsFiddle sorunu gösteren bir azalma sınav hal Lütfen bu hiçbir sebep yoktur olmamalı "dinamik" unsurları üzerinde çalışmak. Ben maskaralık diyorum ...
shenanigans gnarf

46

CSS:

.focus {
    border-color:red;
}

JQuery:

  $(document).ready(function() {

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

22

İşte şu anda kabul edilenden daha sağlam bir cevap:

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

(elem.type || elem.href)Yanlış pozitifleri filtrelemek için testin eklendiğini unutmayın body. Bu şekilde, form denetimleri ve köprüler dışındaki tüm öğeleri filtrelediğimizden emin oluruz.

( Ben Alman tarafından bu özgeçmişten alınmıştır .)


13

Nisan 2015 Güncellemesi

Bu soru bir süredir gündeme geldiğinden ve bazı yeni sözleşmeler devreye girdiğinden, .liveyöntemin amortismana uğradığından bahsetmem gerektiğini hissediyorum .

Yerine, .onyöntem şimdi tanıtıldı.

Onların dokümantasyon nasıl çalıştığını açıklamak oldukça yararlıdır;

.On () yöntemi, jQuery nesnesindeki geçerli olarak seçili öğe kümesine olay işleyicileri ekler. JQuery 1.7'den itibaren .on () yöntemi, olay işleyicilerini eklemek için gereken tüm işlevleri sağlar. Eski jQuery olay yöntemlerinden dönüştürme konusunda yardım için bkz. .Bind (), .delegate () ve .live ().

Bu nedenle, 'girdi odaklı' etkinliği hedeflemeniz için bunu bir komut dosyasında kullanabilirsiniz. Gibi bir şey:

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

Bu oldukça sağlamdır ve hatta SEKME tuşunu da kullanmanızı sağlar.


2

Ne sonra tamamen emin değilim ama bu girdi öğeleri (veya div?) Bir değişken olarak durumunu depolayarak elde edilebilir gibi geliyor:

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

Yaptığım şey bu, ama küresel bir javascript değişkeni yerine rastgele bir CSS sınıfı kullandım.
bloudermilk

Bunun bir varyasyonunu kullandım. Yeni jQuery eklentisine gerek yok. Bu beni mutlu bir kampçı yapıyor!
Dennis Day

1

Bir öğenin durumunu işaretlemek için sınıfları kullanmaya alternatif olarak dahili veri deposu işlevselliğidir .

Not: Boole ve istediğiniz her şeyi data()fonksiyonu kullanarak saklayabilirsiniz . Sadece iplerle ilgili değil :)

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

Ve sonra sadece elementlerin durumuna erişme meselesi.



1

Bunu simüle etmek için mouseOver ve mouseOut'u kullanmayı düşündünüz mü? Ayrıca mouseEnter ve mouseLeave


Temelde jQuery'nin vurgulu ile yaptığım şey bu. Biri fare girişi ve diğeri fare çıkışı için olmak üzere iki işlev sağlarsınız.
bloudermilk

0

Her iki durumu da (vurgulanmış, odaklanmış) doğru / yanlış bayraklar olarak takip edin ve her değiştiğinde, her ikisi de yanlışsa kenarlığı kaldıran bir işlev çalıştırın, aksi takdirde kenarlığı gösterir.

Yani: onfocus setleri odaklandı = true, onblur setleri odaklandı = false. onmouseover setleri asılı kaldı = doğru, onmouseout setleri asılı kaldı = yanlış. Bu olayların her birinden sonra kenarlık ekleyen / silen bir işlev çalıştırın.


0

Bildiğim kadarıyla, tarayıcıya ekrandaki herhangi bir girişin odak olup olmadığını soramazsınız, bir çeşit odak izleme ayarlamanız gerekir.

Genellikle "noFocus" adlı bir değişken var ve true olarak ayarlayın. Sonra noFocus'u yanlış yapan tüm girişlere bir focus olayı eklerim. Sonra noFocus öğesini true değerine ayarlayan tüm girişlere bir blur olayı eklerim.

Bunu oldukça kolay bir MooTools sınıfı var, eminim aynı şeyi yapmak için bir jquery eklentisi oluşturabilirsiniz.

Bu oluşturulduktan sonra, herhangi bir kenar değiştirme yapmadan önce noFocus'u kontrol edebilirsiniz.




0

Kullanıcı yeni bir değer yazmadan önce seçmek zorunda kalmamak için bir metin girişinin içeriğini seçmek () (vurgulamak) için ayarlanmış bir .live ("odak") olayı vardı.

$ (FormObj) .Select ();

Farklı tarayıcılar arasındaki tuhaflıklar nedeniyle, seçim bazen buna neden olan tıklama tarafından geçersiz kılınır ve imleci metin alanına yerleştirmenin hemen ardından içeriğin seçimini kaldırır (çoğunlukla FF'de çalıştı, ancak IE'de başarısız oldu)

Seçime hafif bir gecikme koyarak bunu çözebileceğimi düşündüm ...

setTimeout (fonksiyonu () {$ (formObj) .Select ();}, 200);

Bu iyi çalıştı ve seçim devam edecek, ama komik bir sorun ortaya çıktı .. Eğer bir alandan diğerine sekmiş olursanız, seçim yapılmadan önce odak sonraki alana geçerdi. Seçim odağı çaldığından, odak geri döner ve yeni bir "odak" olayını tetikler. Bu, ekranın her yerinde dans eden bir dizi giriş seçimi ile sona erdi.

Uygulanabilir bir çözüm, select () işlemini gerçekleştirmeden önce alanın hala odaklanıp odaklanmadığını kontrol etmek olacaktır, ancak belirtildiği gibi, kontrol etmenin basit bir yolu yoktur ... Neyin olması gerektiğini çevirmek yerine sadece tüm otomatik vurgulamayı dağıttım. alt rutinlerle yüklü büyük bir işleve tek bir jQuery select () çağrısı ...


0

Yaptığım yara, jQuery focus () işlevi içinde eklenen ve kaldırılan .elementhasfocus adlı rasgele bir sınıf oluşturmaktır. Fareyle üzerine gelindiğinde hover () işlevi çalıştığında .elementhasfocus öğesini kontrol eder:

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

Dolayısıyla, bu sınıfa sahip değilse (okuma: div içindeki hiçbir öğenin odağı yoksa) kenarlık kaldırılır. Aksi takdirde hiçbir şey olmaz.


-2

Basit

 <input type="text" /> 



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

    alert("I am in Focus");

     });
 </script>

Bu, şu anda hangi öğenin odakta olduğunu söylemez. Yeni bir eleman odağı aldığında çağrılır. Dolayısıyla, bir öğenin odağı zaten varsa ve bu öğenin 'bu' olup olmadığını bilmek istiyorsanız, bu kod işe yaramaz.
Alexis Wilke
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.