问题
I want to change the Sk.inputfun()
for Skulpt to let the user type in a <textarea>
and hit the ENTER
key to submit. I need to pass in a single function to Skulpt that gets user input, however, I can't find any way to do this other than prompt()
.
The only way I could think to do this was to delay the return using setTimeout()
until an event triggered the enter key button and changed a flag.
var enterPressed = false;
$("#output").keyup(function(e){
if((e.keyCode || e.which) == 13) { //Enter keycode
enterPressed = true;
}
});
and then to wait for the change I had:
Sk.configure({
inputfun: function (prompt) {
function checkFlag() {
if(enterPressed) {
enterPressed = false
return $('#output').val();
} else {
window.setTimeout(checkFlag, 100);
}
}
return checkFlag();
},
inputfunTakesPrompt: true,
output: outf,
read: builtinRead
});
However this dosen't work for a few reasons. a) The timeout function can't return a value, and b) Timeout dosen't even delay the return function, and it simply returns nothing.
I have tried using .done()
as well, but couldn't get it to work.
There doesn't seem to be any way to do this that I could find online, any help would be much appreciated!
回答1:
You need to return a Promise from your inputfun, which you then resolve when return gets pressed. (If you're not familiar with Promises, they are well worth a look - <grossSimplification>they let you write asynchronous code using synchronous logic</grossSimplification>).
Something like this (using your code as a base):
Sk.configure({
inputfun: function () {
// the function returns a promise to give a result back later...
return new Promise(function(resolve,reject){
$("#input").on("keyup",function(e){
if (e.keyCode == 13)
{
// remove keyup handler from #output
$("#input").off("keyup");
// resolve the promise with the value of the input field
resolve($("#input").val());
}
})
})
},
output: outf,
read: builtinRead
});
I've assumed an input element with an ID of input is receiving stdin. Looking at your OP, you were talking about a textarea (although JQuery .val() should work fine on this). On the basis of what you've called your textarea ("output") it seems that your intention was for both stdin and stdout to involve a shared textarea. If so, I'm not sure how you're going to be able to distinguish between what's been generated by stdin and what's been (subsequently) entered by the user. Thus the code above assumes a separate input field.
I had a similar use case to you, and the way I gave the illusion of an integrated console for both stdin and stdout was to have a span with contenteditable at the end of my output div. On keycode == 13, before I resolved the promise and sent back what the user had typed, I took the text out of the input span and appended it to the output div.
来源:https://stackoverflow.com/questions/43733896/wait-for-an-event-to-occur-within-a-function-in-javascript-for-skulpt