CSS ": hover" ı etkinleştiren saf JavaScript'te fareyle üzerine gelme simülasyonunu nasıl yapabilirim?


83

mouseoverChrome'da simüle etmek için kod bulmaya çalışıyordum, ancak "fareyle üzerine gelme" dinleyicisi çalıştırılsa da, CSS "üzerine gelme" bildirimi hiçbir zaman ayarlanmadı!

Ben de denedim:

//Called within mouseover listener
theElement.classList.add("hover");

Ancak hiçbir şey, hoverbeyanında beyan edilen unsuru değiştirmiyor gibi görünüyor .

Mümkün mü?


6
@PSL Sanırım yapmak istediği şey :hoverbir öğeye zorlama durumu.
Benjamin Gruenbaum

1
@BenjaminGruenbaum Yup haklısın. Yanlış anlamışım.
PSL

1
Bu bir kopya değil. Diğer soru jQuery ile ilgili. Bu soru saf JS ile ilgili.
Chuck Le Butt

1
@Monk OQ jQuery etiketini içeriyordu. Bu bir kopya.
JasonMArcher

1
@JasonMArcher Soru (ve cevabı) saf JS ile ilgili. Muhtemelen yanlış düşündüklerini düşünmüyor musunuz?
Chuck Le Butt

Yanıtlar:


106

Yapamazsın. Güvenilir bir olay değil .

Kullanıcı aracısı tarafından, kullanıcı etkileşiminin bir sonucu olarak veya DOM'daki değişikliklerin doğrudan bir sonucu olarak oluşturulan olaylara, DocumentEvent.createEvent aracılığıyla komut dosyası tarafından oluşturulan olaylara tanınmayan ayrıcalıklarla kullanıcı aracısı tarafından güvenilir. ("Event") yöntemi, Event.initEvent () yöntemi kullanılarak değiştirildi veya EventTarget.dispatchEvent () yöntemi aracılığıyla gönderilir. Güvenilir olayların isTrusted özniteliğinin true değeri varken, güvenilmeyen olayların isTrusted öznitelik değeri false şeklindedir.

Çoğu güvenilmeyen olay , tıklama veya DOMActivate olayları dışında varsayılan eylemleri tetiklememelidir .

Bir sınıf eklemeniz ve bunu mouseover / mouseout olaylarına manuel olarak eklemeniz / kaldırmanız gerekir.


4
@Tim, aslında nedenini cevaplamıyor . Sadece soruyu değiştirir .
Pacerier

7
@Pacerier, kullanıcı tarafından başlatılmadığı için güvenilen bir olay değil. O öyle diyor orada cevabım yukarıda alıntıda. Kelimenin tam anlamıyla cevabın başladığı şey bu.
Benjamin Gruenbaum

1
@BenjaminGruenbaum, "tıklama veya DOMActivate olayları dışında" alıntı yapıyorum . "Fareyle üzerine gelme" nin bu istisna listesinde olmaması için özel olan nedir? Neden "odak " dememize izin veriliyor ama "havada asılı kalmıyoruz?" Bunlar cevaplamamız gereken sorular, başka bir şeyi cevaplamak sadece soruyu değiştirmektir .
Pacerier

1
Fareyle üzerine gelmenin (ve sürükle ve bırak için tıklama veya fare yukarı ve aşağı ile birlikte) bir kullanıcının sistemini ele geçiriyormuş gibi davranabileceğini veya görünebileceğini (otomasyon durumlarını görmezden gelirseniz) varsayıyorum, bu yüzden desteklemek ideal değildir. Söyleyemem seçeneğini tıklayın, ancak odak, kullanıcının örneğin eksik veya yanlış veriler içeren bir metin alanına (ör. Form alanı doğrulama kontrolleri) odaklanmasını istediği hedef form alanına veya öğeye otomatik odaklanmaya izin verir. Ama bu sadece benim varsayımlarım.
David

2
Evet, kulağa ne kadar saçma gelse de, odaklanmanın olmadığı yerde bir kullanıcı etkileşiminden kaynaklanıyormuş gibi görünmesini sağlayabilirsiniz. Pratikte - tarayıcı API'leri memnuniyetle spesifikasyona uymaz ve güvenilmeyen olaylar olarak odaklanmayı ve tıklamayı göz ardı eder (en azından Chrome). Örneğin, bir Chrome uzantısı için bir uzantı yükleme düğmesine tıklamayı simüle etmeyi deneyin ve ne olacağını görün :)
Benjamin Gruenbaum

39

Fareyle üzerine gelme olayını şu şekilde simüle edebilirsiniz:

HTML

<div id="name">My Name</div>

JavaScript

var element = document.getElementById('name');
element.addEventListener('mouseover', function() {
  console.log('Event triggered');
});

var event = new MouseEvent('mouseover', {
  'view': window,
  'bubbles': true,
  'cancelable': true
});

element.dispatchEvent(event);

Teşekkürler, Tek ihtiyacım olan baloncuklardı! Developer Console Inspector'daki bir öğeyi sağ tıklayın ve "Konsolda kullan" (Firefox) veya "Global değişken olarak sakla" (Chrome) seçeneğini belirleyin. Daha sonra, örneğin, temp0.dispatchEvent(new MouseEvent('mouseover', {bubbles: true})) araç ipuçlarını veya yalnızca fareyle üzerine gelindiğinde görünen diğer içerikleri şekillendirmek için çok yararlı olabilirsiniz .
Denis Howe

Bu fantastik.
isyan

1
@DenisHowe Bu kullanım durumu için, :hovdevtools'da stil denetçisinin üst kısmındaki düğmeyi kontrol etmelisiniz. İncelenmekte olan öğede istediğiniz herhangi bir sahte sınıfı etkinleştirmenize olanak tanır.
hallo

17

Arka fon

Otomatik testler yazmaya çalışırken, belirli bir sayfadaki tüm öğelerin aldığı belirli bir dizi öğenin, üzerine gelme etkinlikleri için css tarafından ayarlanan bazı css özelliklerine sahip olduğunu doğrulamak için bu soruya rastladım.

Yukarıdaki yanıt mükemmel bir şekilde açıklasa da, neden sadece JS ile fareyle üzerine gelme olayını tetiklemenin ve ardından ilgili bazı css değerlerini araştırmanın mümkün olmadığını mükemmel bir şekilde açıklasa da, "CSS'yi etkinleştiren saf JavaScript'te fareyle üzerine gelmeyi nasıl simüle ederim" sorusunu yanıtlıyor. : vurgulu ”?" sadece kısmen.

Feragatname

Bu yüksek performanslı bir çözüm değildir. Bunu yalnızca performansın önemli olmadığı otomatik testler için kullanıyoruz.

Çözüm

simulateCssEvent = function(type){
    var id = 'simulatedStyle';

    var generateEvent = function(selector){
        var style = "";
        for (var i in document.styleSheets) {
            var rules = document.styleSheets[i].cssRules;
            for (var r in rules) {
                if(rules[r].cssText && rules[r].selectorText){
                    if(rules[r].selectorText.indexOf(selector) > -1){
                        var regex = new RegExp(selector,"g")
                        var text = rules[r].cssText.replace(regex,"");
                        style += text+"\n";
                    }
                }
            }
        }
        $("head").append("<style id="+id+">"+style+"</style>");
    };

    var stopEvent = function(){
        $("#"+id).remove();
    };

    switch(type) {
        case "hover":
            return generateEvent(":hover");
        case "stop":
            return stopEvent();
    }
}

Açıklama

generateEvent tüm css dosyalarını okur,: hover'ı boş bir dizeyle değiştirir ve uygular. Bu, tüm: vurgulu stillerin uygulandığı bir etkiye sahiptir. Artık, güçlü bir stil araştırılabilir ve Simülasyonu durdurarak başlangıç ​​durumuna geri dönülebilir.

Fareyle üzerine gelme efektini neden sadece ilgilendiğimiz öğe için değil de tüm belgeye uygulayıp ardından bir element.css (...) gerçekleştiriyoruz?

Bu şekilde yapıldığında, stil satır içi olarak uygulanır, bu, orijinal css vurgulu stil tarafından geçersiz kılınmayabilecek diğer stilleri geçersiz kılar.

Şimdi tek bir öğe için fareyle üzerine gelme simülasyonunu nasıl yapabilirim?

Bu performans değil, o yüzden yapmasan iyi olur. Gerekirse, stilin öğeniz için geçerli olup olmadığını ve yalnızca bu stilleri kullanıp kullanmadığını element.is (selectorOfInterest) ile kontrol edebilirsiniz.

Misal

Jasmine'de örneğin şimdi şunları gerçekleştirebilirsiniz:

describe("Simulate CSS Event", function() {
    it("Simulate Link Hover", function () {
      expect($("a").css("text-decoration")).toBe("none");
      simulateCssEvent('hover');
      expect($("a").css("text-decoration")).toBe("underline");
      simulateCssEvent('stop');
      expect($("a").css("text-decoration")).toBe("none");
    });
});

