Add websocket client
This commit is contained in:
		@@ -62,7 +62,15 @@ $(document).ready(function() {
 | 
			
		||||
				var predicted = predictDestination(new THREE.Vector3(Number($('#x').val()),Number($('#y').val()),Number($('#z').val())),new THREE.Vector2(Number($('#azmuth').val()),Number($('#inclination').val())),$('#intel_frame option:selected').val());
 | 
			
		||||
				$('#intel_predicted').html(predicted);
 | 
			
		||||
		});
 | 
			
		||||
  
 | 
			
		||||
		$('#client-bar-control').click(function() {
 | 
			
		||||
			$('#client-term-container').toggleClass("hidden");
 | 
			
		||||
			$('#client-ico-down').toggleClass("hidden");
 | 
			
		||||
			$('#client-ico-up').toggleClass("hidden");
 | 
			
		||||
		});
 | 
			
		||||
		$('#client-login').click(function() { reconnect();})
 | 
			
		||||
 | 
			
		||||
		startup();
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										561
									
								
								js/local.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										561
									
								
								js/local.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,561 @@
 | 
			
		||||
// A Simple WSClient for PennMUSH
 | 
			
		||||
// -grapenut
 | 
			
		||||
 | 
			
		||||
var defaultHost = "ats.trekmush.org";
 | 
			
		||||
var defaultPort = '1701';
 | 
			
		||||
 | 
			
		||||
// pre-define the connection object, later it will be set to
 | 
			
		||||
// conn = WSClient.open('ws://host:port/wsclient')
 | 
			
		||||
var conn = null;
 | 
			
		||||
 | 
			
		||||
// user information
 | 
			
		||||
var login = document.getElementById('client-login');
 | 
			
		||||
var username = document.getElementById('username');
 | 
			
		||||
var password = document.getElementById('password');
 | 
			
		||||
 | 
			
		||||
// terminal is the container for output, cmdprompt, quicklinks and the entry box.
 | 
			
		||||
var terminal = document.getElementById('client-term');
 | 
			
		||||
 | 
			
		||||
// the main terminal output window
 | 
			
		||||
var output = WSClient.output(document.getElementById('client-term-output'));
 | 
			
		||||
 | 
			
		||||
// update the command prompt without modifying the main output
 | 
			
		||||
var cmdprompt = WSClient.output(document.getElementById('client-term-prompt'));
 | 
			
		||||
 | 
			
		||||
// clickable command links that do some common tasks (who, look, @mail, etc)
 | 
			
		||||
var quicklinks = document.getElementById('quicklinks');
 | 
			
		||||
 | 
			
		||||
// the user input box
 | 
			
		||||
var entry = WSClient.input(document.getElementById('client-term-entry'));
 | 
			
		||||
 | 
			
		||||
// settings popup and the different configuration options
 | 
			
		||||
/*var settingsContainer = document.getElementById('settings-container');
 | 
			
		||||
var settingsForm = document.getElementById('settings');
 | 
			
		||||
var fontSelect = document.getElementById('fontSelect');
 | 
			
		||||
var fontSize = document.getElementById('fontSize');
 | 
			
		||||
var fontBold = document.getElementById('fontBold');
 | 
			
		||||
var forceSSL = document.getElementById('forceSSL');
 | 
			
		||||
var keepAliveTime = document.getElementById('keepAliveTime');
 | 
			
		||||
var keepAliveLabel = document.getElementById('keepAliveLabel');
 | 
			
		||||
*/
 | 
			
		||||
// info window (show the credits)
 | 
			
		||||
//var infoContainer = document.getElementById('info-container');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***********************************************/
 | 
			
		||||
/**  Body  **/
 | 
			
		||||
 | 
			
		||||
// called by body.onLoad
 | 
			
		||||
