// Display.js
// css columns
//https://developer.mozilla.org/en-US/docs/Web/CSS/columns
(function () {
/* global AdventureJS A */
/**
* @class AdventureJS.Display
* @ajsnavheading EngineClasses
* @param {Game} game A reference to the game instance.
* @param {containerId|HTMLElement} containerId An ID for an HTML element to build the game to.
* @summary Manages the main game display including all related HTML elements.
* @classdesc
* <p>
* <strong>Display</strong> creates and manages the game display,
* including the main input and output areas and the status bar.
* It also manages custom compasses, verb docks and inventory
* docks. Authors can customize the display with custom CSS.
* CSS styles for Display can be found in
* <a href="/css/adventurejs.css">adventurejs.css</a>.
* To learn more, see the
* </p>
*/
class Display {
constructor(containerId, game, game_name) {
game.log(
"L1005",
"log",
1,
"[Display.js] Constructing display.",
"Display"
);
/**
* A reference back to the main {@link AdventureJS.Game|Game} object.
* @var {Object} AdventureJS.Display#game
* @default {}
*/
this.game = game;
/**
* An array that contains a list of references to the
* HTML element of any compasses, including the one
* in the status bar as well as any custom compasses.
* @var {compasses} AdventureJS.Display#compasses
* @default []
*/
this.compasses = [];
/**
* An array that contains a list of references to the
* HTML elements of any verb docks.
* @var {verbdocks} AdventureJS.Display#verbdocks
* @default []
*/
this.verbdocks = [];
/**
* An array that contains a list of references to the
* HTML elements of any room docks.
* @var {roomdocks} AdventureJS.Display#roomdocks
* @default []
*/
this.roomdocks = [];
/**
* An array that contains a list of references to the
* HTML elements of any room content docks.
* @var {contentdocks} AdventureJS.Display#contentdocks
* @default []
*/
this.contentdocks = [];
/**
* An array that contains a list of references to the
* HTML elements of any exit docks.
* @var {exitdocks} AdventureJS.Display#exitdocks
* @default []
*/
this.exitdocks = [];
/**
* An array that contains a list of references to the
* HTML elements of any inventory docks.
* @var {inventorydocks} AdventureJS.Display#inventorydocks
* @default []
*/
this.inventorydocks = [];
/**
* An array that contains a list of references to the
* HTML elements of any description docks.
* @var {inventorydocks} AdventureJS.Display#descriptiondocks
* @default []
*/
this.descriptiondocks = [];
/**
* An array that contains a list of references to the
* HTML elements of any image docks.
* @var {imagedocks} AdventureJS.Display#imagedocks
* @default []
*/
this.imagedocks = [];
/**
* An array that contains a list of references to the
* HTML elements of all docks.
* @var {docks} AdventureJS.Display#docks
* @default []
*/
this.docks = [];
/**
* A reference to the game's HTML display element.
* @var {HTMLElement} AdventureJS.Display#displayEl
* @default null
*/
this.displayEl = null;
/**
* The ID of the game's HTML display element.
* @var {HTMLElement} AdventureJS.Display#containerId
* @default null
*/
this.containerId = null;
this.initialize(containerId, game_name);
this.updateDisplaySizes();
}
updateDisplaySizes() {
const style = document.documentElement.style;
/* container contains game */
const container = this.containerEl.getBoundingClientRect();
style.setProperty(
"--ajs-actual-container-height",
`${container.height}px`
);
style.setProperty("--ajs-actual-container-width", `${container.width}px`);
style.setProperty("--ajs-actual-container-left", `${container.left}px`);
style.setProperty("--ajs-actual-container-top", `${container.top}px`);
/* content contains titlebar, statusbar, output, input */
const content = this.contentEl.getBoundingClientRect();
style.setProperty("--ajs-actual-content-height", `${content.height}px`);
style.setProperty("--ajs-actual-content-width", `${content.width}px`);
style.setProperty("--ajs-actual-content-left", `${content.left}px`);
style.setProperty("--ajs-actual-content-top", `${content.top}px`);
/* output is set display:flex so it expands to fit between
titlebar, statusbar, and input */
const output = this.outputContainerEl.getBoundingClientRect();
style.setProperty("--ajs-actual-output-height", `${output.height}px`);
style.setProperty("--ajs-actual-output-width", `${output.width}px`);
style.setProperty("--ajs-actual-output-left", `${output.left}px`);
style.setProperty("--ajs-actual-output-top", `${output.top}px`);
/* input has a set height but we want to account for padding */
const input = this.inputContainerEl.getBoundingClientRect();
style.setProperty("--ajs-actual-input-height", `${input.height}px`);
style.setProperty("--ajs-actual-input-width", `${input.width}px`);
style.setProperty("--ajs-actual-input-left", `${input.left}px`);
style.setProperty("--ajs-actual-input-top", `${input.top}px`);
/* ui contains title and status */
const ui = this.uiEl.getBoundingClientRect();
style.setProperty("--ajs-actual-ui-height", `${ui.height}px`);
style.setProperty("--ajs-actual-ui-width", `${ui.width}px`);
style.setProperty("--ajs-actual-ui-left", `${ui.left}px`);
style.setProperty("--ajs-actual-ui-top", `${ui.top}px`);
/* status has a set height but we want to account for padding */
const status = this.statusbarEl.getBoundingClientRect();
style.setProperty("--ajs-actual-statusbar-height", `${status.height}px`);
style.setProperty("--ajs-actual-statusbar-width", `${status.width}px`);
style.setProperty("--ajs-actual-statusbar-left", `${status.left}px`);
style.setProperty("--ajs-actual-statusbar-top", `${status.top}px`);
/* status has a set height but we want to account for padding */
const title = this.titlebarEl.getBoundingClientRect();
style.setProperty("--ajs-actual-titlebar-height", `${title.height}px`);
style.setProperty("--ajs-actual-titlebar-width", `${title.width}px`);
style.setProperty("--ajs-actual-titlebar-left", `${title.left}px`);
style.setProperty("--ajs-actual-titlebar-top", `${title.top}px`);
const topdocks = this.topDocksContainerEl.getBoundingClientRect();
style.setProperty("--ajs-actual-topdocks-height", `${topdocks.height}px`);
style.setProperty("--ajs-actual-topdocks-width", `${topdocks.width}px`);
style.setProperty("--ajs-actual-topdocks-left", `${topdocks.left}px`);
style.setProperty("--ajs-actual-topdocks-top", `${topdocks.top}px`);
const bottomdocks = this.bottomDocksContainerEl.getBoundingClientRect();
style.setProperty(
"--ajs-actual-bottomdocks-height",
`${bottomdocks.height}px`
);
style.setProperty(
"--ajs-actual-bottomdocks-width",
`${bottomdocks.width}px`
);
style.setProperty(
"--ajs-actual-bottomdocks-left",
`${bottomdocks.left}px`
);
style.setProperty("--ajs-actual-bottomdocks-top", `${bottomdocks.top}px`);
// .ajs-output-container
}
/**
* Append classes to the last line of input.
* @memberof AdventureJS.Display
* @method AdventureJS.Display#appendClassesToLastInput
* @param {String} classes
*/
appendClassesToLastInput(classes) {
let inputs = this.outputEl.querySelectorAll(".ajs-player-input");
let last_input = inputs.item(inputs.length - 1);
last_input.classList.add(classes);
}
/**
* Append classes to the last line of output.
* @memberof AdventureJS.Display
* @method AdventureJS.Display#appendClassesToLastOutput
* @param {String} classes
*/
appendClassesToLastOutput(classes) {
let outputs = this.outputEl.querySelectorAll(
".ajs-p:not(.ajs-player-input):not(.ajs-debug)"
);
let last_output = outputs.item(outputs.length - 1);
last_output.classList.add(classes);
}
/**
* Hide the game's statusbar.
* @memberof AdventureJS.Display
* @method AdventureJS.Display#hideStatusbar
* @returns {boolean}
*/
hideStatusbar() {
this.statusbarEl.classList.add("ajs-hide");
this.statusbarEl.ariaHidden = true;
this.updateDisplaySizes();
return true;
}
/**
* Show the game's statusbar.
* @memberof AdventureJS.Display
* @method AdventureJS.Display#showStatusbar
* @returns {boolean}
*/
showStatusbar() {
this.statusbarEl.classList.remove("ajs-hide");
this.statusbarEl.ariaHidden = false;
this.updateDisplaySizes();
return true;
}
/**
* Hide the game's titlebar.
* @memberof AdventureJS.Display
* @method AdventureJS.Display#hideTitlebar
* @returns {boolean}
*/
hideTitlebar() {
this.titlebarEl.classList.add("ajs-hide");
this.titlebarEl.ariaHidden = true;
this.updateDisplaySizes();
return true;
}
/**
* Show the game's titlebar.
* @memberof AdventureJS.Display
* @method AdventureJS.Display#showTitlebar
* @returns {boolean}
*/
showTitlebar() {
this.titlebarEl.classList.remove("ajs-hide");
this.titlebarEl.ariaHidden = false;
this.updateDisplaySizes();
return true;
}
/**
* The game's title.
* @var {String} AdventureJS.Display#title
* @default ""
*/
get title() {
return this.titleEl.innerText;
}
set title(title) {
this.titleEl.innerText = title;
}
/**
* The game's version.
* @var {String} AdventureJS.Display#version
* @default ""
*/
get version() {
return this.versionEl.innerText;
}
set version(version) {
this.versionEl.innerText = version;
}
/**
* The game's author.
* @var {String} AdventureJS.Display#author
* @default ""
*/
get author() {
return this.authorEl.innerText;
}
set author(author) {
this.authorEl.innerText = author;
}
/**
* The current room's name.
* @var {String} AdventureJS.Display#room
* @default ""
*/
get room() {
return this.roomEl.innerText;
}
set room(room) {
this.roomEl.innerText = room;
}
/**
* The current score.
* @var {String} AdventureJS.Display#score
* @default ""
*/
get score() {
return this.scoreEl.innerText;
}
set score(score) {
this.scoreEl.innerText = score;
}
}
AdventureJS.Display = Display;
})();