Cleaned out old tests of js weclient component.

This commit is contained in:
Griatch 2016-02-10 22:32:08 +01:00
parent 1044006303
commit 07471d1e8f
4 changed files with 0 additions and 1054 deletions

View file

@ -1,298 +0,0 @@
/*
Evennia ajax webclient (javascript component)
The client is composed of several parts:
templates/webclient.html - the main page
webclient/views.py - the django view serving the template (based on urls.py pattern)
evennia/server/webclient.py - the server component receiving requests from the client
this file - the javascript component handling dynamic ajax content
This implements an ajax mud client for use with Evennia, using jQuery
for simplicity. It communicates with the Twisted server on the address
/webclientdata through POST requests. Each request must at least
contain the 'mode' of the request to be handled by the protocol:
mode 'receive' - tell the server that we are ready to receive data. This is a
long-polling (comet-style) request since the server
will not reply until it actually has data available.
The returned data object has two variables 'msg' and 'data'
where msg should be output and 'data' is an arbitrary piece
of data the server and client understands (not used in default
client).
mode 'input' - the user has input data on some form. The POST request
should also contain variables 'msg' and 'data' where
the 'msg' is a string and 'data' is an arbitrary piece
of data from the client that the server knows how to
deal with (not used in this example client).
mode 'init' - starts the connection. All setup the server is requered to do
should happen at this point. The server returns a data object
with the 'msg' property containing the server address.
mode 'close' - closes the connection. The server closes the session and does
cleanup at this point.
*/
// jQuery must be imported by the calling html page before this script
// There are plenty of help on using the jQuery library on http://jquery.com/
$.fn.appendCaret = function() {
/* jQuery extension that will forward the caret to the end of the input, and
won't harm other elements (although calling this on multiple inputs might
not have the expected consequences).
Thanks to
http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
for the good starting point. */
return this.each(function() {
var range,
// Index at where to place the caret.
end,
self = this;
if (self.setSelectionRange) {
// other browsers
end = self.value.length;
self.focus();
// NOTE: Need to delay the caret movement until after the callstack.
setTimeout(function() {
self.setSelectionRange(end, end);
}, 0);
}
else if (self.createTextRange) {
// IE
end = self.value.length - 1;
range = self.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', end);
// NOTE: I haven't tested to see if IE has the same problem as
// W3C browsers seem to have in this context (needing to fire
// select after callstack).
range.select();
}
});
};
// Server communications
var CLIENT_HASH = '0'; // variable holding the client id
function webclient_receive(){
// This starts an asynchronous long-polling request. It will either timeout
// or receive data from the 'webclientdata' url. In both cases a new request will
// immediately be started.
$.ajax({
type: "POST",
url: "/webclientdata",
async: true, // Turns off browser loading indicator
cache: false, // Forces browser reload independent of cache
timeout:30000, // Timeout in ms. After this time a new long-poll will be started.
dataType:"json",
data: {mode:'receive', 'suid':CLIENT_HASH},
// callback methods
success: function(data){ // called when request to waitreceive completes
msg_display("out", data.msg); // Add response to the message area
webclient_receive(); // immediately start a new request
},
error: function(XMLHttpRequest, textStatus, errorThrown){
webclient_receive(); // A possible timeout. Resend request immediately
},
});
};
function webclient_input(arg, no_update){
// Send an input from the player to the server
// no_update is used for sending idle messages behind the scenes.
var outmsg = typeof(arg) != 'undefined' ? arg : $("#inputfield").val();
$.ajax({
type: "POST",
url: "/webclientdata",
async: true,
cache: false,
timeout: 30000,
data: {mode:'input', msg:outmsg, data:'NoData', 'suid':CLIENT_HASH},
//callback methods
success: function(data){
//if (outmsg.length > 0 ) msg_display("inp", outmsg) // echo input on command line
if (no_update == undefined) {
history_add(outmsg);
HISTORY_POS = 0;
$('#inputform')[0].reset(); // clear input field
}
},
error: function(XMLHttpRequest, textStatus, errorThrown){
msg_display("err", "Error: Server returned an error or timed out. Try resending or reloading the page.");
},
})
}
function webclient_init(){
// Start the connection by making sure the server is ready
$.ajax({
type: "POST",
url: "/webclientdata",
async: true,
cache: false,
timeout: 50000,
dataType:"json",
data: {mode:'init', 'suid':CLIENT_HASH},
// callback methods
success: function(data){ // called when request to initdata completes
$("#connecting").remove() // remove the "connecting ..." message.
CLIENT_HASH = data.suid // unique id hash given from server
// A small timeout to stop 'loading' indicator in Chrome
setTimeout(function () {
$("#playercount").fadeOut('slow', webclient_set_sizes);
}, 10000);
// Report success
msg_display('sys',"Connected to " + data.msg + ". Websockets not available: Using ajax client without OOB support.");
// Wait for input
webclient_receive();
},
error: function(XMLHttpRequest, textStatus, errorThrown){
msg_display("err", "Connection error ..." + " (" + errorThrown + ")");
setTimeout('webclient_receive()', 15000); // try again after 15 seconds
},
});
}
function webclient_close(){
// Kill the connection and do house cleaning on the server.
$.ajax({
type: "POST",
url: "/webclientdata",
async: false,
cache: false,
timeout: 50000,
dataType: "json",
data: {mode: 'close', 'suid': CLIENT_HASH},
success: function(data){
CLIENT_HASH = '0';
alert("Mud client connection was closed cleanly.");
},
error: function(XMLHttpRequest, textStatus, errorThrown){
CLIENT_HASH = '0';
}
});
}
// Display messages
function msg_display(type, msg){
// Add a div to the message window.
// type gives the class of div to use.
$("#messagewindow").append(
"<div class='msg "+ type +"'>"+ msg +"</div>");
// scroll message window to bottom
$('#messagewindow').animate({scrollTop: $('#messagewindow')[0].scrollHeight});
}
// Input history mechanism
var HISTORY_MAX_LENGTH = 21
var HISTORY = new Array();
HISTORY[0] = '';
var HISTORY_POS = 0;
function history_step_back() {
// step backwards in history stack
HISTORY_POS = Math.min(++HISTORY_POS, HISTORY.length-1);
return HISTORY[HISTORY.length-1 - HISTORY_POS];
}
function history_step_fwd() {
// step forward in history stack
HISTORY_POS = Math.max(--HISTORY_POS, 0);
return HISTORY[HISTORY.length-1 - HISTORY_POS];
}
function history_add(input) {
// add an entry to history
if (input != HISTORY[HISTORY.length-1]) {
if (HISTORY.length >= HISTORY_MAX_LENGTH) {
HISTORY.shift(); // kill oldest history entry
}
HISTORY[HISTORY.length-1] = input;
HISTORY[HISTORY.length] = '';
}
}
// Catching keyboard shortcuts
$(document).keydown( function(event) {
// Get the pressed key (normalized by jQuery)
var code = event.which,
inputField = $("#inputfield");
// always focus input field no matter which key is pressed
inputField.focus();
// Special keys recognized by client
//msg_display("out", "key code pressed: " + code); // debug
if (code == 13) { // Enter Key
webclient_input();
event.preventDefault();
}
else {
if (code == 38) { // arrow up 38
inputField.val(history_step_back()).appendCaret();
}
else if (code == 40) { // arrow down 40
inputField.val(history_step_fwd()).appendCaret();
}
}
});
// handler to avoid double-clicks until the ajax request finishes
$("#inputsend").one("click", webclient_input)
function webclient_set_sizes() {
// Sets the size of the message window
var win_h = $(document).height();
//var win_w = $('#wrapper').width();
var inp_h = $('#inputform').outerHeight(true);
//var inp_w = $('#inputsend').outerWidth(true);
$("#messagewindow").css({'height': win_h - inp_h - 1});
//$("#inputfield").css({'width': win_w - inp_w - 20});
}
// Callback function - called when page has finished loading (gets things going)
$(document).ready(function(){
// remove the "no javascript" warning, since we obviously have javascript
$('#noscript').remove();
// set sizes of elements and reposition them
webclient_set_sizes();
// a small timeout to stop 'loading' indicator in Chrome
setTimeout(function () {
webclient_init();
}, 500);
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
setInterval(function() {
webclient_input("idle", true);
}, 60000*3);
});
// Callback function - called when the browser window resizes
$(window).resize(webclient_set_sizes);
// Callback function - called when page is closed or moved away from.
$(window).bind("beforeunload", webclient_close);

