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 */
|
/* Overall element look */
|
||||||
html, body { height: 100% }
|
html, body, #clientwrapper { height: 100% }
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
@ -94,31 +94,54 @@ div {margin:0px;}
|
||||||
|
|
||||||
/* Main scrolling message area */
|
/* Main scrolling message area */
|
||||||
#messagewindow {
|
#messagewindow {
|
||||||
position: relative;
|
position: absolute;
|
||||||
height: 90%;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Input area containing input field and button */
|
/* Input area containing input field and button */
|
||||||
#inputform {
|
#inputform {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: .8em 0;
|
padding: 0;
|
||||||
bottom: -50px;
|
bottom: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-top: 1px solid #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
#inputcontrol {
|
#inputcontrol {
|
||||||
padding: 0 .8em;
|
width: 100%;
|
||||||
overflow: auto
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Input field */
|
/* 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 {
|
#inputfield {
|
||||||
float: left;
|
float: left;
|
||||||
width: 93%;
|
width: 95%;
|
||||||
height: 40px;
|
border: 0;
|
||||||
margin-right: .5em
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#inputfield:focus {
|
#inputfield:focus {
|
||||||
|
|
@ -127,27 +150,23 @@ div {margin:0px;}
|
||||||
|
|
||||||
/* Input 'send' button */
|
/* Input 'send' button */
|
||||||
#inputsend {
|
#inputsend {
|
||||||
float: left;
|
float: right;
|
||||||
width: 4%
|
width: 3%;
|
||||||
}
|
max-width: 25px;
|
||||||
|
margin-right: 10px;
|
||||||
#inputfield, #inputsend {
|
border: 0;
|
||||||
height: 40px;
|
background: #555;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prompt area above input field */
|
/* prompt area above input field */
|
||||||
#prompt {
|
#prompt {
|
||||||
margin-top: .8em;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No javascript warning */
|
/* No javascript warning */
|
||||||
#connecting {
|
#connecting {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
padding: .5em .9em
|
padding: .5em .9em
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,29 +25,46 @@ var input_history = function() {
|
||||||
|
|
||||||
history[0] = ''; // the very latest input is empty for new entry.
|
history[0] = ''; // the very latest input is empty for new entry.
|
||||||
|
|
||||||
var back = function () {
|
var back = function (scratchInput) {
|
||||||
// step backwards in history stack
|
// step backwards in history stack
|
||||||
history_pos = Math.min(++history_pos, history.length - 1);
|
history_pos = Math.min(++history_pos, history.length - 1);
|
||||||
return history[history.length - 1 - history_pos];
|
return history[history.length - 1 - history_pos];
|
||||||
};
|
};
|
||||||
var fwd = function () {
|
var fwd = function (scratchInput) {
|
||||||
// step forwards in history stack
|
// step forwards in history stack
|
||||||
history_pos = Math.max(--history_pos, 0);
|
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) {
|
var add = function (input) {
|
||||||
// add a new entry to history, don't repeat latest
|
// 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) {
|
if (history.length >= history_max) {
|
||||||
history.shift(); // kill oldest entry
|
history.shift(); // kill oldest entry
|
||||||
}
|
}
|
||||||
history[history.length-1] = input;
|
history[history.length-1] = input;
|
||||||
history[history.length] = '';
|
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,
|
return {back: back,
|
||||||
fwd: fwd,
|
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
|
// Grab text from inputline and send to Evennia
|
||||||
function doSendText() {
|
function doSendText() {
|
||||||
inputfield = $("#inputfield");
|
inputfield = $("#inputfield");
|
||||||
|
isInputDirty = false;
|
||||||
var outtext = inputfield.val();
|
var outtext = inputfield.val();
|
||||||
if (outtext.length > 7 && outtext.substr(0, 7) == "##send ") {
|
if (outtext.length > 7 && outtext.substr(0, 7) == "##send ") {
|
||||||
// send a specific oob instruction
|
// send a specific oob instruction
|
||||||
|
|
@ -76,6 +94,7 @@ function doSendText() {
|
||||||
// catch all keyboard input, handle special chars
|
// catch all keyboard input, handle special chars
|
||||||
function onKeydown (event) {
|
function onKeydown (event) {
|
||||||
var code = event.which;
|
var code = event.which;
|
||||||
|
var history_entry = null;
|
||||||
inputfield = $("#inputfield");
|
inputfield = $("#inputfield");
|
||||||
inputfield.focus();
|
inputfield.focus();
|
||||||
|
|
||||||
|
|
@ -83,22 +102,76 @@ function onKeydown (event) {
|
||||||
doSendText();
|
doSendText();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
else if (code === 38) { // Arrow up
|
else if (inputfield[0].selectionStart == inputfield.val().length) {
|
||||||
inputfield.val(input_history.back());
|
// Only process up/down arrow if cursor is at the end of the line.
|
||||||
event.preventDefault();
|
if (code === 38) { // Arrow up
|
||||||
|
history_entry = input_history.back();
|
||||||
}
|
}
|
||||||
else if (code === 40) { // Arrow down
|
else if (code === 40) { // Arrow down
|
||||||
inputfield.val(input_history.fwd());
|
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();
|
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
|
// Handle resizing of client
|
||||||
function doWindowResize() {
|
function doWindowResize() {
|
||||||
var winh = $(document).height();
|
|
||||||
var formh = $('#inputform').outerHeight(true);
|
var formh = $('#inputform').outerHeight(true);
|
||||||
$("#messagewindow").css({'height': winh - formh - 1});
|
var message_scrollh = $("#messagewindow").prop("scrollHeight");
|
||||||
$("#inputform").css({'bottom': JSON.stringify(-$("#inputform").height()-10)+"px"});
|
$("#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
|
// Handle text coming from the server
|
||||||
|
|
@ -143,8 +216,11 @@ function onDefault(cmdname, args, kwargs) {
|
||||||
$(window).bind("resize", doWindowResize);
|
$(window).bind("resize", doWindowResize);
|
||||||
$("#inputfield").bind("resize", doWindowResize);
|
$("#inputfield").bind("resize", doWindowResize);
|
||||||
|
|
||||||
// Evenit when any key is pressed
|
// Event when any key is pressed
|
||||||
$(document).keydown(onKeydown);
|
$(document).keydown(onKeydown)
|
||||||
|
.bind("keyup", resizeInputField)
|
||||||
|
.bind("paste", resizeInputField)
|
||||||
|
.bind("cut", resizeInputField);
|
||||||
|
|
||||||
// Event when client finishes loading
|
// Event when client finishes loading
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
|
||||||
|
|
@ -56,18 +56,14 @@ JQuery available.
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="noscript" class="err">
|
<noscript class="err">
|
||||||
<h3>Javascript Error: The Evennia MUD client requires that you
|
<h3>Javascript Error: The Evennia MUD client requires that you
|
||||||
have Javascript activated.</h3>
|
have Javascript activated.</h3>
|
||||||
<p>Turn off eventual script blockers and/or switch to a
|
<p>Turn off eventual script blockers and/or switch to a
|
||||||
web browser supporting javascript. <p>
|
web browser supporting javascript. <p>
|
||||||
This error could also be due to not being able to access
|
This error could also be due to not being able to access
|
||||||
the online jQuery javascript library.</p>
|
the online jQuery javascript library.</p>
|
||||||
<!-- This is will only fire if javascript is actually active -->
|
</noscript>
|
||||||
<script language="javascript" type="text/javascript">
|
|
||||||
$('#noscript').remove();
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- main client -->
|
<!-- main client -->
|
||||||
<div id=clientwrapper>
|
<div id=clientwrapper>
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
<input id="inputsend" type="button" onClick="doSendText()" value=">"/>
|
<input id="inputsend" type="button" onClick="doSendText()" value=">"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="inputsizer"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue