Làm cách nào để mô phỏng thao tác di chuột qua trong JavaScript thuần túy kích hoạt CSS “: hover”?


82

Tôi đã cố gắng tìm mã để mô phỏng mouseovertrong Chrome nhưng mặc dù trình nghe "di chuột qua" được kích hoạt, khai báo CSS "di chuột" không bao giờ được đặt!

Tôi cũng đã thử làm:

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

Nhưng dường như không có gì thay đổi phần tử thành những gì được khai báo trong hoverkhai báo của nó .

Điều này có khả thi không?


6
@PSL Tôi nghĩ những gì anh ấy muốn làm là buộc :hovertrạng thái trên một phần tử.
Benjamin Gruenbaum

1
@BenjaminGruenbaum Yup bạn nói đúng. Tôi đã hiểu nhầm.
PSL

1
Đây không phải là một bản sao. Câu hỏi còn lại là về jQuery. Câu hỏi này là về JS thuần túy.
Chuck Lê Butt

1
@Monk OQ bao gồm thẻ jQuery. Đây là một bản sao.
JasonMArcher

1
@JasonMArcher Câu hỏi (và câu trả lời của nó) là về JS thuần túy. Bạn không nghĩ rằng có nhiều khả năng họ đã đánh nhầm nó.
Chuck Le Butt vào

Câu trả lời:


106

Bạn không thể. Đây không phải là một sự kiện đáng tin cậy .

Các sự kiện được tạo bởi tác nhân người dùng, do tương tác của người dùng hoặc là kết quả trực tiếp của các thay đổi đối với DOM, được tác nhân người dùng tin cậy với các đặc quyền không dành cho các sự kiện được tạo bởi tập lệnh thông qua DocumentEvent.createEvent ("Sự kiện"), được sửa đổi bằng phương thức Event.initEvent () hoặc được gửi qua phương thức EventTarget.dispatchEvent (). Thuộc tính isTrusted của các sự kiện đáng tin cậy có giá trị là true, trong khi các sự kiện không đáng tin cậy có giá trị thuộc tính isTrusted là false.

Hầu hết các sự kiện không đáng tin cậy sẽ không kích hoạt các hành động mặc định , ngoại trừ các sự kiện nhấp chuột hoặc Kích hoạt DOM.

Bạn phải thêm một lớp và thêm / xóa lớp đó trên các sự kiện di chuột qua / di chuột theo cách thủ công.


4
@Tim, Nó không thực sự trả lời tại sao . Nó chỉ thay đổi câu hỏi .
Pacerier

7
@Pacerier đây không phải là một sự kiện đáng tin cậy vì nó không được khởi tạo bởi người dùng. Nó nói như vậy ngay ở phần trích dẫn ở trên trong câu trả lời của tôi. Đó thực sự là câu trả lời bắt đầu với.
Benjamin Gruenbaum

1
@BenjaminGruenbaum, tôi đang trích dẫn "ngoại trừ các sự kiện nhấp chuột hoặc Kích hoạt DOM" . Điều gì đặc biệt về "hover" mà nó không nằm trong danh sách ngoại lệ này? Tại sao chúng ta được phép gọi là "tiêu điểm" mà không phải là "di chuột"? Đây là những câu hỏi chúng ta phải trả lời, trả lời bất cứ điều gì khác chỉ là thay đổi câu hỏi .
Pacerier

1
Tôi giả định rằng di chuột (và kết hợp với nhấp hoặc chuột lên và xuống để kéo và thả), có thể hoạt động hoặc xuất hiện giống như chiếm quyền điều khiển hệ thống của người dùng (nếu bạn bỏ qua các trường hợp tự động hóa), vì vậy nó không lý tưởng để hỗ trợ. Nhấp vào Tôi không thể nói, nhưng tiêu điểm sẽ cho phép tự động lấy tiêu điểm đến trường biểu mẫu đích hoặc phần tử mà nhà thiết kế trang web muốn người dùng tập trung vào, chẳng hạn như trường văn bản có dữ liệu bị thiếu hoặc không chính xác (ví dụ: kiểm tra xác thực trường biểu mẫu). Nhưng đó chỉ là giả định của tôi.
David

2
Vâng, nghe có vẻ vô lý, bạn có thể làm cho nó có vẻ là tiêu điểm được tạo ra bởi một tương tác của người dùng mà nó không phải là. Trong thực tế - các API của trình duyệt sẽ sẵn sàng không tuân theo thông số kỹ thuật và bỏ qua tiêu điểm và nhấp chuột như các sự kiện không đáng tin cậy (ít nhất là Chrome). Hãy thử ví dụ mô phỏng một nhấp chuột vào một phần mở rộng nút cài đặt cho một phần mở rộng chrome và xem những gì sẽ xảy ra :)
Benjamin Gruenbaum

37

Bạn có thể mô phỏng sự kiện di chuột qua như sau:

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

Cảm ơn, tất cả những gì tôi cần là bong bóng! Nhấp chuột phải vào một phần tử trong Trình kiểm tra bảng điều khiển dành cho nhà phát triển và thực hiện "Sử dụng trong bảng điều khiển" (Firefox) hoặc "Lưu trữ dưới dạng biến chung" (Chrome). Sau đó, bạn có thể, ví dụ: temp0.dispatchEvent(new MouseEvent('mouseover', {bubbles: true})) Rất hữu ích để tạo kiểu cho chú giải công cụ hoặc nội dung khác chỉ xuất hiện khi di chuột qua.
Denis Howe

Cái này thật tuyệt.
rebard

1
@DenisHowe Đối với trường hợp sử dụng đó, bạn nên kiểm tra :hovnút ở đầu trình kiểm tra kiểu trong devtools. Nó cho phép bạn kích hoạt bất kỳ giả cổ nào bạn thích trên phần tử đang được kiểm tra.
hallo

17

Lý lịch

Tôi tình cờ gặp câu hỏi này trong khi cố gắng viết các bài kiểm tra tự động, để xác minh rằng một tập hợp các phần tử nhất định trên một trang nhất định đều nhận được một số thuộc tính css do css đặt cho các sự kiện di chuột.

Mặc dù câu trả lời ở trên giải thích một cách hoàn hảo, tại sao không thể chỉ đơn giản kích hoạt sự kiện di chuột bằng JS và sau đó thăm dò một số giá trị css quan tâm, nhưng nó trả lời câu hỏi ban đầu "Làm cách nào để mô phỏng một lần di chuột qua trong JavaScript thuần túy kích hoạt CSS" :bay lượn"?" chỉ một phần.

Khước từ

Đây không phải là một giải pháp hiệu quả. Chúng tôi chỉ sử dụng nó để kiểm tra tự động, nơi hiệu suất không phải là mối quan tâm.

Giải pháp

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

Giải trình

createEvent đọc tất cả các tệp css, thay thế: di chuột bằng một chuỗi trống và áp dụng nó. Điều này có tác dụng, tất cả: kiểu di chuột đều được áp dụng. Bây giờ người ta có thể thăm dò để tìm kiểu hú và đặt trở lại trạng thái ban đầu bằng cách dừng Mô phỏng.

Tại sao chúng ta áp dụng hiệu ứng di chuột cho toàn bộ tài liệu chứ không chỉ cho phần tử quan tâm bằng cách lấy từ các trang tính và sau đó thực hiện một element.css (...)?

Xong như vậy, kiểu sẽ được áp dụng nội tuyến, kiểu này sẽ ghi đè các kiểu khác, kiểu này có thể không bị kiểu di chuột css ban đầu ghi đè.

Bây giờ tôi sẽ mô phỏng di chuột như thế nào cho một phần tử?

Đây không phải là hiệu suất, vì vậy tốt hơn không nên. Nếu phải, bạn có thể kiểm tra với element.is (selectorOfInterest) nếu kiểu áp dụng cho phần tử của bạn và chỉ sử dụng những kiểu đó.

Thí dụ

Trong Jasmine, bạn có thể thực hiện:

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
Câu trả lời này là tuyệt vời! Rất tiếc, nó không thành công trên các phiên bản Chrome gần đây trên các trang có bảng định kiểu được cung cấp từ các máy chủ khác do Chrome hạn chế quyền truy cập vào các yêu cầu nguồn gốc chéo. Xem câu trả lời của tôi để biết giải pháp hỗ trợ điều này :)
FThompson

6

Những gì tôi thường làm gì trong trường hợp này là thêm một lớp sử dụng javascript .. và gắn cùng CSS:hoverđể lớp này

Hãy thử sử dụng

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

Hoặc đối với các trình duyệt cũ hơn:

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

tất nhiên bạn sẽ phải sử dụng onmouseoutđể loại bỏ lớp "di chuột" khi bạn rời khỏi phần tử ...


Điều này sẽ không thực hiện những gì OP yêu cầu, mặc dù nó có thể ít nhiều đi đúng hướng. Sẽ tốt hơn nếu sử dụng các kỹ thuật đính kèm trình xử lý sự kiện hiện đại.
Pointy

xin lỗi, hiểu lầm câu hỏi
Yotam Omer

@Điểm câu hỏi yêu cầu javascript thuần túy .. làm cách nào để các sự kiện có thể được đính kèm theo cách khác?
Yotam Omer

2
Không đủ tốt? Đó là JavaScript "thuần túy" và trên thực tế nó sẽ đính kèm một hàm như một trình xử lý cho một sự kiện. Trong Internet Explorer, (gần như) tương đương attachEvent()sẽ được sử dụng.
Pointy

Đáng nói. Hỗ trợ IE9 và 10 addEventListenervà đó là cách tốt nhất để đính kèm các sự kiện, attachEventchỉ cần chỉnh sửa trong IE8 (trở xuống). Yotam, nếu anh ta thêm một trình xử lý khác vào onmouseoverbằng cách đặt thuộc tính trực tiếp (thay vì sau đó thêm trình xử lý sự kiện) thì nó sẽ ghi đè sự kiện hiện được đặt. Xem câu hỏi này về sự khác biệt.
Benjamin Gruenbaum

4

Bạn có thể sử dụng pseudo: styler , một thư viện có thể áp dụng các lớp giả CSS cho các phần tử.

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

Tuyên bố từ chối trách nhiệm: Tôi là đồng tác giả của thư viện này. Chúng tôi đã thiết kế nó để hỗ trợ thêm các biểu định kiểu gốc chéo, đặc biệt để sử dụng trong các tiện ích mở rộng của Chrome, nơi bạn có thể thiếu kiểm soát đối với các quy tắc CSS của trang.


1
Điều này có vẻ thực sự hoạt động khá tốt, ngay cả khi kết hợp với window.getComputedStyle(<youElement>)sau khi thiết lập kiểu giả. Cảm ơn!
Daniel Veihelmann

2

Tôi giả sử bạn muốn kiểm tra CSS sau khi thao tác dom, nhưng ngay sau khi bạn di chuyển chuột trở lại devtools, sự kiện sẽ không hoạt động trên phần tử html đó nữa. Bạn có thể muốn có một cái gì đó như tùy chọn: di chuột trong devtools cho các sự kiện javascript của bạn. Điều đó không tồn tại, nhưng bạn có thể mô phỏng nó.

  1. Mở devtools của bạn và nhấp vào nó để kích hoạt nó.
  2. Kích hoạt sự kiện trên yếu tố bạn quan tâm.
  3. Không di chuyển chuột, hãy mở bảng lệnh devtools bằng ctrl + shift + p và chọn 'vô hiệu hóa javascript' bằng bàn phím của bạn.

Vì javascript bị tắt nên nó không có cơ hội sửa đổi lại (các) phần tử. Bạn có thể vào devtools và kiểm tra css và html như thể bạn đang di chuột, nhấp chuột hoặc làm điều gì đó khác với nó. Sau khi hoàn tất, hãy chuyển đến bảng lệnh một lần nữa và chọn 'kích hoạt javascript'.


Kỹ thuật gọn gàng, nhưng trừ khi tôi hiểu lầm ý định của bạn, điều này không đã tồn tại trong DevTools! Trong cả Chrome / Chromium và trình phát triển của Firefox, có một :hovnút ở đầu trình kiểm tra kiểu (bên cạnh hộp nhập "Bộ lọc"). Nhấp :hovnở một loạt các hộp kiểm, mỗi dán nhãn với một pseudoclass: :active, :focus, :focus-within, :hover, và :visited. Và việc kiểm tra bất kỳ hộp nào trong số các hộp này sẽ kích hoạt giả cổ tương ứng của nó trên phần tử đang được kiểm tra.
hallo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.