View file

@ -1,289 +0,0 @@
/*
* Evennia webclient library. Load this into your <head> html page
* template with
*
* <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
* <script webclient/js/evennia.js</script>
*
* In your template you can then put elements with specific ids that
* evennia will look for. Evennia will via this library relay text to
* specific divs if given, or to the "text" div if not.
*
*/
/*
* global vars
*/
var websocket;
/*
* Configuration variables
* (set by the user)
*/
var echo_to_textarea = true;
/*
* Evennia OOB command map; this holds custom js functions
* that the OOB handler supports. Each key is the name
* of a js callback function. External development is
* done by adding functions func(data) to this object,
* where data is the data object sent from the server.
*/
oob_commands = {
"text": function(data) {
// basic div redistributor making
// use of the default text relay.
// Use in combination with the
// divclass oob argument to send
// text to different DOM element classes.
var msg = data.text;
var divclass = data.divclass;
toClass(divclass, msg);
}
};
/*
* Send text to given element class
*/
toClass = function(divclass, data) {
// loop over all objects of divclass
//console.log("toClass: " + divclass + " " + data);
$("." + divclass).each(function() {
switch (divclass) {
case "textoutput":
// update the bottom of the normal text area
// and scroll said area.
var oldtext = $.trim($(this).val());
$(this).val(oldtext + "\n" + data);
//$(this).scrollTop($(this)[0].scrollHeight);
break;
case "lookoutput":
// update the look text box
$(this).val(data);
break;
}
});
}
/*
* Send data to Evennia. This data is always sent
* as an JSON object. {key:arg, ...}
* key "cmd" - a text input command (in arg)
* other keys - interpreted as OOB command keys and their args
* (can be an array)
*/
dataSend = function(classname, data) {
// client -> Evennia.
var outdata = {classname: data}; // for testing
//websocket.send(JSON.stringify(data)) // send to Evennia
}
/*
* Data coming from Evennia to client. This data
* is always on the form of a JSON object {key:arg}
*/
dataRecv = function(event) {
// Evennia -> client
var data = JSON.parse(event.data);
// send to be printed in element class
for (var cmdname in data) {
if (data.hasOwnProperty(cmdname) && cmdname in oob_commands) {
try {
oob_commands[cmdname](data);
}
catch(error) {
alert("Crash in function " + cmdname + "(data): " + error);
}
}
}
}
/*
* Input history objects
*/
historyObj = function () {
// history object storage
return {"current": undefined, // save the current input
"hpos": 0, // position in history
"store": []} // history steore
}
addHistory = function(obj, lastentry) {
// Add text to the history
if (!obj.hasOwnProperty("input_history")) {
// create a new history object
obj.input_history = new historyObj();
}
if (lastentry && obj.input_history.store && obj.input_history.store[0] != lastentry) {
// don't store duplicates.
obj.input_history.store.unshift(lastentry);
obj.input_history.hpos = -1;
obj.input_history.current = undefined;
}
}
getHistory = function(obj, lastentry, step) {
// step +1 or -1 in history
if (!obj.hasOwnProperty("input_history")) {
// create a new history object
obj.input_history = new historyObj();
}
var history = obj.input_history;
var lhist = history.store.length;
var hpos = history.hpos + step;
if (typeof(obj.input_history.current) === "undefined") {
obj.input_history.current = lastentry;
}
if (hpos < 0) {
// get the current but remove the cached one so it
// can be replaced.
obj.input_history.hpos = -1;
var current = obj.input_history.current;
obj.input_history.current = undefined;
return current;
}
hpos = Math.max(0, Math.min(hpos, lhist-1));
//console.log("lhist: " + lhist + " hpos: " + hpos + " current: " + obj.input_history.current);
obj.input_history.hpos = hpos;
return history.store[hpos];
}
/*
* Initialization
*/
initialize = function() {
// register events
// single line input
$(".input_singleline").on("submit", function(event) {
// input from the single-line input field
event.preventDefault(); // stop form from switching page
var field = $(this).find("input");
var msg = field.val();
addHistory(this, msg);
field.val("");
dataSend("inputfield", msg);
if (echo_to_textarea) {
// echo to textfield
toClass("textoutput", msg);
toClass("lookoutput", msg);
toClass("listoutput", msg);
}
});
$(".input_singleline :input").on("keyup", function(event) {
switch (event.keyCode) {
case 13: // Enter
event.preventDefault();
$(this).trigger("submit");
break
case 38: // Up
event.preventDefault();
var lastentry = $(this).val();
var hist = getHistory(this.form, lastentry, 1);
if (hist) $(this).val(hist);
break
case 40: // Down
event.preventDefault();
var lastentry = $(this).val();
var hist = getHistory(this.form, lastentry, -1);
if (hist) $(this).val(hist);
break
default:
}
});
// textarea input
$(".input_multiline").on("submit", function(event) {
// input from the textarea input
event.preventDefault(); // stop form from switching page
var field = $(this).find("textarea");
var msg = field.val();
addHistory(this, msg);
field.val("");
dataSend("inputfield", msg);
if (echo_to_textarea) {
// echo to textfield
toClass("textarea", msg);
toClass("lookarea", msg);
toClass("listarea", msg);
}
});
$(".input_multiline :input").on("keyup", function(event) {
// Ctrl + <key> commands
if (event.ctrlKey) {
switch (event.keyCode) {
case 13: // Ctrl + Enter
event.preventDefault();
$(this).trigger("submit");
break
case 38: // Ctrl + Up
event.preventDefault();
var lastentry = $(this).val();
var hist = getHistory(this.form, lastentry, 1);
if (hist) $(this).val(hist);
break
case 40: // Ctrl + Down
event.preventDefault();
var lastentry = $(this).val();
var hist = getHistory(this.form, lastentry, -1);
if (hist) $(this).val(hist);
break
default:
}
}
});
//console.log("windowsize: " + $(window).height() + " footerheight: " + $('.footer').height())
//$(window).on("resize", function(event) {
// $('.textoutput').css({height:($(window).height() - 120 + "px")});
//});
// resizing
// make sure textarea fills surrounding div
//$('.textoutput').css({height:($(window).height()-$('.footer').height())+'px'});
//$('.textoutput').css({height:($(window).height() - 120 + "px")});
// configurations
$(".echo").on("change", function(event) {
// configure echo on/off checkbox button
event.preventDefault();
echo_to_textarea = $(this).prop("checked");
});
// initialize the websocket connection
//websocket = new WebSocket(wsurl);
//websocket.onopen = function(event) {};
//websocket.onclose = function(event) {};
//websocket.onerror = function(event) {};
//websocket.onmessage = dataOut;
}
/*
* Kick system into gear first when
* the document has loaded fully.
*/
$(document).ready(function() {
// a small timeout to stop 'loading' indicator in Chrome
setTimeout(function () {
initialize();
}, 500);
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
setInterval(function() {
dataSend("textinput", "idle");
}, 60000*3);
});

