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
This commit is contained in:
parent
de177398aa
commit
2134d6dd4a
4 changed files with 138 additions and 47 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -56,18 +56,14 @@ JQuery available.
|
|||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div id="noscript" class="err">
|
||||
<noscript class="err">
|
||||
<h3>Javascript Error: The Evennia MUD client requires that you
|
||||
have Javascript activated.</h3>
|
||||
<p>Turn off eventual script blockers and/or switch to a
|
||||
web browser supporting javascript. <p>
|
||||
This error could also be due to not being able to access
|
||||
the online jQuery javascript library.</p>
|
||||
<!-- This is will only fire if javascript is actually active -->
|
||||
<script language="javascript" type="text/javascript">
|
||||
$('#noscript').remove();
|
||||
</script>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<!-- main client -->
|
||||
<div id=clientwrapper>
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@
|
|||
<div id="inputform">
|
||||
<div id="prompt"></div>
|
||||
<div id="inputcontrol">
|
||||
<textarea id="inputfield" type="text"> </textarea>
|
||||
<textarea id="inputfield" type="text"></textarea>
|
||||
<input id="inputsend" type="button" onClick="doSendText()" value=">"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="inputsizer"></div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue