diff --git a/js/002-config/fc-js-init.js b/js/002-config/fc-js-init.js index 62d42623db99d1fd188f9515d8d3129635e6b299..6141ced53d9bf02b955a9cb84d686eb01cbfaffc 100644 --- a/js/002-config/fc-js-init.js +++ b/js/002-config/fc-js-init.js @@ -71,4 +71,3 @@ App.UI.SlaveInteract = {}; App.UI.View = {}; App.Update = {}; App.Utils = {}; -App.Utils.Pronouns = {}; \ No newline at end of file diff --git a/src/gui/css/mainStyleSheet.css b/src/gui/css/mainStyleSheet.css index 37d1b869d0b7d0a87ddcaf78e6982284e498065c..f9e22da0b9006f450a96fe4ce49366d8fcda9941 100644 --- a/src/gui/css/mainStyleSheet.css +++ b/src/gui/css/mainStyleSheet.css @@ -372,4 +372,20 @@ div.flex-container { /* TODO unify tooltip systems */ .hasTooltip { text-decoration: underline; -} \ No newline at end of file +} + +/* interactable tooltip-like container - created/destroyed dynamically */ +.details-overlay { + display: inline-block; + font-size: smaller; + width: max-content; + height: max-content; + border-style: solid; + border-color: slategray; + border-width: 2px; + border-radius: 3px; + background-color: rgb(17, 17, 17); + padding: 3px; + position: absolute; + text-indent: 0; +} diff --git a/src/gui/interactiveDetails.js b/src/gui/interactiveDetails.js new file mode 100644 index 0000000000000000000000000000000000000000..1e9ad9db1a72ba88950c2ad3cb80d261a955159f --- /dev/null +++ b/src/gui/interactiveDetails.js @@ -0,0 +1,44 @@ +/** + * Displays a value that you can click on to get some details in an overlay + */ +App.UI.DOM.InteractiveDetails = class { + /** + * @param {string} linkText text to use for the show/hide link + * @param {function(): HTMLElement|DocumentFragment} [detailsGenerator] function which generates the contents of the details overlay (omit to disable details) + * @param {string[]} [linkClasses=[]] list of extra CSS classes to apply to the link + */ + constructor(linkText, detailsGenerator, linkClasses=[]) { + this.span = App.UI.DOM.makeElement("span", "", "details-overlay"); + this.span.style.visibility = "hidden"; + this.link = App.UI.DOM.link(linkText, () => this.toggle()); + this.link.classList.add(...linkClasses); + this.func = detailsGenerator; + this.shown = false; + } + + /** + * Toggle the visibility of the overlay (changing the render state) + */ + toggle() { + this.shown = !this.shown; + if (this.shown) { + if (this.func) { + $(this.span).empty().append(this.func()); + this.span.style.visibility = "visible"; + } + } else { + $(this.span).empty(); + this.span.style.visibility = "hidden"; + } + } + + /** + * Render the object to the page + * @returns {DocumentFragment} + */ + render() { + const frag = document.createDocumentFragment(); + frag.append(this.link, this.span); + return frag; + } +}; diff --git a/src/js/slaveCostJS.js b/src/js/slaveCostJS.js index d1d8ee2a0c242260e13fabcfb4fbf219765c0728..65123bbca5f07c4935bf52372ffe9266bc29fae0 100644 --- a/src/js/slaveCostJS.js +++ b/src/js/slaveCostJS.js @@ -1596,24 +1596,11 @@ globalThis.Beauty = function(s) { globalThis.BeautyTooltip = function(slave) { - // Make a link. Text should be slave's beauty. Clicking the link will display detailed info about that beauty where the link used to be + // Make a link. Text should be slave's beauty. Clicking the link will display detailed info about that beauty over the top of the page (tooltip-style) const beauty = Beauty(slave); - const el = new DocumentFragment(); - let span = document.createElement("span"); - span.id = "beauty-link"; - if (V.cheatMode || V.debugMode) { - span.append(showerButton()); - } else { - App.UI.DOM.appendNewElement("span", span, beauty, ["pink", "bold"]); - } - el.append(span); - - span = document.createElement("span"); - span.id = "BeautyTooltip"; - el.append(span); - - return el; - + const displayFunc = V.cheatMode || V.debugMode ? BeautyDisplay : undefined; + const interactor = new App.UI.DOM.InteractiveDetails(beauty.toString(), displayFunc, ["pink", "bold"]); + return interactor.render(); // Upon the link being clicked, set up some links to sort the info and a span to show it in function BeautyDisplay() { @@ -1631,11 +1618,9 @@ globalThis.BeautyTooltip = function(slave) { App.UI.DOM.link("Descending", () => { direction = "descending"; jQuery('#cheatBeautyContents').empty().append(BeautyFrame()); }, []) ])); - let cheatBeautyContents = document.createElement('div'); + let cheatBeautyContents = App.UI.DOM.appendNewElement("div", el, BeautyFrame()); cheatBeautyContents.id = "cheatBeautyContents"; - cheatBeautyContents.appendChild(BeautyFrame()); - el.appendChild(cheatBeautyContents); - App.UI.DOM.appendNewElement("div", el, `${beauty * 2}/2 is ${beauty}, their total score`); + App.UI.DOM.appendNewElement("div", el, `${beauty * 2}/2 is ${beauty}, ${getPronouns(slave).her} total score`); return el; // Set up the frame that contains the info @@ -1675,32 +1660,6 @@ globalThis.BeautyTooltip = function(slave) { return el; } } - - function hiderButton() { - const link = App.UI.DOM.link( - `${beauty}:`, - () => { - jQuery("#beauty-link").empty().append(showerButton()); - jQuery('#BeautyTooltip').empty(); - } - ); - link.style.color = "pink"; - link.style.fontWeight = "bold"; - return link; - } - - function showerButton() { - const link = App.UI.DOM.link( - beauty, - () => { - jQuery("#beauty-link").empty().append(hiderButton()); - jQuery('#BeautyTooltip').empty().append(BeautyDisplay()); - } - ); - link.style.color = "pink"; - link.style.fontWeight = "bold"; - return link; - } }; // this is a port of the FResult widget @@ -2170,25 +2129,13 @@ globalThis.FResult = function(s, forSale = 0) { * @returns {Node} */ globalThis.FResultTooltip = function(slave, forSale = 0) { - // Make a link. Text should be slave's FResult. Clicking the link will display detailed info about that beauty where the link used to be - const el = new DocumentFragment(); - let span = document.createElement("span"); - span.id = "f-result-link"; - if (V.cheatMode || V.debugMode) { - span.append(showerButton()); - } else { - App.UI.DOM.appendNewElement("span", span, `${FResult(slave, forSale)}.`, ["lightcoral", "bold"]); - } - el.append(span); - - span = document.createElement("span"); - span.id = "FResultTooltip"; - el.append(span); - - return el; + // Make a link. Text should be slave's FResult. Clicking the link will display detailed info about that FResult over the top of the page (tooltip-style) + const displayFunc = V.cheatMode || V.debugMode ? FResultDisplay : undefined; + const interactor = new App.UI.DOM.InteractiveDetails(FResult(slave, forSale).toString(), displayFunc, ["lightcoral", "bold"]); + return interactor.render(); /** Upon the link being clicked, set up some links to sort the info and a span to show it in - * @returns {Node} + * @returns {HTMLElement} */ function FResultDisplay() { let criteria = "value"; @@ -2205,10 +2152,8 @@ globalThis.FResultTooltip = function(slave, forSale = 0) { App.UI.DOM.link("Descending", () => { direction = "descending"; jQuery('#cheatFResultContents').empty().append(FResultFrame); }, []) ])); - let cheatFResultContents = document.createElement('div'); + let cheatFResultContents = App.UI.DOM.appendNewElement("div", el, FResultFrame()); cheatFResultContents.id = "cheatFResultContents"; - cheatFResultContents.appendChild(FResultFrame()); - el.appendChild(cheatFResultContents); return el; /** Set up the frame that contains the info @@ -2234,7 +2179,7 @@ globalThis.FResultTooltip = function(slave, forSale = 0) { domCell.style.float = "left"; domCell.style.width = "3em"; - let textNode = document.createTextNode(line.value); + let textNode = document.createTextNode(line.value.toString()); if (line.value > 0) { domCell.className = "green"; } else if (line.value < 0) { @@ -2250,31 +2195,6 @@ globalThis.FResultTooltip = function(slave, forSale = 0) { return el; } } - function hiderButton() { - const link = App.UI.DOM.link( - `${FResult(slave, forSale)}:`, - () => { - jQuery("#f-result-link").empty().append(showerButton()); - jQuery('#FResultTooltip').empty(); - } - ); - link.style.color = "lightcoral"; - link.style.fontWeight = "bold"; - return link; - } - - function showerButton() { - const link = App.UI.DOM.link( - `${FResult(slave, forSale)}.`, - () => { - jQuery("#f-result-link").empty().append(hiderButton()); - jQuery('#FResultTooltip').empty().append(FResultDisplay()); - } - ); - link.style.color = "lightcoral"; - link.style.fontWeight = "bold"; - return link; - } }; /**