Tuesday 14 May 2013

A shell/dos style input in HTML


A return to text input.

It could be said I have had a little bit of a hobby in attempting to get a satisfying command line input for text entry for a html page. This is probably quite simple for some one with more html/css/jquery skills than me.

The history of this is at some point in the past I wanted to create a very simple web based text adventure. Just for fun. I think I spent more time working on the text input than I did on any other component.

I think I have arrived at a fairly minimal solution that works on Firefox, chrome and IE9 (and probably above). It is very simple and that make me happy.

Ok lets loot at the html code for it

<!doctype html>
<html>
  <head>
    <script src='jquery-2.0.0.min.js' ></script>
    <script src='main.js' ></script>
    <style>
      .main-area {
        width:25em;
        height:500px;
        background-color:#333;
        color:#ccc;
        margin: auto;
        overflow-y:hidden;

      }
      .main-area .line {
        margin-left:1em;
      }
      .main-area .input {
        margin-left:0.3em;
        margin-bottom:0.1em;
      }
      .main-area .input div {
        display:inline;
      }
      .main-area .input .prompt {
        width:1em;
      }
      .main-area .input input {
        background-color:#333;
        color:#ccc;
        border:none;
        width:24em;
      }
    </style>
  </head>
  <body>
    <div class='main-area'>
      <div class='input' > <div class='prompt'>&gt</div> <div class='input-area'><input type=text></input></div> </div>
    </div>    
  </body>
</html>

I am using JQuery 2, you can probably use an earlier version but I have not tested it.

In a real application you tend to not inline your css but I was just playing so found it easier. Most of the css is just setting up some colors and nice margins along with getting stuff centered on the page.

The actual html just specifies a main-area where the text will be output and inside that the input area, the bit where you type.

The input area just has a > symbol to hint this is where you type and a text input box.

We power this very simple html code using Coffeescript. Here it is.

# Coffee file

# Handles user input
class TextInput
  constructor: (@callback) ->
    @input = $('.main-area .input input')
    @focus()
    scrollToBottom()
    @input.keydown (evt) =>
      if evt.keyCode == 13 #return pressed
        callback @input.val()
        @input.val("")

  focus: () ->
    @input.focus()

scrollToBottom = () ->
  $(".main-area").animate({ scrollTop: $('.main-area')[0].scrollHeight}, 1000)

$ ->
  echo = (enteredText) ->
    output = "
You typed: #{enteredText}
" $('.main-area .input').before output scrollToBottom() input = new TextInput(echo) # Refocus if user click on play area. $('.main-area').click () => input.focus()


About 30 lines including comments. The TextInput class monitors your keystrokes on the input line and calls a callback when you press return. My example callback just adds a line the text output and triggers a scroll to the bottom of the dislay area. This is important to keep the text input line shown.

Finally whenever the user clicks in the main-area the text input gets focus. This makes it look more like a single window like a shell/dos prompt and is handled in the last two lines of code.

I quite like this solution mostly because it is very simple and I really like simple. It does keep on adding elements into the main-area div tag so if you spent all week typing away in it it would use a lot of memory. Remove the first div tag  contain a line when you add a new line if you have say over 200 of them is pretty simple.

There are no scroll bars and that may be a show killer. I am pretty sure something like iscroll would sort you out here.

Finally some people prefer to keep the text input at the bottom of the main-area. I kind of like it moving down the screen as it fills with input but my views change from week to week.

Hopefully you might find this useful.

No comments:

Post a Comment