function startup() {
 | 
			
		||||
  // load browser cookie and parse settings
 | 
			
		||||
  //settings.load();
 | 
			
		||||
 | 
			
		||||
  // set the initial screen dimensions (use for multi-window output)
 | 
			
		||||
//  terminal.style.left = settings.SCREEN_LEFT + 'em';
 | 
			
		||||
//  terminal.style.right = settings.SCREEN_RIGHT + 'em';
 | 
			
		||||
 | 
			
		||||
//  terminal.style.top = settings.SCREEN_TOP + 'em';
 | 
			
		||||
//  terminal.style.bottom = settings.SCREEN_BOT + 'em';
 | 
			
		||||
 | 
			
		||||
  // set some obvious ChangeMe values if there are none saved
 | 
			
		||||
//  if (username.value === '') {
 | 
			
		||||
//    username.value = 'Username';
 | 
			
		||||
//  }
 | 
			
		||||
/*
 | 
			
		||||
  if (password.value === '') {
 | 
			
		||||
    password.value = 'Password';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // autoconnect, if desired
 | 
			
		||||
  settings.autoConnect.val && reconnect();
 | 
			
		||||
*/
 | 
			
		||||
  // start the keepalive loop
 | 
			
		||||
  keepalive();
 | 
			
		||||
 | 
			
		||||
  // set focus on the input box
 | 
			
		||||
  //refocus();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// called by body.onUnload
 | 
			
		||||
function shutdown() {
 | 
			
		||||
  // if we have an active connection,
 | 
			
		||||
  // send a QUIT command and exit gracefully
 | 
			
		||||
  if (conn && conn.socket.readyState === 1) {
 | 
			
		||||
    conn.sendText('QUIT');
 | 
			
		||||
    setTimeout(conn.close, 1000);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  conn = null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***********************************************/
 | 
			
		||||
/**  Callbacks  **/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// the user pressed enter
 | 
			
		||||
entry.onEnter = function(cmd) {
 | 
			
		||||
  // detect whether we have an overlay showing and close it
 | 
			
		||||
/*  if (settingsContainer.style.visibility === 'visible') {
 | 
			
		||||
    settings.save();
 | 
			
		||||
  } else if (infoContainer.style.visibility === 'visible') {
 | 
			
		||||
    infoContainer.style.visibility = 'hidden';
 | 
			
		||||
  } else { */
 | 
			
		||||
    // no overlay, submit user input
 | 
			
		||||
    if (conn && conn.socket.readyState === 1) {
 | 
			
		||||
      // send current user input to the MUSH
 | 
			
		||||
      conn.sendText(cmd);
 | 
			
		||||
 | 
			
		||||
      // and echo to the terminal
 | 
			
		||||
      settings.localEcho.val && msg(cmd);
 | 
			
		||||
    } else {
 | 
			
		||||
      // auto-reconnect if the connection was lost
 | 
			
		||||
      settings.autoReConnect.val && reconnect();
 | 
			
		||||
    }
 | 
			
		||||
  //}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// the user pressed escape
 | 
			
		||||
/* entry.onEscape = function() {
 | 
			
		||||
  toggle_overlays();
 | 
			
		||||
}; */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* settingsForm.onsubmit = function () {
 | 
			
		||||
  settings.save();
 | 
			
		||||
 | 
			
		||||
  entry.focus();
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}; */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
settingsForm.onkeydown = function(e) {
 | 
			
		||||
  var code = (e.keyCode ? e.keyCode : e.which);
 | 
			
		||||
 | 
			
		||||
  if (code == 27) {
 | 
			
		||||
    // escape pressed, toggle form input and delete command elements
 | 
			
		||||
    toggle_overlay();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// automatically update port +/- 1 when forceSSL is changed
 | 
			
		||||
// 4201 -> 4202 with ssl
 | 
			
		||||
// this maybe is a bit awkward, but I didn't come up with a better idea
 | 
			
		||||
/*forceSSL.onchange = function() {
 | 
			
		||||
  if (forceSSL.checked) {
 | 
			
		||||
    serverPort.value = parseInt(serverPort.value) + 1;
 | 
			
		||||
  } else {
 | 
			
		||||
    serverPort.value = parseInt(serverPort.value) - 1;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
// close the info window on any key press
 | 
			
		||||
infoContainer.onkeydown = function(e) {
 | 
			
		||||
  var code = (e.keyCode ? e.keyCode : e.which);
 | 
			
		||||
 | 
			
		||||
  toggle_overlay();
 | 
			
		||||
};
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***********************************************/
 | 
			
		||||
/**  Focus  **/
 | 
			
		||||
 | 
			
		||||
// put focus back on the user input box
 | 
			
		||||
// unless it's in another input box (e.g. username/password/settings)
 | 
			
		||||
function refocus() {
 | 
			
		||||
  if (((window.getSelection == "undefined") ||
 | 
			
		||||
       (window.getSelection() == "")) &&
 | 
			
		||||
      ((document.getSelection == "undefined") ||
 | 
			
		||||
       (document.getSelection() == "")) &&
 | 
			
		||||
     !((document.activeElement.tagName === "INPUT") &&
 | 
			
		||||
       (document.activeElement.type.search(/image/gi) === -1)))
 | 
			
		||||
  {
 | 
			
		||||
    entry.focus();
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// move the input cursor to the end of the input elements current text
 | 
			
		||||
function move_cursor_to_end(el) {
 | 
			
		||||
  if (typeof el.selectionStart == "number") {
 | 
			
		||||
      el.selectionStart = el.selectionEnd = el.value.length;
 | 
			
		||||
  } else if (typeof el.createTextRange != "undefined") {
 | 
			
		||||
      el.focus();
 | 
			
		||||
      var range = el.createTextRange();
 | 
			
		||||
      range.collapse(false);
 | 
			
		||||
      range.select();
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
// close anything that may be showing or bring up the settings
 | 
			
		||||
function toggle_overlay() {
 | 
			
		||||
  if (settingsContainer.style.visibility === 'visible') {
 | 
			
		||||
    settings.show();
 | 
			
		||||
    settings.reconfigure();
 | 
			
		||||
  } else if (infoContainer.style.visibility === 'visible') {
 | 
			
		||||
    infoContainer.style.visibility = 'hidden';
 | 
			
		||||
  } else {
 | 
			
		||||
    // no overlay, bring up settings
 | 
			
		||||
    settings.show();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  entry.focus();
 | 
			
		||||
};
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***********************************************/
 | 
			
		||||
/**  Terminal  **/
 | 
			
		||||
 | 
			
		||||
// send a log message to the terminal output
 | 
			
		||||
function msg(data) {
 | 
			
		||||
  output.appendMessage('logMessage', data);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function xch_cmd(command) {
 | 
			
		||||
  output.onCommand(command);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// execute pueblo command
 | 
			
		||||
// a '??' token in command will be replaced with user input
 | 
			
		||||
output.onCommand = function (command) {
 | 
			
		||||
  var cmd = WSClient.parseCommand(command);
 | 
			
		||||
 | 
			
		||||
  // send the parsed command to the MUSH
 | 
			
		||||
  conn && conn.sendText(cmd);
 | 
			
		||||
  settings.localEcho.val && msg(cmd);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// clear the child elements from any element (like the output window)
 | 
			
		||||
function clearscreen () {
 | 
			
		||||
  output.clear();
 | 
			
		||||
  cmdprompt.clear();
 | 
			
		||||
  entry.clear();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// keepalive function continually calls itself and sends the IDLE command
 | 
			
		||||
function keepalive () {
 | 
			
		||||
  conn && settings.keepAlive.val && conn.sendText("IDLE");
 | 
			
		||||
  setTimeout(keepalive, settings.keepAliveTime.val*1000.0);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// connect or reconnect to the MUSH
 | 
			
		||||
function reconnect() {
 | 
			
		||||
 | 
			
		||||
  // we can't do websockets, redirect to 505
 | 
			
		||||
  if (!window.WebSocket){
 | 
			
		||||
    window.location.replace("/505.htm");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  entry.focus();
 | 
			
		||||
 | 
			
		||||
  // clean up the old connection gracefully
 | 
			
		||||
  if (conn) {
 | 
			
		||||
    var old = conn;
 | 
			
		||||
    old.sendText('QUIT');
 | 
			
		||||
    setTimeout(function () { old.close(); }, 1000);
 | 
			
		||||
    conn = null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  msg('%% Reconnecting to server...\r\n');
 | 
			
		||||
 | 
			
		||||
  // detect whether to use SSL or not
 | 
			
		||||
  var proto = ((window.location.protocol == "https:") || settings.forceSSL.val) ? 'wss://' : 'ws://';
 | 
			
		||||
 | 
			
		||||
  // open a new connection to ws://host:port/wsclient
 | 
			
		||||
  conn = WSClient.connect(proto + settings.serverAddress.val + ":" + settings.serverPort.val + '/wsclient');
 | 
			
		||||
 | 
			
		||||
  // auto-login if username and password are not the default values
 | 
			
		||||
  conn.onOpen = function (text) {
 | 
			
		||||
    msg("%% Connected.");
 | 
			
		||||
//    if (username.value.toUpperCase() !== "USERNAME" && username.value !== "") {
 | 
			
		||||
  //    setTimeout(function () {
 | 
			
		||||
//        conn.sendText('connect "' + username.value + '" ' + password.value);
 | 
			
		||||
//      }, 4000);
 | 
			
		||||
    //}
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // send a log message if there is a connection error
 | 
			
		||||
  conn.onError = function (evt) {
 | 
			
		||||
    msg("%% Connection error!");
 | 
			
		||||
    console.log('error', evt);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // send a log message when connection closed
 | 
			
		||||
  conn.onClose = function (evt) {
 | 
			
		||||
    msg("%% Connection closed.");
 | 
			
		||||
    console.log('close', evt);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // handle incoming plain text
 | 
			
		||||
  // this will parse ansi color codes, but won't render untrusted HTML
 | 
			
		||||
  conn.onText = function (text) {
 | 
			
		||||
    var reg = /^FugueEdit > /;
 | 
			
		||||
 | 
			
		||||
    // detect if we are capturing a FugueEdit string
 | 
			
		||||
    if (text.search(reg) !== -1) {
 | 
			
		||||
      // replace the user input with text, sans the FugueEdit bit
 | 
			
		||||
      entry.value = text.replace(reg, "");
 | 
			
		||||
    } else {
 | 
			
		||||
      // append text to the output window
 | 
			
		||||
      output.appendText(text);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // handle incoming JSON object
 | 
			
		||||
  conn.onObject = function (obj) {
 | 
			
		||||
    // just send a log message
 | 
			
		||||
    // could use this for lots of neat stuff
 | 
			
		||||
    // maps, huds, combat logs in a separate window
 | 
			
		||||
    console.log('object', obj);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // handle incoming HTML from the MUSH
 | 
			
		||||
  // it's already been encoded and trusted by the MUSH
 | 
			
		||||
  conn.onHTML = function (fragment) {
 | 
			
		||||
    // just append it to the terminal output
 | 
			
		||||
    output.appendHTML(fragment);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // handle incoming pueblo tags
 | 
			
		||||
  // currently implements xch_cmd and xch_hint
 | 
			
		||||
  conn.onPueblo = function (tag, attrs) {
 | 
			
		||||
    // just append it to the terminal output
 | 
			
		||||
    output.appendPueblo(tag, attrs);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // handle incoming command prompt
 | 
			
		||||
  conn.onPrompt = function (text) {
 | 
			
		||||
    // replace anything in cmdprompt with text
 | 
			
		||||
    // cmdprompt is an emulated terminal, so use appendText() to get ansi parsed
 | 
			
		||||
    cmdprompt.root.innerHTML = '';
 | 
			
		||||
    cmdprompt.appendText(text + '\r\n');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***********************************************/
 | 
			
		||||
/**  Settings  **/
 | 
			
		||||
 | 
			
		||||
var SettingsClass = (function (window, document, undefined) {
 | 
			
		||||
 | 
			
		||||
  this.localEcho = {val: true};
 | 
			
		||||
  this.autoConnect = {val: true};
 | 
			
		||||
  this.autoReConnect = {val: true};
 | 
			
		||||
  this.numInputLines = {val: 3};
 | 
			
		||||
  this.serverAddress = {val: defaultHost};
 | 
			
		||||
  this.serverPort = {val: defaultPort};
 | 
			
		||||
  this.forceSSL = {val: false};
 | 
			
		||||
  this.keepAlive = {val: true};
 | 
			
		||||
  this.keepAliveTime = {val: 600};
 | 
			
		||||
  this.fontSelect = {val: "Courier New"};
 | 
			
		||||
  this.fontSize = {val: 10};
 | 
			
		||||
  this.fontBold = {val: false};
 | 
			
		||||
 | 
			
		||||
  this.SCREEN_TOP = 3;
 | 
			
		||||
  this.SCREEN_BOT = 3;
 | 
			
		||||
  this.SCREEN_LEFT = 3;
 | 
			
		||||
  this.SCREEN_RIGHT = 3;
 | 
			
		||||
 | 
			
		||||
  this.doc = document;
 | 
			
		||||
 | 
			
		||||
//  settingsContainer.style.visibility = 'hidden';
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  this.updateFonts = function() {
 | 
			
		||||
    document.body.style.fontFamily = fontSelect.value + ", 'Courier New', monospace";
 | 
			
		||||
    document.body.style.fontSize = fontSize.value + 'pt';
 | 
			
		||||
    document.body.style.fontWeight = (fontBold.checked ? "bold" : "normal");;
 | 
			
		||||
    keepAliveLabel.innerHTML='KeepAlive('+keepAliveTime.value+'s)';
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*  this.show = function () {
 | 
			
		||||
    if (settingsContainer.style.visibility === 'visible') {
 | 
			
		||||
//      settingsContainer.style.visibility = 'hidden';
 | 
			
		||||
//      this.reconfigure();
 | 
			
		||||
    } else {
 | 
			
		||||
      // restore form values from actual settings
 | 
			
		||||
      var opts = document.getElementsByClassName('option');
 | 
			
		||||
      for (var i=0; i < opts.length; i++)
 | 
			
		||||
      {
 | 
			
		||||
        var opt = this[opts[i].id];
 | 
			
		||||
        if (opt) {
 | 
			
		||||
          if (opts[i].type.toUpperCase() === 'CHECKBOX') {
 | 
			
		||||
            opts[i].checked = opt.val;
 | 
			
		||||
          } else {
 | 
			
		||||
            opts[i].value = opt.val;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      settingsContainer.style.visibility = 'visible';
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
  this.cookie = function (c_name) {
 | 
			
		||||
    var c_value = this.doc.cookie;
 | 
			
		||||
    var c_start = c_value.indexOf(" " + c_name + "=");
 | 
			
		||||
 | 
			
		||||
    if (c_start == -1)
 | 
			
		||||
    {
 | 
			
		||||
      c_start = c_value.indexOf(c_name + "=");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (c_start == -1) {
 | 
			
		||||
      c_value = null;
 | 
			
		||||
    } else {
 | 
			
		||||
      c_start = c_value.indexOf("=", c_start) + 1;
 | 
			
		||||
 | 
			
		||||
      var c_end = c_value.indexOf(";", c_start);
 | 
			
		||||
 | 
			
		||||
      if (c_end == -1) {
 | 
			
		||||
        c_end = c_value.length;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      c_value = unescape(c_value.substring(c_start,c_end));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return c_value;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  // Load values from cookies, or save the cookie on first visitl
 | 
			
		||||
  this.load = function () {
 | 
			
		||||
    var opts = document.getElementsByClassName('option');
 | 
			
		||||
    var exdate=new Date();
 | 
			
		||||
    exdate.setDate(exdate.getDate() + 365*10);
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < opts.length; i++)
 | 
			
		||||
    {
 | 
			
		||||
      var opt = this[opts[i].id];
 | 
			
		||||
 | 
			
		||||
      if (opt) {
 | 
			
		||||
        if (opts[i].type.toUpperCase() === 'CHECKBOX') {
 | 
			
		||||
          var val = this.cookie(opts[i].id);
 | 
			
		||||
          if (val && val != 'undefined') {
 | 
			
		||||
            opt.val = (val.toUpperCase() === 'TRUE');
 | 
			
		||||
          } else {
 | 
			
		||||
            this.doc.cookie = opts[i].id + "=" + opt.val
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          opts[i].checked = opt.val;
 | 
			
		||||
        } else {
 | 
			
		||||
          var val = this.cookie(opts[i].id);
 | 
			
		||||
          if (val && val != 'undefined') {
 | 
			
		||||
            opt.val = val;
 | 
			
		||||
          } else {
 | 
			
		||||
            this.doc.cookie = opts[i].id + "=" + opt.val
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          opts[i].value = opt.val;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//    this.reconfigure();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
  // Save form values to settings values, and settings values to cookies
 | 
			
		||||
  this.save = function () {
 | 
			
		||||
    var opts = document.getElementsByClassName('option');
 | 
			
		||||
    var exdate=new Date();
 | 
			
		||||
    exdate.setDate(exdate.getDate() + 365*10);
 | 
			
		||||
 | 
			
		||||
    for (var i = 0; i < opts.length; i++)
 | 
			
		||||
    {
 | 
			
		||||
      var opt = this[opts[i].id];
 | 
			
		||||
 | 
			
		||||
      // copy form values to settings values
 | 
			
		||||
      if (opt) {
 | 
			
		||||
        if (opts[i].type.toUpperCase() === 'CHECKBOX') {
 | 
			
		||||
          if (opts[i].checked !== opt.val) {
 | 
			
		||||
            opt.val = opts[i].checked;
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          if (opts[i].value !== opt.val) {
 | 
			
		||||
            opt.val = opts[i].value;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // save settings value to cookie
 | 
			
		||||
        this.doc.cookie=opts[i].id + "=" + opt.val + "; expires="+exdate.toUTCString();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  //  this.reconfigure();
 | 
			
		||||
 | 
			
		||||
    // toggle visibility
 | 
			
		||||
//    settingsContainer.style.visibility = 'hidden';
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Resize or otherwise modify the output window to reflect the new settings
 | 
			
		||||
/*  this.reconfigure = function() {
 | 
			
		||||
    document.body.style.fontFamily = this.fontSelect.val + ", 'Courier New', monospace";
 | 
			
		||||
    document.body.style.fontSize = this.fontSize.val + 'pt';
 | 
			
		||||
    document.body.style.fontWeight = (this.fontBold.val ? "bold" : "normal");;
 | 
			
		||||
    output.root.style.bottom = 4.0+parseInt(this.numInputLines.val) + 'em';
 | 
			
		||||
    quicklinks.style.bottom = 2.0+parseInt(this.numInputLines.val) + 'em';
 | 
			
		||||
    cmdprompt.root.style.bottom = 1.0+parseInt(this.numInputLines.val) + 'em';
 | 
			
		||||
    entry.root.style.height = parseInt(this.numInputLines.val) + 'em';
 | 
			
		||||
    keepAliveLabel.innerHTML='KeepAlive('+keepAliveTime.value+'s)';
 | 
			
		||||
  };
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var settings = new SettingsClass(window,document,undefined);
 | 
			
		||||
							
								
								
									
										985
									
								
								js/wsclient.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										985
									
								
								js/wsclient.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,985 @@
 | 
			
		||||
//////////////////////////////////////////////////////////////////
 | 
			
		||||
// WebSockClient for PennMUSH
 | 
			
		||||
// There is no license. Just make a neato game with it.
 | 
			
		||||
//////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
var WSClient = (function (window, document, undefined) {
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // MU* protocol carried over the WebSocket API.
 | 
			
		||||
  function Connection(url) {
 | 
			
		||||
    var that = this;
 | 
			
		||||
    
 | 
			
		||||
    this.url = url;
 | 
			
		||||
    this.socket = null;
 | 
			
		||||
    this.isOpen = false;
 | 
			
		||||
    
 | 
			
		||||
    Connection.reconnect(that);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  Connection.CHANNEL_TEXT = 't';
 | 
			
		||||
  Connection.CHANNEL_JSON = 'j';
 | 
			
		||||
  Connection.CHANNEL_HTML = 'h';
 | 
			
		||||
  Connection.CHANNEL_PUEBLO = 'p';
 | 
			
		||||
  Connection.CHANNEL_PROMPT = '>';
 | 
			
		||||
 | 
			
		||||
  Connection.reconnect = function (that) {
 | 
			
		||||
    that.reconnect();
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  Connection.onopen = function (that, evt) {
 | 
			
		||||
    that.isOpen = true;
 | 
			
		||||
    that.onOpen && that.onOpen(evt);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.onerror = function (that, evt) {
 | 
			
		||||
    that.onError && that.onError(evt);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.onclose = function (that, evt) {
 | 
			
		||||
    that.onClose && that.onClose(evt);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.onmessage = function (that, evt) {
 | 
			
		||||
    that.onMessage && that.onMessage(evt.data[0], evt.data.substring(1));
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.prototype.reconnect = function () {
 | 
			
		||||
    var that = this;
 | 
			
		||||
    
 | 
			
		||||
    // quit the old connection, if we have one
 | 
			
		||||
    if (this.socket) {
 | 
			
		||||
      var old = this.socket;
 | 
			
		||||
      this.sendText('QUIT');
 | 
			
		||||
      setTimeout(old.close, 1000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.socket = new window.WebSocket(this.url);
 | 
			
		||||
    this.isOpen = false;
 | 
			
		||||
 | 
			
		||||
    this.socket.onopen = function (evt) {
 | 
			
		||||
      Connection.onopen(that, evt);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    this.socket.onerror = function (evt) {
 | 
			
		||||
      Connection.onerror(that, evt);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    this.socket.onclose = function (evt) {
 | 
			
		||||
      Connection.onclose(that, evt);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    this.socket.onmessage = function (evt) {
 | 
			
		||||
      Connection.onmessage(that, evt);
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  Connection.prototype.isConnected = function() {
 | 
			
		||||
    return (this.socket && this.isOpen && (this.socket.readyState === 1));
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.prototype.close = function () {
 | 
			
		||||
    this.socket && this.socket.close();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.prototype.sendText = function (data) {
 | 
			
		||||
    this.isConnected() && this.socket.send(Connection.CHANNEL_TEXT + data + '\r\n');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.prototype.sendObject = function (data) {
 | 
			
		||||
    this.isConnected() && this.socket.send(Connection.CHANNEL_JSON + window.JSON.stringify(data));
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.prototype.onOpen = null;
 | 
			
		||||
  Connection.prototype.onError = null;
 | 
			
		||||
  Connection.prototype.onClose = null;
 | 
			
		||||
 | 
			
		||||
  Connection.prototype.onMessage = function (channel, data) {
 | 
			
		||||
    switch (channel) {
 | 
			
		||||
    case Connection.CHANNEL_TEXT:
 | 
			
		||||
      this.onText && this.onText(data);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case Connection.CHANNEL_JSON:
 | 
			
		||||
      this.onObject && this.onObject(window.JSON.parse(data));
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case Connection.CHANNEL_HTML:
 | 
			
		||||
      if (this.onHTML) {
 | 
			
		||||
        var div = document.createElement('div');
 | 
			
		||||
        div.innerHTML = data;
 | 
			
		||||
 | 
			
		||||
        var fragment = document.createDocumentFragment();
 | 
			
		||||
        for (var child = div.firstChild; child; child = child.nextSibling) {
 | 
			
		||||
          fragment.appendChild(child);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.onHTML(fragment);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case Connection.CHANNEL_PUEBLO:
 | 
			
		||||
      if (this.onPueblo) {
 | 
			
		||||
        var tag, attrs;
 | 
			
		||||
 | 
			
		||||
        var idx = data.indexOf(' ');
 | 
			
		||||
        if (idx !== -1) {
 | 
			
		||||
          tag = data.substring(0, idx);
 | 
			
		||||
          attrs = data.substring(idx + 1);
 | 
			
		||||
        } else {
 | 
			
		||||
          tag = data;
 | 
			
		||||
          attrs = '';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.onPueblo(tag.toUpperCase(), attrs);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    
 | 
			
		||||
    case Connection.CHANNEL_PROMPT:
 | 
			
		||||
      this.onPrompt && this.onPrompt(data);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      window.console && window.console.log('unhandled message', channel, data);
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Connection.prototype.onText = null;
 | 
			
		||||
  Connection.prototype.onObject = null;
 | 
			
		||||
  Connection.prototype.onHTML = null;
 | 
			
		||||
  Connection.prototype.onPueblo = null;
 | 
			
		||||
  Connection.prototype.onPrompt = null;
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // MU* terminal emulator.
 | 
			
		||||
  function Terminal(root) {
 | 
			
		||||
    this.root = root;
 | 
			
		||||
    
 | 
			
		||||
    this.clear();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Terminal.PARSE_PLAIN = 0;
 | 
			
		||||
  Terminal.PARSE_CR = 1;
 | 
			
		||||
  Terminal.PARSE_ESC1 = 2;
 | 
			
		||||
  Terminal.PARSE_ESC2 = 3;
 | 
			
		||||
 | 
			
		||||
  Terminal.ANSI_NORMAL = 0;
 | 
			
		||||
  Terminal.ANSI_BRIGHT = 1;
 | 
			
		||||
  Terminal.ANSI_UNDERLINE = 4;
 | 
			
		||||
  Terminal.ANSI_BLINK = 5;
 | 
			
		||||
  Terminal.ANSI_INVERSE = 7;
 | 
			
		||||
  Terminal.ANSI_XTERM_FG = 38;
 | 
			
		||||
  Terminal.ANSI_XTERM_BG = 48;
 | 
			
		||||
 | 
			
		||||
  Terminal.DEFAULT_FG = 37;
 | 
			
		||||
  Terminal.DEFAULT_BG = 30;
 | 
			
		||||
  
 | 
			
		||||
  Terminal.UNCLOSED_TAGS = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img',
 | 
			
		||||
          'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////
 | 
			
		||||
  // ansi parsing routines
 | 
			
		||||
  
 | 
			
		||||
  Terminal.encodeState = function (state) {
 | 
			
		||||
    if (!state) {
 | 
			
		||||
      return '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var classes = [];
 | 
			
		||||
 | 
			
		||||
    if (state[Terminal.ANSI_INVERSE]) {
 | 
			
		||||
      var value = state.fg;
 | 
			
		||||
      state.fg = state.bg;
 | 
			
		||||
      state.bg = value;
 | 
			
		||||
      
 | 
			
		||||
      value = state.fg256;
 | 
			
		||||
      state.fg256 = state.bg256;
 | 
			
		||||
      state.bg256 = value;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    var fg = state.fg;
 | 
			
		||||
    var bg = state.bg;
 | 
			
		||||
    
 | 
			
		||||
    if (state[Terminal.ANSI_UNDERLINE]) {
 | 
			
		||||
      classes[classes.length] = 'ansi-' + Terminal.ANSI_UNDERLINE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // make sure to avoid conflict with XTERM256 color's usage of blink (code 5)
 | 
			
		||||
    if (state.fg256) {
 | 
			
		||||
      classes[classes.length] = 'ansi-38-5-' + state.fg;
 | 
			
		||||
    } else {  
 | 
			
		||||
      if (state[Terminal.ANSI_BRIGHT]) {
 | 
			
		||||
        if (state[Terminal.ANSI_INVERSE]) {
 | 
			
		||||
          if (fg !== Terminal.DEFAULT_FG) {
 | 
			
		||||
            classes[classes.length] = 'ansi-' + fg;
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          classes[classes.length] = 'ansi-1-' + fg;
 | 
			
		||||
        }
 | 
			
		||||
      } else if (fg !== Terminal.DEFAULT_FG) {
 | 
			
		||||
        classes[classes.length] = 'ansi-' + fg;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (state.bg256) {
 | 
			
		||||
      classes[classes.length] = 'ansi-48-5-' + state.bg;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (state[Terminal.ANSI_BRIGHT]) {
 | 
			
		||||
        if (state[Terminal.ANSI_INVERSE]) {
 | 
			
		||||
          classes[classes.length] = 'ansi-1-' + (bg + 10);
 | 
			
		||||
        } else {
 | 
			
		||||
          if (bg !== Terminal.DEFAULT_BG) {
 | 
			
		||||
            classes[classes.length] = 'ansi-' + (bg + 10);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else if (bg !== Terminal.DEFAULT_BG) {
 | 
			
		||||
        classes[classes.length] = 'ansi-' + (bg + 10);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (state[Terminal.ANSI_BLINK] && !(state.fg256 || state.bg256)) {
 | 
			
		||||
      classes[classes.length] = 'ansi-' + Terminal.ANSI_BLINK;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return classes.join(' ');
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Terminal.prototype.getANSI = function () {
 | 
			
		||||
    if (!this.ansiState) {
 | 
			
		||||
      this.ansiState = {
 | 
			
		||||
        fg: Terminal.DEFAULT_FG,
 | 
			
		||||
        bg: Terminal.DEFAULT_BG,
 | 
			
		||||
        fg256: false,
 | 
			
		||||
        bg256: false
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this.ansiState;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Terminal.prototype.applyANSI = function (ansi) {
 | 
			
		||||
    switch (ansi.charCodeAt(ansi.length - 1)) {
 | 
			
		||||
    case 109: // m (SGR)
 | 
			
		||||
      var codes = ansi.substring(0, ansi.length - 1).split(';');
 | 
			
		||||
 | 
			
		||||
      var value, state;
 | 
			
		||||
      for (var ii = 0; (value = codes[ii]) !== undefined; ++ii) {
 | 
			
		||||
        if (value.length === 0) {
 | 
			
		||||
          // Empty is treated as the equivalent of 0.
 | 
			
		||||
          value = Terminal.ANSI_NORMAL;
 | 
			
		||||
        } else {
 | 
			
		||||
          value = parseInt(value);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        state = this.getANSI();
 | 
			
		||||
        
 | 
			
		||||
        // check for xterm256 fg/bg first, fallback to standard codes otherwise
 | 
			
		||||
        if (state[Terminal.ANSI_XTERM_FG] && state[Terminal.ANSI_BLINK]) {
 | 
			
		||||
          if (value >= 0 && value <= 255) {
 | 
			
		||||
            state.fg = value;
 | 
			
		||||
            state.fg256 = true;
 | 
			
		||||
            state[Terminal.ANSI_XTERM_FG] = false;
 | 
			
		||||
            state[Terminal.ANSI_BLINK] = false;
 | 
			
		||||
          } else {
 | 
			
		||||
            // invalid xterm256, let's reset the ansi state due to bad codes
 | 
			
		||||
            this.ansiState = null;
 | 
			
		||||
          }
 | 
			
		||||
        } else if (state[Terminal.ANSI_XTERM_BG] && state[Terminal.ANSI_BLINK]) {
 | 
			
		||||
          if (value >= 0 && value <= 255) {
 | 
			
		||||
            state.bg = value;
 | 
			
		||||
            state.bg256 = true;
 | 
			
		||||
            state[Terminal.ANSI_XTERM_BG] = false;
 | 
			
		||||
            state[Terminal.ANSI_BLINK] = false;
 | 
			
		||||
          } else {
 | 
			
		||||
            // invalid xterm256, let's reset the ansi state due to bad codes
 | 
			
		||||
            this.ansiState = null;
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          // detect regular ansi codes
 | 
			
		||||
          switch (value) {
 | 
			
		||||
          case Terminal.ANSI_NORMAL: // reset
 | 
			
		||||
            this.ansiState = null;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          case Terminal.ANSI_BRIGHT:
 | 
			
		||||
          case Terminal.ANSI_UNDERLINE:
 | 
			
		||||
          case Terminal.ANSI_BLINK:
 | 
			
		||||
          case Terminal.ANSI_INVERSE:
 | 
			
		||||
          case Terminal.ANSI_XTERM_FG:
 | 
			
		||||
          case Terminal.ANSI_XTERM_BG:
 | 
			
		||||
            state[value] = true;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          default:
 | 
			
		||||
            if (30 <= value && value <= 37) {
 | 
			
		||||
              state.fg = value;
 | 
			
		||||
            } else if (40 <= value && value <= 47) {
 | 
			
		||||
              state.bg = value - 10;
 | 
			
		||||
            }
 | 
			
		||||
           break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.ansiDirty = true;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Terminal.prototype.write = function (value, start, end) {
 | 
			
		||||
    if (start === end) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this.ansiDirty) {
 | 
			
		||||
      var next = Terminal.encodeState(this.ansiState);
 | 
			
		||||
 | 
			
		||||
      if (this.ansiClass !== next) {
 | 
			
		||||
        this.ansiClass = next;
 | 
			
		||||
        this.span = null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.ansiDirty = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this.ansiClass && !this.span) {
 | 
			
		||||
      this.span = document.createElement('span');
 | 
			
		||||
      this.span.className = this.ansiClass;
 | 
			
		||||
      this.stack[this.stack.length - 1].appendChild(this.span);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var text = document.createTextNode(value.substring(start, end));
 | 
			
		||||
    this.lineBuf[this.lineBuf.length] = text;
 | 
			
		||||
 | 
			
		||||
    this.appendHTML(text);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Terminal.prototype.endLine = function () {
 | 
			
		||||
    var that = this;
 | 
			
		||||
    this.onLine && this.onLine(that, this.lineBuf);
 | 
			
		||||
 | 
			
		||||
    this.write('\n', 0, 1);
 | 
			
		||||
    this.lineBuf.length = 0;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Terminal.prototype.abortParse = function (value, start, end) {
 | 
			
		||||
    switch (this.state) {
 | 
			
		||||
    case Terminal.PARSE_PLAIN:
 | 
			
		||||
      this.write(value, start, end);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case Terminal.PARSE_ESC1:
 | 
			
		||||
      this.write('\u001B', 0, 1);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case Terminal.PARSE_ESC2:
 | 
			
		||||
      this.write('\u001B[', 0, 2);
 | 
			
		||||
      this.write(this.parseBuf, 0, this.parseBuf.length);
 | 
			
		||||
      this.parseBuf = '';
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////
 | 
			
		||||
  // message appending routines
 | 
			
		||||
  
 | 
			
		||||
  // appends a text string to the terminal, parsing ansi escape codes into html/css
 | 
			
		||||
  Terminal.prototype.appendText = function (data) {
 | 
			
		||||
    var start = 0;
 | 
			
		||||
 | 
			
		||||
    // Scan for sequence start characters.
 | 
			
		||||
    // TODO: Could scan with RegExp; not convinced sufficiently simpler/faster.
 | 
			
		||||
    for (var ii = 0, ilen = data.length; ii < ilen; ++ii) {
 | 
			
		||||
      var ch = data.charCodeAt(ii);
 | 
			
		||||
 | 
			
		||||
      // Resynchronize at special characters.
 | 
			
		||||
      switch (ch) {
 | 
			
		||||
      case 10: // newline
 | 
			
		||||
        if (this.state !== Terminal.PARSE_CR) {
 | 
			
		||||
          this.abortParse(data, start, ii);
 | 
			
		||||
          this.endLine();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        start = ii + 1;
 | 
			
		||||
        this.state = Terminal.PARSE_PLAIN;
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      case 13: // carriage return
 | 
			
		||||
        this.abortParse(data, start, ii);
 | 
			
		||||
        this.endLine();
 | 
			
		||||
        start = ii + 1;
 | 
			
		||||
        this.state = Terminal.PARSE_CR;
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      case 27: // escape
 | 
			
		||||
        this.abortParse(data, start, ii);
 | 
			
		||||
        start = ii + 1;
 | 
			
		||||
        this.state = Terminal.PARSE_ESC1;
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Parse other characters.
 | 
			
		||||
      switch (this.state) {
 | 
			
		||||
      case Terminal.PARSE_CR:
 | 
			
		||||
        this.state = Terminal.PARSE_PLAIN;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case Terminal.PARSE_ESC1:
 | 
			
		||||
        if (ch === 91) {
 | 
			
		||||
          // Start of escape sequence (\e[).
 | 
			
		||||
          start = ii + 1;
 | 
			
		||||
          this.state = Terminal.PARSE_ESC2;
 | 
			
		||||
        } else {
 | 
			
		||||
          // Not an escape sequence.
 | 
			
		||||
          this.abortParse(data, start, ii);
 | 
			
		||||
          start = ii;
 | 
			
		||||
          this.state = Terminal.PARSE_PLAIN;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case Terminal.PARSE_ESC2:
 | 
			
		||||
        if (64 <= ch && ch <= 126) {
 | 
			
		||||
          // End of escape sequence.
 | 
			
		||||
          this.parseBuf += data.substring(start, (start = ii + 1));
 | 
			
		||||
          this.applyANSI(this.parseBuf);
 | 
			
		||||
          this.parseBuf = '';
 | 
			
		||||
          this.state = Terminal.PARSE_PLAIN;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Handle tail.
 | 
			
		||||
    switch (this.state) {
 | 
			
		||||
    case Terminal.PARSE_PLAIN:
 | 
			
		||||
      this.write(data, start, data.length);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case Terminal.PARSE_ESC2:
 | 
			
		||||
      this.parseBuf += data.substring(start);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // append an HTML fragment to the terminal
 | 
			
		||||
  Terminal.prototype.appendHTML = function (fragment) {
 | 
			
		||||
    (this.span || this.stack[this.stack.length - 1]).appendChild(fragment);
 | 
			
		||||
 | 
			
		||||
    // TODO: May want to animate this, to make it less abrupt.
 | 
			
		||||
    this.root.scrollTop = this.root.scrollHeight;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // append a log message to the terminal
 | 
			
		||||
  Terminal.prototype.appendMessage = function (classid, message) {
 | 
			
		||||
    var div = document.createElement('div');
 | 
			
		||||
    div.className = classid;
 | 
			
		||||
    
 | 
			
		||||
    // create a text node to safely append the string without rendering code
 | 
			
		||||
    var text = document.createTextNode(message);
 | 
			
		||||
    div.appendChild(text);
 | 
			
		||||
    
 | 
			
		||||
    this.appendHTML(div);
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // push a new html element onto the stack
 | 
			
		||||
  Terminal.prototype.pushElement = function (element) {
 | 
			
		||||
    this.span = null;
 | 
			
		||||
    this.stack[this.stack.length - 1].appendChild(element);
 | 
			
		||||
    this.stack[this.stack.length] = element;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // remove 1 level from the stack, check consistency 
 | 
			
		||||
  Terminal.prototype.popElement = function () {
 | 
			
		||||
    this.span = null;
 | 
			
		||||
 | 
			
		||||
    if (this.stack.length > 1) {
 | 
			
		||||
      --this.stack.length;
 | 
			
		||||
    } else {
 | 
			
		||||
      window.console && window.console.warn('element stack underflow');
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // append a pueblo tag to the terminal stack (or pop if an end tag)
 | 
			
		||||
  Terminal.prototype.appendPueblo = function (tag, attrs) {
 | 
			
		||||
    var html = '<' + tag + (attrs ? ' ' : '') + attrs + '>';
 | 
			
		||||
 | 
			
		||||
    var start;
 | 
			
		||||
    if (tag[0] !== '/') {
 | 
			
		||||
      start = true;
 | 
			
		||||
    } else {
 | 
			
		||||
      start = false;
 | 
			
		||||
      tag = tag.substring(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var selfClosing = false;
 | 
			
		||||
    if ((tag.substring(-1) === '/') || (attrs.substring(-1) === '/')) {
 | 
			
		||||
      selfClosing = true;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (Terminal.UNCLOSED_TAGS.indexOf(tag.toLowerCase()) > -1) {
 | 
			
		||||
      selfClosing = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((tag === 'XCH_PAGE') || 
 | 
			
		||||
        ((tag === 'IMG') && (attrs.search(/xch_graph=(("[^"]*")|('[^']*')|([^\s]*))/i) !== -1))) {
 | 
			
		||||
      //console.log("unhandled pueblo", html);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // we have a starting <tag> (not </tag>)
 | 
			
		||||
    if (start) {
 | 
			
		||||
      var div = document.createElement('div');
 | 
			
		||||
 | 
			
		||||
      html = html.replace(
 | 
			
		||||
        /xch_graph=(("[^"]*")|('[^']*')|([^\s]*))/i,
 | 
			
		||||
        ''
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      html = html.replace(
 | 
			
		||||
        /xch_mode=(("[^"]*")|('[^']*')|([^\s]*))/i,
 | 
			
		||||
        ''
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      html = html.replace(
 | 
			
		||||
        /xch_hint="([^"]*)"/i,
 | 
			
		||||
        'title="$1"'
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      div.innerHTML = html.replace(
 | 
			
		||||
        /xch_cmd="([^"]*)"/i,
 | 
			
		||||
        "onClick='this.onCommand("$1")'"
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      div.firstChild.onCommand = this.onCommand;
 | 
			
		||||
 | 
			
		||||
      div.setAttribute('target', '_blank');
 | 
			
		||||
      
 | 
			
		||||
      // add this tag to the stack to keep track of nested elements
 | 
			
		||||
      this.pushElement(div.firstChild);
 | 
			
		||||
 | 
			
		||||
      // automatically pop the tag if it is self closing
 | 
			
		||||
      if (selfClosing) {
 | 
			
		||||
        this.popElement();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
      // we have an ending </tag> so remove the closed tag from the stack
 | 
			
		||||
      // don't bother for self closing tags with an explicit end tag, we already popped them
 | 
			
		||||
      if (!selfClosing) {
 | 
			
		||||
        this.popElement();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  Terminal.prototype.clear = function() {
 | 
			
		||||
    this.root.innerHTML = '';
 | 
			
		||||
 | 
			
		||||
    this.stack = [this.root];
 | 
			
		||||
 | 
			
		||||
    this.state = Terminal.PARSE_PLAIN;
 | 
			
		||||
    this.line = null;
 | 
			
		||||
    this.lineBuf = [];
 | 
			
		||||
    this.span = null;
 | 
			
		||||
    this.parseBuf = '';
 | 
			
		||||
 | 
			
		||||
    this.ansiClass = '';
 | 
			
		||||
    this.ansiState = null;
 | 
			
		||||
    this.ansiDirty = false;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // setup the pueblo xch_cmd callback
 | 
			
		||||
  Terminal.prototype.onCommand = null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // User input handler (command history, callback events)
 | 
			
		||||
  function UserInput(root) {
 | 
			
		||||
    var that = this;
 | 
			
		||||
    
 | 
			
		||||
    this.root = root;
 | 
			
		||||
    this.history = [];
 | 
			
		||||
    this.ncommand = 0;
 | 
			
		||||
    this.save_current = '';
 | 
			
		||||
    this.current = -1;
 | 
			
		||||
 | 
			
		||||
    this.root.onkeydown = function(evt) {
 | 
			
		||||
      UserInput.onkeydown(that, evt);
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    this.root.onkeyup = function(evt) {
 | 
			
		||||
      UserInput.onkeyup(that, evt);
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // passthrough to the local onKeyDown callback
 | 
			
		||||
  UserInput.onkeydown = function(that, evt) {
 | 
			
		||||
    that.onKeyDown && that.onKeyDown(evt);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // passthrough to the local onKeyUp callback
 | 
			
		||||
  UserInput.onkeyup = function(that, evt) {
 | 
			
		||||
    that.onKeyUp && that.onKeyUp(evt);
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // set the default onKeyDown handler
 | 
			
		||||
  UserInput.prototype.onKeyDown = function(e) {
 | 
			
		||||
    PressKey(this, e);
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // set the default onKeyUp handler
 | 
			
		||||
  UserInput.prototype.onKeyUp = function(e) {
 | 
			
		||||
    ReleaseKey(this, e);
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  UserInput.prototype.onEnter = null;
 | 
			
		||||
  UserInput.prototype.onEscape = null;
 | 
			
		||||
  
 | 
			
		||||
  // push a command onto the history list and clear the input box
 | 
			
		||||
  UserInput.prototype.saveCommand = function() {
 | 
			
		||||
    if (this.root.value !== '') {
 | 
			
		||||
      this.history[this.ncommand] = this.root.value;
 | 
			
		||||
      this.ncommand++;
 | 
			
		||||
      this.save_current = '';
 | 
			
		||||
      this.current = -1;
 | 
			
		||||
      this.root.value = '';
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // cycle the history backward
 | 
			
		||||
  UserInput.prototype.cycleBackward = function() {
 | 
			
		||||
    // save the current entry in case we come back
 | 
			
		||||
    if (this.current < 0) {
 | 
			
		||||
      this.save_current = this.root.value;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // cycle command history backward
 | 
			
		||||
    if (this.current < this.ncommand - 1) {
 | 
			
		||||
      this.current++;
 | 
			
		||||
      this.root.value = this.history[this.ncommand - this.current - 1];
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // cycle the history forward
 | 
			
		||||
  UserInput.prototype.cycleForward = function () {
 | 
			
		||||
    // cycle command history forward
 | 
			
		||||
    if (this.current > 0) {
 | 
			
		||||
      this.current--;
 | 
			
		||||
      this.root.value = this.history[this.ncommand - this.current - 1];
 | 
			
		||||
    } else if (this.current === 0) {
 | 
			
		||||
      // recall the current entry if they had typed something already
 | 
			
		||||
      this.current = -1;
 | 
			
		||||
      this.root.value = this.save_current;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  // move the input cursor to the end of the input elements current text
 | 
			
		||||
  UserInput.prototype.moveCursor = function() {
 | 
			
		||||
    if (typeof this.root.selectionStart === "number") {
 | 
			
		||||
        this.root.selectionStart = this.root.selectionEnd = this.root.value.length;
 | 
			
		||||
    } else if (typeof this.root.createTextRange !== "undefined") {
 | 
			
		||||
        this.focus();
 | 
			
		||||
        var range = this.root.createTextRange();
 | 
			
		||||
        range.collapse(false);
 | 
			
		||||
        range.select();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  // clear the current input text
 | 
			
		||||
  UserInput.prototype.clear = function() {
 | 
			
		||||
    this.root.value = '';
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // get the current text in the input box
 | 
			
		||||
  UserInput.prototype.value = function() {
 | 
			
		||||
    return this.root.value;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // refocus the input box
 | 
			
		||||
  UserInput.prototype.focus = function() {
 | 
			
		||||
    this.root.focus();
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // user-defined keys for command history
 | 
			
		||||
  UserInput.prototype.keyCycleForward = null;
 | 
			
		||||
  UserInput.prototype.keyCycleBackward = null;
 | 
			
		||||
  
 | 
			
		||||
  UserInput.isKeyCycleForward = function(that, key) {
 | 
			
		||||
    if (that && that.keyCycleForward) {
 | 
			
		||||
      return that.keyCycleForward(key);
 | 
			
		||||
    } else {
 | 
			
		||||
      // default key is ctrl+n
 | 
			
		||||
      return (key.code === 78 && key.ctrl);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  UserInput.isKeyCycleBackward = function (that, key) {
 | 
			
		||||
    if (that && that.keyCycleBackward) {
 | 
			
		||||
      return that.keyCycleBackward(key);
 | 
			
		||||
    } else {
 | 
			
		||||
      // default key is ctrl+p
 | 
			
		||||
      return (key.code === 80 && key.ctrl);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
  // some string helper functions for replacing links and user input tokens
 | 
			
		||||
 | 
			
		||||
  // Example onLine() handler that linkifies URLs in text.
 | 
			
		||||
  function LinkHandler(that, lineBuf) {
 | 
			
		||||
    // Merge text so we can scan it.
 | 
			
		||||
    if (!lineBuf.length) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var line = '';
 | 
			
		||||
    for (var ii = 0, ilen = lineBuf.length; ii < ilen; ++ii) {
 | 
			
		||||
      line += lineBuf[ii].nodeValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Scan the merged text for links.
 | 
			
		||||
    var links = LinkHandler.scan(line);
 | 
			
		||||
    if (!links.length) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Find the start and end text nodes.
 | 
			
		||||
    var nodeIdx = 0, nodeStart = 0, nodeEnd = lineBuf[0].nodeValue.length;
 | 
			
		||||
    for (var ii = 0, ilen = links.length; ii < ilen; ++ii) {
 | 
			
		||||
      var info = links[ii], startOff, startNode, endOff, endNode;
 | 
			
		||||
 | 
			
		||||
      while (nodeEnd <= info.start) {
 | 
			
		||||
        nodeStart = nodeEnd;
 | 
			
		||||
        nodeEnd += lineBuf[++nodeIdx].nodeValue.length;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      startOff = info.start - nodeStart;
 | 
			
		||||
      startNode = lineBuf[nodeIdx];
 | 
			
		||||
 | 
			
		||||
      while (nodeEnd < info.end) {
 | 
			
		||||
        nodeStart = nodeEnd;
 | 
			
		||||
        nodeEnd += lineBuf[++nodeIdx].nodeValue.length;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      endOff = info.end - nodeStart;
 | 
			
		||||
      endNode = lineBuf[nodeIdx];
 | 
			
		||||
 | 
			
		||||
      // Wrap the link text.
 | 
			
		||||
      // TODO: In this version, we won't try to cross text nodes.
 | 
			
		||||
      // TODO: Discard any text nodes that are already part of links?
 | 
			
		||||
      if (startNode !== endNode) {
 | 
			
		||||
        window.console && window.console.warn('link', info);
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      lineBuf[nodeIdx] = endNode.splitText(endOff);
 | 
			
		||||
      nodeStart += endOff;
 | 
			
		||||
 | 
			
		||||
      var middleNode = startNode.splitText(startOff);
 | 
			
		||||
      var anchor = document.createElement('a');
 | 
			
		||||
      middleNode.parentNode.replaceChild(anchor, middleNode);
 | 
			
		||||
 | 
			
		||||
      anchor.target = '_blank';
 | 
			
		||||
      if (info.url === '' && info.xch_cmd !== '') {
 | 
			
		||||
        anchor.setAttribute('onClick', 'this.onCommand("'+info.xch_cmd+'");');
 | 
			
		||||
        anchor.onCommand = that.onCommand;
 | 
			
		||||
      } else {
 | 
			
		||||
        anchor.href = info.url;
 | 
			
		||||
      }
 | 
			
		||||
      anchor.appendChild(middleNode);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Link scanner function.
 | 
			
		||||
  // TODO: Customizers may want to replace this, since regular expressions
 | 
			
		||||
  // ultimately limit how clever our heuristics can be.
 | 
			
		||||
  LinkHandler.scan = function (line) {
 | 
			
		||||
    var links = [], result;
 | 
			
		||||
 | 
			
		||||
    LinkHandler.regex.lastIndex = 0;
 | 
			
		||||
    while ((result = LinkHandler.regex.exec(line))) {
 | 
			
		||||
      var info = {};
 | 
			
		||||
 | 
			
		||||
      info.start = result.index + result[1].length;
 | 
			
		||||
      info.xch_cmd = '';
 | 
			
		||||
      if (result[2]) {
 | 
			
		||||
        result = result[2];
 | 
			
		||||
        info.url = result;
 | 
			
		||||
      } else if (result[3]) {
 | 
			
		||||
        result = result[3];
 | 
			
		||||
        info.url = 'mailto:' + result;
 | 
			
		||||
      } else if (result[4]) {
 | 
			
		||||
        result = result[4];
 | 
			
		||||
        info.url = '';
 | 
			
		||||
        info.xch_cmd = 'help ' + result;
 | 
			
		||||
        info.className = "ansi-1-37";
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      info.end = info.start + result.length;
 | 
			
		||||
 | 
			
		||||
      links[links.length] = info;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return links;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // LinkHandler regex:
 | 
			
		||||
  //
 | 
			
		||||
  // 1. Links must be preceded by a non-alphanumeric delimiter.
 | 
			
		||||
  // 2. Links are matched greedily.
 | 
			
		||||
  // 3. URLs must start with a supported scheme.
 | 
			
		||||
  // 4. E-mail addresses are also linkified.
 | 
			
		||||
  // 5. Twitter users and hash tags are also linkified.
 | 
			
		||||
  //
 | 
			
		||||
  // TODO: This can be improved (but also customized). One enhancement might be
 | 
			
		||||
  // to support internationalized syntax.
 | 
			
		||||
  LinkHandler.regex = /(^|[^a-zA-Z0-9]+)(?:((?:http|https):\/\/[-a-zA-Z0-9_.~:\/?#[\]@!$&'()*+,;=%]+)|([-.+a-zA-Z0-9_]+@[-a-zA-Z0-9]+(?:\.[-a-zA-Z0-9]+)+)|(@[a-zA-Z]\w*))/g;
 | 
			
		||||
 | 
			
		||||
  // set the default line handler for the terminal to use the LinkHandler
 | 
			
		||||
  Terminal.prototype.onLine = LinkHandler;
 | 
			
		||||
 | 
			
		||||
  // detect if more user input is required for a pueblo command
 | 
			
		||||
  function ReplaceToken(command) {
 | 
			
		||||
    var cmd = command;
 | 
			
		||||
    var regex = /\?\?/;
 | 
			
		||||
    
 | 
			
		||||
    // check for the search token '??'
 | 
			
		||||
    if (cmd.search(regex) !== -1) {
 | 
			
		||||
      var val = prompt(command);
 | 
			
		||||
      
 | 
			
		||||
      if (val === null) {
 | 
			
		||||
        // user cancelled the prompt, don't send any command
 | 
			
		||||
        cmd = '';
 | 
			
		||||
      } else {
 | 
			
		||||
        // replace the ?? token with the prompt value
 | 
			
		||||
        cmd = cmd.replace(regex, val);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return cmd;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // default handler for key press events
 | 
			
		||||
  function PressKey(that, e) {
 | 
			
		||||
    var key = { code: (e.keyCode ? e.keyCode : e.which),
 | 
			
		||||
                ctrl: e.ctrlKey,
 | 
			
		||||
                shift: e.shiftKey,
 | 
			
		||||
                alt: e.altKey };
 | 
			
		||||
 | 
			
		||||
    var prevent = true;
 | 
			
		||||
    
 | 
			
		||||
    if (UserInput.isKeyCycleBackward(that, key)) {
 | 
			
		||||
 | 
			
		||||
      // cycle history backward
 | 
			
		||||
      that.cycleBackward();
 | 
			
		||||
 | 
			
		||||
    } else if (UserInput.isKeyCycleForward(that, key)) {
 | 
			
		||||
 | 
			
		||||
      // cycle history forward
 | 
			
		||||
      that.cycleForward();
 | 
			
		||||
 | 
			
		||||
    } else if (key.code === 13) {
 | 
			
		||||
      // enter key
 | 
			
		||||
      
 | 
			
		||||
      // save the command string and clear the input box
 | 
			
		||||
      var cmd = that.root.value;
 | 
			
		||||
      that.saveCommand();
 | 
			
		||||
 | 
			
		||||
      // pass through to the local callback for sending data
 | 
			
		||||
      that.onEnter && that.onEnter(cmd);
 | 
			
		||||
        
 | 
			
		||||
    } else if (key.code === 27) {
 | 
			
		||||
 | 
			
		||||
      // pass through to the local callback for the escape key
 | 
			
		||||
      that.onEscape && that.onEscape();
 | 
			
		||||
 | 
			
		||||
    } else { 
 | 
			
		||||
      // didn't capture anything, pass it through
 | 
			
		||||
      prevent = false;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (prevent) {
 | 
			
		||||
      e.preventDefault();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // make sure input retains focus
 | 
			
		||||
    that.focus();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // default handler for key release events
 | 
			
		||||
  function ReleaseKey(that, e) {
 | 
			
		||||
    var key = { code: (e.keyCode ? e.keyCode : e.which),
 | 
			
		||||
                ctrl: e.ctrlKey,
 | 
			
		||||
                shift: e.shiftKey,
 | 
			
		||||
                alt: e.altKey };
 | 
			
		||||
 | 
			
		||||
    if (UserInput.isKeyCycleBackward(that, key) ||
 | 
			
		||||
        UserInput.isKeyCycleForward(that, key)) {
 | 
			
		||||
 | 
			
		||||
      // move the cursor to end of the input text after a history change
 | 
			
		||||
      that.moveCursor();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  // Module exports.
 | 
			
		||||
  var exports = {};
 | 
			
		||||
 | 
			
		||||
  // open a websocket connection to url
 | 
			
		||||
  exports.connect = function (url) {
 | 
			
		||||
    return new Connection(url);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // create a terminal emulator that appends output to root
 | 
			
		||||
  exports.output = function (root) {
 | 
			
		||||
    return new Terminal(root);
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // create an input handler that saves and recalls command history
 | 
			
		||||
  exports.input = function (root) {
 | 
			
		||||
    return new UserInput(root);
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // default key event callback handlers
 | 
			
		||||
  exports.pressKey = PressKey;
 | 
			
		||||
  exports.releaseKey = ReleaseKey;
 | 
			
		||||
  
 | 
			
		||||
  // helper for replacing ?? in string with user input
 | 
			
		||||
  exports.parseCommand = ReplaceToken;
 | 
			
		||||
  
 | 
			
		||||
  // export the LinkHandler just in case it's useful elsewhere
 | 
			
		||||
  exports.parseLinks = LinkHandler;
 | 
			
		||||
  
 | 
			
		||||
  return exports;
 | 
			
		||||
})(window, document);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										567
									
								
								styles/ansi.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										567
									
								
								styles/ansi.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,567 @@
 | 
			
		||||
/******************************************/
 | 
			
		||||
/**  ANSI Colors  **/
 | 
			
		||||
 | 
			
		||||
/* underlined text */
 | 
			
		||||
.ansi-4 { text-decoration: underline; }
 | 
			
		||||
 | 
			
		||||
/* blinking text */
 | 
			
		||||
.ansi-5 {
 | 
			
		||||
    -webkit-animation: blink .75s linear infinite;
 | 
			
		||||
    -moz-animation: blink .75s linear infinite;
 | 
			
		||||
    -ms-animation: blink .75s linear infinite;
 | 
			
		||||
    -o-animation: blink .75s linear infinite;
 | 
			
		||||
    animation: blink .75s linear infinite;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* standard 16 foreground colors */
 | 
			
		||||
.ansi-30 { color: black; }
 | 
			
		||||
.ansi-1-30 { color: gray; }
 | 
			
		||||
.ansi-31 { color: maroon; }
 | 
			
		||||
.ansi-1-31 { color: red; }
 | 
			
		||||
.ansi-32 { color: green; }
 | 
			
		||||
.ansi-1-32 { color: lime; }
 | 
			
		||||
.ansi-33 { color: olive; }
 | 
			
		||||
.ansi-1-33 { color: yellow; }
 | 
			
		||||
.ansi-34 { color: navy; }
 | 
			
		||||
.ansi-1-34 { color: blue; }
 | 
			
		||||
.ansi-35 { color: purple; }
 | 
			
		||||
.ansi-1-35 { color: fuchsia; }
 | 
			
		||||
.ansi-36 { color: teal; }
 | 
			
		||||
.ansi-1-36 { color: aqua; }
 | 
			
		||||
.ansi-37 { color: silver; }
 | 
			
		||||
.ansi-1-37 { color: white; }
 | 
			
		||||
 | 
			
		||||
/* standard 16 background colors */
 | 
			
		||||
.ansi-40 { background-color: black; }
 | 
			
		||||
.ansi-1-40 { background-color: gray; }
 | 
			
		||||
.ansi-41 { background-color: maroon; }
 | 
			
		||||
.ansi-1-41 { background-color: red; }
 | 
			
		||||
.ansi-42 { background-color: green; }
 | 
			
		||||
.ansi-1-42 { background-color: lime; }
 | 
			
		||||
.ansi-43 { background-color: olive; }
 | 
			
		||||
.ansi-1-43 { background-color: yellow; }
 | 
			
		||||
.ansi-44 { background-color: navy; }
 | 
			
		||||
.ansi-1-44 { background-color: blue; }
 | 
			
		||||
.ansi-45 { background-color: purple; }
 | 
			
		||||
.ansi-1-45 { background-color: fuchsia; }
 | 
			
		||||
.ansi-46 { background-color: teal; }
 | 
			
		||||
.ansi-1-46 { background-color: aqua; }
 | 
			
		||||
.ansi-47 { background-color: silver; }
 | 
			
		||||
.ansi-1-47 { background-color: white; }
 | 
			
		||||
 | 
			
		||||
/* xterm256 foreground colors */
 | 
			
		||||
.ansi-38-5-0 { color: #000000; }
 | 
			
		||||
.ansi-38-5-1 { color: #800000; }
 | 
			
		||||
.ansi-38-5-2 { color: #008000; }
 | 
			
		||||
.ansi-38-5-3 { color: #808000; }
 | 
			
		||||
.ansi-38-5-4 { color: #000080; }
 | 
			
		||||
.ansi-38-5-5 { color: #800080; }
 | 
			
		||||
.ansi-38-5-6 { color: #008080; }
 | 
			
		||||
.ansi-38-5-7 { color: #c0c0c0; }
 | 
			
		||||
.ansi-38-5-8 { color: #808080; }
 | 
			
		||||
.ansi-38-5-9 { color: #ff0000; }
 | 
			
		||||
.ansi-38-5-10 { color: #00ff00; }
 | 
			
		||||
.ansi-38-5-11 { color: #ffff00; }
 | 
			
		||||
.ansi-38-5-12 { color: #0000ff; }
 | 
			
		||||
.ansi-38-5-13 { color: #ff00ff; }
 | 
			
		||||
.ansi-38-5-14 { color: #00ffff; }
 | 
			
		||||
.ansi-38-5-15 { color: #ffffff; }
 | 
			
		||||
.ansi-38-5-16 { color: #000000; }
 | 
			
		||||
.ansi-38-5-17 { color: #00005f; }
 | 
			
		||||
.ansi-38-5-18 { color: #000087; }
 | 
			
		||||
.ansi-38-5-19 { color: #0000af; }
 | 
			
		||||
.ansi-38-5-20 { color: #0000d7; }
 | 
			
		||||
.ansi-38-5-21 { color: #0000ff; }
 | 
			
		||||
.ansi-38-5-22 { color: #005f00; }
 | 
			
		||||
.ansi-38-5-23 { color: #005f5f; }
 | 
			
		||||
.ansi-38-5-24 { color: #005f87; }
 | 
			
		||||
.ansi-38-5-25 { color: #005faf; }
 | 
			
		||||
.ansi-38-5-26 { color: #005fd7; }
 | 
			
		||||
.ansi-38-5-27 { color: #005fff; }
 | 
			
		||||
.ansi-38-5-28 { color: #008700; }
 | 
			
		||||
.ansi-38-5-29 { color: #00875f; }
 | 
			
		||||
.ansi-38-5-30 { color: #008787; }
 | 
			
		||||
.ansi-38-5-31 { color: #0087af; }
 | 
			
		||||
.ansi-38-5-32 { color: #0087d7; }
 | 
			
		||||
.ansi-38-5-33 { color: #0087ff; }
 | 
			
		||||
.ansi-38-5-34 { color: #00af00; }
 | 
			
		||||
.ansi-38-5-35 { color: #00af5f; }
 | 
			
		||||
.ansi-38-5-36 { color: #00af87; }
 | 
			
		||||
.ansi-38-5-37 { color: #00afaf; }
 | 
			
		||||
.ansi-38-5-38 { color: #00afd7; }
 | 
			
		||||
.ansi-38-5-39 { color: #00afff; }
 | 
			
		||||
.ansi-38-5-40 { color: #00d700; }
 | 
			
		||||
.ansi-38-5-41 { color: #00d75f; }
 | 
			
		||||
.ansi-38-5-42 { color: #00d787; }
 | 
			
		||||
.ansi-38-5-43 { color: #00d7af; }
 | 
			
		||||
.ansi-38-5-44 { color: #00d7d7; }
 | 
			
		||||
.ansi-38-5-45 { color: #00d7ff; }
 | 
			
		||||
.ansi-38-5-46 { color: #00ff00; }
 | 
			
		||||
.ansi-38-5-47 { color: #00ff5f; }
 | 
			
		||||
.ansi-38-5-48 { color: #00ff87; }
 | 
			
		||||
.ansi-38-5-49 { color: #00ffaf; }
 | 
			
		||||
.ansi-38-5-50 { color: #00ffd7; }
 | 
			
		||||
.ansi-38-5-51 { color: #00ffff; }
 | 
			
		||||
.ansi-38-5-52 { color: #5f0000; }
 | 
			
		||||
.ansi-38-5-53 { color: #5f005f; }
 | 
			
		||||
.ansi-38-5-54 { color: #5f0087; }
 | 
			
		||||
.ansi-38-5-55 { color: #5f00af; }
 | 
			
		||||
.ansi-38-5-56 { color: #5f00d7; }
 | 
			
		||||
.ansi-38-5-57 { color: #5f00ff; }
 | 
			
		||||
.ansi-38-5-58 { color: #5f5f00; }
 | 
			
		||||
.ansi-38-5-59 { color: #5f5f5f; }
 | 
			
		||||
.ansi-38-5-60 { color: #5f5f87; }
 | 
			
		||||
.ansi-38-5-61 { color: #5f5faf; }
 | 
			
		||||
.ansi-38-5-62 { color: #5f5fd7; }
 | 
			
		||||
.ansi-38-5-63 { color: #5f5fff; }
 | 
			
		||||
.ansi-38-5-64 { color: #5f8700; }
 | 
			
		||||
.ansi-38-5-65 { color: #5f875f; }
 | 
			
		||||
.ansi-38-5-66 { color: #5f8787; }
 | 
			
		||||
.ansi-38-5-67 { color: #5f87af; }
 | 
			
		||||
.ansi-38-5-68 { color: #5f87d7; }
 | 
			
		||||
.ansi-38-5-69 { color: #5f87ff; }
 | 
			
		||||
.ansi-38-5-70 { color: #5faf00; }
 | 
			
		||||
.ansi-38-5-71 { color: #5faf5f; }
 | 
			
		||||
.ansi-38-5-72 { color: #5faf87; }
 | 
			
		||||
.ansi-38-5-73 { color: #5fafaf; }
 | 
			
		||||
.ansi-38-5-74 { color: #5fafd7; }
 | 
			
		||||
.ansi-38-5-75 { color: #5fafff; }
 | 
			
		||||
.ansi-38-5-76 { color: #5fd700; }
 | 
			
		||||
.ansi-38-5-77 { color: #5fd75f; }
 | 
			
		||||
.ansi-38-5-78 { color: #5fd787; }
 | 
			
		||||
.ansi-38-5-79 { color: #5fd7af; }
 | 
			
		||||
.ansi-38-5-80 { color: #5fd7d7; }
 | 
			
		||||
.ansi-38-5-81 { color: #5fd7ff; }
 | 
			
		||||
.ansi-38-5-82 { color: #5fff00; }
 | 
			
		||||
.ansi-38-5-83 { color: #5fff5f; }
 | 
			
		||||
.ansi-38-5-84 { color: #5fff87; }
 | 
			
		||||
.ansi-38-5-85 { color: #5fffaf; }
 | 
			
		||||
.ansi-38-5-86 { color: #5fffd7; }
 | 
			
		||||
.ansi-38-5-87 { color: #5fffff; }
 | 
			
		||||
.ansi-38-5-88 { color: #870000; }
 | 
			
		||||
.ansi-38-5-89 { color: #87005f; }
 | 
			
		||||
.ansi-38-5-90 { color: #870087; }
 | 
			
		||||
.ansi-38-5-91 { color: #8700af; }
 | 
			
		||||
.ansi-38-5-92 { color: #8700d7; }
 | 
			
		||||
.ansi-38-5-93 { color: #8700ff; }
 | 
			
		||||
.ansi-38-5-94 { color: #875f00; }
 | 
			
		||||
.ansi-38-5-95 { color: #875f5f; }
 | 
			
		||||
.ansi-38-5-96 { color: #875f87; }
 | 
			
		||||
.ansi-38-5-97 { color: #875faf; }
 | 
			
		||||
.ansi-38-5-98 { color: #875fd7; }
 | 
			
		||||
.ansi-38-5-99 { color: #875fff; }
 | 
			
		||||
.ansi-38-5-100 { color: #878700; }
 | 
			
		||||
.ansi-38-5-101 { color: #87875f; }
 | 
			
		||||
.ansi-38-5-102 { color: #878787; }
 | 
			
		||||
.ansi-38-5-103 { color: #8787af; }
 | 
			
		||||
.ansi-38-5-104 { color: #8787d7; }
 | 
			
		||||
.ansi-38-5-105 { color: #8787ff; }
 | 
			
		||||
.ansi-38-5-106 { color: #87af00; }
 | 
			
		||||
.ansi-38-5-107 { color: #87af5f; }
 | 
			
		||||
.ansi-38-5-108 { color: #87af87; }
 | 
			
		||||
.ansi-38-5-109 { color: #87afaf; }
 | 
			
		||||
.ansi-38-5-110 { color: #87afd7; }
 | 
			
		||||
.ansi-38-5-111 { color: #87afff; }
 | 
			
		||||
.ansi-38-5-112 { color: #87d700; }
 | 
			
		||||
.ansi-38-5-113 { color: #87d75f; }
 | 
			
		||||
.ansi-38-5-114 { color: #87d787; }
 | 
			
		||||
.ansi-38-5-115 { color: #87d7af; }
 | 
			
		||||
.ansi-38-5-116 { color: #87d7d7; }
 | 
			
		||||
.ansi-38-5-117 { color: #87d7ff; }
 | 
			
		||||
.ansi-38-5-118 { color: #87ff00; }
 | 
			
		||||
.ansi-38-5-119 { color: #87ff5f; }
 | 
			
		||||
.ansi-38-5-120 { color: #87ff87; }
 | 
			
		||||
.ansi-38-5-121 { color: #87ffaf; }
 | 
			
		||||
.ansi-38-5-122 { color: #87ffd7; }
 | 
			
		||||
.ansi-38-5-123 { color: #87ffff; }
 | 
			
		||||
.ansi-38-5-124 { color: #af0000; }
 | 
			
		||||
.ansi-38-5-125 { color: #af005f; }
 | 
			
		||||
.ansi-38-5-126 { color: #af0087; }
 | 
			
		||||
.ansi-38-5-127 { color: #af00af; }
 | 
			
		||||
.ansi-38-5-128 { color: #af00d7; }
 | 
			
		||||
.ansi-38-5-129 { color: #af00ff; }
 | 
			
		||||
.ansi-38-5-130 { color: #af5f00; }
 | 
			
		||||
.ansi-38-5-131 { color: #af5f5f; }
 | 
			
		||||
.ansi-38-5-132 { color: #af5f87; }
 | 
			
		||||
.ansi-38-5-133 { color: #af5faf; }
 | 
			
		||||
.ansi-38-5-134 { color: #af5fd7; }
 | 
			
		||||
.ansi-38-5-135 { color: #af5fff; }
 | 
			
		||||
.ansi-38-5-136 { color: #af8700; }
 | 
			
		||||
.ansi-38-5-137 { color: #af875f; }
 | 
			
		||||
.ansi-38-5-138 { color: #af8787; }
 | 
			
		||||
.ansi-38-5-139 { color: #af87af; }
 | 
			
		||||
.ansi-38-5-140 { color: #af87d7; }
 | 
			
		||||
.ansi-38-5-141 { color: #af87ff; }
 | 
			
		||||
.ansi-38-5-142 { color: #afaf00; }
 | 
			
		||||
.ansi-38-5-143 { color: #afaf5f; }
 | 
			
		||||
.ansi-38-5-144 { color: #afaf87; }
 | 
			
		||||
.ansi-38-5-145 { color: #afafaf; }
 | 
			
		||||
.ansi-38-5-146 { color: #afafd7; }
 | 
			
		||||
.ansi-38-5-147 { color: #afafff; }
 | 
			
		||||
.ansi-38-5-148 { color: #afd700; }
 | 
			
		||||
.ansi-38-5-149 { color: #afd75f; }
 | 
			
		||||
.ansi-38-5-150 { color: #afd787; }
 | 
			
		||||
.ansi-38-5-151 { color: #afd7af; }
 | 
			
		||||
.ansi-38-5-152 { color: #afd7d7; }
 | 
			
		||||
.ansi-38-5-153 { color: #afd7ff; }
 | 
			
		||||
.ansi-38-5-154 { color: #afff00; }
 | 
			
		||||
.ansi-38-5-155 { color: #afff5f; }
 | 
			
		||||
.ansi-38-5-156 { color: #afff87; }
 | 
			
		||||
.ansi-38-5-157 { color: #afffaf; }
 | 
			
		||||
.ansi-38-5-158 { color: #afffd7; }
 | 
			
		||||
.ansi-38-5-159 { color: #afffff; }
 | 
			
		||||
.ansi-38-5-160 { color: #d70000; }
 | 
			
		||||
.ansi-38-5-161 { color: #d7005f; }
 | 
			
		||||
.ansi-38-5-162 { color: #d70087; }
 | 
			
		||||
.ansi-38-5-163 { color: #d700af; }
 | 
			
		||||
.ansi-38-5-164 { color: #d700d7; }
 | 
			
		||||
.ansi-38-5-165 { color: #d700ff; }
 | 
			
		||||
.ansi-38-5-166 { color: #d75f00; }
 | 
			
		||||
.ansi-38-5-167 { color: #d75f5f; }
 | 
			
		||||
.ansi-38-5-168 { color: #d75f87; }
 | 
			
		||||
.ansi-38-5-169 { color: #d75faf; }
 | 
			
		||||
.ansi-38-5-170 { color: #d75fd7; }
 | 
			
		||||
.ansi-38-5-171 { color: #d75fff; }
 | 
			
		||||
.ansi-38-5-172 { color: #d78700; }
 | 
			
		||||
.ansi-38-5-173 { color: #d7875f; }
 | 
			
		||||
.ansi-38-5-174 { color: #d78787; }
 | 
			
		||||
.ansi-38-5-175 { color: #d787af; }
 | 
			
		||||
.ansi-38-5-176 { color: #d787d7; }
 | 
			
		||||
.ansi-38-5-177 { color: #d787ff; }
 | 
			
		||||
.ansi-38-5-178 { color: #d7af00; }
 | 
			
		||||
.ansi-38-5-179 { color: #d7af5f; }
 | 
			
		||||
.ansi-38-5-180 { color: #d7af87; }
 | 
			
		||||
.ansi-38-5-181 { color: #d7afaf; }
 | 
			
		||||
.ansi-38-5-182 { color: #d7afd7; }
 | 
			
		||||
.ansi-38-5-183 { color: #d7afff; }
 | 
			
		||||
.ansi-38-5-184 { color: #d7d700; }
 | 
			
		||||
.ansi-38-5-185 { color: #d7d75f; }
 | 
			
		||||
.ansi-38-5-186 { color: #d7d787; }
 | 
			
		||||
.ansi-38-5-187 { color: #d7d7af; }
 | 
			
		||||
.ansi-38-5-188 { color: #d7d7d7; }
 | 
			
		||||
.ansi-38-5-189 { color: #d7d7ff; }
 | 
			
		||||
.ansi-38-5-190 { color: #d7ff00; }
 | 
			
		||||
.ansi-38-5-191 { color: #d7ff5f; }
 | 
			
		||||
.ansi-38-5-192 { color: #d7ff87; }
 | 
			
		||||
.ansi-38-5-193 { color: #d7ffaf; }
 | 
			
		||||
.ansi-38-5-194 { color: #d7ffd7; }
 | 
			
		||||
.ansi-38-5-195 { color: #d7ffff; }
 | 
			
		||||
.ansi-38-5-196 { color: #ff0000; }
 | 
			
		||||
.ansi-38-5-197 { color: #ff005f; }
 | 
			
		||||
.ansi-38-5-198 { color: #ff0087; }
 | 
			
		||||
.ansi-38-5-199 { color: #ff00af; }
 | 
			
		||||
.ansi-38-5-200 { color: #ff00d7; }
 | 
			
		||||
.ansi-38-5-201 { color: #ff00ff; }
 | 
			
		||||
.ansi-38-5-202 { color: #ff5f00; }
 | 
			
		||||
.ansi-38-5-203 { color: #ff5f5f; }
 | 
			
		||||
.ansi-38-5-204 { color: #ff5f87; }
 | 
			
		||||
.ansi-38-5-205 { color: #ff5faf; }
 | 
			
		||||
.ansi-38-5-206 { color: #ff5fd7; }
 | 
			
		||||
.ansi-38-5-207 { color: #ff5fff; }
 | 
			
		||||
.ansi-38-5-208 { color: #ff8700; }
 | 
			
		||||
.ansi-38-5-209 { color: #ff875f; }
 | 
			
		||||
.ansi-38-5-210 { color: #ff8787; }
 | 
			
		||||
.ansi-38-5-211 { color: #ff87af; }
 | 
			
		||||
.ansi-38-5-212 { color: #ff87d7; }
 | 
			
		||||
.ansi-38-5-213 { color: #ff87ff; }
 | 
			
		||||
.ansi-38-5-214 { color: #ffaf00; }
 | 
			
		||||
.ansi-38-5-215 { color: #ffaf5f; }
 | 
			
		||||
.ansi-38-5-216 { color: #ffaf87; }
 | 
			
		||||
.ansi-38-5-217 { color: #ffafaf; }
 | 
			
		||||
.ansi-38-5-218 { color: #ffafd7; }
 | 
			
		||||
.ansi-38-5-219 { color: #ffafff; }
 | 
			
		||||
.ansi-38-5-220 { color: #ffd700; }
 | 
			
		||||
.ansi-38-5-221 { color: #ffd75f; }
 | 
			
		||||
.ansi-38-5-222 { color: #ffd787; }
 | 
			
		||||
.ansi-38-5-223 { color: #ffd7af; }
 | 
			
		||||
.ansi-38-5-224 { color: #ffd7d7; }
 | 
			
		||||
.ansi-38-5-225 { color: #ffd7ff; }
 | 
			
		||||
.ansi-38-5-226 { color: #ffff00; }
 | 
			
		||||
.ansi-38-5-227 { color: #ffff5f; }
 | 
			
		||||
.ansi-38-5-228 { color: #ffff87; }
 | 
			
		||||
.ansi-38-5-229 { color: #ffffaf; }
 | 
			
		||||
.ansi-38-5-230 { color: #ffffd7; }
 | 
			
		||||
.ansi-38-5-231 { color: #ffffff; }
 | 
			
		||||
.ansi-38-5-232 { color: #080808; }
 | 
			
		||||
.ansi-38-5-233 { color: #121212; }
 | 
			
		||||
.ansi-38-5-234 { color: #1c1c1c; }
 | 
			
		||||
.ansi-38-5-235 { color: #262626; }
 | 
			
		||||
.ansi-38-5-236 { color: #303030; }
 | 
			
		||||
.ansi-38-5-237 { color: #3a3a3a; }
 | 
			
		||||
.ansi-38-5-238 { color: #444444; }
 | 
			
		||||
.ansi-38-5-239 { color: #4e4e4e; }
 | 
			
		||||
.ansi-38-5-240 { color: #585858; }
 | 
			
		||||
.ansi-38-5-241 { color: #626262; }
 | 
			
		||||
.ansi-38-5-242 { color: #6c6c6c; }
 | 
			
		||||
.ansi-38-5-243 { color: #767676; }
 | 
			
		||||
.ansi-38-5-244 { color: #808080; }
 | 
			
		||||
.ansi-38-5-245 { color: #8a8a8a; }
 | 
			
		||||
.ansi-38-5-246 { color: #949494; }
 | 
			
		||||
.ansi-38-5-247 { color: #9e9e9e; }
 | 
			
		||||
.ansi-38-5-248 { color: #a8a8a8; }
 | 
			
		||||
.ansi-38-5-249 { color: #b2b2b2; }
 | 
			
		||||
.ansi-38-5-250 { color: #bcbcbc; }
 | 
			
		||||
.ansi-38-5-251 { color: #c6c6c6; }
 | 
			
		||||
.ansi-38-5-252 { color: #d0d0d0; }
 | 
			
		||||
.ansi-38-5-253 { color: #dadada; }
 | 
			
		||||
.ansi-38-5-254 { color: #e4e4e4; }
 | 
			
		||||
.ansi-38-5-255 { color: #eeeeee; }
 | 
			
		||||
 | 
			
		||||
/* xterm256 background colors */
 | 
			
		||||
.ansi-48-5-0 { background-color: #000000; }
 | 
			
		||||
.ansi-48-5-1 { background-color: #800000; }
 | 
			
		||||
.ansi-48-5-2 { background-color: #008000; }
 | 
			
		||||
.ansi-48-5-3 { background-color: #808000; }
 | 
			
		||||
.ansi-48-5-4 { background-color: #000080; }
 | 
			
		||||
.ansi-48-5-5 { background-color: #800080; }
 | 
			
		||||
.ansi-48-5-6 { background-color: #008080; }
 | 
			
		||||
.ansi-48-5-7 { background-color: #c0c0c0; }
 | 
			
		||||
.ansi-48-5-8 { background-color: #808080; }
 | 
			
		||||
.ansi-48-5-9 { background-color: #ff0000; }
 | 
			
		||||
.ansi-48-5-10 { background-color: #00ff00; }
 | 
			
		||||
.ansi-48-5-11 { background-color: #ffff00; }
 | 
			
		||||
.ansi-48-5-12 { background-color: #0000ff; }
 | 
			
		||||
.ansi-48-5-13 { background-color: #ff00ff; }
 | 
			
		||||
.ansi-48-5-14 { background-color: #00ffff; }
 | 
			
		||||
.ansi-48-5-15 { background-color: #ffffff; }
 | 
			
		||||
.ansi-48-5-16 { background-color: #000000; }
 | 
			
		||||
.ansi-48-5-17 { background-color: #00005f; }
 | 
			
		||||
.ansi-48-5-18 { background-color: #000087; }
 | 
			
		||||
.ansi-48-5-19 { background-color: #0000af; }
 | 
			
		||||
.ansi-48-5-20 { background-color: #0000d7; }
 | 
			
		||||
.ansi-48-5-21 { background-color: #0000ff; }
 | 
			
		||||
.ansi-48-5-22 { background-color: #005f00; }
 | 
			
		||||
.ansi-48-5-23 { background-color: #005f5f; }
 | 
			
		||||
.ansi-48-5-24 { background-color: #005f87; }
 | 
			
		||||
.ansi-48-5-25 { background-color: #005faf; }
 | 
			
		||||
.ansi-48-5-26 { background-color: #005fd7; }
 | 
			
		||||
.ansi-48-5-27 { background-color: #005fff; }
 | 
			
		||||
.ansi-48-5-28 { background-color: #008700; }
 | 
			
		||||
.ansi-48-5-29 { background-color: #00875f; }
 | 
			
		||||
.ansi-48-5-30 { background-color: #008787; }
 | 
			
		||||
.ansi-48-5-31 { background-color: #0087af; }
 | 
			
		||||
.ansi-48-5-32 { background-color: #0087d7; }
 | 
			
		||||
.ansi-48-5-33 { background-color: #0087ff; }
 | 
			
		||||
.ansi-48-5-34 { background-color: #00af00; }
 | 
			
		||||
.ansi-48-5-35 { background-color: #00af5f; }
 | 
			
		||||
.ansi-48-5-36 { background-color: #00af87; }
 | 
			
		||||
.ansi-48-5-37 { background-color: #00afaf; }
 | 
			
		||||
.ansi-48-5-38 { background-color: #00afd7; }
 | 
			
		||||
.ansi-48-5-39 { background-color: #00afff; }
 | 
			
		||||
.ansi-48-5-40 { background-color: #00d700; }
 | 
			
		||||
.ansi-48-5-41 { background-color: #00d75f; }
 | 
			
		||||
.ansi-48-5-42 { background-color: #00d787; }
 | 
			
		||||
.ansi-48-5-43 { background-color: #00d7af; }
 | 
			
		||||
.ansi-48-5-44 { background-color: #00d7d7; }
 | 
			
		||||
.ansi-48-5-45 { background-color: #00d7ff; }
 | 
			
		||||
.ansi-48-5-46 { background-color: #00ff00; }
 | 
			
		||||
.ansi-48-5-47 { background-color: #00ff5f; }
 | 
			
		||||
.ansi-48-5-48 { background-color: #00ff87; }
 | 
			
		||||
.ansi-48-5-49 { background-color: #00ffaf; }
 | 
			
		||||
.ansi-48-5-50 { background-color: #00ffd7; }
 | 
			
		||||
.ansi-48-5-51 { background-color: #00ffff; }
 | 
			
		||||
.ansi-48-5-52 { background-color: #5f0000; }
 | 
			
		||||
.ansi-48-5-53 { background-color: #5f005f; }
 | 
			
		||||
.ansi-48-5-54 { background-color: #5f0087; }
 | 
			
		||||
.ansi-48-5-55 { background-color: #5f00af; }
 | 
			
		||||
.ansi-48-5-56 { background-color: #5f00d7; }
 | 
			
		||||
.ansi-48-5-57 { background-color: #5f00ff; }
 | 
			
		||||
.ansi-48-5-58 { background-color: #5f5f00; }
 | 
			
		||||
.ansi-48-5-59 { background-color: #5f5f5f; }
 | 
			
		||||
.ansi-48-5-60 { background-color: #5f5f87; }
 | 
			
		||||
.ansi-48-5-61 { background-color: #5f5faf; }
 | 
			
		||||
.ansi-48-5-62 { background-color: #5f5fd7; }
 | 
			
		||||
.ansi-48-5-63 { background-color: #5f5fff; }
 | 
			
		||||
.ansi-48-5-64 { background-color: #5f8700; }
 | 
			
		||||
.ansi-48-5-65 { background-color: #5f875f; }
 | 
			
		||||
.ansi-48-5-66 { background-color: #5f8787; }
 | 
			
		||||
.ansi-48-5-67 { background-color: #5f87af; }
 | 
			
		||||
.ansi-48-5-68 { background-color: #5f87d7; }
 | 
			
		||||
.ansi-48-5-69 { background-color: #5f87ff; }
 | 
			
		||||
.ansi-48-5-70 { background-color: #5faf00; }
 | 
			
		||||
.ansi-48-5-71 { background-color: #5faf5f; }
 | 
			
		||||
.ansi-48-5-72 { background-color: #5faf87; }
 | 
			
		||||
.ansi-48-5-73 { background-color: #5fafaf; }
 | 
			
		||||
.ansi-48-5-74 { background-color: #5fafd7; }
 | 
			
		||||
.ansi-48-5-75 { background-color: #5fafff; }
 | 
			
		||||
.ansi-48-5-76 { background-color: #5fd700; }
 | 
			
		||||
.ansi-48-5-77 { background-color: #5fd75f; }
 | 
			
		||||
.ansi-48-5-78 { background-color: #5fd787; }
 | 
			
		||||
.ansi-48-5-79 { background-color: #5fd7af; }
 | 
			
		||||
.ansi-48-5-80 { background-color: #5fd7d7; }
 | 
			
		||||
.ansi-48-5-81 { background-color: #5fd7ff; }
 | 
			
		||||
.ansi-48-5-82 { background-color: #5fff00; }
 | 
			
		||||
.ansi-48-5-83 { background-color: #5fff5f; }
 | 
			
		||||
.ansi-48-5-84 { background-color: #5fff87; }
 | 
			
		||||
.ansi-48-5-85 { background-color: #5fffaf; }
 | 
			
		||||
.ansi-48-5-86 { background-color: #5fffd7; }
 | 
			
		||||
.ansi-48-5-87 { background-color: #5fffff; }
 | 
			
		||||
.ansi-48-5-88 { background-color: #870000; }
 | 
			
		||||
.ansi-48-5-89 { background-color: #87005f; }
 | 
			
		||||
.ansi-48-5-90 { background-color: #870087; }
 | 
			
		||||
.ansi-48-5-91 { background-color: #8700af; }
 | 
			
		||||
.ansi-48-5-92 { background-color: #8700d7; }
 | 
			
		||||
.ansi-48-5-93 { background-color: #8700ff; }
 | 
			
		||||
.ansi-48-5-94 { background-color: #875f00; }
 | 
			
		||||
.ansi-48-5-95 { background-color: #875f5f; }
 | 
			
		||||
.ansi-48-5-96 { background-color: #875f87; }
 | 
			
		||||
.ansi-48-5-97 { background-color: #875faf; }
 | 
			
		||||
.ansi-48-5-98 { background-color: #875fd7; }
 | 
			
		||||
.ansi-48-5-99 { background-color: #875fff; }
 | 
			
		||||
.ansi-48-5-100 { background-color: #878700; }
 | 
			
		||||
.ansi-48-5-101 { background-color: #87875f; }
 | 
			
		||||
.ansi-48-5-102 { background-color: #878787; }
 | 
			
		||||
.ansi-48-5-103 { background-color: #8787af; }
 | 
			
		||||
.ansi-48-5-104 { background-color: #8787d7; }
 | 
			
		||||
.ansi-48-5-105 { background-color: #8787ff; }
 | 
			
		||||
.ansi-48-5-106 { background-color: #87af00; }
 | 
			
		||||
.ansi-48-5-107 { background-color: #87af5f; }
 | 
			
		||||
.ansi-48-5-108 { background-color: #87af87; }
 | 
			
		||||
.ansi-48-5-109 { background-color: #87afaf; }
 | 
			
		||||
.ansi-48-5-110 { background-color: #87afd7; }
 | 
			
		||||
.ansi-48-5-111 { background-color: #87afff; }
 | 
			
		||||
.ansi-48-5-112 { background-color: #87d700; }
 | 
			
		||||
.ansi-48-5-113 { background-color: #87d75f; }
 | 
			
		||||
.ansi-48-5-114 { background-color: #87d787; }
 | 
			
		||||
.ansi-48-5-115 { background-color: #87d7af; }
 | 
			
		||||
.ansi-48-5-116 { background-color: #87d7d7; }
 | 
			
		||||
.ansi-48-5-117 { background-color: #87d7ff; }
 | 
			
		||||
.ansi-48-5-118 { background-color: #87ff00; }
 | 
			
		||||
.ansi-48-5-119 { background-color: #87ff5f; }
 | 
			
		||||
.ansi-48-5-120 { background-color: #87ff87; }
 | 
			
		||||
.ansi-48-5-121 { background-color: #87ffaf; }
 | 
			
		||||
.ansi-48-5-122 { background-color: #87ffd7; }
 | 
			
		||||
.ansi-48-5-123 { background-color: #87ffff; }
 | 
			
		||||
.ansi-48-5-124 { background-color: #af0000; }
 | 
			
		||||
.ansi-48-5-125 { background-color: #af005f; }
 | 
			
		||||
.ansi-48-5-126 { background-color: #af0087; }
 | 
			
		||||
.ansi-48-5-127 { background-color: #af00af; }
 | 
			
		||||
.ansi-48-5-128 { background-color: #af00d7; }
 | 
			
		||||
.ansi-48-5-129 { background-color: #af00ff; }
 | 
			
		||||
.ansi-48-5-130 { background-color: #af5f00; }
 | 
			
		||||
.ansi-48-5-131 { background-color: #af5f5f; }
 | 
			
		||||
.ansi-48-5-132 { background-color: #af5f87; }
 | 
			
		||||
.ansi-48-5-133 { background-color: #af5faf; }
 | 
			
		||||
.ansi-48-5-134 { background-color: #af5fd7; }
 | 
			
		||||
.ansi-48-5-135 { background-color: #af5fff; }
 | 
			
		||||
.ansi-48-5-136 { background-color: #af8700; }
 | 
			
		||||
.ansi-48-5-137 { background-color: #af875f; }
 | 
			
		||||
.ansi-48-5-138 { background-color: #af8787; }
 | 
			
		||||
.ansi-48-5-139 { background-color: #af87af; }
 | 
			
		||||
.ansi-48-5-140 { background-color: #af87d7; }
 | 
			
		||||
.ansi-48-5-141 { background-color: #af87ff; }
 | 
			
		||||
.ansi-48-5-142 { background-color: #afaf00; }
 | 
			
		||||
.ansi-48-5-143 { background-color: #afaf5f; }
 | 
			
		||||
.ansi-48-5-144 { background-color: #afaf87; }
 | 
			
		||||
.ansi-48-5-145 { background-color: #afafaf; }
 | 
			
		||||
.ansi-48-5-146 { background-color: #afafd7; }
 | 
			
		||||
.ansi-48-5-147 { background-color: #afafff; }
 | 
			
		||||
.ansi-48-5-148 { background-color: #afd700; }
 | 
			
		||||
.ansi-48-5-149 { background-color: #afd75f; }
 | 
			
		||||
.ansi-48-5-150 { background-color: #afd787; }
 | 
			
		||||
.ansi-48-5-151 { background-color: #afd7af; }
 | 
			
		||||
.ansi-48-5-152 { background-color: #afd7d7; }
 | 
			
		||||
.ansi-48-5-153 { background-color: #afd7ff; }
 | 
			
		||||
.ansi-48-5-154 { background-color: #afff00; }
 | 
			
		||||
.ansi-48-5-155 { background-color: #afff5f; }
 | 
			
		||||
.ansi-48-5-156 { background-color: #afff87; }
 | 
			
		||||
.ansi-48-5-157 { background-color: #afffaf; }
 | 
			
		||||
.ansi-48-5-158 { background-color: #afffd7; }
 | 
			
		||||
.ansi-48-5-159 { background-color: #afffff; }
 | 
			
		||||
.ansi-48-5-160 { background-color: #d70000; }
 | 
			
		||||
.ansi-48-5-161 { background-color: #d7005f; }
 | 
			
		||||
.ansi-48-5-162 { background-color: #d70087; }
 | 
			
		||||
.ansi-48-5-163 { background-color: #d700af; }
 | 
			
		||||
.ansi-48-5-164 { background-color: #d700d7; }
 | 
			
		||||
.ansi-48-5-165 { background-color: #d700ff; }
 | 
			
		||||
.ansi-48-5-166 { background-color: #d75f00; }
 | 
			
		||||
.ansi-48-5-167 { background-color: #d75f5f; }
 | 
			
		||||
.ansi-48-5-168 { background-color: #d75f87; }
 | 
			
		||||
.ansi-48-5-169 { background-color: #d75faf; }
 | 
			
		||||
.ansi-48-5-170 { background-color: #d75fd7; }
 | 
			
		||||
.ansi-48-5-171 { background-color: #d75fff; }
 | 
			
		||||
.ansi-48-5-172 { background-color: #d78700; }
 | 
			
		||||
.ansi-48-5-173 { background-color: #d7875f; }
 | 
			
		||||
.ansi-48-5-174 { background-color: #d78787; }
 | 
			
		||||
.ansi-48-5-175 { background-color: #d787af; }
 | 
			
		||||
.ansi-48-5-176 { background-color: #d787d7; }
 | 
			
		||||
.ansi-48-5-177 { background-color: #d787ff; }
 | 
			
		||||
.ansi-48-5-178 { background-color: #d7af00; }
 | 
			
		||||
.ansi-48-5-179 { background-color: #d7af5f; }
 | 
			
		||||
.ansi-48-5-180 { background-color: #d7af87; }
 | 
			
		||||
.ansi-48-5-181 { background-color: #d7afaf; }
 | 
			
		||||
.ansi-48-5-182 { background-color: #d7afd7; }
 | 
			
		||||
.ansi-48-5-183 { background-color: #d7afff; }
 | 
			
		||||
.ansi-48-5-184 { background-color: #d7d700; }
 | 
			
		||||
.ansi-48-5-185 { background-color: #d7d75f; }
 | 
			
		||||
.ansi-48-5-186 { background-color: #d7d787; }
 | 
			
		||||
.ansi-48-5-187 { background-color: #d7d7af; }
 | 
			
		||||
.ansi-48-5-188 { background-color: #d7d7d7; }
 | 
			
		||||
.ansi-48-5-189 { background-color: #d7d7ff; }
 | 
			
		||||
.ansi-48-5-190 { background-color: #d7ff00; }
 | 
			
		||||
.ansi-48-5-191 { background-color: #d7ff5f; }
 | 
			
		||||
.ansi-48-5-192 { background-color: #d7ff87; }
 | 
			
		||||
.ansi-48-5-193 { background-color: #d7ffaf; }
 | 
			
		||||
.ansi-48-5-194 { background-color: #d7ffd7; }
 | 
			
		||||
.ansi-48-5-195 { background-color: #d7ffff; }
 | 
			
		||||
.ansi-48-5-196 { background-color: #ff0000; }
 | 
			
		||||
.ansi-48-5-197 { background-color: #ff005f; }
 | 
			
		||||
.ansi-48-5-198 { background-color: #ff0087; }
 | 
			
		||||
.ansi-48-5-199 { background-color: #ff00af; }
 | 
			
		||||
.ansi-48-5-200 { background-color: #ff00d7; }
 | 
			
		||||
.ansi-48-5-201 { background-color: #ff00ff; }
 | 
			
		||||
.ansi-48-5-202 { background-color: #ff5f00; }
 | 
			
		||||
.ansi-48-5-203 { background-color: #ff5f5f; }
 | 
			
		||||
.ansi-48-5-204 { background-color: #ff5f87; }
 | 
			
		||||
.ansi-48-5-205 { background-color: #ff5faf; }
 | 
			
		||||
.ansi-48-5-206 { background-color: #ff5fd7; }
 | 
			
		||||
.ansi-48-5-207 { background-color: #ff5fff; }
 | 
			
		||||
.ansi-48-5-208 { background-color: #ff8700; }
 | 
			
		||||
.ansi-48-5-209 { background-color: #ff875f; }
 | 
			
		||||
.ansi-48-5-210 { background-color: #ff8787; }
 | 
			
		||||
.ansi-48-5-211 { background-color: #ff87af; }
 | 
			
		||||
.ansi-48-5-212 { background-color: #ff87d7; }
 | 
			
		||||
.ansi-48-5-213 { background-color: #ff87ff; }
 | 
			
		||||
.ansi-48-5-214 { background-color: #ffaf00; }
 | 
			
		||||
.ansi-48-5-215 { background-color: #ffaf5f; }
 | 
			
		||||
.ansi-48-5-216 { background-color: #ffaf87; }
 | 
			
		||||
.ansi-48-5-217 { background-color: #ffafaf; }
 | 
			
		||||
.ansi-48-5-218 { background-color: #ffafd7; }
 | 
			
		||||
.ansi-48-5-219 { background-color: #ffafff; }
 | 
			
		||||
.ansi-48-5-220 { background-color: #ffd700; }
 | 
			
		||||
.ansi-48-5-221 { background-color: #ffd75f; }
 | 
			
		||||
.ansi-48-5-222 { background-color: #ffd787; }
 | 
			
		||||
.ansi-48-5-223 { background-color: #ffd7af; }
 | 
			
		||||
.ansi-48-5-224 { background-color: #ffd7d7; }
 | 
			
		||||
.ansi-48-5-225 { background-color: #ffd7ff; }
 | 
			
		||||
.ansi-48-5-226 { background-color: #ffff00; }
 | 
			
		||||
.ansi-48-5-227 { background-color: #ffff5f; }
 | 
			
		||||
.ansi-48-5-228 { background-color: #ffff87; }
 | 
			
		||||
.ansi-48-5-229 { background-color: #ffffaf; }
 | 
			
		||||
.ansi-48-5-230 { background-color: #ffffd7; }
 | 
			
		||||
.ansi-48-5-231 { background-color: #ffffff; }
 | 
			
		||||
.ansi-48-5-232 { background-color: #080808; }
 | 
			
		||||
.ansi-48-5-233 { background-color: #121212; }
 | 
			
		||||
.ansi-48-5-234 { background-color: #1c1c1c; }
 | 
			
		||||
.ansi-48-5-235 { background-color: #262626; }
 | 
			
		||||
.ansi-48-5-236 { background-color: #303030; }
 | 
			
		||||
.ansi-48-5-237 { background-color: #3a3a3a; }
 | 
			
		||||
.ansi-48-5-248 { background-color: #444444; }
 | 
			
		||||
.ansi-48-5-239 { background-color: #4e4e4e; }
 | 
			
		||||
.ansi-48-5-240 { background-color: #585858; }
 | 
			
		||||
.ansi-48-5-241 { background-color: #626262; }
 | 
			
		||||
.ansi-48-5-242 { background-color: #6c6c6c; }
 | 
			
		||||
.ansi-48-5-243 { background-color: #767676; }
 | 
			
		||||
.ansi-48-5-244 { background-color: #808080; }
 | 
			
		||||
.ansi-48-5-245 { background-color: #8a8a8a; }
 | 
			
		||||
.ansi-48-5-246 { background-color: #949494; }
 | 
			
		||||
.ansi-48-5-247 { background-color: #9e9e9e; }
 | 
			
		||||
.ansi-48-5-248 { background-color: #a8a8a8; }
 | 
			
		||||
.ansi-48-5-249 { background-color: #b2b2b2; }
 | 
			
		||||
.ansi-48-5-250 { background-color: #bcbcbc; }
 | 
			
		||||
.ansi-48-5-251 { background-color: #c6c6c6; }
 | 
			
		||||
.ansi-48-5-252 { background-color: #d0d0d0; }
 | 
			
		||||
.ansi-48-5-253 { background-color: #dadada; }
 | 
			
		||||
.ansi-48-5-254 { background-color: #e4e4e4; }
 | 
			
		||||
.ansi-48-5-255 { background-color: #eeeeee; }
 | 
			
		||||
 | 
			
		||||
@@ -96,8 +96,72 @@ input[type=radio]:checked + label:before {
 | 
			
		||||
.toolsep { margin-right: 1vw; padding:0;  padding-top: 1vh; padding-bottom: 2.5vh; border-bottom: 1px #AAA solid; height: 1vh; display: block; width: 64%;}
 | 
			
		||||
.calc_data { padding-top: 2.5vh; font-size: 1.5vh;  font-family: 'Open Sans', sans-serif;}
 | 
			
		||||
 | 
			
		||||
#client {
 | 
			
		||||
	position: fixed;
 | 
			
		||||
	bottom: 0px;
 | 
			
		||||
	width: 80%;
 | 
			
		||||
	margin:0;
 | 
			
		||||
}
 | 
			
		||||
#client-bar {
 | 
			
		||||
	width:100%;
 | 
			
		||||
	margin: 0;
 | 
			
		||||
}
 | 
			
		||||
#client-bar-control {
 | 
			
		||||
	margin: 0;
 | 
			
		||||
}
 | 
			
		||||
.client-bar-control-container:hover, .client-bar-control-container:hover a:hover {
 | 
			
		||||
  color: black;
 | 
			
		||||
  background-color: lightgrey;
 | 
			
		||||
}
 | 
			
		||||
.client-bar-control-container {
 | 
			
		||||
	width: 5vw;
 | 
			
		||||
	text-align: center;
 | 
			
		||||
	background-color: black;
 | 
			
		||||
	border-top: 1px solid darkgrey;
 | 
			
		||||
	border-left: 1px solid darkgrey;
 | 
			
		||||
	border-right: 1px solid darkgrey;
 | 
			
		||||
	margin-bottom: 0;
 | 
			
		||||
	border-radius: 5px 5px 0 0;
 | 
			
		||||
	display: block;
 | 
			
		||||
	padding: 0;
 | 
			
		||||
	text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.client-bar-control-container a:link, .client-bar-control-container a:visited { color: white;  text-decoration: none }
 | 
			
		||||
#client-tab-desc{ padding-left: 0.5vw;}
 | 
			
		||||
 | 
			
		||||
#client-term-container {
 | 
			
		||||
  height: 40vh;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  background-color: black;
 | 
			
		||||
}
 | 
			
		||||
#client-term-output {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 30vh;
 | 
			
		||||
  background-color: #111;
 | 
			
		||||
  border-bottom: 1px solid #444;
 | 
			
		||||
  overflow-y: auto;
 | 
			
		||||
  overflow-x: hidden;
 | 
			
		||||
  white-space: pre-wrap;
 | 
			
		||||
  word-wrap: break-word;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  border: 0;
 | 
			
		||||
  font-family: monospace;
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
#client-term-prompt {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 0.9vh;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  white-space: pre-wrap;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  background-color: #111
 | 
			
		||||
}
 | 
			
		||||
.hidden { display: none; }
 | 
			
		||||
#client-term-entry { width: 100%; height: 5vh; border: 0; border-top: 1px solid white; border-bottom: 1px solid white; background-color: #222; margin: 0; padding:0; resize: none; color: silver; vertical-align: middle;}
 | 
			
		||||
 | 
			
		||||
@media only screen and (max-width: 1290px) { #client-tab-desc { display: none; } }
 | 
			
		||||
@media only screen and (max-width: 900px) { .wvg-navbar { height: 6vh; font-size: 1.25em;}  .wvg-controls { width: 65%;}  .wvg-navbar li { padding-left: 1vw; padding-right: 2vw; padding-top: 2.0vh;} .wvg-tools span, .select-route-map {width: 95%;}
 | 
			
		||||
      .menu-button { font-weight: bold; font-size:1.5em; padding-top: 0.5vh;  }}
 | 
			
		||||
@media only screen and (max-width: 500px) { .wvg-controls { width: 100%;}  .wvg-tablink { font-size: 0.75em; padding:0; padding-left: 2vw; padding-right: 2vw;} }
 | 
			
		||||
@media only screen and (max-height: 575px) { .reset-container { height: 4em;} .wvg-controls { overflow-y: auto; margin-bottom: -5vh;} .wvg-tools {font-size: 0.75em;} }
 | 
			
		||||
      .menu-button { font-weight: bold; font-size:1.5em; padding-top: 0.5vh;  }   #client-tab-desc { display: none; } }
 | 
			
		||||
@media only screen and (max-width: 500px) { .wvg-controls { width: 100%;}  .wvg-tablink { font-size: 0.75em; padding:0; padding-left: 2vw; padding-right: 2vw; } }
 | 
			
		||||
@media only screen and (max-height: 575px) { .reset-container { height: 4em;} .wvg-controls { overflow-y: auto; margin-bottom: -5vh;} .wvg-tools {font-size: 0.75em;}  }
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,9 @@
 | 
			
		||||
      <script src="js/mapviewgl.js"></script>
 | 
			
		||||
      <link href="https://fonts.googleapis.com/css?family=Open+Sans|Raleway:400,700,700i" rel="stylesheet">
 | 
			
		||||
      <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> -->
 | 
			
		||||
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
 | 
			
		||||
      <link href="styles/styles.css" rel="stylesheet">
 | 
			
		||||
      <link href="styles/ansi.css" rel="stylesheet">
 | 
			
		||||
      <script src="https://code.jquery.com/jquery-3.1.0.min.js"   integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s="   crossorigin="anonymous"></script>
 | 
			
		||||
      <script src="js/GUI.Utils.js"></script>
 | 
			
		||||
      <script>
 | 
			
		||||
@@ -121,5 +123,23 @@
 | 
			
		||||
    		<div class="reset-container"><span class="reset-button">  Reset </span></div>
 | 
			
		||||
 | 
			
		||||
      </div>
 | 
			
		||||
      <div id="client">
 | 
			
		||||
	      <div id="client-bar">
 | 
			
		||||
		      <span class="client-bar-control-container">
 | 
			
		||||
			      <a href="#" id="client-bar-control"><i id="client-ico-up" class="fa fa-chevron-up" aria-hidden="true"></i><i id="client-ico-down" class="fa fa-chevron-down hidden" aria-hidden="true"></i><b id="client-tab-desc">Client</b></a>
 | 
			
		||||
		      </span>
 | 
			
		||||
	      </div>
 | 
			
		||||
        <div id="client-term-container" class="hidden">
 | 
			
		||||
          <form id="client-term">
 | 
			
		||||
            <div id="client-term-output" class="ansi-37 ansi-40"></div>
 | 
			
		||||
            <div id="client-term-prompt" class="ansi-37 ansi-40"></div>
 | 
			
		||||
            <textarea id="client-term-entry" autocomplete="off" autofocus></textarea>
 | 
			
		||||
            <button id="client-login">(Re)Connect</button>
 | 
			
		||||
          </form>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <script src="js/wsclient.js"></script>
 | 
			
		||||
      <script src="js/local.js"></script>
 | 
			
		||||
  </body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user