JavaScript'te tuşa basma etkinliklerini programlı olarak simüle etmek mümkün müdür?
JavaScript'te tuşa basma etkinliklerini programlı olarak simüle etmek mümkün müdür?
Yanıtlar:
Hem webkit hem de gecko'da çalışan jquery olmayan bir sürüm:
var keyboardEvent = document.createEvent("KeyboardEvent");
var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? "initKeyboardEvent" : "initKeyEvent";
keyboardEvent[initMethod](
"keydown", // event type: keydown, keyup, keypress
true, // bubbles
true, // cancelable
window, // view: should be window
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey
40, // keyCode: unsigned long - the virtual key code, else 0
0 // charCode: unsigned long - the Unicode character associated with the depressed key, else 0
);
document.dispatchEvent(keyboardEvent);
keyCode
her zaman 0'dır ve değiştiremem.
event.which
her zaman olmak 0
kullanırken document.createEvent("KeyboardEvent")
. @lluft bu yorumda ayrıntıları ve benim için çalışan bir çözümü farklı bir ileti dizisinde paylaştı . Temel olarak, document.createEvent('Event')
genel bir etkinlik oluşturmak için kullanmanız ve ardından türü , anahtarın koduna eşit keydown
bir keyCode
özellik olarak ayarlamanız ve vermeniz gerekir.
JQuery 1.3.1'i kullanmaya uygunsanız:
function simulateKeyPress(character) {
jQuery.event.trigger({ type : 'keypress', which : character.charCodeAt(0) });
}
$(function() {
$('body').keypress(function(e) {
alert(e.which);
});
simulateKeyPress("e");
});
trigger
Yerel tarayıcı etkinliklerini taklit etmek için kullanılamayacağını unutmayın .
Ne yapabilirsiniz tetiklemek programlı olduğu keyevent dinleyici ateş ederek keyevents . Korumalı alan güvenlik açısından buna izin vermek mantıklıdır. Bu yeteneği kullanarak, tipik bir gözlemci modeli uygulayabilirsiniz . Bu yöntemi "simüle etme" olarak adlandırabilirsiniz.
Aşağıda bunu jQuery ile birlikte W3C DOM standardında nasıl gerçekleştirebileceğinize dair bir örnek verilmiştir:
function triggerClick() {
var event = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true
});
var cb = document.querySelector('input[type=submit][name=btnK]');
var canceled = !cb.dispatchEvent(event);
if (canceled) {
// preventDefault was called and the event cancelled
} else {
// insert your event-logic here...
}
}
Bu örnek şu adresten uyarlanmıştır: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
JQuery'de:
jQuery('input[type=submit][name=btnK]')
.trigger({
type: 'keypress',
which: character.charCodeAt(0 /*the key to trigger*/)
});
Ancak son zamanlarda tarayıcı-korumalı alandan ayrılan temel öğeleri tetiklemenin [DOM] yolu yoktur. Ve tüm büyük tarayıcı satıcıları bu güvenlik konseptine bağlı kalacaktır.
NPAPI tabanlı ve Flashbox'ın atlanmasına izin veren Adobe Flash gibi eklentilere gelince: bunlar aşamalı olarak kaldırılıyor ; Firefox .
Detaylı açıklama:
Güvenlik nedeniyle yapamazsınız ve yapmamalısınız (Pekka'nın işaret ettiği gibi). Aralarında her zaman bir kullanıcı etkileşimi gerekir. Ayrıca, çeşitli programlı klavye olaylarının kimlik sahtekarlığı saldırılarına yol açacağından, tarayıcı satıcılarının kullanıcılar tarafından dava edilme şansını hayal edin.
Alternatifler ve daha fazla ayrıntı için bu gönderiye bakın. Her zaman flash tabanlı kopyala ve yapıştır özelliği vardır. İşte zarif bir örnek . Aynı zamanda, web'in neden eklenti satıcılarından uzaklaştığının bir kanıtıdır.
Uzak içeriğe programlı olarak erişmek için kaydolma CORS ilkesi durumunda da benzer bir güvenlik zihniyeti uygulanmaktadır .
Yanıt:
Korumalı alan tarayıcı ortamındaki giriş anahtarlarını normal koşullarda programlı olarak tetiklemenin bir yolu yoktur .
Alt satır: Gelecekte, oyunun nihai hedefine veya benzer kullanıcı deneyimlerine yönelik özel tarayıcı modları ve / veya ayrıcalıkları altında mümkün olmayacağını söylemiyorum. Bununla birlikte, bu tür modlara girmeden önce kullanıcıdan Tam Ekran API'sı modeline benzer izinler ve riskler istenir .
Yararlı: Anahtar Kodlar bağlamında, bu araç ve anahtar kodu eşleme kullanışlı olacaktır.
Bilgilendirme: Cevap cevabına göre burada .
Bunun gibi bir öğeye klavye olayları gönderebilirsiniz
element.dispatchEvent(new KeyboardEvent('keypress',{'key':'a'}));
keypress
amortisman yapılmış gibi görünüyor keydown
-> developer.mozilla.org/en-US/docs/Web/Events/keypress
Şunları kullanabilirsiniz dispatchEvent()
:
function simulateKeyPress() {
var evt = document.createEvent("KeyboardEvent");
evt.initKeyboardEvent("keypress", true, true, window,
0, 0, 0, 0,
0, "e".charCodeAt(0))
var body = document.body;
var canceled = !body.dispatchEvent(evt);
if(canceled) {
// A handler called preventDefault
alert("canceled");
} else {
// None of the handlers called preventDefault
alert("not canceled");
}
}
Bunu test etmedim, ancak dispatchEvent () belgesindeki koddan uyarlandı . Muhtemelen bunu ve ayrıca createEvent () ve initKeyEvent () için belgeleri okumak isteyeceksiniz.
initKeyEvent
ya da kullanıp kullanmama konusunda anlaşamadılar initKeyboardEvent()
. Her ikisi de KeyboardEvent () yapıcısını kullanmaktan vazgeçilir .
Klavye olayları oluşturabilir ve gönderebilirsiniz; bunlar uygun kayıtlı olay işleyicilerini tetikler, ancak herhangi bir metin oluşturmazlar örneğin girdi öğesine gönderilirse .
Metin girişini tamamen simüle etmek için bir dizi klavye olayı üretmeniz ve ayrıca giriş öğesinin metnini açıkça ayarlamanız gerekir. Olayların sırası, metin girişini ne kadar ayrıntılı bir şekilde simüle etmek istediğinize bağlıdır.
En basit form:
$('input').val('123');
$('input').change();
Bazı durumlarda keypress
olay gerekli işlevi sağlayamaz. Gönderen mozilla docs biz özellik kullanım dışıdır görebilirsiniz:
Bu özellik artık önerilmemektedir. Bazı tarayıcılar hala desteklese de, zaten ilgili web standartlarından kaldırılmış olabilir, bırakılma sürecinde olabilir veya yalnızca uyumluluk amacıyla saklanabilir. Kullanmaktan kaçının ve mümkünse mevcut kodu güncelleyin; kararınızı yönlendirmek için bu sayfanın altındaki uyumluluk tablosuna bakın. Bu özelliğin herhangi bir zamanda çalışmayabileceğini unutmayın.
Dolayısıyla, keypress
olay sonuç olarak tetiklenen iki olaydan birleştirildiğinden keydown
ve bunu keyup
aynı anahtar için takip ettiğinden , olayları tek tek oluşturun:
element.dispatchEvent(new KeyboardEvent('keydown',{'key':'Shift'}));
element.dispatchEvent(new KeyboardEvent('keyup',{'key':'Shift'}));
Alex2k8'in cevabına dayanarak, jQuery'nin desteklediği tüm tarayıcılarda çalışan revize edilmiş bir sürüm (sorun, o dahili işlevi kullanırken unutması kolay olan jQuery.event.trigger için eksik argümanlardaydı).
// jQuery plugin. Called on a jQuery object, not directly.
jQuery.fn.simulateKeyPress = function (character) {
// Internally calls jQuery.event.trigger with arguments (Event, data, elem).
// That last argument, 'elem', is very important!
jQuery(this).trigger({ type: 'keypress', which: character.charCodeAt(0) });
};
jQuery(function ($) {
// Bind event handler
$('body').keypress(function (e) {
alert(String.fromCharCode(e.which));
console.log(e);
});
// Simulate the key press
$('body').simulateKeyPress('x');
});
Bunu daha da ileriye taşıyabilir ve sadece olayı simüle etmekle kalmaz, aynı zamanda karakteri (bir giriş öğesi ise) ekleyebilir, ancak bunu yapmaya çalışırken birçok çapraz tarayıcı gotcha's vardır. SendKeys gibi daha ayrıntılı bir eklenti kullanın .
İlgilenenler için, aslında klavye giriş olaylarını güvenilir bir şekilde yeniden oluşturabilirsiniz. Giriş alanındaki metni değiştirmek için (imleçleri veya bir giriş karakteri aracılığıyla sayfayı taşıyın) DOM olay modelini yakından takip etmelisiniz: http://www.w3.org/TR/DOM-Level-3-Events/ # h4_events-inputevents
Model şunları yapmalıdır:
Sonra her karakter için:
Ardından, isteğe bağlı olarak çoğu için:
Bu aslında sayfadaki metni javascript (değer ifadelerini değiştirmeden) ile değiştirir ve javascript dinleyicilerini / işleyicilerini uygun şekilde ayarlar. Sıralı javascript uygun sırada tetiklenmezse, giriş kutusundaki metin değişmez, seçimler değişmez veya imleç metin alanındaki bir sonraki boşluğa taşınmaz.
Ne yazık ki kod NDA altında bir işveren için yazılmıştır, bu yüzden onu paylaşamam, ama kesinlikle mümkündür, ancak tüm anahtar girişi "yığını" her öğe için doğru sırayla yeniden oluşturmanız gerekir.
2019 itibariyle bu çözüm benim için çalıştı:
document.dispatchEvent(
new KeyboardEvent("keydown", {
key: "e",
keyCode: 69, // example values.
code: "KeyE", // put everything you need in this object.
which: 69,
shiftKey: false, // you don't need to include values
ctrlKey: false, // if you aren't going to use them.
metaKey: false // these are here for example's sake.
})
);
Tarayıcı oyunumda, simüle edilmiş tuş takımına sahip mobil cihazları desteklemek için kullandım.
Açıklama: Bu kod tek bir keydown
olay gönderirken , gerçek bir tuşa basma bir keydown
olayı (veya daha uzun süre basılı tutulursa birkaçını) ve daha sonra keyup
bu tuşu bıraktığınızda bir olayı tetikler . Eğer gerekiyorsa keyup
da olayları, simüle etmek de mümkündür keyup
değiştirerek olayları "keydown"
için "keyup"
kod parçacığının.
Bu, etkinliği tüm web sayfasına da gönderir document
. Yalnızca belirli bir öğenin etkinliği almasını istiyorsanız document
, istediğiniz öğenin yerine geçebilirsiniz .
Trusted
?)
Bu yaklaşım, tarayıcılar arası anahtar kodunun değerini değiştirmeyi destekler . Kaynak
var $textBox = $("#myTextBox");
var press = jQuery.Event("keypress");
press.altGraphKey = false;
press.altKey = false;
press.bubbles = true;
press.cancelBubble = false;
press.cancelable = true;
press.charCode = 13;
press.clipboardData = undefined;
press.ctrlKey = false;
press.currentTarget = $textBox[0];
press.defaultPrevented = false;
press.detail = 0;
press.eventPhase = 2;
press.keyCode = 13;
press.keyIdentifier = "";
press.keyLocation = 0;
press.layerX = 0;
press.layerY = 0;
press.metaKey = false;
press.pageX = 0;
press.pageY = 0;
press.returnValue = true;
press.shiftKey = false;
press.srcElement = $textBox[0];
press.target = $textBox[0];
press.type = "keypress";
press.view = Window;
press.which = 13;
$textBox.trigger(press);
sadece CustomEvent kullanın
Node.prototype.fire=function(type,options){
var event=new CustomEvent(type);
for(var p in options){
event[p]=options[p];
}
this.dispatchEvent(event);
}
4 eski ctrl + z simüle etmek istiyorum
window.addEventListener("keyup",function(ev){
if(ev.ctrlKey && ev.keyCode === 90) console.log(ev); // or do smth
})
document.fire("keyup",{ctrlKey:true,keyCode:90,bubbles:true})
İşte size gerçekten yardımcı olan bir kütüphane: https://cdn.rawgit.com/ccampbell/mousetrap/2e5c2a8adbe80a89050aaf4e02c45f02f1cc12d4/tests/libs/key-event.js
Nereden geldiğini bilmiyorum, ama yardımcı oluyor. Bu bir ekler .simulate()
yöntemi window.KeyEvent
sadece ile kullanmak, böylece KeyEvent.simulate(0, 13)
bir taklit için enter
veya KeyEvent.simulate(81, 81)
bir için 'Q'
.
Https://github.com/ccampbell/mousetrap/tree/master/tests adresinden aldım .
Bu benim için çalıştı ve benim metinlerim için bir keyup simüle ediyor. Tüm sayfanın için istiyorum eğer sadece koymak KeySimulation()
üzerine <body>
böyle <body onmousemove="KeySimulation()">
olmadığını onmousemove
o zaman onmouseover
ya onload
eserleri de.
<script>
function KeySimulation()
{
var e = document.createEvent("KeyboardEvent");
if (e.initKeyboardEvent) { // Chrome, IE
e.initKeyboardEvent("keyup", true, true, document.defaultView, "Enter", 0, "", false, "");
} else { // FireFox
e.initKeyEvent("keyup", true, true, document.defaultView, false, false, false, false, 13, 0);
}
document.getElementById("MyTextArea").dispatchEvent(e);
}
</script>
<input type="button" onclick="KeySimulation();" value=" Key Simulation " />
<textarea id="MyTextArea" rows="15" cols="30"></textarea>
initKeyboardEvent
kaldırılmış olduğuna dikkat edin . ( Kaynak )
Bir konsol bağlamında kolay kullanım nedeniyle bir kez tek sıralıydı. Ama muhtemelen hala yararlı.
var pressthiskey = "q"/* <-- q for example */;
var e = new Event("keydown");
e.key = pressthiskey;
e.keyCode = e.key.charCodeAt(0);
e.which = e.keyCode;
e.altKey = false;
e.ctrlKey = true;
e.shiftKey = false;
e.metaKey = false;
e.bubbles = true;
document.dispatchEvent(e);
İşte Chrome ve Chromium'da çalışan bir çözüm (yalnızca bu platformları test ettiler). Görünüşe göre Chrome'un anahtar kodları ele almak için bazı hataları veya kendi yaklaşımları var, bu nedenle bu özellik KeyboardEvent'e ayrı olarak eklenmelidir.
function simulateKeydown (keycode,isCtrl,isAlt,isShift){
var e = new KeyboardEvent( "keydown", { bubbles:true, cancelable:true, char:String.fromCharCode(keycode), key:String.fromCharCode(keycode), shiftKey:isShift, ctrlKey:isCtrl, altKey:isAlt } );
Object.defineProperty(e, 'keyCode', {get : function() { return this.keyCodeVal; } });
e.keyCodeVal = keycode;
document.dispatchEvent(e);
}
Ben bulmak başardı budur:
function createKeyboardEvent(name, key, altKey, ctrlKey, shiftKey, metaKey, bubbles) {
var e = new Event(name)
e.key = key
e.keyCode = e.key.charCodeAt(0)
e.which = e.keyCode
e.altKey = altKey
e.ctrlKey = ctrlKey
e.shiftKey = shiftKey
e.metaKey = metaKey
e.bubbles = bubbles
return e
}
var name = 'keydown'
var key = 'a'
var event = createKeyboardEvent(name, key, false, false, false, false, true)
document.addEventListener(name, () => {})
document.dispatchEvent(event)
TypeScript destekli çözümle yerel JavaScript:
KeyCode veya kullandığınız özelliği yazın ve KeyboardEventInit öğesine aktarın
Misal
const event = new KeyboardEvent("keydown", {
keyCode: 38,
} as KeyboardEventInit);
Chrome'da js / typescript ile denedim. İlham için bu cevap sayesinde .
const x = document.querySelector('input');
const keyboardEvent = new KeyboardEvent("keypress", { bubbles: true });
Object.defineProperty(keyboardEvent, "charCode", {
get() {
return 13;
},
});
x.dispatchEvent(keyboardEvent);
kullanıcı söz konusu tuşa basar basmaz, buna bir referans depolayabilir ve herhangi bir HTML öğesinde kullanabilirsiniz:
EnterKeyPressToEmulate<input class="lineEditInput" id="addr333_1" type="text" style="width:60%;right:0%;float:right" onkeydown="keyPressRecorder(event)"></input>
TypeHereToEmulateKeyPress<input class="lineEditInput" id="addr333_2" type="text" style="width:60%;right:0%;float:right" onkeydown="triggerKeyPressOnNextSiblingFromWithinKeyPress(event)">
Itappears Here Too<input class="lineEditInput" id="addr333_3" type="text" style="width:60%;right:0%;float:right;" onkeydown="keyPressHandler(event)">
<script>
var gZeroEvent;
function keyPressRecorder(e)
{
gZeroEvent = e;
}
function triggerKeyPressOnNextSiblingFromWithinKeyPress(TTT)
{
if(typeof(gZeroEvent) != 'undefined') {
TTT.currentTarget.nextElementSibling.dispatchEvent(gZeroEvent);
keyPressHandler(TTT);
}
}
function keyPressHandler(TTT)
{
if(typeof(gZeroEvent) != 'undefined') {
TTT.currentTarget.value+= gZeroEvent.key;
event.preventDefault();
event.stopPropagation();
}
}
</script>
kendi etkinliğinizi oluşturursanız keyCode'u ayarlayabilirsiniz, herhangi bir gerçek klavye etkinliğinden (dispatchEvent'in işinden bu yana hedefleri yoksayarak) mevcut parametreleri kopyalayabilirsiniz ve:
ta = new KeyboardEvent('keypress',{ctrlKey:true,key:'Escape'})
Sorunun, bir tuşa basmayı simüle etmenin javascript yolunu istediğini biliyorum. Ama bir şeyler yapmanın jQuery yolunu arayanlar için:
var e = jQuery.Event("keypress");
e.which = 13 //or e.keyCode = 13 that simulates an <ENTER>
$("#element_id").trigger(e);
İşe bu almanın kritik bir parçası olduğunu fark etmektir charCode
, keyCode
ve which
vardır tüm yöntemleri kaldırılmış . Bu nedenle , tuşa basma olayını işleyen kod bu üçten herhangi birini kullanıyorsa, sahte bir yanıt alır (örneğin, varsayılan 0).
Key press olayına, gibi kullanımdan kaldırılmış bir yöntemle eriştiğiniz sürece key
, TAMAM olmalısınız.
Tamamlanması için, etkinliği tetiklemek için temel Javascript kodunu ekledim:
const rightArrowKey = 39
const event = new KeyboardEvent('keydown',{'key':rightArrowKey})
document.dispatchEvent(event)
Bir 'Sekme' basını simüle etmek istedim ... Trevor'ın cevabını genişleterek, 'sekme' gibi özel bir tuşun basıldığını görebiliriz, ancak bir 'sekme' basının gerçek sonucunu göremiyoruz .. .
bu olayları 'activeElement' ve genel belge nesnesi için her ikisini de göndermeyi denedi - her ikisi için de kod eklendi;
aşağıdaki pasaj :
var element = document.getElementById("firstInput");
document.addEventListener("keydown", function(event) {
console.log('we got key:', event.key, ' keyCode:', event.keyCode, ' charCode:', event.charCode);
/* enter is pressed */
if (event.keyCode == 13) {
console.log('enter pressed:', event);
setTimeout(function() {
/* event.keyCode = 13; event.target.value += 'b'; */
theKey = 'Tab';
var e = new window.KeyboardEvent('focus', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('keydown', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('beforeinput', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('keypress', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('input', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('change', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
e = new window.KeyboardEvent('keyup', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.activeElement.dispatchEvent(e);
}, 4);
setTimeout(function() {
theKey = 'Tab';
var e = new window.KeyboardEvent('focus', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('keydown', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('beforeinput', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('keypress', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('input', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('change', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
e = new window.KeyboardEvent('keyup', {
bubbles: true,
key: theKey,
keyCode: 9,
charCode: 0,
});
document.dispatchEvent(e);
}, 100);
} else if (event.keyCode != 0) {
console.log('we got a non-enter press...: :', event.key, ' keyCode:', event.keyCode, ' charCode:', event.charCode);
}
});
<h2>convert each enter to a tab in JavaScript... check console for output</h2>
<h3>we dispatchEvents on the activeElement... and the global element as well</h3>
<input type='text' id='firstInput' />
<input type='text' id='secondInput' />
<button type="button" onclick="document.getElementById('demo').innerHTML = Date()">
Click me to display Date and Time.</button>
<p id="demo"></p>