mirror of
https://github.com/evennia/evennia.git
synced 2026-03-20 23:06:31 +01:00
Merge branch 'master' of https://github.com/friarzen/evennia into friarzen-master
This commit is contained in:
commit
d4d2d9edcc
7 changed files with 500 additions and 411 deletions
|
|
@ -3,7 +3,9 @@
|
|||
* Evennia Webclient default "send-text-on-enter-key" IO plugin
|
||||
*
|
||||
*/
|
||||
let defaultin_plugin = (function () {
|
||||
let defaultInPlugin = (function () {
|
||||
|
||||
var focusOnKeydown = true;
|
||||
|
||||
//
|
||||
// handle the default <enter> key triggering onSend()
|
||||
|
|
@ -50,14 +52,17 @@ let defaultin_plugin = (function () {
|
|||
|
||||
// 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();
|
||||
// has some other UI element turned off this behavior temporarily?
|
||||
if( focusOnKeydown ) {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +70,12 @@ let defaultin_plugin = (function () {
|
|||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// allow other UI elements to toggle this focus behavior on/off
|
||||
var setKeydownFocus = function (bool) {
|
||||
focusOnKeydown = bool;
|
||||
}
|
||||
|
||||
//
|
||||
// Mandatory plugin init function
|
||||
var init = function () {
|
||||
|
|
@ -81,6 +92,7 @@ let defaultin_plugin = (function () {
|
|||
return {
|
||||
init: init,
|
||||
onKeydown: onKeydown,
|
||||
setKeydownFocus: setKeydownFocus,
|
||||
}
|
||||
})();
|
||||
window.plugin_handler.add("defaultin", defaultin_plugin);
|
||||
window.plugin_handler.add("default_in", defaultInPlugin);
|
||||
|
|
|
|||
|
|
@ -18,39 +18,82 @@ let font_plugin = (function () {
|
|||
};
|
||||
|
||||
//
|
||||
//
|
||||
var setStartingFont = function () {
|
||||
var fontfamily = localStorage.getItem("evenniaFontFamily");
|
||||
if( !fontfamily ) {
|
||||
$(document.body).css("font-family", fontfamily);
|
||||
}
|
||||
|
||||
var fontsize = localStorage.getItem("evenniaFontSize");
|
||||
if( !fontsize ) {
|
||||
$(document.body).css("font-size", fontsize+"em");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
var getActiveFontFamily = function () {
|
||||
var family = "DejaVu Sans Mono";
|
||||
var fontfamily = localStorage.getItem("evenniaFontFamily");
|
||||
if( fontfamily != null ) {
|
||||
family = fontfamily;
|
||||
}
|
||||
return family;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
var getActiveFontSize = function () {
|
||||
var size = "0.9";
|
||||
var fontsize = localStorage.getItem("evenniaFontSize");
|
||||
if( fontsize != null ) {
|
||||
size = fontsize;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
var onFontFamily = function (evnt) {
|
||||
var family = $(evnt.target).val();
|
||||
$(document.body).css("font-family", family);
|
||||
localStorage.setItem("evenniaFontFamily", family);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
var onFontSize = function (evnt) {
|
||||
var size = $(evnt.target).val();
|
||||
$(document.body).css("font-size", size+"em");
|
||||
localStorage.setItem("evenniaFontSize", size);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
var onOptionsUI = function (parentdiv) {
|
||||
var fontselect = $('<select>');
|
||||
var sizeselect = $('<select>');
|
||||
var fontselect = $("<select>");
|
||||
var sizeselect = $("<select>");
|
||||
|
||||
var fonts = Object.keys(font_urls);
|
||||
for (var x = 0; x < fonts.length; x++) {
|
||||
var option = $('<option value="'+fonts[x]+'">'+fonts[x]+'</option>');
|
||||
fontselect.append(option);
|
||||
for( const font of fonts ) {
|
||||
fontselect.append( $("<option value='"+font+"'>"+font+"</option>") );
|
||||
}
|
||||
|
||||
for (var x = 4; x < 21; x++) {
|
||||
var val = (x/10.0);
|
||||
var option = $('<option value="'+val+'">'+x+'</option>');
|
||||
sizeselect.append(option);
|
||||
sizeselect.append( $("<option value='"+val+"'>"+x+"</option>") );
|
||||
}
|
||||
|
||||
fontselect.val('DejaVu Sans Mono'); // default value
|
||||
sizeselect.val('0.9'); // default scaling factor
|
||||
fontselect.val( getActiveFontFamily() );
|
||||
sizeselect.val( getActiveFontSize() );
|
||||
|
||||
// font-family change callback
|
||||
fontselect.on('change', function () {
|
||||
$(document.body).css('font-family', $(this).val());
|
||||
});
|
||||
|
||||
// font size change callback
|
||||
sizeselect.on('change', function () {
|
||||
$(document.body).css('font-size', $(this).val()+"em");
|
||||
});
|
||||
// font change callbacks
|
||||
fontselect.on("change", onFontFamily);
|
||||
sizeselect.on("change", onFontSize);
|
||||
|
||||
// add the font selection dialog control to our parentdiv
|
||||
parentdiv.append('<div style="font-weight: bold">Font Selection:</div>');
|
||||
parentdiv.append("<div style='font-weight: bold'>Font Selection:</div>");
|
||||
parentdiv.append(fontselect);
|
||||
parentdiv.append(sizeselect);
|
||||
}
|
||||
|
|
@ -65,10 +108,12 @@ let font_plugin = (function () {
|
|||
for (var x = 0; x < fonts.length; x++) {
|
||||
if ( fonts[x] != "Monospace" ) {
|
||||
var url = font_urls[ fonts[x] ];
|
||||
var link = $('<link href="'+url+'" rel="stylesheet">');
|
||||
var link = $("<link href='"+url+"' rel='stylesheet'>");
|
||||
head.append( link );
|
||||
}
|
||||
}
|
||||
|
||||
setStartingFont();
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,12 @@
|
|||
*/
|
||||
let goldenlayout = (function () {
|
||||
|
||||
var myLayout;
|
||||
var myLayout; // The actively used GoldenLayout API object.
|
||||
|
||||
var evenniaGoldenLayouts = new Map(); // key/value Map for each selectable layout.
|
||||
var activeLayoutName = "default"; // The object key of the active evenniaGoldenLayout
|
||||
var activeLayoutModified = false; // Has the active layout been modified by the user, without being saved?
|
||||
|
||||
var knownTypes = ["all", "untagged", "testing"];
|
||||
var untagged = [];
|
||||
|
||||
|
|
@ -80,6 +85,7 @@ let goldenlayout = (function () {
|
|||
|
||||
myLayout.emit("stateChanged");
|
||||
$("#renamebox").remove();
|
||||
window.plugins["default_in"].setKeydownFocus(true);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -137,6 +143,7 @@ let goldenlayout = (function () {
|
|||
renamebox = $("<div id='renamebox'>");
|
||||
renamebox.append("<input type='textbox' id='renameboxin' value='"+title+"'>");
|
||||
renamebox.insertBefore( content );
|
||||
window.plugins["default_in"].setKeydownFocus(false);
|
||||
} else {
|
||||
closeRenameDropdown();
|
||||
}
|
||||
|
|
@ -275,8 +282,35 @@ let goldenlayout = (function () {
|
|||
component.container.extendState({ "types": types, "updateMethod": updateMethod });
|
||||
});
|
||||
|
||||
var state = JSON.stringify( myLayout.toConfig() );
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedState", state );
|
||||
// update localstorage
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedState", JSON.stringify(myLayout.toConfig()) );
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedStateName", activeLayoutName );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var onClearLocalstorage = function (evnt) {
|
||||
myLayout.off( "stateChanged", onStateChanged );
|
||||
localStorage.removeItem( "evenniaGoldenLayoutSavedState" );
|
||||
localStorage.removeItem( "evenniaGoldenLayoutSavedStateName" );
|
||||
location.reload();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -331,37 +365,6 @@ let goldenlayout = (function () {
|
|||
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 );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
|
|
@ -379,6 +382,210 @@ let goldenlayout = (function () {
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var registerComponents = function (myLayout) {
|
||||
|
||||
// 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 input component
|
||||
myLayout.registerComponent( "input", function (container, componentState) {
|
||||
var promptfield = $("<div class='prompt'></div>");
|
||||
var formcontrol = $("<textarea type='text' class='inputfield form-control'></textarea>");
|
||||
var button = $("<button type='button' class='inputsend'>></button>");
|
||||
|
||||
var inputfield = $("<div class='inputfieldwrapper'>")
|
||||
.append( button )
|
||||
.append( formcontrol );
|
||||
|
||||
$("<div class='inputwrap'>")
|
||||
.append( promptfield )
|
||||
.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);
|
||||
});
|
||||
|
||||
// register the generic "evennia" component
|
||||
myLayout.registerComponent( "evennia", function (container, componentState) {
|
||||
let div = $("<div class='content'></div>");
|
||||
initComponent(div, container, componentState, "all", "newlines");
|
||||
container.on("destroy", calculateUntaggedTypes);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var resetUI = function (newLayout) {
|
||||
var mainsub = document.getElementById("main-sub");
|
||||
|
||||
// rebuild the original HTML stacking
|
||||
var messageDiv = $("#messagewindow").detach();
|
||||
messageDiv.prependTo( mainsub );
|
||||
|
||||
// out with the old
|
||||
myLayout.destroy();
|
||||
|
||||
// in with the new
|
||||
myLayout = new window.GoldenLayout( newLayout, mainsub );
|
||||
|
||||
// re-register our main, input and generic evennia components.
|
||||
registerComponents( myLayout );
|
||||
|
||||
// call all other plugins to give them a chance to registerComponents.
|
||||
for( let plugin in window.plugins ) {
|
||||
if( "onLayoutChanged" in window.plugins[plugin] ) {
|
||||
window.plugins[plugin].onLayoutChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// finish the setup and actually start GoldenLayout
|
||||
myLayout.init();
|
||||
|
||||
// work out which types are untagged based on our pre-configured layout
|
||||
calculateUntaggedTypes();
|
||||
|
||||
// Set the Event handler for when the client window changes size
|
||||
$(window).bind("resize", scrollAll);
|
||||
|
||||
// Set Save State callback
|
||||
myLayout.on( "stateChanged", onStateChanged );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var onSwitchLayout = function (evnt) {
|
||||
// get the new layout name from the select box
|
||||
var name = $(evnt.target).val();
|
||||
var saveButton = $(".savelayout");
|
||||
|
||||
// check to see if the layout is in the list of known layouts
|
||||
if( evenniaGoldenLayouts.has(name) ) {
|
||||
var newLayout = evenniaGoldenLayouts.get(name);
|
||||
|
||||
// reset the activeLayout
|
||||
activeLayoutName = name;
|
||||
activeLayoutModified = false;
|
||||
|
||||
if( activeLayoutName === "default" ) {
|
||||
saveButton.prop( "disabled", true );
|
||||
} else {
|
||||
saveButton.prop( "disabled", false );
|
||||
}
|
||||
|
||||
// store the newly requested layout into localStorage.
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedState", JSON.stringify(newLayout) );
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedStateName", activeLayoutName );
|
||||
|
||||
// pull the trigger
|
||||
resetUI( newLayout );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// upload the named layout to the Evennia server as an option
|
||||
var uploadLayouts = function () {
|
||||
if( window.Evennia.isConnected() && myLayout.isInitialised ) {
|
||||
var obj = {};
|
||||
|
||||
// iterate over each layout, storing the json for each into our temp obj
|
||||
for( const key of evenniaGoldenLayouts.keys() ) {
|
||||
if( key !== "default" ) {
|
||||
obj[key] = JSON.stringify( evenniaGoldenLayouts.get(key) );
|
||||
}
|
||||
}
|
||||
|
||||
// store our temp object as json out to window.options.webclientLayouts
|
||||
window.options["webclientActiveLayout"] = activeLayoutName;
|
||||
window.options["webclientLayouts"] = JSON.stringify( obj );
|
||||
window.Evennia.msg("webclient_options", [], window.options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var onRemoveLayout = function (evnt) {
|
||||
var name = $(evnt.target).parent().attr("id");
|
||||
var layout = $("#"+name);
|
||||
|
||||
evenniaGoldenLayouts.delete(name);
|
||||
layout.remove();
|
||||
|
||||
uploadLayouts();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// This is a helper function for when adding items from the OptionsUI's layout listing
|
||||
var addLayoutUI = function (layoutDiv, name) {
|
||||
var div = $("<div id='"+name+"' >");
|
||||
|
||||
var option = $("<input type='button' class='goldenlayout' value='"+name+"'>");
|
||||
option.on("click", onSwitchLayout);
|
||||
div.append(option);
|
||||
|
||||
if( name !== "default" && name !== activeLayoutName ) {
|
||||
var remove = $("<input type='button' class='removelayout' value='X'>");
|
||||
remove.on("click", onRemoveLayout);
|
||||
div.append(remove);
|
||||
}
|
||||
|
||||
layoutDiv.append(div);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var onSaveLayout = function () {
|
||||
// get the name from the select box
|
||||
var name = $("#layoutName").val();
|
||||
var layouts = $("#goldenlayouts");
|
||||
|
||||
// make sure we have a valid name
|
||||
if( name !== "" ) {
|
||||
// Is this name new or pre-existing?
|
||||
if( !evenniaGoldenLayouts.has(name) ) {
|
||||
// this is a new name, so add a new UI item for it.
|
||||
addLayoutUI( layouts, name );
|
||||
}
|
||||
|
||||
// Force Close the Options Menu so that it isn't part of the saved layout.
|
||||
window.plugins["options2"].onOpenCloseOptions();
|
||||
|
||||
// store the current layout to the local list of layouts
|
||||
evenniaGoldenLayouts.set( name, myLayout.toConfig() );
|
||||
activeLayoutName = name;
|
||||
activeLayoutModified = false;
|
||||
|
||||
// store the newly requested layout into localStorage.
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedState", JSON.stringify( evenniaGoldenLayouts.get(name) ) );
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedStateName", activeLayoutName );
|
||||
|
||||
uploadLayouts();
|
||||
|
||||
resetUI( evenniaGoldenLayouts.get(name) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Public
|
||||
//
|
||||
|
|
@ -393,13 +600,38 @@ let goldenlayout = (function () {
|
|||
|
||||
|
||||
//
|
||||
// Add new HTML message to an existing Div pane, while
|
||||
// honoring the pane's updateMethod and scroll state, etc.
|
||||
//
|
||||
var onKeydown = function(evnt) {
|
||||
var renamebox = document.getElementById("renamebox");
|
||||
if( renamebox ) {
|
||||
return true;
|
||||
var addMessageToPaneDiv = function (textDiv, message) {
|
||||
let atBottom = false;
|
||||
let updateMethod = textDiv.attr("updateMethod");
|
||||
|
||||
if ( updateMethod === "replace" ) {
|
||||
textDiv.html(message);
|
||||
} else if ( updateMethod === "append" ) {
|
||||
textDiv.append(message);
|
||||
} else { // line feed
|
||||
textDiv.append("<div class='out'>" + message + "</div>");
|
||||
}
|
||||
|
||||
// Calculate the scrollback state.
|
||||
//
|
||||
// This check helps us avoid scrolling to the bottom when someone is
|
||||
// manually scrolled back, trying to read their backlog.
|
||||
// Auto-scrolling would force them to re-scroll to their previous scroll position.
|
||||
// Which, on fast updating games, destroys the utility of scrolling entirely.
|
||||
//
|
||||
//if( textDiv.scrollTop === (textDiv.scrollHeight - textDiv.offsetHeight) ) {
|
||||
atBottom = true;
|
||||
//}
|
||||
|
||||
// if we are at the bottom of the window already, scroll to display the new content
|
||||
if( atBottom ) {
|
||||
let scrollHeight = textDiv.prop("scrollHeight");
|
||||
let clientHeight = textDiv.prop("clientHeight");
|
||||
textDiv.scrollTop( scrollHeight - clientHeight );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -445,6 +677,66 @@ let goldenlayout = (function () {
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var onGotOptions = function (args, kwargs) {
|
||||
// Reset the UI if the JSON layout sent from the server doesn't match the client's current JSON
|
||||
if( "webclientLayouts" in kwargs ) {
|
||||
var layouts = JSON.parse( kwargs["webclientLayouts"] );
|
||||
|
||||
// deserialize key/layout pairs into evenniaGoldenLayouts
|
||||
for( var key in layouts ) {
|
||||
if( key !== "default" && layouts.hasOwnProperty(key) ) { // codacy.com guard-rail
|
||||
evenniaGoldenLayouts.set( key, JSON.parse(layouts[key]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var onOptionsUI = function (parentdiv) {
|
||||
var layoutName = $("<input id='layoutName' type='text' class='layoutName'>");
|
||||
var saveButton = $("<input type='button' class='savelayout' value='Close Options and Save'>");
|
||||
var layoutDiv = $("<div id='goldenlayouts'>");
|
||||
|
||||
if( activeLayoutName === "default" ) {
|
||||
saveButton.prop( "disabled", true );
|
||||
}
|
||||
|
||||
for (const name of evenniaGoldenLayouts.keys() ) {
|
||||
addLayoutUI(layoutDiv, name);
|
||||
}
|
||||
|
||||
// currently active layout
|
||||
layoutName.val( activeLayoutName );
|
||||
layoutName.on("keydown", function (evnt) {
|
||||
var name = $(evnt.target).val();
|
||||
if( name === "default" || name === "" ) {
|
||||
saveButton.prop( "disabled", true );
|
||||
} else {
|
||||
saveButton.prop( "disabled", false );
|
||||
}
|
||||
});
|
||||
|
||||
// Layout selection on-change callback
|
||||
saveButton.on("click", onSaveLayout);
|
||||
|
||||
var saveDiv = $("<div class='goldenlayout-save-ui'>");
|
||||
saveDiv.append(layoutName);
|
||||
saveDiv.append(saveButton);
|
||||
|
||||
// add the selection dialog control to our parentdiv
|
||||
parentdiv.addClass("goldenlayout-options-ui");
|
||||
parentdiv.append("<div>GoldenLayout Options:</div>");
|
||||
parentdiv.append("<div>Activate a new layout:</div>");
|
||||
parentdiv.append(layoutDiv);
|
||||
parentdiv.append("<div>Save current layout as (best if used when logged in):</div>");
|
||||
parentdiv.append(saveDiv);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var onText = function (args, kwargs) {
|
||||
|
|
@ -453,11 +745,9 @@ let goldenlayout = (function () {
|
|||
|
||||
var msgHandled = false;
|
||||
divs.forEach( function (div) {
|
||||
let updateMethod = div.attr("updateMethod");
|
||||
let txt = args[0];
|
||||
|
||||
// yes, so add this text message to the target div
|
||||
routeMsg( div, txt, updateMethod );
|
||||
addMessageToPaneDiv( div, txt );
|
||||
msgHandled = true;
|
||||
});
|
||||
|
||||
|
|
@ -483,72 +773,49 @@ let goldenlayout = (function () {
|
|||
|
||||
|
||||
//
|
||||
// required Init me
|
||||
// required Init
|
||||
var init = function (options) {
|
||||
// Set up our GoldenLayout instance built off of the default main-sub div
|
||||
var savedState = localStorage.getItem( "evenniaGoldenLayoutSavedState" );
|
||||
var activeName = localStorage.getItem( "evenniaGoldenLayoutSavedStateName" );
|
||||
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 );
|
||||
// pre-load the evenniaGoldenLayouts with the hard-coded default
|
||||
evenniaGoldenLayouts.set( "default", window.goldenlayout_config );
|
||||
|
||||
if( activeName !== null ) {
|
||||
activeLayoutName = activeName;
|
||||
}
|
||||
|
||||
myLayout = new GoldenLayout( window.goldenlayout_config, mainsub );
|
||||
if( savedState !== null ) {
|
||||
// Overwrite the global-variable configuration from
|
||||
// webclient/js/plugins/goldenlayout_default_config.js
|
||||
// with the version from localstorage
|
||||
evenniaGoldenLayouts.set( activeLayoutName, JSON.parse(savedState) );
|
||||
} else {
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedState", JSON.stringify( window.goldenlayout_config ) );
|
||||
localStorage.setItem( "evenniaGoldenLayoutSavedStateName", "default" );
|
||||
}
|
||||
|
||||
myLayout = new window.GoldenLayout( evenniaGoldenLayouts.get(activeLayoutName), mainsub );
|
||||
|
||||
$("#prompt").remove(); // remove the HTML-defined prompt div
|
||||
$("#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 promptfield = $("<div class='prompt'></div>");
|
||||
var formcontrol = $("<textarea type='text' class='inputfield form-control'></textarea>");
|
||||
var button = $("<button type='button' class='inputsend'>></button>");
|
||||
|
||||
var inputfield = $("<div class='inputfieldwrapper'>")
|
||||
.append( button )
|
||||
.append( formcontrol );
|
||||
|
||||
$("<div class='inputwrap'>")
|
||||
.append( promptfield )
|
||||
.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);
|
||||
});
|
||||
registerComponents( myLayout );
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
init: init,
|
||||
postInit: postInit,
|
||||
onKeydown: onKeydown,
|
||||
onGotOptions: onGotOptions,
|
||||
onOptionsUI: onOptionsUI,
|
||||
onText: onText,
|
||||
getGL: function () { return myLayout; },
|
||||
addKnownType: addKnownType,
|
||||
onTabCreate: onTabCreate,
|
||||
routeMessage: routeMessage,
|
||||
addMessageToPaneDiv: addMessageToPaneDiv,
|
||||
}
|
||||
}());
|
||||
window.plugin_handler.add("goldenlayout", goldenlayout);
|
||||
|
|
|
|||
|
|
@ -17,16 +17,16 @@
|
|||
* 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 and before the goldenlayout.js plugin, add:
|
||||
* <script src={% static "webclient/js/plugins/hotbuttons.js" %} type="text/javascript"></script>
|
||||
* before the goldenlayout.js plugin tags or after the splithandler.js <script></script> plugin tags
|
||||
*
|
||||
* If you are using goldenlayout.js, uncomment the hotbuttons component in goldenlayout_default_config.js
|
||||
* Then uncomment the hotbuttons component in goldenlayout_default_config.js
|
||||
*
|
||||
* Run: evennia collectstatic (say "yes" to the overwrite prompt)
|
||||
*
|
||||
* Start Evennia
|
||||
*
|
||||
* REQUIRES: goldenlayout.js OR splithandler.js
|
||||
* REQUIRES: goldenlayout.js
|
||||
*/
|
||||
let hotbuttons = (function () {
|
||||
var dependenciesMet = false;
|
||||
|
|
@ -95,47 +95,22 @@ let hotbuttons = (function () {
|
|||
}
|
||||
|
||||
|
||||
// Public
|
||||
|
||||
//
|
||||
// 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 );
|
||||
// Handle the HotButtons part of a Webclient_Options event
|
||||
var onGotOptions = function(args, kwargs) {
|
||||
if( dependenciesMet && kwargs["HotButtons"] ) {
|
||||
var buttonOptions = kwargs["HotButtons"];
|
||||
$.each( buttonOptions, function( key, value ) {
|
||||
assignButton(key, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Create and register the hotbuttons golden-layout component
|
||||
var buildComponent = function () {
|
||||
var onLayoutChanged = function () {
|
||||
var myLayout = window.plugins["goldenlayout"].getGL();
|
||||
|
||||
myLayout.registerComponent( "hotbuttons", function (container, componentState) {
|
||||
|
|
@ -158,46 +133,21 @@ let hotbuttons = (function () {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
// Public
|
||||
|
||||
//
|
||||
// Handle the HotButtons part of a Webclient_Options event
|
||||
var onGotOptions = function(args, kwargs) {
|
||||
if( dependenciesMet && kwargs["HotButtons"] ) {
|
||||
var buttonOptions = kwargs["HotButtons"];
|
||||
$.each( buttonOptions, function( key, value ) {
|
||||
assignButton(key, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Initialize me
|
||||
var init = function() {
|
||||
// Are we using splithandler?
|
||||
if( window.plugins["splithandler"] ) {
|
||||
addButtonsUI();
|
||||
dependenciesMet = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
var postInit = function() {
|
||||
// Are we using GoldenLayout?
|
||||
if( window.plugins["goldenlayout"] ) {
|
||||
buildComponent();
|
||||
onLayoutChanged();
|
||||
dependenciesMet = true;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
init: function() {},
|
||||
postInit: postInit,
|
||||
onGotOptions: onGotOptions,
|
||||
onLayoutChanged: onLayoutChanged,
|
||||
}
|
||||
})();
|
||||
window.plugin_handler.add("hotbuttons", hotbuttons);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
*/
|
||||
let spawns = (function () {
|
||||
|
||||
var ignoreDefaultKeydown = false;
|
||||
|
||||
var spawnmap = {}; // { id1: { r:regex, t:tag } } pseudo-array of regex-tag pairs
|
||||
|
||||
//
|
||||
|
|
@ -42,12 +40,12 @@ let spawns = (function () {
|
|||
|
||||
//
|
||||
var onFocusIn = function (evnt) {
|
||||
ignoreDefaultKeydown = true;
|
||||
window.plugins["default_in"].setKeydownFocus(false);
|
||||
}
|
||||
|
||||
//
|
||||
var onFocusOut = function (evnt) {
|
||||
ignoreDefaultKeydown = false;
|
||||
window.plugins["default_in"].setKeydownFocus(true);
|
||||
onAlterTag(evnt); // percolate event so closing the pane, etc saves any last changes.
|
||||
}
|
||||
|
||||
|
|
@ -121,14 +119,6 @@ let spawns = (function () {
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
// OnKeydown -- if the Options window is open, capture focus
|
||||
//
|
||||
var onKeydown = function(evnt) {
|
||||
return ignoreDefaultKeydown;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// init
|
||||
//
|
||||
|
|
@ -148,7 +138,6 @@ let spawns = (function () {
|
|||
init: init,
|
||||
onOptionsUI: onOptionsUI,
|
||||
onText: onText,
|
||||
onKeydown: onKeydown,
|
||||
}
|
||||
})();
|
||||
window.plugin_handler.add("spawns", spawns);
|
||||
|
|
|
|||
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Evennia Options GUI plugin
|
||||
*
|
||||
* This code deals with all of the UI and events related to Options.
|
||||
*
|
||||
*/
|
||||
let options_plugin = (function () {
|
||||
//
|
||||
// addOptionsUI
|
||||
var addOptionsUI = function () {
|
||||
var content = [ // TODO dynamically create this based on the options{} hash
|
||||
'<label><input type="checkbox" data-setting="gagprompt" value="value">Don\'t echo prompts to the main text area</label>',
|
||||
'<br />',
|
||||
'<label><input type="checkbox" data-setting="helppopup" value="value">Open help in popup window</label>',
|
||||
'<br />',
|
||||
'<hr />',
|
||||
'<label><input type="checkbox" data-setting="notification_popup" value="value">Popup notification</label>',
|
||||
'<br />',
|
||||
'<label><input type="checkbox" data-setting="notification_sound" value="value">Play a sound</label>',
|
||||
'<br />',
|
||||
].join("\n");
|
||||
|
||||
// Create a new options Dialog
|
||||
plugins['popups'].createDialog( 'optionsdialog', 'Options', content );
|
||||
}
|
||||
|
||||
//
|
||||
// addHelpUI
|
||||
var addHelpUI = function () {
|
||||
// Create a new Help Dialog
|
||||
plugins['popups'].createDialog( 'helpdialog', 'Help', "" );
|
||||
}
|
||||
|
||||
// addToolbarButton
|
||||
var addToolbarButton = function () {
|
||||
var optionsbutton = $( [
|
||||
'<button id="optionsbutton" type="button" aria-haspopup="true" aria-owns="#optionsdialog">',
|
||||
'⚙',
|
||||
'<span class="sr-only sr-only-focusable">Settings</span>',
|
||||
'</button>',
|
||||
].join("") );
|
||||
$('#toolbar').append( optionsbutton );
|
||||
}
|
||||
|
||||
//
|
||||
// Opens the options dialog
|
||||
var doOpenOptions = function () {
|
||||
if (!Evennia.isConnected()) {
|
||||
alert("You need to be connected.");
|
||||
return;
|
||||
}
|
||||
|
||||
plugins['popups'].togglePopup("#optionsdialog");
|
||||
}
|
||||
|
||||
//
|
||||
// When the user changes a setting from the interface
|
||||
var onOptionCheckboxChanged = function () {
|
||||
var name = $(this).data("setting");
|
||||
var value = this.checked;
|
||||
|
||||
var changedoptions = {};
|
||||
changedoptions[name] = value;
|
||||
Evennia.msg("webclient_options", [], changedoptions);
|
||||
|
||||
options[name] = value;
|
||||
}
|
||||
|
||||
// Public functions
|
||||
|
||||
//
|
||||
// onKeydown check for 'ESC' key.
|
||||
var onKeydown = function (event) {
|
||||
var code = event.which;
|
||||
|
||||
if (code === 27) { // Escape key
|
||||
if ($('#helpdialog').is(':visible')) {
|
||||
plugins['popups'].closePopup("#helpdialog");
|
||||
return true;
|
||||
}
|
||||
if ($('#optionsdialog').is(':visible')) {
|
||||
plugins['popups'].closePopup("#optionsdialog");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Called when options settings are sent from server
|
||||
var onGotOptions = function (args, kwargs) {
|
||||
options = kwargs;
|
||||
|
||||
$.each(kwargs, function(key, value) {
|
||||
var elem = $("[data-setting='" + key + "']");
|
||||
if (elem.length === 0) {
|
||||
console.log("Could not find option: " + key);
|
||||
console.log(args);
|
||||
console.log(kwargs);
|
||||
} else {
|
||||
elem.prop('checked', value);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Called when the user logged in
|
||||
var onLoggedIn = function (args, kwargs) {
|
||||
$('#optionsbutton').removeClass('hidden');
|
||||
Evennia.msg("webclient_options", [], {});
|
||||
}
|
||||
|
||||
//
|
||||
// Display a "prompt" command from the server
|
||||
var onPrompt = function (args, kwargs) {
|
||||
// also display the prompt in the output window if gagging is disabled
|
||||
if (("gagprompt" in options) && (!options["gagprompt"])) {
|
||||
plugin_handler.onText(args, kwargs);
|
||||
}
|
||||
|
||||
// don't claim this Prompt as completed.
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure to close any dialogs on connection lost
|
||||
var onConnectionClose = function () {
|
||||
$('#optionsbutton').addClass('hidden');
|
||||
plugins['popups'].closePopup("#optionsdialog");
|
||||
plugins['popups'].closePopup("#helpdialog");
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure to close any dialogs on connection lost
|
||||
var onText = function (args, kwargs) {
|
||||
// is helppopup set? and if so, does this Text have type 'help'?
|
||||
if ('helppopup' in options && options['helppopup'] ) {
|
||||
if (kwargs && ('type' in kwargs) && (kwargs['type'] == 'help') ) {
|
||||
$('#helpdialogcontent').prepend('<div>'+ args + '</div>');
|
||||
plugins['popups'].togglePopup("#helpdialog");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Register and init plugin
|
||||
var init = function () {
|
||||
// Add GUI components
|
||||
addOptionsUI();
|
||||
addHelpUI();
|
||||
|
||||
// Add Options toolbar button.
|
||||
addToolbarButton();
|
||||
|
||||
// Pressing the settings button
|
||||
$("#optionsbutton").bind("click", doOpenOptions);
|
||||
|
||||
// Checking a checkbox in the settings dialog
|
||||
$("[data-setting]").bind("change", onOptionCheckboxChanged);
|
||||
|
||||
console.log('Options Plugin Initialized.');
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
onKeydown: onKeydown,
|
||||
onLoggedIn: onLoggedIn,
|
||||
onGotOptions: onGotOptions,
|
||||
onPrompt: onPrompt,
|
||||
onConnectionClose: onConnectionClose,
|
||||
onText: onText,
|
||||
}
|
||||
})()
|
||||
plugin_handler.add('options', options_plugin);
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
let options2 = (function () {
|
||||
|
||||
var options_container = null ;
|
||||
var optionsContainer = null ;
|
||||
|
||||
//
|
||||
// When the user changes a setting from the interface
|
||||
|
|
@ -51,35 +51,6 @@ let options2 = (function () {
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
// Create and register the "options" golden-layout component
|
||||
var createOptionsComponent = function () {
|
||||
var myLayout = window.plugins["goldenlayout"].getGL();
|
||||
|
||||
myLayout.registerComponent( "options", function (container, componentState) {
|
||||
var plugins = window.plugins;
|
||||
options_container = container.getElement();
|
||||
|
||||
// build the buttons
|
||||
var div = $("<div class='accordion' style='overflow-y:scroll; height:inherit;'>");
|
||||
|
||||
for( let plugin in plugins ) {
|
||||
if( "onOptionsUI" in plugins[plugin] ) {
|
||||
var card = $("<div class='card'>");
|
||||
var body = $("<div>");
|
||||
|
||||
plugins[plugin].onOptionsUI( body );
|
||||
|
||||
card.append(body);
|
||||
card.appendTo( div );
|
||||
}
|
||||
}
|
||||
|
||||
div.appendTo( options_container );
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// handler for the "Options" button
|
||||
var onOpenCloseOptions = function () {
|
||||
var optionsComponent = {
|
||||
|
|
@ -92,7 +63,7 @@ let options2 = (function () {
|
|||
|
||||
// Create a new GoldenLayout tab filled with the optionsComponent above
|
||||
var myLayout = window.plugins["goldenlayout"].getGL();
|
||||
if( ! options_container ) {
|
||||
if( ! optionsContainer ) {
|
||||
// open new optionsComponent
|
||||
var main = myLayout.root.getItemsByType("stack")[0].getActiveContentItem();
|
||||
|
||||
|
|
@ -102,16 +73,19 @@ let options2 = (function () {
|
|||
.closeElement
|
||||
.off("click")
|
||||
.click( function () {
|
||||
options_container = null;
|
||||
optionsContainer = null;
|
||||
tab.contentItem.remove();
|
||||
window.plugins["default_in"].setKeydownFocus(true);
|
||||
});
|
||||
options_container = tab.contentItem;
|
||||
optionsContainer = tab.contentItem;
|
||||
}
|
||||
});
|
||||
main.parent.addChild( optionsComponent );
|
||||
|
||||
window.plugins["default_in"].setKeydownFocus(false);
|
||||
} else {
|
||||
options_container.remove();
|
||||
options_container = null;
|
||||
optionsContainer.remove();
|
||||
optionsContainer = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,6 +106,34 @@ let options2 = (function () {
|
|||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Create and register the "options" golden-layout component
|
||||
var onLayoutChanged = function () {
|
||||
var myLayout = window.plugins["goldenlayout"].getGL();
|
||||
|
||||
myLayout.registerComponent( "options", function (container, componentState) {
|
||||
var plugins = window.plugins;
|
||||
optionsContainer = container.getElement();
|
||||
|
||||
// build the buttons
|
||||
var div = $("<div class='accordion' style='overflow-y:scroll; height:inherit;'>");
|
||||
|
||||
for( let plugin in plugins ) {
|
||||
if( "onOptionsUI" in plugins[plugin] ) {
|
||||
var card = $("<div class='card'>");
|
||||
var body = $("<div>");
|
||||
|
||||
plugins[plugin].onOptionsUI( body );
|
||||
|
||||
card.append(body);
|
||||
card.appendTo( div );
|
||||
}
|
||||
}
|
||||
|
||||
div.appendTo( optionsContainer );
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Called when the user logged in
|
||||
var onLoggedIn = function (args, kwargs) {
|
||||
|
|
@ -165,7 +167,7 @@ let options2 = (function () {
|
|||
var postInit = function() {
|
||||
// Are we using GoldenLayout?
|
||||
if( window.plugins["goldenlayout"] ) {
|
||||
createOptionsComponent();
|
||||
onLayoutChanged();
|
||||
|
||||
$("#optionsbutton").bind("click", onOpenCloseOptions);
|
||||
}
|
||||
|
|
@ -176,10 +178,12 @@ let options2 = (function () {
|
|||
init: init,
|
||||
postInit: postInit,
|
||||
onGotOptions: onGotOptions,
|
||||
onLayoutChanged: onLayoutChanged,
|
||||
onLoggedIn: onLoggedIn,
|
||||
onOptionsUI: onOptionsUI,
|
||||
onPrompt: onPrompt,
|
||||
onOptionCheckboxChanged: onOptionCheckboxChanged,
|
||||
onOpenCloseOptions: onOpenCloseOptions,
|
||||
}
|
||||
})();
|
||||
window.plugin_handler.add("options2", options2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue