Made a rudimentary gui for the webclient. Some data is going through to webclient, but currently html conversion is not working.

This commit is contained in:
Griatch 2016-02-11 21:55:44 +01:00
parent 33b73c7430
commit 66641b54ab
4 changed files with 230 additions and 90 deletions

View file

@ -52,6 +52,7 @@ An "emitter" object must have a function
var Evennia = { var Evennia = {
debug: true, debug: true,
initialized: false,
// Initialize. // Initialize.
// startup Evennia emitter and connection. // startup Evennia emitter and connection.
@ -68,13 +69,19 @@ An "emitter" object must have a function
// Evennia.emit to return data to Client. // Evennia.emit to return data to Client.
// //
init: function(opts) { init: function(opts) {
if (this.initialized) {
// make it safe to call multiple times.
return;
}
this.initialized = true;
opts = opts || {}; opts = opts || {};
this.emitter = opts.emitter || new DefaultEmitter(); this.emitter = opts.emitter || new DefaultEmitter();
if (opts.connection) { if (opts.connection) {
this.connection = opts.connection; this.connection = opts.connection;
} }
else if (window.WebSocket) { else if (window.WebSocket && wsactive) {
this.connection = new WebsocketConnection(); this.connection = new WebsocketConnection();
if (!this.connection) { if (!this.connection) {
this.connection = new AjaxCometConnection(); this.connection = new AjaxCometConnection();
@ -82,7 +89,7 @@ An "emitter" object must have a function
} else { } else {
this.connection = new AjaxCometConnection(); this.connection = new AjaxCometConnection();
} }
// this.connection = opts.connection || window.WebSocket ? new WebsocketConnection() : new AjaxCometConnection(); log('Evennia initialized.')
}, },
// Client -> Evennia. // Client -> Evennia.
@ -115,16 +122,17 @@ An "emitter" object must have a function
// //
// Args: // Args:
// event (event): Event received from Evennia // event (event): Event received from Evennia
// data (obj): // args (array): Arguments to listener
// kwargs (obj): keyword-args to listener
// //
emit: function (cmdname, data) { emit: function (cmdname, args, kwargs) {
log('emit called with args: + ' + cmdname + ',' + data); log('emit called with args: ' + cmdname + ',' + args + ',' + kwargs);
if (data.cmdid) { if (kwargs.cmdid) {
cmdmap[data.cmdid].apply(this, [data]); cmdmap[kwargs.cmdid].apply(this, [args, kwargs]);
delete cmdmap[cmddata.cmdid]; delete cmdmap[kwargs.cmdid];
} }
else { else {
this.emitter.emit(cmdname, data); this.emitter.emit(cmdname, args, kwargs);
} }
}, },
@ -135,7 +143,7 @@ An "emitter" object must have a function
// the Server. An alternative can be overridden in Evennia.init. // the Server. An alternative can be overridden in Evennia.init.
// //
var DefaultEmitter = function () { var DefaultEmitter = function () {
var cmdmap = {}; var listeners = {};
// Emit data to all listeners tied to a given cmdname // Emit data to all listeners tied to a given cmdname
// //
// Args: // Args:
@ -144,11 +152,11 @@ An "emitter" object must have a function
// called as function(kwargs). // called as function(kwargs).
// kwargs (obj): Argument to the listener. // kwargs (obj): Argument to the listener.
// //
var emit = function (cmdname, kwargs) { var emit = function (cmdname, args, kwargs) {
log('emit', cmdname, kwargs); log('emit', cmdname, args, kwargs);
if (cmdmap[cmdname]) { if (listeners[cmdname]) {
cmdmap[cmdname].apply(this, kwargs); listeners[cmdname].apply(this, [args, kwargs]);
}; };
}; };
@ -161,7 +169,7 @@ An "emitter" object must have a function
// //
var on = function (cmdname, listener) { var on = function (cmdname, listener) {
if (typeof(listener === 'function')) { if (typeof(listener === 'function')) {
cmdmap[cmdname] = listener; listeners[cmdname] = listener;
}; };
}; };
@ -171,7 +179,7 @@ An "emitter" object must have a function
// cmdname (str): Name of event to handle // cmdname (str): Name of event to handle
// //
var off = function (cmdname) { var off = function (cmdname) {
delete cmdmap[cmdname] delete listeners[cmdname]
}; };
return {emit:emit, on:on, off:off} return {emit:emit, on:on, off:off}
}; };
@ -184,17 +192,21 @@ An "emitter" object must have a function
// Handle Websocket open event // Handle Websocket open event
websocket.onopen = function (event) { websocket.onopen = function (event) {
log('Websocket connection openened. ', event); log('Websocket connection openened. ', event);
Evennia.emit('socket:open', event); Evennia.emit('socket:open', [], event);
}; };
// Handle Websocket close event // Handle Websocket close event
websocket.onclose = function (event) { websocket.onclose = function (event) {
log('WebSocket connection closed.'); log('WebSocket connection closed.');
Evennia.emit('socket:close', event); Evennia.emit('socket:close', [], event);
}; };
// Handle websocket errors // Handle websocket errors
websocket.onerror = function (event) { websocket.onerror = function (event) {
log("Websocket error to ", wsurl, event); log("Websocket error to ", wsurl, event);
Evennia.emit('socket:error', event.data); Evennia.emit('socket:error', [], event);
if (websocket.readyState === websocket.CLOSED) {
log("Websocket failed. Falling back to Ajax...");
Evennia.connection = AjaxCometConnection();
}
}; };
// Handle incoming websocket data [cmdname, kwargs] // Handle incoming websocket data [cmdname, kwargs]
websocket.onmessage = function (event) { websocket.onmessage = function (event) {
@ -203,13 +215,14 @@ An "emitter" object must have a function
return; return;
} }
// Parse the incoming data, send to emitter // Parse the incoming data, send to emitter
// Incoming data is on the form [cmdname, kwargs] // Incoming data is on the form [cmdname, args, kwargs]
data = JSON.parse(data); data = JSON.parse(data);
log("incoming " + data); log("incoming " + data);
Evennia.emit(data[0], data[1]); Evennia.emit(data[0], data[1], data[2]);
}; };
websocket.msg = function(data) { websocket.msg = function(cmdname, args, kwargs) {
websocket.send(JSON.stringify(data)); // send
websocket.send(JSON.stringify([cmdname, args, kwargs]));
}; };
return websocket; return websocket;
@ -221,11 +234,11 @@ An "emitter" object must have a function
log("Trying ajax ..."); log("Trying ajax ...");
var client_hash = '0'; var client_hash = '0';
// Send Client -> Evennia. Called by Evennia.send. // Send Client -> Evennia. Called by Evennia.send.
var msg = function(data) { var msg = function(cmdname, args, kwargs) {
$.ajax({type: "POST", url: "/webclientdata", $.ajax({type: "POST", url: "/webclientdata",
async: true, cache: false, timeout: 30000, async: true, cache: false, timeout: 30000,
dataType: "json", dataType: "json",
data: {mode:'input', msg: data, 'suid': client_hash}, data: {mode:'input', msg: [cmdname, args, kwargs], 'suid': client_hash},
success: function(data) {}, success: function(data) {},
error: function(req, stat, err) { error: function(req, stat, err) {
log("COMET: Server returned error. " + err); log("COMET: Server returned error. " + err);
@ -243,7 +256,7 @@ An "emitter" object must have a function
dataType: "json", dataType: "json",
data: {mode: 'receive', 'suid': client_hash}, data: {mode: 'receive', 'suid': client_hash},
success: function(data) { success: function(data) {
Evennia.emit(data[0], data[1]) Evennia.emit(data[0], data[1], data[2])
}, },
error: function() { error: function() {
poll() // timeout; immediately re-poll poll() // timeout; immediately re-poll
@ -285,15 +298,9 @@ function log(msg) {
// Called when page has finished loading (kicks the client into gear) // Called when page has finished loading (kicks the client into gear)
$(document).ready(function() { $(document).ready(function() {
// a small timeout to stop 'loading' indicator in Chrome
setTimeout( function () { setTimeout( function () {
log('Evennia initialized...')
Evennia.init() Evennia.init()
},
}, 500); 500
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes) );
setInterval(function() {
log('Idle tick.');
}, 60000*3);
}); });

View file

@ -13,16 +13,152 @@
*/ */
// //
// GUI Helpers // GUI Elements
// //
//
// Manage history for input line
//
var inputlog = function() {
var history_max = 21;
var history = new Array();
var history_pos = 0;
history[0] = ''; // the very latest input is empty for new entry.
function history_back() {
// step backwards in history stack
history_pos = Math.min(++history_pos, history.length - 1);
return history[history.length - 1 - history_pos];
}
function history_fwd() {
// step forwards in history stack
history_pos = Math.max(--history_pos, 0);
return history[history.length -1 - history_pos];
}
function history_add(input) {
// add a new entry to history, don't repeat latest
if (input != history[history.length-1]) {
if (history.length >= history_max) {
history.shift(); // kill oldest entry
}
history[history.length-1] = input;
history[history.length] = '';
}
}
return {back: history_back,
fwd: history_fwd,
add: history_add}
};
$.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();
}
});
};
// GUI Event Handlers
$(document).keydown( function(event) {
// catch all keyboard input, handle special chars
var code = event.which;
inputfield = $("#inputfield");
inputfield.focus();
if (code === 13) { // Enter key sends text
outtext = inputfield.val()
inputlog.add(outtext)
Evennia.msg("text", [outtext], {});
event.prevetDefault()
}
else if (code === 38) { // Arrow up
inputfield.val(inputlog.back()).appendCaret();
}
else if (code === 40) { // Arrow down
inputfield.val(inputlog.fwd()).appendCaret();
}
});
// client size setter
function set_window_size() {
var winh = $(document).height();
var formh = $('#inputform').outerHeight(true);
$("#messagewindow").css({'height': winh - formh - 1});
}
// Event - called when window resizes
$(window).resize(set_window_size);
// //
// Listeners // Listeners
// //
function doText(args, kwargs) {
// append message to previous ones
$("#messagewindow").append(
"<div class='msg out>" + args[0] + "</div>");
// scroll message window to bottom
$("#messagewindow").animate({scrollTop: $('#messageindow')[0].scrollHeight});
}
function doPrompt(args, kwargs) {
// show prompt
$('prompt').replaceWith(
"<div id='prompt' class='msg out'>" + args[0] + "</div>");
}
$(document).ready(function() {
// a small timeout to stop 'loading' indicator in Chrome
Evennia.init()
// register listeners
Evennia.emitter.on("text", doText);
Evennia.emitter.on("prompt", doPrompt);
set_window_size();
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
setInterval(function() {
log('Idle tick.');
Evennia.msg("text", ["idle"], {});
},
60000*3
);
});
//
// Senders
//

View file

@ -14,60 +14,66 @@ JQuery available.
<meta name="author" content="Evennia" /> <meta name="author" content="Evennia" />
<meta name="generator" content="Evennia" /> <meta name="generator" content="Evennia" />
<link rel='stylesheet' type="text/css" media="screen" href="{% static "webclient/css/webclient.css" %}"> <link rel='stylesheet' type="text/css" media="screen" href={% static "webclient/css/webclient.css" %}>
<script src="http://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript" charset="utf-8"></script> <!-- Import JQuery and warn if there is a problem -->
<!--for offline testing, download the jquery library from jquery.com--> {% block jquery_import %}
<!--script src="/media/javascript/jquery-1.11.1.js" type="text/javascript" charset="utf-8"></script--> <script src="http://code.jquery.com/jquery-2.1.1.min.js" type="text/javascript" charset="utf-8"></script>
{% endblock %}
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
if(!window.jQuery){document.write("<div class='err'>jQuery library not found or the online version could not be reached.</div>");} if(!window.jQuery) {
document.write("<div class='err'>jQuery library not found or the online version could not be reached.</div>");
}
</script> </script>
<!-- Set up javascript url --> <!-- Set up Websocket url and load the evennia.js library-->
<script language="javascript" type="text/javascript"> <script language="javascript" type="text/javascript">
{% if websocket_enabled %}
var wsactive = true;
{% else %}
var wsactive = false;
{% endif %}
{% if websocket_url %} {% if websocket_url %}
var wsurl = "{{websocket_url}}:{{websocket_port}}"; var wsurl = "{{websocket_url}}:{{websocket_port}}";
{% else %} {% else %}
var wsurl = "ws://" + this.location.hostname + ":{{websocket_port}}"; var wsurl = "ws://" + this.location.hostname + ":{{websocket_port}}";
{% endif %} {% endif %}
document.write("\<script src=\"{% static "webclient/js/evennia.js" %}\" type=\"text/javascript\" charset=\"utf-8\"\>\</script\>")
</script> </script>
<script src={% static "webclient/js/evennia.js" %} language="javascript" type="text/javascript" charset="utf-8"/></script>
<!-- Load gui library -->
{% block guilib_import %}
<script src={% static "webclient/js/webclient_gui.js" %} language="javascript" type="text/javascript" charset="utf-8"></script>
{% endblock %}
</head> </head>
<body> <body>
<div id="connecting"> <div id="connecting">
{% block Connecting %} {% block connecting %}
{% endblock %} {% endblock %}
</div> </div>
<div id="noscript"> <div id="noscript" class="err">
<h3>Javascript Error: The Evennia MUD client requires that you have Javascript activated.</h3> <h3>Javascript Error: The Evennia MUD client requires that you
<p>Turn off eventual script blockers and/or switch to a web have Javascript activated.</h3>
browser supporting javascript.</p> <p>Turn off eventual script blockers and/or switch to a
<p>For admins: The error could also be due to not being able web browser supporting javascript. <p>
to access the online jQuery javascript library. If you are This error could also be due to not being able to access
testing the client without an internet connection, you have the online jQuery javascript library.</p>
to previously download the jQuery library from <!-- This is will only fire if javascript is actually active -->
http://code.jquery.com (it's just one file) and then edit
webclient.html to point to the local copy.</p>
</div>
<!-- This is will only fire if js is actually active -->
<script language="javascript" type="text/javascript"> <script language="javascript" type="text/javascript">
$('#noscript').remove(); $('#noscript').remove();
</script> </script>
</div>
<!-- main client -->
<div id=clientwrapper> <div id=clientwrapper>
{% block client %} {% block client %}
{% endblock %} {% endblock %}
</div> </div>
<!-- import this after the client -->
{% block guilib_import %}
<script src="webclient/js/webclient_gui.js" language="javascript" type="test/javascript"> </script>
{% endblock %}
</body> </body>
</html> </html>

View file

@ -1,30 +1,21 @@
{% extends "webclient/base.html" %} {% extends "webclient/base.html" %}
{% block guilib_import %} <!-- Django-template blocks available for overloading:
{% endblock %} - connecting - custom connect messages
- jquery_import - for changing to a local jquery version
- guilib_import - for using your own gui lib
-->
{% block connecting %}
{% endblock %}
{% block client %} {% block client %}
<h1>Webclient!</h1> <div id="client">
<div id="messagewindow"> mainarea </div>
<div id="inputform">
<textarea name="inputfield" type="text"> </textarea>
</div>
</div>
<form>
<input id="maininput" type="text" name="input">
<input type="button" value="Send" onClick="sendInput()">
</form>
<script language="javascript" type="text/javascript">
var sendInput = function() {
var inmsg = $("#maininput").val();
log("sendInput: " + inmsg);
Evennia.msg("echo", [inmsg], {});
};
</script>
{% endblock %} {% endblock %}