diff --git a/css/gui/tooltips/hasTooltip.css b/css/gui/tooltips/hasTooltip.css deleted file mode 100644 index d5eafa88bc64b3e50a015fe8ece4b33f5f52a8d5..0000000000000000000000000000000000000000 --- a/css/gui/tooltips/hasTooltip.css +++ /dev/null @@ -1,16 +0,0 @@ -/* 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; - z-index: 2; - text-indent: 0; -} diff --git a/css/gui/tooltips/tippy.css b/css/gui/tooltips/tippy.css index fb794aeb62b0d1f4826c808f364fe28fc13c376c..72ffb2760d993eedc924831c52faf1c88168a1b5 100644 --- a/css/gui/tooltips/tippy.css +++ b/css/gui/tooltips/tippy.css @@ -1,5 +1,9 @@ .has-tooltip { - text-decoration: underline dotted lightblue; + text-decoration: underline dotted; +} + +.tippy-content { + text-indent: initial; } .tippy-content ul { @@ -8,3 +12,7 @@ .tippy-content ul:not(.choices-strip) { padding-left: 10px; } + +.tippy-content .tip-details { + font-size: smaller; +} diff --git a/src/endWeek/saSocialEffects.js b/src/endWeek/saSocialEffects.js index e8e53e7c8ea833918011f944859610f202b2fe96..bc135392d95fe43667bbde7f30c5edd24c182481 100644 --- a/src/endWeek/saSocialEffects.js +++ b/src/endWeek/saSocialEffects.js @@ -916,37 +916,33 @@ App.SlaveAssignment.saSocialEffects = function(slave) { } function renderTooltip() { - const el = document.createDocumentFragment(); + const el = document.createElement("div"); + el.classList.add("tip-details", "grid-2columns-auto"); for (const effect of socialEffects) { - const domLine = document.createElement('div'); - domLine.style.display = "float"; - const domCell = document.createElement('span'); - domCell.style.float = "left"; - domCell.style.width = "3em"; - let text = ""; - if (Math.round(effect.magnitude) === 0) { - text = '0'; - domCell.className = "gray"; - } else if (effect.magnitude > 0) { + let className; + if (effect.magnitude > 0) { for (let i = 0; i < effect.magnitude; ++i) { text += "+"; } - domCell.className = "green"; + className = "green"; } else if (effect.magnitude < 0) { for (let i = 0; i > effect.magnitude; --i) { text += "-"; } - domCell.className = "red"; + className = "red"; + } else { + text = '0'; + className = "gray"; } - domCell.append(text); - domLine.append(domCell); + App.UI.DOM.appendNewElement("span", el, text, className); - domLine.append(effect.shortDesc); + const div = document.createElement('div'); + div.append(effect.shortDesc); if (effect.FS) { - domLine.append(` (${effect.FS})`); + div.append(` (${effect.FS})`); } - el.appendChild(domLine); + el.appendChild(div); } return el; } @@ -965,14 +961,17 @@ App.SlaveAssignment.saSocialEffects = function(slave) { const sum = positiveSum + negativeSum; frag.append(`Society has a `); if (sum > 0) { - const details = new App.UI.DOM.InteractiveDetails("positive", renderTooltip, ["green", "major-link", "underline"]); - frag.append(details.render(), ` overall view of ${slave.slaveName} `, sumFrag, `, which improves your reputation and advances social progress.`); + const opinion = App.UI.DOM.makeElement("span", "positive", ["green", "major-link", "has-tooltip"]); + tippy(opinion, {content: renderTooltip(), placement: "right"}); + frag.append(opinion, ` overall view of ${slave.slaveName} `, sumFrag, `, which improves your reputation and advances social progress.`); } else if (sum === 0) { - const details = new App.UI.DOM.InteractiveDetails("neutral", renderTooltip, ["yellow", "major-link", "underline"]); - frag.append(details.render(), ` overall view of ${slave.slaveName} `, sumFrag, `; ${he} had no net impact on your reputation or social progress this week.`); + const opinion = App.UI.DOM.makeElement("span", "neutral", ["yellow", "major-link", "has-tooltip"]); + tippy(opinion, {content: renderTooltip(), placement: "right"}); + frag.append(opinion, ` overall view of ${slave.slaveName} `, sumFrag, `; ${he} had no net impact on your reputation or social progress this week.`); } else { - const details = new App.UI.DOM.InteractiveDetails("negative", renderTooltip, ["red", "major-link", "underline"]); - frag.append(details.render(), ` overall view of ${slave.slaveName} `, sumFrag, `, which decreases your reputation and retards social progress.`); + const opinion = App.UI.DOM.makeElement("span", "negative", ["red", "major-link", "has-tooltip"]); + tippy(opinion, {content: renderTooltip(), placement: "right"}); + frag.append(opinion, ` overall view of ${slave.slaveName} `, sumFrag, `, which decreases your reputation and retards social progress.`); } } diff --git a/src/gui/interactiveDetails.js b/src/gui/interactiveDetails.js deleted file mode 100644 index 548e501761cd932478733926f30d1fcab011cbd8..0000000000000000000000000000000000000000 --- a/src/gui/interactiveDetails.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * 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 = detailsGenerator ? App.UI.DOM.link(linkText, () => this.toggle()) : App.UI.DOM.makeElement("span", linkText); - 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) { - $(this.span).empty().append(this.func()); - // by default, the CSS will try to show it as inline-block on the right - this.span.style.removeProperty("right"); // reset style in case we'd moved it last time it was shown - const overlayRect = this.span.getBoundingClientRect(); - const linkRect = this.link.getBoundingClientRect(); - if (overlayRect.right > window.innerWidth) { - if (overlayRect.width < linkRect.left) { - // if it won't fit in the default position, but it *will* fit on the left, force it to move over to the left side of the link - this.span.style.right = "100%"; - } - // if it won't fit on either side, give up and leave it where it is. TODO: maybe do something smarter? - } - this.span.style.visibility = "visible"; - } else { - $(this.span).empty(); - this.span.style.visibility = "hidden"; - } - } - - /** - * Render the object to the page - * @returns {HTMLSpanElement} - */ - render() { - const containingSpan = document.createElement("span"); - containingSpan.style.position = "relative"; // required for absolute positioning to work correctly later - containingSpan.append(this.link, this.span); - return containingSpan; - } -}; diff --git a/src/js/slaveCostJS.js b/src/js/slaveCostJS.js index 778d7f550bdff8e9eb1c1fd130d985616c0da4d1..09267c6cf09e4a80d81f602d33b186a694a15d23 100644 --- a/src/js/slaveCostJS.js +++ b/src/js/slaveCostJS.js @@ -1637,9 +1637,16 @@ 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 over the top of the page (tooltip-style) const beauty = Beauty(slave); - const displayFunc = V.cheatMode || V.debugMode ? BeautyDisplay : undefined; - const interactor = new App.UI.DOM.InteractiveDetails(beauty.toString(), displayFunc, ["pink", "bold"]); - return interactor.render(); + const span = App.UI.DOM.makeElement("span", beauty.toString(), ["pink", "bold"]); + if (V.cheatMode || V.debugMode) { + span.tabIndex = 0; + span.classList.add("has-tooltip"); + tippy(span, { + content: BeautyDisplay(), + placement: "right", interactive: true, trigger: "click" + }); + } + return span; // Upon the link being clicked, set up some links to sort the info and a span to show it in function BeautyDisplay() { @@ -1648,6 +1655,7 @@ globalThis.BeautyTooltip = function(slave) { // Heading line that handles sorting let el = document.createElement('div'); + el.classList.add("tip-details"); el.appendChild(document.createTextNode(`Sort by: `)); el.appendChild(App.UI.DOM.generateLinksStrip([ @@ -1676,37 +1684,27 @@ globalThis.BeautyTooltip = function(slave) { // Set up the frame that contains the info function BeautyFrame() { - let el = document.createDocumentFragment(); - let beautyArray; + let el = document.createElement("div"); + el.classList.add("grid-2columns-auto"); + let beautyArray; if ((criteria === "text" && direction === "descending") || (criteria === "value" && direction === "ascending")) { beautyArray = BeautyArray(slave).sort((a, b) => (a[criteria] > b[criteria]) ? 1 : -1); } else { beautyArray = BeautyArray(slave).sort((a, b) => (a[criteria] < b[criteria]) ? 1 : -1); } - let domLine; - let domCell; beautyArray.forEach((line) => { line.value = (Math.floor(line.value * 10) / 10); - domLine = document.createElement('div'); - domLine.style.display = "float"; - domCell = document.createElement('span'); - domCell.style.float = "left"; - domCell.style.width = "3em"; - let textNode = document.createTextNode(line.value); + let className; if (line.value > 0) { - domCell.className = "green"; + className = "green"; } else if (line.value < 0) { - domCell.className = "red"; + className = "red"; } - domCell.appendChild(textNode); - domLine.appendChild(domCell); - - textNode = document.createTextNode(line.text); - domLine.appendChild(textNode); - el.appendChild(domLine); + App.UI.DOM.appendNewElement("div", el, line.value.toString(), className); + App.UI.DOM.appendNewElement("div", el, line.text); }); return el; } @@ -2186,9 +2184,16 @@ globalThis.FResult = function(s, forSale = 0) { */ globalThis.FResultTooltip = function(slave, forSale = 0) { // 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(); + const span = App.UI.DOM.makeElement("span", FResult(slave, forSale).toString(), ["lightcoral", "bold"]); + if (V.cheatMode || V.debugMode) { + span.tabIndex = 0; + span.classList.add("has-tooltip"); + tippy(span, { + content: FResultDisplay(), + placement: "right", interactive: true, trigger: "click" + }); + } + return span; /** Upon the link being clicked, set up some links to sort the info and a span to show it in * @returns {HTMLElement} @@ -2199,6 +2204,7 @@ globalThis.FResultTooltip = function(slave, forSale = 0) { // Heading line that handles sorting const el = document.createElement('div'); + el.classList.add("tip-details"); el.appendChild(document.createTextNode(`Sort by: `)); el.appendChild(App.UI.DOM.generateLinksStrip([ @@ -2225,40 +2231,31 @@ globalThis.FResultTooltip = function(slave, forSale = 0) { return el; /** Set up the frame that contains the info - * @returns {DocumentFragment} + * @returns {HTMLDivElement} */ function FResultFrame() { - let el = document.createDocumentFragment(); - let fResultArray; + let el = document.createElement("div"); + el.classList.add("grid-2columns-auto"); + let fResultArray; if ((criteria === "text" && direction === "descending") || (criteria === "value" && direction === "ascending")) { fResultArray = FResultArray(slave, forSale).sort((a, b) => (a[criteria] > b[criteria]) ? 1 : -1); } else { fResultArray = FResultArray(slave, forSale).sort((a, b) => (a[criteria] < b[criteria]) ? 1 : -1); } - let domLine; - let domCell; fResultArray.forEach((line) => { line.value = (Math.floor(line.value * 10) / 10); - domLine = document.createElement('div'); - domLine.style.display = "float"; - domCell = document.createElement('span'); - domCell.style.float = "left"; - domCell.style.width = "3em"; - let textNode = document.createTextNode(line.value.toString()); + let className; if (line.value > 0) { - domCell.className = "green"; + className = "green"; } else if (line.value < 0) { - domCell.className = "red"; + className = "red"; } - domCell.appendChild(textNode); - domLine.appendChild(domCell); + App.UI.DOM.appendNewElement("div", el, line.value.toString(), className); - textNode = document.createTextNode(line.text); - domLine.appendChild(textNode); - el.appendChild(domLine); + App.UI.DOM.appendNewElement("div", el, line.text); }); return el; }