View file

@ -1,428 +0,0 @@
/*
Evennia websocket webclient (javascript component)
The client is composed of two parts:
/server/portal/websocket_client.py - the portal-side component
this file - the javascript component handling dynamic content
messages sent to the client is one of two modes:
OOB("func1",args, "func2",args, ...) - OOB command executions, this will
call unique javascript functions
func1(args), func2(args) etc.
text - any other text is considered a normal text output in the main output window.
*/
// If on, allows client user to send OOB messages to server by
// prepending with ##OOB{}, for example ##OOB{"echo":[1,2,3,4]}
var DEBUG = true
//
// Custom OOB functions
// functions defined here can be called by name by the server. For
// example input OOB{"echo":(args),{kwargs}} will trigger a function named
// echo(args, kwargs). The commands the server understands is set by
// settings.OOB_PLUGIN_MODULES
function echo(args, kwargs) {
// example echo function.
doShow("out", "ECHO return: " + args) }
function list (args, kwargs) {
// show in main window
doShow("out", args) }
function send (args, kwargs) {
// show in main window. SEND returns kwargs {name:value}.
for (var sendvalue in kwargs) {
doShow("out", sendvalue + " = " + kwargs[sendvalue]);}
}
function report (args, kwargs) {
// show in main window. REPORT returns kwargs
// {attrfieldname:value}
for (var name in kwargs) {
doShow("out", name + " = " + kwargs[name]) }
}
function repeat (args, kwargs) {
// called by repeating oob funcs
doShow("out", args) }
function err (args, kwargs) {
// display error
doShow("err", args) }
// Map above functions with oob command names
var CMD_MAP = {"echo":echo, "LIST":list, "SEND":send, "REPORT":report, "error":err};
//
// Webclient code
//
function webclient_init(){
// called when client is just initializing
websocket = new WebSocket(wsurl);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt) {
// called when client is first connecting
$("#connecting").remove(); // remove the "connecting ..." message
doShow("sys", "Using websockets - connected to " + wsurl + ".")
setTimeout(function () {
$("#numplayers").fadeOut('slow', doSetSizes);
}, 10000);
}
function onClose(evt) {
// called when client is closing
CLIENT_HASH = 0;
alert("Mud client connection was closed cleanly.");
}
function onMessage(evt) {
// called when the Evennia is sending data to client.
// Such data is always prepended by a 3-letter marker
// OOB, PRT or CMD, defining its operation
var inmsg = evt.data;
if (inmsg.length < 4) return;
var mode = inmsg.substr(0, 3);
var message = inmsg.slice(3);
if (mode == "OOB") {
// dynamically call oob methods if available
// The incoming data is on the form [cmdname, [args], {kwargs}]
try {
if (message.length < 1) {
throw "Usage: ##OOB [[commandname, [args], {kwargs}], ...]"
}
var oobcmd = JSON.parse(message);
doShow("debug", "Received OOB: " + message + " parsed: " + oobcmd);
// call each command tuple in turn
var cmdname = oobcmd[0];
var args = oobcmd[1];
var kwargs = oobcmd[2];
// match cmdname with a command existing in the
// CMD_MAP mapping
if (cmdname in CMD_MAP == false) {
throw "oob command " + cmdname + " is not supported by client.";
}
// we have a matching oob command in CMD_MAP.
// Prepare the error message beforehand
// Execute
try {
CMD_MAP[cmdname](args, kwargs);
}
catch(error) {
doShow("err", "Client could not execute OOB function" + "cmdname" + "(" + args + kwargs + ").");
}
}
catch(error) {
doShow("err", error);
}
}
else if (mode == "PRT") {
// handle prompt
doPrompt("prompt", message);
}
else if (mode == "CMD") {
// normal command operation
// normal message
doShow('out', message);
}
}
function onError(evt) {
// called on a server error
doShow('err', "Connection error trying to access websocket on " + wsurl + ". " + "Contact the admin and/or check settings.WEBSOCKET_CLIENT_URL.");
}
function doSend(){
// relays data from client to Evennia.
// If OOB_debug is set, allows OOB test data using the syntax
// ##OOB[funcname, args, kwargs]
outmsg = $("#inputfield").val();
history_add(outmsg);
HISTORY_POS = 0;
$('#inputform')[0].reset(); // clear input field
if (outmsg.length > 4 && outmsg.substr(0, 5) == "##OOB") {
// OOB direct input
var outmsg = outmsg.slice(5);
if (outmsg == "UNITTEST") {
// unittest mode
doShow("out", "OOB testing mode ...");
doOOB(["ECHO", ["Echo test"]]);
doOOB(["LIST", ["COMMANDS"]]);
doOOB(["SEND", ["CHARACTER_NAME"]]);
doOOB(["REPORT", ["TEST"]]);
doOOB(["UNREPORT", ["TEST"]]);
doOOB(["REPEAT", [1, "ECHO"]]);
doOOB(["UNREPEAT", [1, "ECHO"]]);
doShow("out", "... OOB testing mode done.");
return
}
// send a manual OOB instruction
try {
doShow("debug", "OOB input: " + outmsg);
if (outmsg.length == 0) {
throw "Usage: ##OOB [[commandname, [args], {kwargs}], ...]";
}
else {
doOOB(outmsg);
}
}
catch(err) {
doShow("err", err)
}
}
else {
// normal output
websocket.send("CMD" + outmsg); }
}
function doOOB(cmdstring){
// Send OOB data from client to Evennia.
// Takes input strings with syntax ["cmdname", args, kwargs]
doShow("debug", "into doOOB... " + cmdstring)
try {
var cmdtuple = JSON.parse(cmdstring);
var oobmsg = "";
if (cmdtuple instanceof Array == false) {
// a single command instruction without arguments
oobmsg = [cmdtuple, [], {}];
}
else {
switch (cmdtuple.length) {
case 0:
throw "No command given";
case 1:
// [cmdname]
oobmsg = [cmdtuple[0], [], {}];
break;
case 2:
// [cmdname, args]
oobmsg = [cmdtuple[0], cmdtuple[1], {}];
break;
case 3:
// [cmdname, args, kwargs]
oobmsg = [cmdtuple[0], cmdtuple[1], cmdtuple[2]];
break;
default:
throw "Malformed OOB instruction: " + cmdstring;
}
// convert to string and send it to the server
oobmsg = JSON.stringify(oobmsg);
websocket.send("OOB" + oobmsg);
}
}
catch(error) {
doShow("err", "OOB output " + cmdtuple + " is not on the right form: " + error);
}
}
function doShow(type, msg){
// Add msg to the main output window.
// type gives the class of div to use.
// The default types are
// "out" (normal output) or "err" (red error message)
if (type == "debug") {
if (DEBUG) {
type = "out";
msg = "DEBUG: " + msg;
}
else {
return;
}
}
// output
$("#messagewindow").append(
"<div class='msg "+ type +"'>"+ msg +"</div>");
// scroll message window to bottom
$('#messagewindow').animate({scrollTop: $('#messagewindow')[0].scrollHeight});
}
function doPrompt(type, msg){
// Display prompt
$('#prompt').replaceWith(
"<div id='prompt' class='msg "+ type +"'>" + msg + "</div>");
}
function doSetSizes() {
// Sets the size of the message window
var win_h = $(document).height();
//var win_w = $('#wrapper').width();
var inp_h = $('#inputform').outerHeight(true);
//var inp_w = $('#inputsend').outerWidth(true);
$("#messagewindow").css({'height': win_h - inp_h - 1});
//$("#inputfield").css({'width': win_w - inp_w - 20});
}
//
// Input code
//
// Input history
var HISTORY_MAX_LENGTH = 21
var HISTORY = new Array();
HISTORY[0] = '';
var HISTORY_POS = 0;
function history_step_back() {
// step backwards in history stack
HISTORY_POS = Math.min(++HISTORY_POS, HISTORY.length-1);
return HISTORY[HISTORY.length-1 - HISTORY_POS];
}
function history_step_fwd() {
// step forward in history stack
HISTORY_POS = Math.max(--HISTORY_POS, 0);
return HISTORY[HISTORY.length-1 - HISTORY_POS];
}
function history_add(input) {
// add an entry to history
if (input != HISTORY[HISTORY.length-1]) {
if (HISTORY.length >= HISTORY_MAX_LENGTH) {
HISTORY.shift(); // kill oldest history entry
}
HISTORY[HISTORY.length-1] = input;
HISTORY[HISTORY.length] = '';
}
}
// Catching keyboard shortcuts
$.fn.appendCaret = function() {
/* jQuery extension that will forward the caret to the end of the input, and
won't harm other elements (although calling this on multiple inputs might
not have the expected consequences).
Thanks to
http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
for the good starting point. */
return this.each(function() {
var range,
// Index at where to place the caret.
end,
self = this;
if (self.setSelectionRange) {
// other browsers
end = self.value.length;
self.focus();
// NOTE: Need to delay the caret movement until after the callstack.
setTimeout(function() {
self.setSelectionRange(end, end);
}, 0);
}
else if (self.createTextRange) {
// IE
end = self.value.length - 1;
range = self.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', end);
// NOTE: I haven't tested to see if IE has the same problem as
// W3C browsers seem to have in this context (needing to fire
// select after callstack).
range.select();
}
});
};
$.fn.appendCaret = function() {
/* jQuery extension that will forward the caret to the end of the input, and
won't harm other elements (although calling this on multiple inputs might
not have the expected consequences).
Thanks to
http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
for the good starting point. */
return this.each(function() {
var range,
// Index at where to place the caret.
end,
self = this;
if (self.setSelectionRange) {
// other browsers
end = self.value.length;
self.focus();
// NOTE: Need to delay the caret movement until after the callstack.
setTimeout(function() {
self.setSelectionRange(end, end);
}, 0);
}
else if (self.createTextRange) {
// IE
end = self.value.length - 1;
range = self.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', end);
// NOTE: I haven't tested to see if IE has the same problem as
// W3C browsers seem to have in this context (needing to fire
// select after callstack).
range.select();
}
});
};
// Input jQuery callbacks
$(document).keydown( function(event) {
// Get the pressed key (normalized by jQuery)
var code = event.which,
inputField = $("#inputfield");
// always focus input field no matter which key is pressed
inputField.focus();
// Special keys recognized by client
//doShow("out", "key code pressed: " + code); // debug
if (code == 13) { // Enter Key
doSend();
event.preventDefault();
}
else {
if (code == 38) { // arrow up 38
inputField.val(history_step_back()).appendCaret();
}
else if (code == 40) { // arrow down 40
inputField.val(history_step_fwd()).appendCaret();
}
}
});
// handler to avoid double-clicks until the ajax request finishes
//$("#inputsend").one("click", webclient_input)
// Callback function - called when the browser window resizes
$(window).resize(doSetSizes);
// Callback function - called when page is closed or moved away from.
//$(window).bind("beforeunload", webclient_close);
//
// Callback function - called when page has finished loading (kicks the client into gear)
$(document).ready(function(){
// remove the "no javascript" warning, since we obviously have javascript
$('#noscript').remove();
// set sizes of elements and reposition them
doSetSizes();
// a small timeout to stop 'loading' indicator in Chrome
setTimeout(function () {
webclient_init();
}, 500);
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
setInterval(function() {
doSend("idle")
}, 60000*3);
});

View file

@ -1,39 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="../css/evennia.css" />
</head>
<body>
<!-- Config menu button -->
<div id="header">
<a href="#configmenu" class="button">Config</a>
</div>
<!-- Config menu itself -->
<div id="configmenu">
<!-- close button -->
<a href="#" class="close">&times;</a>
</div>
<div id="main">
<!--Outputs -->
<div class="textoutput">Test textoutput </div>
<div id="sidepanel">
<div class="lookoutput">Look textoutput </div>
<div class="contentoutput">Content textoutput </div>
</div>
</div>
<!-- Inputs -->
<div id="footer">
<form class="input_singleline" action="send">
<!-- multi-line input -->
<textarea id="input_multiline_field"></textarea>
<input id="sendbutton" type="submit" value="Send">
</form>
</div>
</body>
</html>