Starting work on the new weblib component
This commit is contained in:
parent
7ad1229a7b
commit
f0c9128ff8
2 changed files with 473 additions and 272 deletions
|
|
@ -1,289 +1,201 @@
|
||||||
/*
|
/*
|
||||||
* Evennia webclient library. Load this into your <head> html page
|
Evenna webclient library
|
||||||
* template with
|
|
||||||
*
|
This javascript library handles all communication between Evennia and
|
||||||
* <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
|
whatever client front end is used.
|
||||||
* <script webclient/js/evennia.js</script>
|
|
||||||
*
|
|
||||||
* In your template you can then put elements with specific ids that
|
* Evennia - library communication
|
||||||
* evennia will look for. Evennia will via this library relay text to
|
|
||||||
* specific divs if given, or to the "text" div if not.
|
The library will try to communicate with Evennia using websockets
|
||||||
*
|
(evennia/server/portal/webclient.py). However, if the web browser is
|
||||||
|
old and does not support websockets, it will instead fall back to a
|
||||||
|
long-polling (AJAX/COMET) type of connection
|
||||||
|
(using evennia/server/portal/webclient_ajax.py)
|
||||||
|
|
||||||
|
All messages are valid JSON array on single form: ["funcname", arg, arg,, ...]
|
||||||
|
This represents a JS function called as funcname(arg, arg, ...)
|
||||||
|
|
||||||
|
* Front-end interface
|
||||||
|
|
||||||
|
This library makes the "Evennia" object available. It has the following
|
||||||
|
functions:
|
||||||
|
|
||||||
|
|
||||||
|
- Evennia.init(options)
|
||||||
|
This must be called by the frontend to intialize the library. The
|
||||||
|
argument is an js object with the following possible keys:
|
||||||
|
'connection': Either 'websocket' or 'comet'.
|
||||||
|
'cmdhandler': An optional custom command handler for
|
||||||
|
managing outgoing commands from the server. If not
|
||||||
|
supplied, the default will be used. It must have a msg() function.
|
||||||
|
- Evennia.msg(funcname, [args,...], callback)
|
||||||
|
Send a command to the server. You can also provide a function
|
||||||
|
to call with the return of the call (not all commands will return
|
||||||
|
anything, like 'text' type commands).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
A
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//
|
||||||
* global vars
|
// Custom OOB functions
|
||||||
*/
|
// functions defined here can be called by name by the server. For
|
||||||
var websocket;
|
// 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() {
|
||||||
* Configuration variables
|
var id = 0;
|
||||||
* (set by the user)
|
var map = {};
|
||||||
*/
|
|
||||||
|
|
||||||
var echo_to_textarea = true;
|
var Evennia = {
|
||||||
|
debug: true,
|
||||||
|
// called by the frontend to send a command to the backend
|
||||||
|
cmd: function (cmd, params, callback) {
|
||||||
|
var msg = params ? [cmd, [params], {}] : [cmd, [], {}];
|
||||||
|
params.id = id++;
|
||||||
|
|
||||||
/*
|
log('cmd called with following args:', cmd, params, callback);
|
||||||
* 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 = {
|
websocket.send('OOB' + JSON.stringify(msg));
|
||||||
"text": function(data) {
|
|
||||||
// basic div redistributor making
|
if (typeof callback === 'function') {
|
||||||
// use of the default text relay.
|
map[id] = callback;
|
||||||
// Use in combination with the
|
}
|
||||||
// divclass oob argument to send
|
},
|
||||||
// text to different DOM element classes.
|
|
||||||
var msg = data.text;
|
// called by the backend to emit an event to the global emitter
|
||||||
var divclass = data.divclass;
|
emit: function (event, data) {
|
||||||
toClass(divclass, msg);
|
if (data.id) {
|
||||||
|
map[data.id].apply(this, [event, data]);
|
||||||
|
delete map[data.id];
|
||||||
|
}
|
||||||
|
Evennia.emitter.emit(event, data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// startup Evennia emitter and connection
|
||||||
|
init: function (opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
Evennia.emitter = opts.emitter || new Emitter();
|
||||||
|
Evennia.websocket = new Connection();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
// wrapper for websocket setup
|
||||||
* Send text to given element class
|
var Connection = function () {
|
||||||
*/
|
var websocket = new WebSocket(wsurl);
|
||||||
toClass = function(divclass, data) {
|
websocket.onopen = function (event) {
|
||||||
// loop over all objects of divclass
|
Evennia.emit('socket:open', event);
|
||||||
//console.log("toClass: " + divclass + " " + data);
|
};
|
||||||
$("." + divclass).each(function() {
|
websocket.onclose = function (event) {
|
||||||
switch (divclass) {
|
log('WebSocket connection closed.')
|
||||||
case "textoutput":
|
Evennia.emit('socket:close', event);
|
||||||
// update the bottom of the normal text area
|
};
|
||||||
// and scroll said area.
|
websocket.onmessage = function (event) {
|
||||||
var oldtext = $.trim($(this).val());
|
if (typeof event.data !== 'string' && event.data.length < 0) {
|
||||||
$(this).val(oldtext + "\n" + data);
|
return;
|
||||||
//$(this).scrollTop($(this)[0].scrollHeight);
|
|
||||||
break;
|
|
||||||
case "lookoutput":
|
|
||||||
// update the look text box
|
|
||||||
$(this).val(data);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only acceptable mode is OOB
|
||||||
|
var mode = event.data.substr(0, 3);
|
||||||
|
|
||||||
|
if (mode === 'OOB') {
|
||||||
|
// parse the rest of the response
|
||||||
|
var res = JSON.parse(event.data.substr(3));
|
||||||
|
log(res);
|
||||||
|
var cmd = res[0];
|
||||||
|
var args = res[1];
|
||||||
|
Evennia.emit(cmd, args[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
websocket.onerror = function (event) {
|
||||||
|
log("Websocket error to ", wsurl, event);
|
||||||
|
Evennia.emit('socket:error', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
return websocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
// basic emitter, can be overridden in evennia init
|
||||||
|
var Emitter = function () {
|
||||||
|
var map = {};
|
||||||
|
|
||||||
|
// emit to listeners of given event
|
||||||
|
var emit = function (event, params) {
|
||||||
|
log('emit', event, params);
|
||||||
|
if (map[event] && map[event] === Array) {
|
||||||
|
map[event].forEach(function (val) {
|
||||||
|
val.apply(this, params);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
// bind listener to event, only allow one instance of handler
|
||||||
* Send data to Evennia. This data is always sent
|
var on = function (event, handler) {
|
||||||
* as an JSON object. {key:arg, ...}
|
if (!map[event]) {
|
||||||
* key "cmd" - a text input command (in arg)
|
map[event] = [];
|
||||||
* 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
|
|
||||||
}
|
}
|
||||||
|
if (map[event].indexOf(handler) >= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map[event].push(handler);
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
// remove handler from event
|
||||||
* Data coming from Evennia to client. This data
|
var off = function (event, handler) {
|
||||||
* is always on the form of a JSON object {key:arg}
|
if (map[event]) {
|
||||||
*/
|
var listener = map[event].indexOf(handler);
|
||||||
dataRecv = function(event) {
|
if (listener >= 0) {
|
||||||
// Evennia -> client
|
map[event].splice(listener, 1);
|
||||||
var data = JSON.parse(event.data);
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// send to be printed in element class
|
return {
|
||||||
for (var cmdname in data) {
|
emit: emit,
|
||||||
if (data.hasOwnProperty(cmdname) && cmdname in oob_commands) {
|
on: on,
|
||||||
try {
|
off: off
|
||||||
oob_commands[cmdname](data);
|
};
|
||||||
}
|
};
|
||||||
catch(error) {
|
|
||||||
alert("Crash in function " + cmdname + "(data): " + error);
|
window.Evennia = Evennia;
|
||||||
}
|
})();
|
||||||
}
|
|
||||||
|
function log() {
|
||||||
|
if (Evennia.debug) {
|
||||||
|
console.log(arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Callback function - called when page has finished loading (kicks the client into gear)
|
||||||
* 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(){
|
$(document).ready(function(){
|
||||||
|
// remove the "no javascript" warning, since we obviously have javascript
|
||||||
|
$('#noscript').remove();
|
||||||
|
|
||||||
// a small timeout to stop 'loading' indicator in Chrome
|
// a small timeout to stop 'loading' indicator in Chrome
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
initialize();
|
log('Evennia initialized...')
|
||||||
|
Evennia.init();
|
||||||
}, 500);
|
}, 500);
|
||||||
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
|
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
|
||||||
setInterval(function() {
|
setInterval(function() {
|
||||||
dataSend("textinput", "idle");
|
log('Idle tick.');
|
||||||
}, 60000*3);
|
}, 60000*3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
289
evennia/web/webclient/static/webclient/js/evennia_weblib_test.js
Normal file
289
evennia/web/webclient/static/webclient/js/evennia_weblib_test.js
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
});
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue