Як я змоделюю наведення курсору на чистому JavaScript, який активує CSS “: наведення”?


83

Я намагався знайти код для імітації mouseoverв Chrome, але, незважаючи на те, що слухач "наведення курсора" запускається, декларація CSS "наведення" ніколи не встановлюється!

Я спробував також зробити:

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

Але, здається, ніщо не змінює елемент на те, що заявлено в його hoverдекларації.

Чи можливо це?


6
@PSL Я думаю, що він хоче зробити, це примусити :hoverстан до елемента.
Бенджамін Груенбаум,

1
@BenjaminGruenbaum Так, ти маєш рацію. Я неправильно зрозумів.
PSL

1
Це не дублікат. Інше питання стосується jQuery. Це питання стосується чисто JS.
Чак Ле Батт

1
@Monk OQ включав тег jQuery. Це дублікат.
JasonMArcher

1
@JasonMArcher Питання (і відповідь на нього) стосується чистого JS. Вам не здається, що швидше за все вони помилились.
Чак Ле Батт

Відповіді:


106

Ви не можете. Це не довірена подія .

Події, що генеруються користувальницьким агентом, або в результаті взаємодії з користувачем, або як безпосередній результат змін у DOM, довіряються користувацькому агенту з привілеями, які не надаються подіям, згенерованим сценарієм за допомогою DocumentEvent.createEvent ("Подія") метод, модифікований за допомогою методу Event.initEvent () або відправлений через метод EventTarget.dispatchEvent (). Атрибут isTrusted довірених подій має значення true, тоді як ненадійні події мають значення атрибута isTrusted значення false.

Більшість ненадійних подій не повинні ініціювати дії за замовчуванням , за винятком подій click або DOMActivate.

Вам потрібно додати клас і додавати / видаляти це в подіях наведення / наведення миші вручну.


4
@Tim, насправді це не відповідає чому . Це просто змінює питання .
Pacerier

7
@Pacerier це не довірена подія, оскільки її не ініціював користувач. Це прямо сказано там, у цитаті вище у моїй відповіді. Буквально з чого починається відповідь.
Бенджамін Груенбаум,

1
@BenjaminGruenbaum, я цитую "за винятком подій click або DOMActivate" . Що такого особливого в "зависанні", що його немає в цьому списку винятків? Чому нам дозволено називати "фокус", а не "наведення"? Це питання, на які ми маємо відповісти, відповідь на будь-що інше просто змінює питання .
Pacerier

1
Я вважаю, що наведення курсору (і в поєднанні з клацанням або мишею вгору та вниз для перетягування та падіння) може поводитися або виглядати як викрадення системи користувача (якщо ви ігноруєте випадки автоматизації), тому не ідеально підтримувати. Клацніть Я не можу сказати, але фокус дозволить автофокус на цільове поле форми або елемент, який дизайнер сайту хоче, щоб користувач зосередився на скажімо, наприклад, текстовому полі з відсутніми або неправильними даними (наприклад, перевірки перевірки поля форми). Але це лише мої припущення.
Девід

2
Так, як би абсурдно це не звучало, ви можете зробити так, щоби фокус був спричинений взаємодією користувача там, де цього не було. На практиці - API браузера із задоволенням не слухатимуться специфікації та ігноруватиме фокус та клацнути як ненадійні події (принаймні Chrome). Спробуйте, наприклад, імітувати натискання кнопки встановлення розширення для розширення chrome, і подивіться, що трапиться :)
Бенджамін Груенбаум,

39

Ви можете імітувати подію наведення курсору так:

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

Дякую, все, що мені потрібно, це бульбашки! Клацніть правою кнопкою миші елемент у інспекторі консолі розробника та виконайте "Використати в консолі" (Firefox) або "Зберігати як глобальну змінну" (Chrome). Тоді ви можете, наприклад, temp0.dispatchEvent(new MouseEvent('mouseover', {bubbles: true})) Дуже корисно для оформлення підказок чи іншого вмісту, який відображається лише при наведенні курсора миші.
Денис Хоу,

Це фантастика.
повстання

2
@DenisHowe Для цього випадку ви повинні перевірити :hovкнопку у верхній частині інспектора стилів у devtools. Це дозволяє активувати будь-який псевдоклас, який вам подобається, на елементі, що перевіряється.
привіт

17

Передумови

Я наткнувся на це питання, намагаючись написати автоматизовані тести, щоб переконатися, що певний набір елементів на даній сторінці, які всі отримують, має певний набір властивостей css, встановлених css для подій при наведенні.

Хоча наведена вище відповідь прекрасно пояснює, чому неможливо просто викликати подію наведення за допомогою JS, а потім перевірити якесь значення css, яке цікавить, воно відповідає на початкове запитання "Як я змоделюю наведення курсору на чистому JavaScript, який активує CSS" : hover ”?" лише частково.

