How to have function trigger from a keypress in node? - javascript

I have a script written in javascript which does something to a drone that I have. As of now I run that script in my shell like this node foo.js and the script runs till I abort it using control C. But now I want to be able to run that script and have it listen for keyboard events that I give it (such as ENTER, up/down arrow key, spacebar), and depending on the event it performs a specific function. And when I am done I should be still able to press control C to stop the program. It would be awesome if someone could help me. I am still in highschool and very new to programming.
Here is the script for reference:
var arDrone = require('ar-drone');
var client = arDrone.createClient();
client.takeoff();
client
.after(10000, function() {
this.stop();
this.land();
});

Each keyboard key has a special key code (i.e. f = 70). You can find that here:
http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
I would use jQuery to trigger these events, the first is any keystroke:
$(function() {
$('client').keydown();
$('client').keypress();
$('client').keyup();
});
The second is specific keystrokes:
$function() {
var e = $.Event('keypress');
e.which = 39; // right arrow
$('client').trigger(e);
});
So then you would have a function called trigger that checked for specific numbers, and you would move your drone accordingly.

Related

How do I simulate human behaviour with client side javascript to play a flash game?

My intention:
Let's say you have two players, A and B, playing the same flash game embedded in their page but on two different computers.
If player A presses 'W' to jump or hits "PLAY" to jump, player B should see the same movement in their browser.
What I've already tried:
const game = document.getElementById('game');
var e = null;
game.addEventListener('keydown', (event) => {
if (event.keyCode == 37) {
console.log('Left was pressed');
} else if (event.keyCode == 39) {
console.log('Right was pressed');
};
e = event;
});
I've sent this event over to player B (using sockets)
e = // get it from player A
game.dispatchEvent(e)
This doesn't work. I believe that I need some sort of client side selenium thing so that I can simulate real keypresses onto html elements (in my case it's a flash game). However, I've failed to find one.
Is there a way to do what I want?
Basically you can create a new Event('keydown'), see this. On SO you can already see questions about programmatically induce a keyboard event, see this. However, you intend to export an event, send it and import it. You will need to implement an export, as far as I know and an import as well. But, if you manage to export the values you need correctly, then creating an event should not be very difficult.
However, I advise you to separate event handling from the functions which could be triggered by events. It is much wiser than your current approach to refactor your code, so functionalities can be executed without hack-creating an event and then you can just call your functionalities. You will need to communicate between Flash and Javascript for that purpose, see here and, you can also consider using WebSockets for better network protocol, to help in your gaming project.

Not able to shift focus to Shipment Nbr field on Shipments screen

I'm using the built in Acumatica browser commands to insert a new shipment record by pressing a function key. The function Key triggers the command with px.searchFrame(window.top,"main")['px_alls'].ds.executeCommand("Insert"); For some reason, it triggers the insert command, but it doesn't shift the focus to the Shipment Nbr input field. Also, if you try to shift the focus manually using var field=px_alls["edShipmentNbr"]; field.focus(); that doesn't work either. I've been able to shift the focus to other fields, so I know the code is correct, but I can't figure out why the focus can't be shifted to the Shipment Nbr input. Any ideas on what else can be done? It's not just the Insert command either. Calling the Cancel command, which should shift the focus, doesn't work either.
What's strange is that the Insert command can be called by pressing Ctrl+Insert, and it works perfectly.
I built some code that shifts the focus to the ship date field and then tabs backwards 5 times, which emulates correctly what the insert command should do, but it only works intermittently on the client's computer.
Thanks
The Acumatica Framework provides built-in support for keyboard shortcuts via the following properties defined in PXButtonAttribute:
ShortcutShift = true/false : Determines Shift key presence
ShortcutCtrl = true/false : Determines Control key presence
ShortcutChar = ‘x’ : Determines shortcut character
Below is the sample to insert new Shipment when the user presses F2. Since the code snippet below utilizes capabilities of the framework, by pressing F2 the user executes the Insert command from the SOShipmentEntry BLC instead of simulating button click in JavaScript. This approach guarantees that all logic embedded into the Insert command, including setting focus to the Shipment Nbr input, is properly executed.
public class SOShipmentEntryExt : PXGraphExtension<SOShipmentEntry>
{
public class PXInsertShortCut<TNode> : PXInsert<TNode>
where TNode : class, IBqlTable, new()
{
public PXInsertShortCut(PXGraph graph, string name)
: base(graph, name)
{
}
public PXInsertShortCut(PXGraph graph, Delegate handler)
: base(graph, handler)
{
}
[PXUIField(DisplayName = ActionsMessages.Insert, MapEnableRights = PXCacheRights.Insert, MapViewRights = PXCacheRights.Insert)]
[PXInsertButton(ShortcutChar = (char)113)]
protected override IEnumerable Handler(PXAdapter adapter)
{
return base.Handler(adapter);
}
}
public PXInsertShortCut<SOShipment> Insert;
}
If you're executing a callback to the server in JavaScript, the callback return might set focus to another field after it finishes execution. Your focus() statement works but the callback return performs another focus() on a different control after yours.
Hooking the Ajax callback allows you to put your focus() statement after the Acumatica framework focus():
window.addEventListener('load', function () { px_callback.addHandler(ActionCallback); });
function ActionCallback(callbackContext) {
px_alls["edShipmentNbr"].focus();
};

