From 2134d6dd4a26a18251f6d28ab3a27332460fd586 Mon Sep 17 00:00:00 2001 From: NatePri Date: Sun, 10 Apr 2016 04:58:01 -0700 Subject: [PATCH] Minor webclient enhancements - Fixed window resize bug - Improved history handling to be less destructive to text the user has entered - Made input area automatically resize to fit its contents --- .../static/webclient/css/webclient.css | 65 +++++++---- .../static/webclient/js/webclient_gui.js | 108 +++++++++++++++--- .../webclient/templates/webclient/base.html | 8 +- .../templates/webclient/webclient.html | 4 +- 4 files changed, 138 insertions(+), 47 deletions(-) diff --git a/evennia/web/webclient/static/webclient/css/webclient.css b/evennia/web/webclient/static/webclient/css/webclient.css index 93c6e02c9..ec59742e5 100644 --- a/evennia/web/webclient/static/webclient/css/webclient.css +++ b/evennia/web/webclient/static/webclient/css/webclient.css @@ -8,7 +8,7 @@ --- */ /* Overall element look */ -html, body { height: 100% } +html, body, #clientwrapper { height: 100% } body { margin: 0; padding: 0; @@ -94,31 +94,54 @@ div {margin:0px;} /* Main scrolling message area */ #messagewindow { - position: relative; - height: 90%; + position: absolute; overflow: auto; padding: 1em; + box-sizing: border-box; + top: 0; + left: 0; + right: 0; + bottom: 70px; } /* Input area containing input field and button */ #inputform { position: absolute; width: 100%; - padding: .8em 0; - bottom: -50px; + padding: 0; + bottom: 0; + margin: 0; + padding-bottom: 10px; + border-top: 1px solid #555; } #inputcontrol { - padding: 0 .8em; - overflow: auto + width: 100%; + padding: 0; } /* Input field */ +#inputfield, #inputsend, #inputsizer { + display: block; + box-sizing: border-box; + min-height: 50px; + background: #000; + color: #fff; + padding: 0 .45em; + font-size: 1.1em; + font-family: 'DejaVu Sans Mono', Consolas, Inconsolata, 'Lucida Console', monospace; +} + +#inputsizer { + margin-left: -9999px; + line-height: normal; +} + #inputfield { float: left; - width: 93%; - height: 40px; - margin-right: .5em + width: 95%; + border: 0; + resize: none; } #inputfield:focus { @@ -127,27 +150,23 @@ div {margin:0px;} /* Input 'send' button */ #inputsend { - float: left; - width: 4% -} - -#inputfield, #inputsend { - height: 40px; - border: 1px solid #555; - background: #000; - color: #fff; - padding: .4em .45em; - font-size: 1.1em; - font-family: 'DejaVu Sans Mono', Consolas, Inconsolata, 'Lucida Console', monospace; + float: right; + width: 3%; + max-width: 25px; + margin-right: 10px; + border: 0; + background: #555; } /* prompt area above input field */ #prompt { - margin-top: .8em; + margin-top: 10px; } /* No javascript warning */ #connecting { + position: absolute; + width: 100%; padding: .5em .9em } diff --git a/evennia/web/webclient/static/webclient/js/webclient_gui.js b/evennia/web/webclient/static/webclient/js/webclient_gui.js index 7f11160e9..060fafa8d 100644 --- a/evennia/web/webclient/static/webclient/js/webclient_gui.js +++ b/evennia/web/webclient/static/webclient/js/webclient_gui.js @@ -25,29 +25,46 @@ var input_history = function() { history[0] = ''; // the very latest input is empty for new entry. - var back = function () { + var back = function (scratchInput) { // step backwards in history stack history_pos = Math.min(++history_pos, history.length - 1); return history[history.length - 1 - history_pos]; }; - var fwd = function () { + var fwd = function (scratchInput) { // step forwards in history stack history_pos = Math.max(--history_pos, 0); - return history[history.length -1 - history_pos]; + return history[history.length - 1 - history_pos]; }; var add = function (input) { // add a new entry to history, don't repeat latest - if (input && input != history[history.length-1]) { + if (input && input != history[history.length-2]) { if (history.length >= history_max) { history.shift(); // kill oldest entry } history[history.length-1] = input; history[history.length] = ''; }; + // reset the position to the last history entry + history_pos = 0; }; + var end = function () { + // move to the end of the history stack + history_pos = 0; + return history[history.length -1]; + } + + var scratch = function (input) { + // Put the input into the last history entry (which is normally empty) + // without making the array larger as with add. + // Allows for in-progress editing to be saved. + history[history.length-1] = input; + } + return {back: back, fwd: fwd, - add: add} + add: add, + end: end, + scratch: scratch} }(); // @@ -57,6 +74,7 @@ var input_history = function() { // Grab text from inputline and send to Evennia function doSendText() { inputfield = $("#inputfield"); + isInputDirty = false; var outtext = inputfield.val(); if (outtext.length > 7 && outtext.substr(0, 7) == "##send ") { // send a specific oob instruction @@ -76,29 +94,84 @@ function doSendText() { // catch all keyboard input, handle special chars function onKeydown (event) { var code = event.which; + var history_entry = null; inputfield = $("#inputfield"); inputfield.focus(); if (code === 13) { // Enter key sends text doSendText(); event.preventDefault(); - } - else if (code === 38) { // Arrow up - inputfield.val(input_history.back()); + } + else if (inputfield[0].selectionStart == inputfield.val().length) { + // Only process up/down arrow if cursor is at the end of the line. + if (code === 38) { // Arrow up + history_entry = input_history.back(); + } + else if (code === 40) { // Arrow down + history_entry = input_history.fwd(); + } + } + + if (history_entry !== null) { + // Doing a history navigation; replace the text in the input. + inputfield.val(history_entry); event.preventDefault(); } - else if (code === 40) { // Arrow down - inputfield.val(input_history.fwd()); - event.preventDefault(); + else { + // Save the current contents of the input to the history scratch area. + setTimeout(function () { + // Need to wait until after the key-up to capture the value. + input_history.scratch(inputfield.val()); + input_history.end(); + }, 0); } }; +var resizeInputField = function () { + var min_height = 50; + var max_height = 300; + var prev_text_len = 0; + + // Check to see if we should change the height of the input area + return function () { + inputfield = $("#inputfield"); + var scrollh = inputfield.prop("scrollHeight"); + var clienth = inputfield.prop("clientHeight"); + var newh = 0; + var curr_text_len = inputfield.val().length; + + if (scrollh > clienth && scrollh <= max_height) { + // Need to make it bigger + newh = scrollh; + } + else if (curr_text_len < prev_text_len) { + // There is less text in the field; try to make it smaller + // To avoid repaints, we draw the text in an offscreen element and + // determine its dimensions. + var sizer = $('#inputsizer') + .css("width", inputfield.prop("clientWidth")) + .text(inputfield.val()); + newh = sizer.prop("scrollHeight"); + } + + if (newh != 0) { + newh = Math.min(newh, max_height); + if (clienth != newh) { + inputfield.css("height", newh + "px"); + doWindowResize(); + } + } + prev_text_len = curr_text_len; + } +}(); + // Handle resizing of client function doWindowResize() { - var winh = $(document).height(); var formh = $('#inputform').outerHeight(true); - $("#messagewindow").css({'height': winh - formh - 1}); - $("#inputform").css({'bottom': JSON.stringify(-$("#inputform").height()-10)+"px"}); + var message_scrollh = $("#messagewindow").prop("scrollHeight"); + $("#messagewindow") + .css({"bottom": formh}) // leave space for the input form + .scrollTop(message_scrollh); // keep the output window scrolled to the bottom } // Handle text coming from the server @@ -143,8 +216,11 @@ function onDefault(cmdname, args, kwargs) { $(window).bind("resize", doWindowResize); $("#inputfield").bind("resize", doWindowResize); -// Evenit when any key is pressed -$(document).keydown(onKeydown); +// Event when any key is pressed +$(document).keydown(onKeydown) + .bind("keyup", resizeInputField) + .bind("paste", resizeInputField) + .bind("cut", resizeInputField); // Event when client finishes loading $(document).ready(function() { diff --git a/evennia/web/webclient/templates/webclient/base.html b/evennia/web/webclient/templates/webclient/base.html index 490391f6e..6f62d8c2a 100644 --- a/evennia/web/webclient/templates/webclient/base.html +++ b/evennia/web/webclient/templates/webclient/base.html @@ -56,18 +56,14 @@ JQuery available. {% endblock %} -
+
+
diff --git a/evennia/web/webclient/templates/webclient/webclient.html b/evennia/web/webclient/templates/webclient/webclient.html index 3052bcbd9..fc53f0820 100644 --- a/evennia/web/webclient/templates/webclient/webclient.html +++ b/evennia/web/webclient/templates/webclient/webclient.html @@ -14,12 +14,12 @@
- +
+
- {% endblock %}