Застереження

Це не ефективне рішення. Ми використовуємо його лише для автоматизованого тестування, де продуктивність не турбує.

Рішення

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

Пояснення

generateEvent читає всі файли css,, замінює: hover порожнім рядком і застосовує його. Це призводить до того, що застосовуються стилі all: hover. Тепер можна зондувати стиль з висотою і повернутися до початкового стану, зупинивши моделювання.

Чому ми застосовуємо ефект наведення для всього документа, а не лише для цікавить елемента, отримуючи з аркушів, а потім виконуємо element.css (...)?

Якщо зробити це, стиль буде застосовано вбудовано, це замінить інші стилі, які можуть не бути замінені оригінальним стилем наведення курсора css.

Як я тепер змоделюю наведення для одного елемента?

Це не ефективно, тому краще не робіть. Якщо потрібно, ви можете перевірити елемент.is (selectorOfInterest), чи застосовується стиль до вашого елемента, і використовувати лише ці стилі.

Приклад

У Jasmine ви можете, наприклад, зараз виконати:

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
Ця відповідь чудова! На жаль, це не вдається в останніх версіях Chrome на сторінках із таблицями стилів, що подаються від інших хостів, через те, що Chrome обмежує доступ до запитів про перехресне походження. Дивіться мою відповідь на рішення, яке це підтримує :)
FThompson

6

У цьому випадку я зазвичай роблю додавання класу за допомогою javascript .. і приєднання до цього класу того самого CSS, що :hoverі

Спробуйте використовувати

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

Або для старих браузерів:

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

вам, звичайно, доведеться використовувати, onmouseoutщоб видалити клас "зависання", коли ви залишаєте елемент ...


Це не буде робити того, що вимагає ОП, хоча це, мабуть, більш-менш по правильній лінії. Краще було б використовувати сучасні прийоми вкладення обробників подій.
Пойнті

вибачте, неправильно зрозуміле запитання
Йотам Омер

@Pointy питання запитує чистий javascript .. як події можна прикріпити інакше?
Йотам Омер,

2
Не досить добре? Це "чистий" JavaScript, і він насправді додасть функцію обробника події. В Internet Explorer використовується (майже) еквівалент attachEvent().
Пойнті

Варто згадати. Підтримка IE9 та 10, addEventListenerі це найкращий спосіб приєднати події, обробка attachEventпотрібна лише в IE8 (і нижче). Йотаме, якщо він додасть ще один обробник onmouseover, встановивши атрибут безпосередньо (а не додаючи прослуховувач подій), він замінить встановлену в даний момент подію. Подивіться це питання на різницю.
Бенджамін Груенбаум,

4

Ви можете використовувати псевдо: стилер , бібліотеку, яка може застосовувати псевдокласи CSS до елементів.

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

Застереження: Я є співавтором цієї бібліотеки. Ми розробили його для додаткової підтримки таблиць стилів з перехресним походженням, спеціально для використання в розширеннях Chrome, де, ймовірно, вам не вистачає контролю над правилами CSS сторінки.


1
Здається, це насправді працює досить добре, навіть у поєднанні з window.getComputedStyle(<youElement>)після встановлення псевдостилю. Дякую!
Даніель Вейхельман

2

Я припускаю, що ви хочете перевірити CSS після маніпулювання dom, але як тільки ви повернете курсор миші до devtools, подія більше не активна для цього елемента html. Напевно, ви хотіли б мати щось на зразок: hover у devtools для ваших подій javascript. Цього не існує, але ви можете змоделювати це.

  1. Відкрийте ваші devtools і клацніть на ньому, щоб зробити його активним.
  2. Активуйте подію на елементі, який вас цікавить.
  3. Не рухаючи мишу, відкрийте командну панель devtools за допомогою комбінації клавіш ctrl + shift + p та виберіть на клавіатурі «вимкнути javascript».

Оскільки javascript вимкнено, він не має можливості змінити елементи знову. Ви можете перейти до devtools і перевірити css та html так, ніби ви наводили на них курсор, клацали або робили щось інше. Закінчивши, знову перейдіть до командної панелі та виберіть "увімкнути javascript".


Акуратні техніка, але якщо я зрозумів ваші наміри, це робить вже існує в Devtools! В обох інструментах Chrome / Chromium та Firefox є :hovкнопка у верхній частині інспектора стилів (поруч із полем вводу "Фільтр"). Клацання :hovрозширює серію прапорців, кожен позначений pseudoclass: :active, :focus, :focus-within, :hover, і :visited. І перевірка будь-якого з цих вікон активує відповідний псевдоклас на елементі, що перевіряється.
привіт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.