-1

I don't have a lot of hope for this one, but I have to ask. I am hoping, for didactic purposes, to come up with some means by which a student could load a simple javascript program into a browser, and have it interact with them in the old-fashioned command line manner, where it prints a line and then reads a line of input. This works fine if you use prompt(), but the fact that it creates popups is aesthetically annoying, and today's browsers cheerfully volunteer to stifle the scripts which overuse it. The problem is, prompt() appears to be the only way browser Javascript has of actually pausing a script to wait for input. If we avoid it, that throws us immediately into having to deal with a real-time GUI event input model.

I've been looking for a way to fake it -- to set up some kind of environment in which it is possible for a Javascript method to wait for input and then return when it's given. The best possibility I've got so far is to connect it to a Java applet, but the java applet brand is kind of poisoned now and I doubt people would want to install the plugin. Could there be another way? Worker threads? A browser add-on? Some server-side trick? Does anyone have an idea?


This question is now years old... I wonder if the addition of promises and async/await to Javascript makes this any more possible now?

...I sort of got it to work. If the read-eval-print loop is in an async function and uses await for the line that reads input, you can indeed make an old fashioned linear read-eval-print loop in an event-driven browser environment. But I don't think you can make the main thread wait on input without an async function, except with the grandfathered prompt method (which they're now getting ready to deprecate).

Paul Kienitz
  • 878
  • 6
  • 25
  • Er... Also `alert()` pauses it for a while. And `confirm()` too. Well, even I am searching for a solution similar to this. – Praveen Kumar Purushothaman Apr 24 '16 at 19:41
  • 1
    This may be a duplicate, but that linked question really has nothing at all to do with this one. Note that a real CLI program on, say, Linux probably doesn't use `sleep()` at all - it just uses blocking synchronous IO. A good answer to this question would involve a description of some sort of input mechanism and event handling. Plenty of interactive help desk chat tools already do this stuff. – Pointy Apr 24 '16 at 19:48
  • 3
    In browser JavaScript, "wait for input" means "wait for an event to happen". – Pointy Apr 24 '16 at 19:49
  • If you want to make a client-side webpage to teach students about using a shell, you'd have to write some kind of emulator (lots of work). If you want to teach students _JavaScript_, do it vanilla or using a major framework, inventing your own synchronous input thing will mean they're totally lost when it comes to writing code in the real world. – Paul S. Apr 24 '16 at 20:05
  • In browser JavaScript, "wait for input" means "wait for an event to happen" ........ except with prompt() and confirm(), which stick out as blatant exceptions. Obviously they got grandfathered in and wouldn't be included if Javascript were being invented today. But they are there. I'm just wishing there was some way to either extend or modify that capability. Could a Firefox extension change their behavior? – Paul Kienitz Apr 24 '16 at 22:21
  • 1
    How about Nodejs? That's javascript in the command line, and a very simple install. – Dylan Apr 24 '16 at 22:25
  • I think this might be a possible duplicate of http://stackoverflow.com/questions/17437147/javascript-prompt-alternative – Akshat Mahajan Apr 24 '16 at 22:41
  • Synchronous IO is not something that is natural or built into any machine architecture that I know of, which are all interrupt-driven at the lowest levels (the equivalent of a HW-generated "event"). To implement the otherwise almost universal experience of synchronous IO, the operating systems (+drivers, RTLs, and/or compilers) implement the notion of coroutines under the hood. If I were to try to implement what you are requesting in JS, I would probably try to use one of the JS Coroutine libraries, such as the one described here: https://medium.com/@dashron/coroutines-2cd5c41c088a – RBarryYoung May 04 '21 at 16:31

1 Answers1

4

The technical term for what you want is a REPL: a Read-Evaluate-Print-Loop. There are many REPLs out there.

The Best Browser-Based Solution

Use Google Chrome's inbuilt console! It's a Javascript REPL that can also let you interact with a web page. You can access it by using Ctrl+Shift+I on Windows and Unix inside Chrome, or the equivalent command on a Mac (Google it!).

enter image description here

To load a file and play with it, all your students need to do is create a directory structure like this:

project
|--> index.html
|--> javascript.js

make sure index.html has a script tag that points to javascript.js, and then open index.html with Chrome. Voila! You have loaded a Javascript file, and can now play around with it in Chrome.

It's the best solution because you get the full power of the DOM, can do REPL stuff, and is virtually painless - everyone uses Chrome, and your students can even go home and mess around with it completely.

A Browser-Based Alternative

Rather than reinvent the wheel, you can also use Repl.it.

It's a browser-based Javascript REPL website that supports inserting an arbitrary Javascript program, and interacting with its contents. This is the closest you'll probably get to meeting your requirements - it'll be unable to interact with the DOM (obviously), but it'll more than work.

enter image description here

Non-Browser-Based Alternative

If the requirement for a web-based solution can be relaxed, simply using Node.js' inbuilt REPL on a terminal can be more than sufficient.

You could install Node on your lab's computers, and have people play with Javascript in that capacity. There'll be no DOM, but you could certainly have them write functions and algorithms to solve simple problems. Plus, it'd be a good way to introduce them to the fact that Javascript is no longer client-side-bound.

The fact that you'll be interacting with Javascript in an actual terminal, rather than an emulated one in the browser, is another neat bonus.

If I've Misunderstood...

Some of the question comments make it sound like you want a way to be able to interact with terminal utilities using Javascript from a browser. If that is the case, this is impossible.

There is no way for Javascript to evaluate, parse or do anything on the command line that isn't written using Javascript. You cannot expect the equivalent of a bash ls using a browser-based solution - that's because browsers don't have access to your underlying filesystem, which is a good thing. You cannot run sed, awk, grep, etc. for the same reason - Unix utilities are inaccessible to a browser. There are ways to run Unix utilities using Node, of course, but then you will be teaching them how to use Node, rather than how to play with the Unix console.

If all you want, however, is a way to SSH from a browser into a common environment, there are certainly browser-based ways to do that. FireSSH is a Firefox plugin (now also ported to Chrome) that lets people SSH into a common server. They can then do ls, vim, etc. and have it run in the server, with the results piped back to their browser screen. You'll have to think carefully about security in this case, of course, but I think simply giving people user permissions for this server should more than suffice.

Note that FireSSH doesn't use Javascript to parse or do anything - all it is doing is relaying commands you type to a server, having the server execute those commands remotely, and then piping the results back to your screen.

Alternatives to Prompt

I added this after understanding OP's requirements in more detail.

This is a question that has been asked before. I am fond of library solutions, and in 2013, iocream.js was developed for just this sort of browser functionality. You can embed it in a page, and use the jin function to assign values.

If going with a Node.js solution, by far the best approach is to make use of the prompt library. I personally find it very useful for embedding within Node.js applications.

SpiderMonkey is Mozilla's C++-based Javascript engine, and supports a function called readline(). Unfortunately, there doesn't appear to be a mainstream browser implementation.

shaedrich
  • 5,457
  • 3
  • 26
  • 42
Akshat Mahajan
  • 9,543
  • 4
  • 35
  • 44
  • Thank you for a thorough coverage of the subject. I guess there's more out there than I realized. I did look at the Chrome console, and it's close, in that you can type in javascript expressions and stuff... but I have not seen a way for a script to read a line from the console as input, and then continue on the next line once input is received. Can it do that? Can repl.it do that? – Paul Kienitz Apr 24 '16 at 22:15
  • 1
    Not with Chrome, sadly, or even REPL.it. However, SpiderMonkey can: http://stackoverflow.com/questions/16307415/take-user-input-with-javascript-in-the-console Unfortunately, SpiderMonkey doesn't have a mainstream console implementation (you can consult [Wiki](https://en.wikipedia.org/wiki/SpiderMonkey), however). You can still use `prompt()` in REPL.it, though, and with Chrome it makes sense. – Akshat Mahajan Apr 24 '16 at 22:34
  • @PaulKienitz Only Node.js offers this type of functionality, but it certainly isn't browser-based. Good news is that there is an open-source project to let you accomplish just that: [web-terminal](https://www.npmjs.com/package/web-terminal). In conjunction with the NPM library [prompt](https://github.com/flatiron/prompt), you can get a fair bit of functionality. – Akshat Mahajan Apr 24 '16 at 22:37
  • 1
    @PaulKienitz I take back my last comment. It appears this question has been asked before [here](http://stackoverflow.com/questions/17437147/javascript-prompt-alternative), and people have found satisfactory answers. – Akshat Mahajan Apr 24 '16 at 22:41
  • 1
    @PaulKienitz You can use Chrome in conjunction with a third party library called iocream.js to accomplish a prompt feature in conjunction with a REPL. I think that should more than solve your problem :) and this is the option I would recommend. – Akshat Mahajan Apr 24 '16 at 22:48
  • Ah well, iocream is a noble effort, but it can't get around the fundamentally asynchronous nature of input. – Paul Kienitz Apr 26 '16 at 04:12
  • @PaulKienitz Not quite sure I follow. iocream mimics a C++ input stream - calling `jin` should allow it to read from the command line when inside a REPL. Is this not what happens? – Akshat Mahajan Apr 26 '16 at 04:35
  • The whole point of the question is to see if there's a way to perform input in a way that doesn't involve introducing asynchronous control flow. If it can't do that, there's no point in using any of the rest. – Paul Kienitz Apr 26 '16 at 06:26