Merge branch 'goldenlayout_develop' of https://github.com/friarzen/evennia into friarzen-goldenlayout_develop
This commit is contained in:
commit
1b9efff99d
8 changed files with 919 additions and 125 deletions
117
evennia/web/webclient/static/webclient/css/goldenlayout.css
Normal file
117
evennia/web/webclient/static/webclient/css/goldenlayout.css
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#clientwrapper #main {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#clientwrapper #main #main-sub {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toolbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#optionsbutton {
|
||||||
|
font-size: .9rem;
|
||||||
|
width: .9rem;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body .lm_popout {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lm_title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#typelist {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typelistsub {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
width: max-content;
|
||||||
|
background-color: #333333;
|
||||||
|
line-height: .5em;
|
||||||
|
padding: .3em;
|
||||||
|
font-size: .9em;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renamebox {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renameboxin {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#updatelist {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.updatelistsub {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
width: max-content;
|
||||||
|
background-color: #333333;
|
||||||
|
line-height: .5em;
|
||||||
|
padding: .3em;
|
||||||
|
font-size: .9em;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inputcontrol {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputwrap {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputsend {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1;
|
||||||
|
height: inherit;
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputfield {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
height: inherit;
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputfield:focus {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glbutton {
|
||||||
|
font-size: 0.6em;
|
||||||
|
line-height: 1.3em;
|
||||||
|
padding: .5em;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Evennia Webclient default 'send-text-on-enter-key' IO plugin
|
* Evennia Webclient default "send-text-on-enter-key" IO plugin
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
let defaultin_plugin = (function () {
|
let defaultin_plugin = (function () {
|
||||||
|
|
@ -8,16 +8,48 @@ let defaultin_plugin = (function () {
|
||||||
//
|
//
|
||||||
// handle the default <enter> key triggering onSend()
|
// handle the default <enter> key triggering onSend()
|
||||||
var onKeydown = function (event) {
|
var onKeydown = function (event) {
|
||||||
$("#inputfield").focus();
|
// find where the key comes from
|
||||||
if ( (event.which === 13) && (!event.shiftKey) ) { // Enter Key without shift
|
var inputfield = $(".inputfield:focus");
|
||||||
var inputfield = $("#inputfield");
|
|
||||||
var outtext = inputfield.val();
|
if( inputfield.length < 1 ) { // non-goldenlayout backwards compatibility
|
||||||
var lines = outtext.trim().replace(/[\r]+/,"\n").replace(/[\n]+/, "\n").split("\n");
|
inputfield = $("#inputfield:focus");
|
||||||
for (var i = 0; i < lines.length; i++) {
|
}
|
||||||
plugin_handler.onSend( lines[i].trim() );
|
|
||||||
}
|
// check for important keys
|
||||||
inputfield.val('');
|
switch (event.which) {
|
||||||
event.preventDefault();
|
case 9: // ignore tab key -- allows normal focus control
|
||||||
|
case 16: // ignore shift
|
||||||
|
case 17: // ignore alt
|
||||||
|
case 18: // ignore control
|
||||||
|
case 20: // ignore caps lock
|
||||||
|
case 144: // ignore num lock
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13: // Enter key
|
||||||
|
var outtext = inputfield.val(); // Grab the text from which-ever inputfield is focused
|
||||||
|
if ( outtext && !event.shiftKey ) { // Enter Key without shift --> send Mesg
|
||||||
|
var lines = outtext.trim().replace(/[\r]+/,"\n").replace(/[\n]+/, "\n").split("\n");
|
||||||
|
for (var i = 0; i < lines.length; i++) {
|
||||||
|
plugin_handler.onSend( lines[i].trim() );
|
||||||
|
}
|
||||||
|
inputfield.val(""); // Clear this inputfield
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
inputfield.blur();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Anything else, focus() a textarea if needed, and allow the default event
|
||||||
|
default:
|
||||||
|
// is an inputfield actually focused?
|
||||||
|
if( inputfield.length < 1 ) {
|
||||||
|
// Nope, focus the last .inputfield found in the DOM (or #inputfield)
|
||||||
|
// :last only matters if multi-input plugins are in use
|
||||||
|
inputfield = $(".inputfield:last");
|
||||||
|
inputfield.focus();
|
||||||
|
if( inputfield.length < 1 ) { // non-goldenlayout backwards compatibility
|
||||||
|
$("#inputfield").focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -26,15 +58,14 @@ let defaultin_plugin = (function () {
|
||||||
//
|
//
|
||||||
// Mandatory plugin init function
|
// Mandatory plugin init function
|
||||||
var init = function () {
|
var init = function () {
|
||||||
// Handle pressing the send button
|
// Handle pressing the send button, this only applies to non-goldenlayout setups
|
||||||
$("#inputsend")
|
$("#inputsend")
|
||||||
.bind("click", function (event) {
|
.bind("click", function (evnt) {
|
||||||
|
// simulate a carriage return
|
||||||
var e = $.Event( "keydown" );
|
var e = $.Event( "keydown" );
|
||||||
e.which = 13;
|
e.which = 13;
|
||||||
$('#inputfield').trigger(e);
|
$("#inputfield").focus().trigger(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('DefaultIn initialized');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -42,4 +73,4 @@ let defaultin_plugin = (function () {
|
||||||
onKeydown: onKeydown,
|
onKeydown: onKeydown,
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
plugin_handler.add('defaultin', defaultin_plugin);
|
window.plugin_handler.add("defaultin", defaultin_plugin);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,519 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Golden Layout plugin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
let goldenlayout = (function () {
|
||||||
|
|
||||||
|
var myLayout;
|
||||||
|
var knownTypes = ["all", "untagged"];
|
||||||
|
var untagged = [];
|
||||||
|
|
||||||
|
var newTabConfig = {
|
||||||
|
title: "Untitled",
|
||||||
|
type: "component",
|
||||||
|
componentName: "evennia",
|
||||||
|
componentState: {
|
||||||
|
types: "all",
|
||||||
|
updateMethod: "newlines",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var newInputConfig = {
|
||||||
|
title: "input",
|
||||||
|
type: "component",
|
||||||
|
componentName: "input",
|
||||||
|
id: "inputComponent",
|
||||||
|
};
|
||||||
|
|
||||||
|
// helper function: filter vals out of array
|
||||||
|
function filter (vals, array) {
|
||||||
|
if( Array.isArray( vals ) && Array.isArray( array ) ) {
|
||||||
|
let tmp = array.slice();
|
||||||
|
vals.forEach( function (val) {
|
||||||
|
while( tmp.indexOf(val) > -1 ) {
|
||||||
|
tmp.splice( tmp.indexOf(val), 1 );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
// pass along whatever we got, since our arguments aren't right.
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Calculate all knownTypes minus the "all" type,
|
||||||
|
// then filter out all types that have been mapped to a pane.
|
||||||
|
var calculateUntaggedTypes = function () {
|
||||||
|
// set initial untagged list
|
||||||
|
untagged = filter( ["all", "untagged"], knownTypes);
|
||||||
|
// for each .content pane
|
||||||
|
$(".content").each( function () {
|
||||||
|
let types = $(this).attr("types");
|
||||||
|
if ( typeof types !== "undefined" ) {
|
||||||
|
untagged = filter( types.split(" "), untagged );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var closeRenameDropdown = function () {
|
||||||
|
let content = $("#renamebox").parent().parent().parent().parent()[0];
|
||||||
|
let title = $("#renameboxin").val();
|
||||||
|
|
||||||
|
let components = myLayout.root.getItemsByType("component");
|
||||||
|
|
||||||
|
components.forEach( function (component) {
|
||||||
|
let element = component.tab.header.parent.element[0];
|
||||||
|
if( (element === content) && (component.tab.isActive) ) {
|
||||||
|
component.setTitle( title );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
myLayout.emit("stateChanged");
|
||||||
|
$("#renamebox").remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var closeTypelistDropdown = function () {
|
||||||
|
let content = $("#typelist").parent().find(".content");
|
||||||
|
let checkboxes = $("#typelist :input");
|
||||||
|
|
||||||
|
let types = [];
|
||||||
|
checkboxes.each( function (idx) {
|
||||||
|
if( $(checkboxes[idx]).prop("checked") ) {
|
||||||
|
types.push( $(checkboxes[idx]).val() );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
content.attr("types", types.join(" "));
|
||||||
|
myLayout.emit("stateChanged");
|
||||||
|
|
||||||
|
calculateUntaggedTypes();
|
||||||
|
$("#typelist").remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var closeUpdatelistDropdown = function () {
|
||||||
|
let content = $("#updatelist").parent().find(".content");
|
||||||
|
let value = $("input[name=upmethod]:checked").val();
|
||||||
|
|
||||||
|
content.attr("updateMethod", value );
|
||||||
|
myLayout.emit("stateChanged");
|
||||||
|
$("#updatelist").remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle the renameDropdown
|
||||||
|
var renameDropdown = function (evnt) {
|
||||||
|
let element = $(evnt.data.contentItem.element);
|
||||||
|
let content = element.find(".content");
|
||||||
|
let title = evnt.data.contentItem.config.title;
|
||||||
|
let renamebox = document.getElementById("renamebox");
|
||||||
|
|
||||||
|
// check that no other dropdown is open
|
||||||
|
if( document.getElementById("typelist") ) {
|
||||||
|
closeTypelistDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( document.getElementById("updatelist") ) {
|
||||||
|
closeUpdatelistDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !renamebox ) {
|
||||||
|
renamebox = $("<div id='renamebox'>");
|
||||||
|
renamebox.append("<input type='textbox' id='renameboxin' value='"+title+"'>");
|
||||||
|
renamebox.insertBefore( content );
|
||||||
|
} else {
|
||||||
|
closeRenameDropdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onSelectTypesClicked = function (evnt) {
|
||||||
|
let element = $(evnt.data.contentItem.element);
|
||||||
|
let content = element.find(".content");
|
||||||
|
let selectedTypes = content.attr("types");
|
||||||
|
let menu = $("<div id='typelist'>");
|
||||||
|
let div = $("<div class='typelistsub'>");
|
||||||
|
|
||||||
|
if( selectedTypes ) {
|
||||||
|
selectedTypes = selectedTypes.split(" ");
|
||||||
|
}
|
||||||
|
knownTypes.forEach( function (itype) {
|
||||||
|
let choice;
|
||||||
|
if( selectedTypes && selectedTypes.includes(itype) ) {
|
||||||
|
choice = $("<label><input type='checkbox' value='"+itype+"' checked='checked'/>"+itype+"</label>");
|
||||||
|
} else {
|
||||||
|
choice = $("<label><input type='checkbox' value='"+itype+"'/>"+itype+"</label>");
|
||||||
|
}
|
||||||
|
choice.appendTo(div);
|
||||||
|
});
|
||||||
|
div.appendTo(menu);
|
||||||
|
|
||||||
|
element.prepend(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle the typeDropdown
|
||||||
|
var typeDropdown = function (evnt) {
|
||||||
|
let typelist = document.getElementById("typelist");
|
||||||
|
|
||||||
|
// check that no other dropdown is open
|
||||||
|
if( document.getElementById("renamebox") ) {
|
||||||
|
closeRenameDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( document.getElementById("updatelist") ) {
|
||||||
|
closeUpdatelistDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !typelist ) {
|
||||||
|
onSelectTypesClicked(evnt);
|
||||||
|
} else {
|
||||||
|
closeTypelistDropdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onUpdateMethodClicked = function (evnt) {
|
||||||
|
let element = $(evnt.data.contentItem.element);
|
||||||
|
let content = element.find(".content");
|
||||||
|
let updateMethod = content.attr("updateMethod");
|
||||||
|
let nlchecked = (updateMethod === "newlines") ? "checked='checked'" : "";
|
||||||
|
let apchecked = (updateMethod === "append") ? "checked='checked'" : "";
|
||||||
|
let rpchecked = (updateMethod === "replace") ? "checked='checked'" : "";
|
||||||
|
|
||||||
|
let menu = $("<div id='updatelist'>");
|
||||||
|
let div = $("<div class='updatelistsub'>");
|
||||||
|
|
||||||
|
let newlines = $("<label><input type='radio' name='upmethod' value='newlines' "+nlchecked+"/>Newlines</label>");
|
||||||
|
let append = $("<label><input type='radio' name='upmethod' value='append' "+apchecked+"/>Append</label>");
|
||||||
|
let replace = $("<label><input type='radio' name='upmethod' value='replace' "+rpchecked+"/>Replace</label>");
|
||||||
|
|
||||||
|
newlines.appendTo(div);
|
||||||
|
append.appendTo(div);
|
||||||
|
replace.appendTo(div);
|
||||||
|
|
||||||
|
div.appendTo(menu);
|
||||||
|
|
||||||
|
element.prepend(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle the updateDropdown
|
||||||
|
var updateDropdown = function (evnt) {
|
||||||
|
let updatelist = document.getElementById("updatelist");
|
||||||
|
|
||||||
|
// check that no other dropdown is open
|
||||||
|
if( document.getElementById("renamebox") ) {
|
||||||
|
closeRenameDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( document.getElementById("typelist") ) {
|
||||||
|
closeTypelistDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !updatelist ) {
|
||||||
|
onUpdateMethodClicked(evnt);
|
||||||
|
} else {
|
||||||
|
closeUpdatelistDropdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onActiveTabChange = function (tab) {
|
||||||
|
let renamebox = document.getElementById("renamebox");
|
||||||
|
let typelist = document.getElementById("typelist");
|
||||||
|
let updatelist = document.getElementById("updatelist");
|
||||||
|
|
||||||
|
if( renamebox ) {
|
||||||
|
closeRenameDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( typelist ) {
|
||||||
|
closeTypelistDropdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( updatelist ) {
|
||||||
|
closeUpdatelistDropdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save the GoldenLayout state to localstorage whenever it changes.
|
||||||
|
var onStateChanged = function () {
|
||||||
|
let components = myLayout.root.getItemsByType("component");
|
||||||
|
components.forEach( function (component) {
|
||||||
|
if( component.hasId("inputComponent") ) { return; } // ignore input components
|
||||||
|
|
||||||
|
let textDiv = component.container.getElement().children(".content");
|
||||||
|
let types = textDiv.attr("types");
|
||||||
|
let updateMethod = textDiv.attr("updateMethod");
|
||||||
|
component.container.extendState({ "types": types, "updateMethod": updateMethod });
|
||||||
|
});
|
||||||
|
|
||||||
|
var state = JSON.stringify( myLayout.toConfig() );
|
||||||
|
localStorage.setItem( "evenniaGoldenLayoutSavedState", state );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onTabCreate = function (tab) {
|
||||||
|
//HTML for the typeDropdown
|
||||||
|
let renameDropdownControl = $("<span class='lm_title' style='font-size: 1em;width: 1.5em;'>\u2B57</span>");
|
||||||
|
let typeDropdownControl = $("<span class='lm_title' style='font-size: 1.5em;width: 1em;'>⮛</span>");
|
||||||
|
let updateDropdownControl = $("<span class='lm_title' style='font-size: 1.5em;width: 1em;'>⮛</span>");
|
||||||
|
let splitControl = $("<span class='lm_title' style='font-size: 2em;width: 1em;'>+</span>");
|
||||||
|
|
||||||
|
// track dropdowns when the associated control is clicked
|
||||||
|
renameDropdownControl.click( tab, renameDropdown );
|
||||||
|
|
||||||
|
typeDropdownControl.click( tab, typeDropdown );
|
||||||
|
|
||||||
|
updateDropdownControl.click( tab, updateDropdown );
|
||||||
|
|
||||||
|
// track adding a new tab
|
||||||
|
splitControl.click( tab, function (evnt) {
|
||||||
|
evnt.data.header.parent.addChild( newTabConfig );
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add the typeDropdown to the header
|
||||||
|
tab.element.prepend( renameDropdownControl );
|
||||||
|
tab.element.append( typeDropdownControl );
|
||||||
|
tab.element.append( updateDropdownControl );
|
||||||
|
tab.element.append( splitControl );
|
||||||
|
|
||||||
|
if( tab.contentItem.config.componentName === "Main" ) {
|
||||||
|
tab.element.prepend( $("#optionsbutton").clone(true).addClass("lm_title") );
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.header.parent.on( "activeContentItemChanged", onActiveTabChange );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onInputCreate = function (tab) {
|
||||||
|
//HTML for the typeDropdown
|
||||||
|
let splitControl = $("<span class='lm_title' style='font-size: 2em;width: 1em;'>+</span>");
|
||||||
|
|
||||||
|
// track adding a new tab
|
||||||
|
splitControl.click( tab, function (evnt) {
|
||||||
|
evnt.data.header.parent.addChild( newInputConfig );
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add the typeDropdown to the header
|
||||||
|
tab.element.append( splitControl );
|
||||||
|
|
||||||
|
tab.header.parent.on( "activeContentItemChanged", onActiveTabChange );
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var scrollAll = function () {
|
||||||
|
let components = myLayout.root.getItemsByType("component");
|
||||||
|
components.forEach( function (component) {
|
||||||
|
if( component.hasId("inputComponent") ) { return; } // ignore input components
|
||||||
|
|
||||||
|
let textDiv = component.container.getElement().children(".content");
|
||||||
|
let scrollHeight = textDiv.prop("scrollHeight");
|
||||||
|
let clientHeight = textDiv.prop("clientHeight");
|
||||||
|
textDiv.scrollTop( scrollHeight - clientHeight );
|
||||||
|
});
|
||||||
|
myLayout.updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var routeMsg = function (textDiv, txt, updateMethod) {
|
||||||
|
if ( updateMethod === "replace" ) {
|
||||||
|
textDiv.html(txt);
|
||||||
|
} else if ( updateMethod === "append" ) {
|
||||||
|
textDiv.append(txt);
|
||||||
|
} else { // line feed
|
||||||
|
textDiv.append("<div class='out'>" + txt + "</div>");
|
||||||
|
}
|
||||||
|
let scrollHeight = textDiv.prop("scrollHeight");
|
||||||
|
let clientHeight = textDiv.prop("clientHeight");
|
||||||
|
textDiv.scrollTop( scrollHeight - clientHeight );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var initComponent = function (div, container, state, defaultTypes, updateMethod) {
|
||||||
|
// set this container"s content div types attribute
|
||||||
|
if( state ) {
|
||||||
|
div.attr("types", state.types);
|
||||||
|
div.attr("updateMethod", state.updateMethod);
|
||||||
|
} else {
|
||||||
|
div.attr("types", defaultTypes);
|
||||||
|
div.attr("updateMethod", updateMethod);
|
||||||
|
}
|
||||||
|
div.appendTo( container.getElement() );
|
||||||
|
container.on("tab", onTabCreate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Public
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onKeydown = function(evnt) {
|
||||||
|
var renamebox = document.getElementById("renamebox");
|
||||||
|
if( renamebox ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var onText = function (args, kwargs) {
|
||||||
|
// If the message is not itself tagged, we"ll assume it
|
||||||
|
// should go into any panes with "all" and "untagged" set
|
||||||
|
var msgtype = "untagged";
|
||||||
|
|
||||||
|
if ( kwargs && "type" in kwargs ) {
|
||||||
|
msgtype = kwargs["type"];
|
||||||
|
if ( ! knownTypes.includes(msgtype) ) {
|
||||||
|
// this is a new output type that can be mapped to panes
|
||||||
|
knownTypes.push(msgtype);
|
||||||
|
untagged.push(msgtype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let messageDelivered = false;
|
||||||
|
let components = myLayout.root.getItemsByType("component");
|
||||||
|
|
||||||
|
components.forEach( function (component) {
|
||||||
|
if( component.hasId("inputComponent") ) { return; } // ignore the input component
|
||||||
|
|
||||||
|
let textDiv = component.container.getElement().children(".content");
|
||||||
|
let attrTypes = textDiv.attr("types");
|
||||||
|
let paneTypes = attrTypes ? attrTypes.split(" ") : [];
|
||||||
|
let updateMethod = textDiv.attr("updateMethod");
|
||||||
|
let txt = args[0];
|
||||||
|
|
||||||
|
// is this message type listed in this pane"s types (or is this pane catching "all")
|
||||||
|
if( paneTypes.includes(msgtype) || paneTypes.includes("all") ) {
|
||||||
|
routeMsg( textDiv, txt, updateMethod );
|
||||||
|
messageDelivered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is this pane catching "upmapped" messages?
|
||||||
|
// And is this message type listed in the untagged types array?
|
||||||
|
if( paneTypes.includes("untagged") && untagged.includes(msgtype) ) {
|
||||||
|
routeMsg( textDiv, txt, updateMethod );
|
||||||
|
messageDelivered = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( messageDelivered ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// unhandled message
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var postInit = function () {
|
||||||
|
// finish the setup and actually start GoldenLayout
|
||||||
|
myLayout.init();
|
||||||
|
|
||||||
|
// Set the Event handler for when the client window changes size
|
||||||
|
$(window).bind("resize", scrollAll);
|
||||||
|
|
||||||
|
// Set Save State callback
|
||||||
|
myLayout.on( "stateChanged", onStateChanged );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// required Init me
|
||||||
|
var init = function (options) {
|
||||||
|
// Set up our GoldenLayout instance built off of the default main-sub div
|
||||||
|
var savedState = localStorage.getItem( "evenniaGoldenLayoutSavedState" );
|
||||||
|
var mainsub = document.getElementById("main-sub");
|
||||||
|
|
||||||
|
if( savedState !== null ) {
|
||||||
|
// Overwrite the global-variable configuration with the version from localstorage
|
||||||
|
window.goldenlayout_config = JSON.parse( savedState );
|
||||||
|
}
|
||||||
|
|
||||||
|
myLayout = new GoldenLayout( window.goldenlayout_config, mainsub );
|
||||||
|
|
||||||
|
$("#inputcontrol").remove(); // remove the cluttered, HTML-defined input divs
|
||||||
|
|
||||||
|
// register our component and replace the default messagewindow with the Main component
|
||||||
|
myLayout.registerComponent( "Main", function (container, componentState) {
|
||||||
|
let main = $("#messagewindow").addClass("content");
|
||||||
|
initComponent(main, container, componentState, "untagged", "newlines" );
|
||||||
|
});
|
||||||
|
|
||||||
|
// register our new input component
|
||||||
|
myLayout.registerComponent( "input", function (container, componentState) {
|
||||||
|
var inputfield = $("<textarea type='text' class='inputfield form-control'></textarea>");
|
||||||
|
var button = $("<button type='button' class='inputsend'>></button>");
|
||||||
|
|
||||||
|
$("<div class='inputwrap'>")
|
||||||
|
.append( button )
|
||||||
|
.append( inputfield )
|
||||||
|
.appendTo( container.getElement() );
|
||||||
|
|
||||||
|
button.bind("click", function (evnt) {
|
||||||
|
// focus our textarea
|
||||||
|
$( $(evnt.target).siblings(".inputfield")[0] ).focus();
|
||||||
|
// fake a carriage return event
|
||||||
|
var e = $.Event("keydown");
|
||||||
|
e.which = 13;
|
||||||
|
$( $(evnt.target).siblings(".inputfield")[0] ).trigger(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
container.on("tab", onInputCreate);
|
||||||
|
});
|
||||||
|
|
||||||
|
myLayout.registerComponent( "evennia", function (container, componentState) {
|
||||||
|
let div = $("<div class='content'></div>");
|
||||||
|
initComponent(div, container, componentState, "all", "newlines");
|
||||||
|
container.on("destroy", calculateUntaggedTypes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
init: init,
|
||||||
|
postInit: postInit,
|
||||||
|
onKeydown: onKeydown,
|
||||||
|
onText: onText,
|
||||||
|
getGL: function () { return myLayout; },
|
||||||
|
addKnownType: function (newtype) { knownTypes.push(newtype); },
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
window.plugin_handler.add("goldenlayout", goldenlayout);
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Define the default GoldenLayout-based config
|
||||||
|
*
|
||||||
|
* The layout defined here will need to be customized based on which plugins
|
||||||
|
* you are using and what layout you want players to see by default.
|
||||||
|
*
|
||||||
|
* This needs to be loaded in the HTML before the goldenlayout.js plugin
|
||||||
|
*
|
||||||
|
* The contents of the global variable will be overwritten by what is in the
|
||||||
|
* browser's localstorage after visiting this site.
|
||||||
|
*
|
||||||
|
* For full documentation on all of the keywords see:
|
||||||
|
* http://golden-layout.com/docs/Config.html
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
var goldenlayout_config = { // Global Variable used in goldenlayout.js init()
|
||||||
|
content: [{
|
||||||
|
type: "column",
|
||||||
|
content: [{
|
||||||
|
type: "row",
|
||||||
|
content: [{
|
||||||
|
type: "column",
|
||||||
|
content: [{
|
||||||
|
type: "component",
|
||||||
|
componentName: "Main",
|
||||||
|
isClosable: false, // remove the 'x' control to close this
|
||||||
|
tooltip: "Main - drag to desird position.",
|
||||||
|
componentState: {
|
||||||
|
types: "untagged",
|
||||||
|
updateMethod: "newlines",
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
// }, { // Uncomment the following to add a default hotbuttons component
|
||||||
|
// type: "component",
|
||||||
|
// componentName: "hotbuttons",
|
||||||
|
// id: "inputComponent", // mark 'ignore this component during output message processing'
|
||||||
|
// height: 6,
|
||||||
|
// isClosable: false,
|
||||||
|
}, {
|
||||||
|
type: "component",
|
||||||
|
componentName: "input",
|
||||||
|
id: "inputComponent", // mark for ignore
|
||||||
|
height: 12, // percentage
|
||||||
|
tooltip: "Input - The last input in the layout is always the default.",
|
||||||
|
}, {
|
||||||
|
type: "component",
|
||||||
|
componentName: "input",
|
||||||
|
id: "inputComponent", // mark for ignore
|
||||||
|
height: 12, // percentage
|
||||||
|
isClosable: false, // remove the 'x' control to close this
|
||||||
|
tooltip: "Input - The last input in the layout is always the default.",
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
@ -3,29 +3,29 @@
|
||||||
* Evennia Webclient Command History plugin
|
* Evennia Webclient Command History plugin
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
let history_plugin = (function () {
|
let history = (function () {
|
||||||
|
|
||||||
// Manage history for input line
|
// Manage history for input line
|
||||||
var history_max = 21;
|
var historyMax = 21;
|
||||||
var history = new Array();
|
var history = new Array();
|
||||||
var history_pos = 0;
|
var historyPos = 0;
|
||||||
|
|
||||||
history[0] = ''; // the very latest input is empty for new entry.
|
history[0] = ""; // the very latest input is empty for new entry.
|
||||||
|
|
||||||
//
|
//
|
||||||
// move back in the history
|
// move back in the history
|
||||||
var back = function () {
|
var back = function () {
|
||||||
// step backwards in history stack
|
// step backwards in history stack
|
||||||
history_pos = Math.min(++history_pos, history.length - 1);
|
historyPos = Math.min(++historyPos, history.length - 1);
|
||||||
return history[history.length - 1 - history_pos];
|
return history[history.length - 1 - historyPos];
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// move forward in the history
|
// move forward in the history
|
||||||
var fwd = function () {
|
var fwd = function () {
|
||||||
// step forwards in history stack
|
// step forwards in history stack
|
||||||
history_pos = Math.max(--history_pos, 0);
|
historyPos = Math.max(--historyPos, 0);
|
||||||
return history[history.length - 1 - history_pos];
|
return history[history.length - 1 - historyPos];
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -33,23 +33,13 @@ let history_plugin = (function () {
|
||||||
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-2]) {
|
if (input && input != history[history.length-2]) {
|
||||||
if (history.length >= history_max) {
|
if (history.length >= historyMax) {
|
||||||
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
|
historyPos = 0;
|
||||||
history_pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add input to the scratch line
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
|
|
@ -58,21 +48,26 @@ let history_plugin = (function () {
|
||||||
// Handle up arrow and down arrow events.
|
// Handle up arrow and down arrow events.
|
||||||
var onKeydown = function(event) {
|
var onKeydown = function(event) {
|
||||||
var code = event.which;
|
var code = event.which;
|
||||||
var history_entry = null;
|
var historyEntry = null;
|
||||||
var inputfield = $("#inputfield");
|
|
||||||
|
|
||||||
if (code === 38) { // Arrow up
|
// Only process up/down arrow if cursor is at the end of the line.
|
||||||
history_entry = back();
|
if (code === 38 && event.shiftKey) { // Arrow up
|
||||||
|
historyEntry = back();
|
||||||
}
|
}
|
||||||
else if (code === 40) { // Arrow down
|
else if (code === 40 && event.shiftKey) { // Arrow down
|
||||||
history_entry = fwd();
|
historyEntry = fwd();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (history_entry !== null) {
|
// are we processing an up or down history event?
|
||||||
// Performing a history navigation
|
if (historyEntry !== null) {
|
||||||
// replace the text in the input and move the cursor to the end of the new value
|
// Doing a history navigation; replace the text in the input and
|
||||||
inputfield.val('');
|
// move the cursor to the end of the new value
|
||||||
inputfield.blur().focus().val(history_entry);
|
var inputfield = $(".inputfield:focus");
|
||||||
|
if( inputfield.length < 1 ) { // pre-goldenlayout backwards compatibility
|
||||||
|
inputfield = $("#inputfield");
|
||||||
|
}
|
||||||
|
inputfield.val("");
|
||||||
|
inputfield.blur().focus().val(historyEntry);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -84,19 +79,13 @@ let history_plugin = (function () {
|
||||||
// Listen for onSend lines to add to history
|
// Listen for onSend lines to add to history
|
||||||
var onSend = function (line) {
|
var onSend = function (line) {
|
||||||
add(line);
|
add(line);
|
||||||
return null; // we are not returning an altered input line
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Init function
|
|
||||||
var init = function () {
|
|
||||||
console.log('History Plugin Initialized.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: init,
|
init: function () {},
|
||||||
onKeydown: onKeydown,
|
onKeydown: onKeydown,
|
||||||
onSend: onSend,
|
onSend: onSend,
|
||||||
}
|
}
|
||||||
})()
|
}());
|
||||||
plugin_handler.add('history', history_plugin);
|
window.plugin_handler.add("history", history);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Assignable 'hot-buttons' Plugin
|
* Assignable "hot-buttons" Plugin
|
||||||
*
|
*
|
||||||
* This adds a bar of 9 buttons that can be shift-click assigned whatever is in the textinput buffer, so you can simply
|
* This adds a bar of 9 buttons that can be shift-click assigned,
|
||||||
* click the button again and have it execute those commands, instead of having to type it all out again and again.
|
* whatever text is in the bottom textinput buffer will be copied.
|
||||||
|
* Once assigned, clicking the button again and have it execute those commands.
|
||||||
*
|
*
|
||||||
* It stores these commands as server side options.
|
* It stores these commands as server side options.
|
||||||
*
|
*
|
||||||
|
|
@ -12,51 +13,26 @@
|
||||||
* Stop Evennia
|
* Stop Evennia
|
||||||
*
|
*
|
||||||
* Copy this file to mygame/web/static_overrides/webclient/js/plugins/hotbuttons.js
|
* Copy this file to mygame/web/static_overrides/webclient/js/plugins/hotbuttons.js
|
||||||
* Copy evennia/web/webclient/templates/webclient/base.html to mygame/web/template_overrides/webclient/base.html
|
*
|
||||||
|
* Copy evennia/web/webclient/templates/webclient/base.html to
|
||||||
|
* mygame/web/template_overrides/webclient/base.html
|
||||||
*
|
*
|
||||||
* Edit mygame/web/template_overrides/webclient/base.html to add:
|
* Edit mygame/web/template_overrides/webclient/base.html to add:
|
||||||
* <script src={% static "webclient/js/plugins/hotbuttons.js" %} language="javascript" type="text/javascript"></script>
|
* <script src={% static "webclient/js/plugins/hotbuttons.js" %} type="text/javascript"></script>
|
||||||
* after the other <script></script> plugin tags.
|
* before the goldenlayout.js plugin tags or after the splithandler.js <script></script> plugin tags
|
||||||
*
|
*
|
||||||
* Run: evennia collectstatic (say 'yes' to the overwrite prompt)
|
* If you are using goldenlayout.js, uncomment the hotbuttons component in goldenlayout_default_config.js
|
||||||
|
*
|
||||||
|
* Run: evennia collectstatic (say "yes" to the overwrite prompt)
|
||||||
* Start Evennia
|
* Start Evennia
|
||||||
|
*
|
||||||
|
* REQUIRES: goldenlayout.js OR splithandler.js
|
||||||
*/
|
*/
|
||||||
plugin_handler.add('hotbuttons', (function () {
|
let hotbuttons = (function () {
|
||||||
|
var dependenciesMet = false;
|
||||||
|
|
||||||
var num_buttons = 9;
|
var numButtons = 9;
|
||||||
var command_cache = new Array(num_buttons);
|
var commandCache = new Array;
|
||||||
|
|
||||||
//
|
|
||||||
// Add Buttons
|
|
||||||
var addButtonsUI = function () {
|
|
||||||
var buttons = $( [
|
|
||||||
'<div id="buttons" class="split split-vertical">',
|
|
||||||
' <div id="buttonsform">',
|
|
||||||
' <div id="buttonscontrol" class="input-group">',
|
|
||||||
' <button class="btn" id="assign_button0" type="button" value="button0">unassigned</button>',
|
|
||||||
' <button class="btn" id="assign_button1" type="button" value="button1">unassigned</button>',
|
|
||||||
' <button class="btn" id="assign_button2" type="button" value="button2">unassigned</button>',
|
|
||||||
' <button class="btn" id="assign_button3" type="button" value="button3">unassigned</button>',
|
|
||||||
' <button class="btn" id="assign_button4" type="button" value="button4">unassigned</button>',
|
|
||||||
' <button class="btn" id="assign_button5" type="button" value="button5">unassigned</button>',
|
|
||||||
' <button class="btn" id="assign_button6" type="button" value="button6">unassigned</button>',
|
|
||||||
' <button class="btn" id="assign_button7" type="button" value="button7">unassigned</button>',
|
|
||||||
' <button class="btn" id="assign_button8" type="button" value="button8">unassigned</button>',
|
|
||||||
' </div>',
|
|
||||||
' </div>',
|
|
||||||
'</div>',
|
|
||||||
].join("\n") );
|
|
||||||
|
|
||||||
// Add buttons in front of the existing #inputform
|
|
||||||
$('#input').prev().replaceWith(buttons);
|
|
||||||
|
|
||||||
Split(['#main','#buttons','#input'], {
|
|
||||||
sizes: [85,5,10],
|
|
||||||
direction: 'vertical',
|
|
||||||
gutterSize: 4,
|
|
||||||
minSize: [150,20,50],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// collect command text
|
// collect command text
|
||||||
|
|
@ -64,7 +40,7 @@ plugin_handler.add('hotbuttons', (function () {
|
||||||
// make sure text has something in it
|
// make sure text has something in it
|
||||||
if( text && text.length ) {
|
if( text && text.length ) {
|
||||||
// cache the command text
|
// cache the command text
|
||||||
command_cache[n] = text;
|
commandCache[n] = text;
|
||||||
|
|
||||||
// is there a space in the command, indicating "command argument" syntax?
|
// is there a space in the command, indicating "command argument" syntax?
|
||||||
if( text.indexOf(" ") > 0 ) {
|
if( text.indexOf(" ") > 0 ) {
|
||||||
|
|
@ -83,13 +59,13 @@ plugin_handler.add('hotbuttons', (function () {
|
||||||
// change button text to "unassigned"
|
// change button text to "unassigned"
|
||||||
$("#assign_button"+n).text( "unassigned" );
|
$("#assign_button"+n).text( "unassigned" );
|
||||||
// clear current command
|
// clear current command
|
||||||
command_cache[n] = "unassigned";
|
commandCache[n] = "unassigned";
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// actually send the command associated with the button that is clicked
|
// actually send the command associated with the button that is clicked
|
||||||
var sendImmediate = function(n) {
|
var sendImmediate = function(n) {
|
||||||
var text = command_cache[n];
|
var text = commandCache[n];
|
||||||
if( text.length ) {
|
if( text.length ) {
|
||||||
Evennia.msg("text", [text], {});
|
Evennia.msg("text", [text], {});
|
||||||
}
|
}
|
||||||
|
|
@ -99,55 +75,129 @@ plugin_handler.add('hotbuttons', (function () {
|
||||||
// send, assign, or clear the button
|
// send, assign, or clear the button
|
||||||
var hotButtonClicked = function(e) {
|
var hotButtonClicked = function(e) {
|
||||||
var button = $("#assign_button"+e.data);
|
var button = $("#assign_button"+e.data);
|
||||||
console.log("button " + e.data + " clicked");
|
|
||||||
if( button.text() == "unassigned" ) {
|
if( button.text() == "unassigned" ) {
|
||||||
// Assign the button and send the full button state to the server using a Webclient_Options event
|
// Assign the button and send the full button state to the server using a Webclient_Options event
|
||||||
assignButton( e.data, $('#inputfield').val() );
|
var input = $(".inputfield:last");
|
||||||
Evennia.msg("webclient_options", [], { "HotButtons": command_cache });
|
if( input.length < 1 ) {
|
||||||
|
input = $("#inputfield");
|
||||||
|
}
|
||||||
|
assignButton( e.data, input.val() );
|
||||||
|
Evennia.msg("webclient_options", [], { "HotButtons": commandCache });
|
||||||
} else {
|
} else {
|
||||||
if( e.shiftKey ) {
|
if( e.shiftKey ) {
|
||||||
// Clear the button and send the full button state to the server using a Webclient_Options event
|
// Clear the button and send the full button state to the server using a Webclient_Options event
|
||||||
clearButton(e.data);
|
clearButton(e.data);
|
||||||
Evennia.msg("webclient_options", [], { "HotButtons": command_cache });
|
Evennia.msg("webclient_options", [], { "HotButtons": commandCache });
|
||||||
} else {
|
} else {
|
||||||
sendImmediate(e.data);
|
sendImmediate(e.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add Buttons UI for SplitHandler
|
||||||
|
var addButtonsUI = function () {
|
||||||
|
var buttons = $( [
|
||||||
|
"<div id='buttons' class='split split-vertical'>",
|
||||||
|
" <div id='buttonsform'>",
|
||||||
|
" <div id='buttonscontrol' class='input-group'>",
|
||||||
|
" <button class='btn' id='assign_button0' type='button' value='button0'>unassigned</button>",
|
||||||
|
" <button class='btn' id='assign_button1' type='button' value='button1'>unassigned</button>",
|
||||||
|
" <button class='btn' id='assign_button2' type='button' value='button2'>unassigned</button>",
|
||||||
|
" <button class='btn' id='assign_button3' type='button' value='button3'>unassigned</button>",
|
||||||
|
" <button class='btn' id='assign_button4' type='button' value='button4'>unassigned</button>",
|
||||||
|
" <button class='btn' id='assign_button5' type='button' value='button5'>unassigned</button>",
|
||||||
|
" <button class='btn' id='assign_button6' type='button' value='button6'>unassigned</button>",
|
||||||
|
" <button class='btn' id='assign_button7' type='button' value='button7'>unassigned</button>",
|
||||||
|
" <button class='btn' id='assign_button8' type='button' value='button8'>unassigned</button>",
|
||||||
|
" </div>",
|
||||||
|
" </div>",
|
||||||
|
"</div>",
|
||||||
|
].join("\n") );
|
||||||
|
|
||||||
|
// Add buttons in front of the existing #inputform
|
||||||
|
$("#input").prev().replaceWith(buttons);
|
||||||
|
|
||||||
|
Split(["#main","#buttons","#input"], {
|
||||||
|
sizes: [85,5,10],
|
||||||
|
direction: "vertical",
|
||||||
|
gutterSize: 4,
|
||||||
|
minSize: [150,20,50],
|
||||||
|
});
|
||||||
|
|
||||||
|
for( var n=0; n<numButtons; n++ ) {
|
||||||
|
commandCache.push("unassigned");
|
||||||
|
$("#assign_button"+n).click( n, hotButtonClicked );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create and register the hotbuttons golden-layout component
|
||||||
|
var buildComponent = function () {
|
||||||
|
var myLayout = window.plugins["goldenlayout"].getGL();
|
||||||
|
|
||||||
|
myLayout.registerComponent( "hotbuttons", function (container, componentState) {
|
||||||
|
// build the buttons
|
||||||
|
var div = $("<div class='input-group'>");
|
||||||
|
|
||||||
|
var len = commandCache.length;
|
||||||
|
for( var x=len; x < len + numButtons; x++ ) {
|
||||||
|
commandCache.push("unassigned");
|
||||||
|
|
||||||
|
// initialize button command cache and onClick handler
|
||||||
|
var button = $("<button class='btn' id='assign_button"+x+"' type='button' value='button"+x+"'>");
|
||||||
|
button.html("unassigned");
|
||||||
|
button.click( x, hotButtonClicked );
|
||||||
|
|
||||||
|
button.appendTo( div );
|
||||||
|
}
|
||||||
|
|
||||||
|
div.appendTo( container.getElement() );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Public
|
// Public
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle the HotButtons part of a Webclient_Options event
|
// Handle the HotButtons part of a Webclient_Options event
|
||||||
var onGotOptions = function(args, kwargs) {
|
var onGotOptions = function(args, kwargs) {
|
||||||
console.log( args );
|
if( dependenciesMet && kwargs["HotButtons"] ) {
|
||||||
console.log( kwargs );
|
var buttonOptions = kwargs["HotButtons"];
|
||||||
if( kwargs['HotButtons'] ) {
|
$.each( buttonOptions, function( key, value ) {
|
||||||
var buttons = kwargs['HotButtons'];
|
|
||||||
$.each( buttons, function( key, value ) {
|
|
||||||
assignButton(key, value);
|
assignButton(key, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize me
|
// Initialize me
|
||||||
var init = function() {
|
var init = function() {
|
||||||
|
// Are we using splithandler?
|
||||||
// Add buttons to the UI
|
if( window.plugins["splithandler"] ) {
|
||||||
addButtonsUI();
|
addButtonsUI();
|
||||||
|
dependenciesMet = true;
|
||||||
// assign button cache
|
|
||||||
for( var n=0; n<num_buttons; n++ ) {
|
|
||||||
command_cache[n] = "unassigned";
|
|
||||||
$("#assign_button"+n).click( n, hotButtonClicked );
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log("HotButtons Plugin Initialized.");
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
var postInit = function() {
|
||||||
|
// Are we using GoldenLayout?
|
||||||
|
if( window.plugins["goldenlayout"] ) {
|
||||||
|
buildComponent();
|
||||||
|
dependenciesMet = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
|
postInit: postInit,
|
||||||
onGotOptions: onGotOptions,
|
onGotOptions: onGotOptions,
|
||||||
}
|
}
|
||||||
})());
|
})();
|
||||||
|
window.plugin_handler.add("hotbuttons", hotbuttons);
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,20 @@ var plugin_handler = (function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// normally init() is all that is needed, but some cases may require a second
|
||||||
|
// pass to avoid chicken/egg dependencies between two plugins.
|
||||||
|
var postInit = function () {
|
||||||
|
// does this plugin need postInit() to be called?
|
||||||
|
for( let n=0; n < ordered_plugins.length; n++ ) {
|
||||||
|
let plugin = ordered_plugins[n];
|
||||||
|
if( 'postInit' in plugin ) {
|
||||||
|
plugin.postInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
add: add,
|
add: add,
|
||||||
onKeydown: onKeydown,
|
onKeydown: onKeydown,
|
||||||
|
|
@ -241,6 +255,7 @@ var plugin_handler = (function () {
|
||||||
onConnectionClose: onConnectionClose,
|
onConnectionClose: onConnectionClose,
|
||||||
onSend: onSend,
|
onSend: onSend,
|
||||||
init: init,
|
init: init,
|
||||||
|
postInit: postInit,
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
@ -285,5 +300,8 @@ $(document).ready(function() {
|
||||||
// Initialize all plugins
|
// Initialize all plugins
|
||||||
plugin_handler.init();
|
plugin_handler.init();
|
||||||
|
|
||||||
|
// Finish Initializing any plugins that need a second stage
|
||||||
|
plugin_handler.postInit();
|
||||||
|
|
||||||
console.log("Completed Webclient setup");
|
console.log("Completed Webclient setup");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ JQuery available.
|
||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||||
|
|
||||||
<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" %}>
|
||||||
|
|
||||||
<link rel="icon" type="image/x-icon" href="/static/website/images/evennia_logo.png" />
|
<link rel="icon" type="image/x-icon" href="/static/website/images/evennia_logo.png" />
|
||||||
|
|
@ -64,19 +63,35 @@ JQuery available.
|
||||||
<script src={% static "webclient/js/evennia.js" %} language="javascript" type="text/javascript" charset="utf-8"/></script>
|
<script src={% static "webclient/js/evennia.js" %} language="javascript" type="text/javascript" charset="utf-8"/></script>
|
||||||
|
|
||||||
<!-- set up splits before loading the GUI -->
|
<!-- set up splits before loading the GUI -->
|
||||||
|
<!--
|
||||||
<script src="https://unpkg.com/split.js@1.5.9/dist/split.min.js"></script>
|
<script src="https://unpkg.com/split.js@1.5.9/dist/split.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
|
||||||
|
-->
|
||||||
|
<script type="text/javascript" src="https://golden-layout.com/files/latest/js/goldenlayout.min.js"></script>
|
||||||
|
<link type="text/css" rel="stylesheet" href="https://golden-layout.com/files/latest/css/goldenlayout-base.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="https://golden-layout.com/files/latest/css/goldenlayout-dark-theme.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href={% static "webclient/css/goldenlayout.css" %} />
|
||||||
|
|
||||||
<!-- Load gui library -->
|
<!-- Load gui library -->
|
||||||
{% block guilib_import %}
|
{% block guilib_import %}
|
||||||
<script src={% static "webclient/js/webclient_gui.js" %} language="javascript" type="text/javascript" charset="utf-8"></script>
|
<script src={% static "webclient/js/webclient_gui.js" %} language="javascript" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src={% static "webclient/js/plugins/goldenlayout_default_config.js" %} type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/popups.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/popups.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/options.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/options.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/history.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/history.js" %} language="javascript" type="text/javascript"></script>
|
||||||
|
<!--
|
||||||
<script src={% static "webclient/js/plugins/splithandler.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/splithandler.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/default_in.js" %} language="javascript" type="text/javascript"></script>
|
-->
|
||||||
<script src={% static "webclient/js/plugins/oob.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/oob.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/notifications.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/notifications.js" %} language="javascript" type="text/javascript"></script>
|
||||||
|
<!--
|
||||||
|
<script src={% static "webclient/js/plugins/hotbuttons.js" %} language="javascript" type="text/javascript"></script>
|
||||||
|
-->
|
||||||
|
<script src={% static "webclient/js/plugins/goldenlayout.js" %} language="javascript" type="text/javascript"></script>
|
||||||
|
<!--
|
||||||
|
<script src={% static "webclient/js/plugins/dual_input.js" %} language="javascript" type="text/javascript"></script>
|
||||||
|
-->
|
||||||
|
<script src={% static "webclient/js/plugins/default_in.js" %} language="javascript" type="text/javascript"></script>
|
||||||
<script src={% static "webclient/js/plugins/default_out.js" %} language="javascript" type="text/javascript"></script>
|
<script src={% static "webclient/js/plugins/default_out.js" %} language="javascript" type="text/javascript"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue