2009-12-13 75 views
24

Tôi đang cố gắng kích hoạt sự kiện bàn phím đến trang bằng javascript trên Chrome. Tôi đã có một cách tiếp cận được sử dụng để làm việc trên Firefox:Kích hoạt sự kiện bàn phím trên Chrome

pressKey = function(key, shift) { 
    var evt = document.createEvent('KeyboardEvent'); 
    evt.initKeyEvent("keypress", false, true, null, false, false, 
        shift, false, keyCode(key), key.charCodeAt(0)); 
    document.dispatchEvent(evt); 
} 

nơi chính là chìa khóa mong muốn và keyCode thay đổi chữ thường thành highercase và cũng kêu gọi charCodeAt().

Vấn đề của tôi là sự kiện trên Safari/Chrome không có initKeyEvent, nhưng initKeyboardEvent. Sự khác biệt chính mà tôi có thể nhận thấy là bạn phải chuyển khóa như một keyIdentifier (giống như một ký tự unicode) thay vì truyền mã khóa và keychar. Tuy nhiên tôi vẫn không thể xoay xở để làm cho nó hoạt động được.

Tôi cũng đã thử phương pháp tiếp cận JQuery được mô tả here mà không thành công.

EDIT: tôi sửa lỗi này xa hơn một chút và có vẻ như rằng sự kiện trên Chrome không kích hoạt các thính giả, nhưng keyCode/charCode luôn là 0. Tôi đã cố gắng để thiết lập evt.keyCode hoặc evt.charCode với không thành công.

+1

Tôi đã xóa nhận xét khỏi câu hỏi và đặt câu trả lời, vì tôi nghĩ rằng thậm chí không thực sự giải quyết được câu hỏi, nó có thể thực sự hữu ích cho những người gặp vấn đề tương tự như tôi đã làm. – fserb

+0

Làm thế nào bạn giải quyết được vấn đề? Tôi cũng đang đối mặt với vấn đề mô phỏng nhấn phím trái và phải trên chrome/safari. Nhưng không thành công, bạn đã làm thế nào? – MaX

+0

Bạn đã thử giải pháp tôi đã đăng chưa? Nó làm việc cho tôi và có lẽ sẽ giúp bạn đạt được mục tiêu của bạn, do đó, nó lạ với tôi rằng bạn chấp nhận câu trả lời của riêng bạn "nó là một lỗi". – Dennis

Trả lời

5

Tôi chỉ muốn ném đoạn trích cơ bản này ra khỏi đó. Nó hoạt động trong Chrome và dựa trên bản hack được đề cập bởi Paul Irish.
Nó sử dụng charCode thay vì keyCode (có thể hữu ích trong một số trường hợp), nhưng thích ứng với keyCode nếu bạn vui lòng.

var keyboardEvent = new KeyboardEvent('keypress', {bubbles:true}); 
Object.defineProperty(keyboardEvent, 'charCode', {get:function(){return this.charCodeVal;}}); 
keyboardEvent.charCodeVal = [your char code]; 
document.body.dispatchEvent(keyboardEvent); 
+0

không phải là initKeyboardEvent? – SuperUberDuper

19

Tôi đã theo dõi điều này xuống đến bug on Webkit nơi sự kiện được tạo chỉ chứa KeyIdentifier nhưng không có mã khóa/mã khóa như có thể thấy trên browser source code. Dường như có một bản vá đang diễn ra để giải quyết vấn đề này. Vì vậy, tôi đoán đây không phải là một câu hỏi thích hợp nữa ...

+1

Hãy nhớ chấp nhận câu trả lời của riêng bạn khi bạn có thể – Graviton

+1

Mọi người đã báo cáo thành công với hack tuyệt đẹp này tại đây: http://stackoverflow.com/a/10520017/89484 –

+9

Không nên ai đó trong dự án Chromium hoặc Webkit đã sửa lỗi này bằng cách hiện nay? (Đã gần 5 năm rồi ...) –

2

Tùy thuộc vào nhu cầu của bạn, TextEvent có thể hoạt động. (Nó làm việc cho tôi cho nhu cầu của tôi -. Cho chrome Đây không phải là qua trình duyệt thử nghiệm, nhưng sau đó, câu hỏi là cụ thể về chrome.)