jquery terminal submit command without pressing enter

How can i submit a command without pressing the enter button?
I need to make the terminal recognize the speech (that part is already done) and visualize it like a command, than virtually press enter to get an ajax response, is it possible? thanks
push create new interpreter when you have new prompt and new set of commands, to execute the command you can use exec:
term.exec('command');
it will echo the command and execute your command (if you pass true as second argument it will not echo prompt and command being executed), for instancec if you have:
var term = $('...').terminal({
foo: function() {
this.echo('foo');
}
});
term.exec('foo');
will execute your foo function.
or you can simulate keydown event for enter:
var e = $.Event("keydown");
e.ctrlKey = ctrl;
e.altKey = alt;
e.shiftKey = shift;
e.which = e.keyCode = 13;
$(document.documentElement || window).trigger(e);
if you're adding text using term.insert('word'); it will be better to use key down event.
EDIT: key down event may not work with a recent version of jQuery Terminal to trigger the event with jQuery events look at Jest tests.

Inject custom function to onclick event

What I'm trying to do is to record all user activity on a given web page, so I'm using socket.io to send the events registered on the page, to the server with something like this:
$(document).on('click.mynamespace', function(event){
var elem = event.target;
socket.emit('my-message', { 'element' : elem };
}
The problem I'm facing is when the target element is a link of this kind My link. Whatever function is called and the page unloads (disconnecting my socket) before the socket.emit statement is executed properly.
I want to make this as universal as possible since this will be working as a plugin, and would like it to adjust to any kind of environment over which I will have no control.
So, is there a way to "highjack" all click events, send them first with my custom function, and then continue with the "normal" execution, whatever it may be?
EDIT
It seems only FF (tested on 14.0.1) causes the socket.emit event not to finish. Chrome 21.0.x seems to be working but not sure if this is by "chance".
EDIT 2
The function someFunctionThatRedirects actually redirects in this way window.location.ref = clickedurl
Events bubble upwards, so clicked element gets it's event fired before your socket.emit, you can change the way the functions work to make them do their actions in the order you want as follows
function someFunctionThatRedirects(){
window.redirectTo = 'myNewPage';
}
$(document).on('click.mynamespace', function(event){
var elem = $(event.target)[0];
socket.emit('my-message', { 'element' : elem };
if(window.redirectTo !== undefined) window.location.href = window.redirectTo;
}

Javascript event handling and flow control

I'm attempting to build a webpage that loads depending on the input provided. I'm having some trouble wrapping my head around event handling in javascript, basically. Coming from python, if I wanted to wait for a specific keyboard input before moving on to the next object to display, I would create a while loop and put a key listener inside it.
Python:
def getInput():
while 1:
for event in pygame.event.get(): #returns a list of events from the keyboard/mouse
if event.type == KEYDOWN:
if event.key == "enter": # for example
do function()
return
elif event.key == "up":
do function2()
continue
else: continue # for clarity
In trying to find a way to implement this in DOM/javascript, I seem to just crash the page (I assume due to the While Loop), but I presume this is because my event handling is poorly written. Also, registering event handlers with "element.onkeydown = function;" difficult for me to wrap my head around, and setInterval(foo(), interval] hasn't brought me much success.
Basically, I want a "listening" loop to do a certain behavior for key X, but to break when key Y is hit.
In JavaScript, you give up control of the main loop. The browser runs the main loop and calls back down into your code when an event or timeout/interval occurs. You have to handle the event and then return so that the browser can get on with doing other things, firing events, and so on.
So you cannot have a ‘listening’ loop. The browser does that for you, giving you the event and letting you deal with it, but once you've finished handling the event you must return. You can't fall back into a different loop. This means you can't write step-by-step procedural code; if you have state that persists between event calls you must store it, eg. in a variable.
This approach cannot work:
<input type="text" readonly="readonly" value="" id="status" />
var s= document.getElementById('status');
s.value= 'Press A now';
while (true) {
var e= eventLoop.nextKeyEvent(); // THERE IS NO SUCH THING AS THIS
if (e.which=='a')
break
}
s.value= 'Press Y or N';
while (true) {
var e= eventLoop.nextKeyEvent();
if (e.which=='y') ...
Step-by-step code has to be turned inside out so that the browser calls down to you, instead of you calling up to the browser:
var state= 0;
function keypressed(event) {
var key= String.fromCharCode(event? event.which : window.event.keyCode); // IE compatibility
switch (state) {
case 0:
if (key=='a') {
s.value= 'Press Y or N';
state++;
}
break;
case 1:
if (key=='y') ...
break;
}
}
s.value= 'Press A now';
document.onkeypress= keypressed;
You can also make code look a little more linear and clean up some of the state stuff by using nested anonymous functions:
s.value= 'Press A now';
document.onkeypress= function(event) {
var key= String.fromCharCode(event? event.which : window.event.keyCode);
if (key=='a') {
s.value= 'Press Y or N';
document.onkeypress= function(event) {
var key= String.fromCharCode(event? event.which : window.event.keyCode);
if (key=='y') ...
};
}
};
you should not use such loops in javascript. basically you do not want to block the browser from doing its job. Thus you work with events (onkeyup/down).
also instead of a loop you should use setTimeout if you want to wait a little and continue if something happened
you can do sth like that:
<html>
<script>
var dataToLoad = new Array('data1', 'data2', 'data3' );
var pos = 0;
function continueData(ev) {
// do whatever checks you need about key
var ele = document.getElementById("mydata");
if (pos < dataToLoad.length)
{
ele.appendChild(document.createTextNode(dataToLoad[pos]));
pos++;
}
}
</script>
<body onkeyup="continueData()"><div id="mydata"></div></body></html>
everytime a key is released the next data field is appended
For easier implementation of event handling I recommend you to use a library such as Prototype or Jquery (Note that both links take you to their respective Event handling documentation.
In order to use them you have to keep in mind 3 things:
What DOM element you want to observe
What Event you want to capture
What action will the event trigger
This three points are mutually inclusive, meaning you need to take care of the 3 when writing the code.
So having this in mind, using Prototype, you could do this:
Event.observe($('id_of_the_element_to_observe'), 'keypress', function(ev) {
// the argument ev is the event object that has some useful information such
// as which keycode was pressed.
code_to_run;
});
Here is the code of a more useful example, a CharacterCounter (such as the one found in Twitter, but surely a lot less reliable ;) ):
var CharacterCounter = Class.create({
initialize: function(input, counter, max_chars) {
this.input = input;
this.counter = counter;
this.max_chars = max_chars;
Event.observe(this.input, 'keypress', this.keyPressHandler.bind(this));
Event.observe(this.input, 'keyup', this.keyUpHandler.bind(this));
},
keyUpHandler: function() {
words_left = this.max_chars - $F(this.input).length;
this.counter.innerHTML = words_left;
},
keyPressHandler: function(e) {
words_left = this.max_chars - $F(this.input).length;
if (words_left <= 0 && this.allowedChars(e.keyCode)) {
e.stop();
}
},
allowedChars: function(keycode) {
// 8: backspace, 37-40: arrow keys, 46: delete
allowed_keycodes = [ 8, 37, 38, 39, 40, 46 ];
if (allowed_keycodes.include(keycode)) {
return false;
}
return true
}
});
Any good browser will crash when it encounters a script that runs too long. This is to prevent malicious websites from locking up the client application.
You cannot have a infinite loop in javascript. Instead, attach an event listener to the window and point do your processing in the handler (think of it as interrupts instead of polling).
Example:
function addEventSimple(obj,evt,fn) {
if (obj.addEventListener)
obj.addEventListener(evt,fn,false);
else if (obj.attachEvent)
obj.attachEvent('on'+evt,fn);
} // method pulled from quirksmode.org for cross-browser compatibility
addEventSimple(window, "keydown", function(e) {
// check keys
});
document.onkeydown = function(e) {
//do what you need to do
}
That's all it takes in javascript. You don't need to loop to wait for the event to happen, whenever the event occurs that function will be called, which in turn can call other functions, do whatever needs to be be done. Think of it as that instead of you having to wait for the event your looking for to happen, the event your looking for will let you know when it happens.
you could attach an event listener to the window object like this
window.captureEvents(Event.KEYPRESS);
window.onkeypress = output;
function output(event) {
alert("you pressed" + event.which);
}
Check out the YUI key listener
http://developer.yahoo.com/yui/docs/YAHOO.util.KeyListener.html
using the key listener, YUI takes care of capturing any events. IN javascript, there will almost never be an instance where you must wait in a while loop for something to happen.
If you need examples of how event handling works, check out these pages.
http://developer.yahoo.com/yui/examples/event/eventsimple.html

Categories