1
Bu cevap harika! Maalesef, Chrome'un çapraz kaynak isteklerine erişimi kısıtlaması nedeniyle diğer ana bilgisayarlardan sunulan stil sayfalarına sahip sayfalarda Chrome'un son sürümlerinde başarısız oluyor. Bunu destekleyen bir çözüm için cevabımı görün :)
FThompson

6

Ne genellikle bu durumda aynısını javascript kullanan bir sınıf ekleyerek .. ve bağlantı olduğu CSSkadar :hoverbu sınıfa

Kullanmayı dene

theElement.addEventListener('onmouseover', 
    function(){ theElement.className += ' hovered' });

Veya daha eski tarayıcılar için:

theElement.onmouseover = function(){theElement.className += ' hovered'};

onmouseoutelementi terk ettiğinizde "hovered" sınıfı kaldırmak için kullanmanız gerekecek ...


Bu, muhtemelen aşağı yukarı doğru çizgide olsa da, OP'nin istediğini yapmayacaktır. Modern olay işleyicisi bağlama tekniklerini kullanmak daha iyi olacaktır.
Sivri

üzgünüm, yanlış anlaşılmış soru
Yotam Omer

@Pointy soru saf javascript'i sorar .. Aksi halde olaylar nasıl eklenebilir?
Yotam Omer

2
Yeterince iyi değil? Bu "saf" JavaScript ve aslında bir olay için işleyici olarak bir işlev ekleyecektir. Internet Explorer'da (neredeyse) eşdeğeri attachEvent()kullanılacaktır.
Sivri

Bahsetmeye değer. IE9 ve 10 desteği addEventListenerve olayları eklemenin en iyi yolu, şimleme attachEventyalnızca IE8'de (ve aşağıda) gereklidir. Yotam, onmouseoverözniteliği doğrudan ayarlayarak (olay dinleyicisini eklemek yerine) başka bir işleyici eklerse, o anda ayarlanan olayı geçersiz kılar. Fark hakkında bu soruyu görün .
Benjamin Gruenbaum

4

Öğelere CSS sözde sınıfları uygulayabilen bir kitaplık olan pseudo: styler'ı kullanabilirsiniz .

(async () => {
  let styler = new PseudoStyler();
  await styler.loadDocumentStyles();
  document.getElementById('button').addEventListener('click', () => {
    const element = document.getElementById('test')
    styler.toggleStyle(element, ':hover');
  })
})();

Feragatname: Bu kitaplığın ortak yazarıyım. Bunu, özellikle sayfanın CSS kuralları üzerinde denetim sahibi olamayacağınız durumlarda Chrome uzantılarında kullanmak üzere, çapraz kaynak stil sayfalarını ek olarak desteklemek için tasarladık.


1
window.getComputedStyle(<youElement>)Sözde stili ayarladıktan sonra ile birleştirildiğinde bile bu aslında oldukça iyi çalışıyor gibi görünüyor . Teşekkürler!
Daniel Veihelmann

2

CSS'yi dom manipülasyonundan sonra incelemek istediğinizi varsayıyorum, ancak farenizi devtool'lara geri götürdüğünüzde, olay artık o html öğesinde etkin değil. Muhtemelen javascript etkinlikleriniz için devtools'da: hover seçeneği gibi bir şeye sahip olmak istersiniz. Bu mevcut değil, ancak simüle edebilirsiniz.

  1. Geliştirici araçlarınızı açın ve etkinleştirmek için üzerine tıklayın.
  2. İlgilendiğiniz öğe üzerinde olayı tetikleyin.
  3. Fareyi hareket ettirmeden ctrl + shift + p ile devtools komut panelini açın ve klavyenizle 'javascript'i devre dışı bırak'ı seçin.

Javascript devre dışı bırakıldığı için, öğeleri tekrar değiştirme şansı bulamaz. Devtool'lara gidip css ve html'yi sanki geziniyormuş, tıklıyor veya onunla başka bir şey yapıyormuş gibi inceleyebilirsiniz. Bitirdikten sonra, komut paneline tekrar gidin ve 'javascript'i etkinleştir'i seçin.


Temiz tekniği, ama senin niyet yanlış sürece bu mu zaten DevTools'un var! Hem Chrome / Chromium hem de Firefox'un geliştiricilerinde, :hovstil denetçisinin üst kısmında bir düğme vardır ("Filtre" giriş kutusunun yanında). Tıklandığında :hovgenişler onay kutularını bir dizi her bir pseudoclass ile etiketlenmiş: :active, :focus, :focus-within, :hover, ve :visited. Ve bu kutulardan herhangi birinin işaretlenmesi, incelenmekte olan eleman üzerindeki ilgili sözde sınıfını etkinleştirir.
hallo
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.