// get a reference to the DOM element you want to affect 
var input = document.getElementsByTagName('input')[0]; 
// create a TextEvent 
var textEvent = document.createEvent('TextEvent'); 
// initialize the TextEvent 
textEvent.initTextEvent('textInput', true, true, null, String.fromCharCode(13)+"\r\n", 9, "en-US"); 
// dispatch ('fire') the TextEvent 
input.dispatchEvent(textEvent); 
+0

Mặc dù điều này kích hoạt sự kiện, nhưng nó không thực sự chèn văn bản. Tính năng "bảo mật" trong Chrome 61? - hãy thử điều này, nó không hoạt động https://gist.github.com/flying19880517/3180456 – mhenry1384

11

Nếu bạn muốn làm điều đó một cách đúng đắn, bạn có thể sử dụng DOM Bàn phím Mức độ sự kiện 4 Bàn phímKhoa cấu trúc và khóa thuộc tính.

Trong các trình duyệt mới nhất hoặc với DOM Keyboard Event Level 3/4 polyfill bạn có thể làm một cái gì đó như thế này:

element.addEventListener(function(e){ console.log(e.key, e.char, e.keyCode) }) 

var e = new KeyboardEvent("keydown", {bubbles : true, cancelable : true, key : "Q", char : "Q", shiftKey : true}); 
element.dispatchEvent(e); 

//If you need legacy property "keyCode". 
// Note: In some browsers you can't overwrite "keyCode" property. (At least in Safari) 
delete e.keyCode; 
Object.defineProperty(e, "keyCode", {"value" : 666}) 

Example

"map event.key to character values of a normal QUERTY (en-US) layout" proposal demo

Lưu ý rằng keyCodecharCode đang bị phản đối trong tất Spec (www .w3.org/TR/DOM-Level-3-Sự kiện /). Vì vậy, không có cơ hội để Chrome triển khai initKeyEvent với hỗ trợ mã phím. Nhưng bạn luôn có thể ghi đè lên giá trị này: CẬP NHẬT: Phương pháp Nhược điểm:

var evt = document.createEvent('KeyboardEvent'); 
evt.initKeyEvent("keypress", false, true, null, false, false, 
       shift, false, keyCode(key), key.charCodeAt(0)); 
if(evt.keyCode != keyCode(key)) { 
    delete evt.keyCode; 
    // Note: In some browsers you can't overwrite "keyCode" property. (At least in Safari) 
    Object.defineProperty(evt, "keyCode", { keyCode(key) }); 
} 

Hoặc bạn có thể cập nhật mẫu sự kiện: CẬP NHẬT: Phương pháp Nhược điểm:

// Note: In some browsers you can't overwrite "keyCode" property. (At least in Safari) 
var _native_keyCode_getter = Object.getOwnPropertyDescriptor(KeyboardEvent.prototype, "keyCode"); 
Object.defineProperty(KeyboardEvent.prototype, "keyCode", { 
    "enumerable" : true, 
    "configurable" : true, 
    "get" : function() { 
     if("__keyCode" in this)return this["__keyCode"]; 

     return _native_keyCode_getter.call(this); 
    }, 
    "set" : function(newValue) { 
     return this["__keyCode"] = isNaN(newValue) ? 0 : newValue; 
    } 
});  

Cập nhật Có nhiều triển khai khác nhau của initKeyboardEvent.Trong polyfill KeyboardEvent của tôi, tôi phát hiện ra nó bằng cách nào đó như thế này (gist):

var _initKeyboardEvent_type = (function(e) { 
    try { 
     e.initKeyboardEvent(
      "keyup" // in DOMString typeArg 
      , false // in boolean canBubbleArg 
      , false // in boolean cancelableArg 
      , global // in views::AbstractView viewArg 
      , "+" // [test]in DOMString keyIdentifierArg | webkit event.keyIdentifier | IE9 event.key 
      , 3 // [test]in unsigned long keyLocationArg | webkit event.keyIdentifier | IE9 event.location 
      , true // [test]in boolean ctrlKeyArg | webkit event.shiftKey | old webkit event.ctrlKey | IE9 event.modifiersList 
      , false // [test]shift | alt 
      , true // [test]shift | alt 
      , false // meta 
      , false // altGraphKey 
     ); 
     return ((e["keyIdentifier"] || e["key"]) == "+" && (e["keyLocation"] || e["location"]) == 3) && (
      e.ctrlKey ? 
       e.altKey ? // webkit 
        1 
        : 
        3 
       : 
       e.shiftKey ? 
        2 // webkit 
        : 
        4 // IE9 
      ) || 9 // FireFox|w3c 
      ; 
    } 
    catch (__e__) { alert("browser do not support KeyboardEvent") } 
})(document.createEvent("KeyboardEvent")); 

var e = document.createEvent("KeyboardEvent"); 
... 
if("initKeyEvent" in e) {//FF 
    //https://developer.mozilla.org/en/DOM/event.initKeyEvent 
    e.initKeyEvent(type, _bubbles, _cancelable, _view, _ctrlKey, _altKey, _shiftKey, _metaKey, _keyCode, _keyCode); 
} 
else if("initKeyboardEvent" in e) {//https://developer.mozilla.org/en/DOM/KeyboardEvent#initKeyboardEvent() 
    if(_try_initKeyboardEvent) { 
     if(_initKeyboardEvent_type == 1) { // webkit 
      //http://stackoverflow.com/a/8490774/1437207 
      //https://bugs.webkit.org/show_bug.cgi?id=13368 
      e.initKeyboardEvent(type, _bubbles, _cancelable, _view, _key, _location, _ctrlKey, _shiftKey, _altKey, _metaKey, _altGraphKey); 
     } 
     else if(_initKeyboardEvent_type == 2) { // old webkit 
      //http://code.google.com/p/chromium/issues/detail?id=52408 
      e.initKeyboardEvent(type, _bubbles, _cancelable, _view, _ctrlKey, _altKey, _shiftKey, _metaKey, _keyCode, _keyCode); 
     } 
     else if(_initKeyboardEvent_type == 3) { // webkit 
      e.initKeyboardEvent(type, _bubbles, _cancelable, _view, _key, _location, _ctrlKey, _altKey, _shiftKey, _metaKey, _altGraphKey); 
     } 
     else if(_initKeyboardEvent_type == 4) { // IE9 
      //http://msdn.microsoft.com/en-us/library/ie/ff975297(v=vs.85).aspx 
      e.initKeyboardEvent(type, _bubbles, _cancelable, _view, _key, _location, _modifiersListArg, _repeat, _locale); 
     } 
     else { // FireFox|w3c 
      //http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent-initKeyboardEvent 
      //https://developer.mozilla.org/en/DOM/KeyboardEvent#initKeyboardEvent() 
      e.initKeyboardEvent(type, _bubbles, _cancelable, _view, _char, _key, _location, _modifiersListArg, _repeat, _locale); 
     } 
    } 
} 
+1

Cả cách giải quyết được đề xuất của bạn đều không hoạt động. Đầu tiên không thành công vì thuộc tính 'keyCode' không thể cấu hình được. Điều thứ hai bởi vì 'get' của bộ mô tả thuộc tính không bao giờ thực sự được gọi. – John

+0

"Lỗi đầu tiên vì thuộc tính keyCode không thể định cấu hình được." Tôi cập nhật phần đa lỗi của mình để sửa các lỗi và khả năng tương thích của trình duyệt – termi

2

Bạn có thể làm việc xung quanh lỗi Webkit sử dụng createEvent('Event') hơn createEvent('KeyboardEvent'), và sau đó gán keyCode tài sản. Xem this answerthis example.

+4

Có một sự khác biệt giữa hai loại. Nếu bạn sử dụng createEvent ("Sự kiện") trong WebKit và gửi một sự kiện với keyCode 13 đến một phần tử biểu mẫu, nó không thực sự bắt chước phím trả về. Nếu có một người nghe lắng nghe keyCode 13, nó sẽ kích hoạt nó, nhưng so sánh với Firefox, nơi nó thực sự bắt chước cách nhấn phím return trên bàn phím và gửi biểu mẫu. Được xử lý chỉ với vấn đề này trong một ngày hoặc lâu hơn và nghĩ rằng tôi muốn chia sẻ. :) – jxpx777

Các vấn đề liên quan