diff --git a/src/interaction/siUtilities.js b/src/interaction/siUtilities.js new file mode 100644 index 0000000000000000000000000000000000000000..bf45f13a50701b8e2d0b0643855e2c559548ef90 --- /dev/null +++ b/src/interaction/siUtilities.js @@ -0,0 +1,150 @@ +/** Find the previous and next slaves' IDs based on the current sort order + * @param {App.Entity.SlaveState} slave + * @returns {[number, number]} - previous and next slave ID + */ +App.UI.SlaveInteract.placeInLine = function(slave) { + const useSlave = assignmentVisible(slave) ? ((s) => assignmentVisible(s)) : ((s) => slave.assignment === s.assignment); + const slaveList = V.slaves.filter(useSlave); + SlaveSort.slaves(slaveList); + const curSlaveIndex = slaveList.findIndex((s) => s.ID === slave.ID); + + let nextIndex; + if (curSlaveIndex + 1 > slaveList.length - 1) { + nextIndex = 0; // wrap around to first slave + } else { + nextIndex = curSlaveIndex + 1; + } + let prevIndex; + if (curSlaveIndex - 1 < 0) { + prevIndex = slaveList.length - 1; // wrap around to last slave + } else { + prevIndex = curSlaveIndex - 1; + } + + return [slaveList[prevIndex].ID, slaveList[nextIndex].ID]; +}; + +/** @typedef RowItem + * @type {object} + * @property {string} [FS] - FS requirement, if any + * @property {string} [text] - link text + * @property {object} [updateSlave] - properties to be merged onto the slave + * @property {object} [update] - properties to be merged into global state + * @property {string} [disabled] - text indicating why the option is unavailable + * @property {string} [note] + */ + +/** Append a simple row of choices with a label to a container, if there are choices to be made. + * @param {Node} parent + * @param {string} label + * @param {RowItem[]} array + * @param {App.Entity.SlaveState} slave + * @param {Function} [refresh] + */ +App.UI.SlaveInteract.appendLabeledChoiceRow = function(parent, label, array, slave, refresh) { + if (array.length > 0) { + let links = document.createElement('div'); + links.append(`${label}: `); + links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "", false, refresh)); + links.className = "choices"; + return parent.appendChild(links); + } +}; + +/** Generate a row of choices + * @param {RowItem[]} array + * @param {App.Entity.SlaveState} slave + * @param {string} [category] - should be in the form of slave.category, the thing we want to update. + * @param {boolean} [accessCheck=false] + * @param {Function} [refresh] + * @returns {HTMLSpanElement} + */ +App.UI.SlaveInteract.generateRows = function(array, slave, category, accessCheck = false, refresh) { + let row = document.createElement('span'); + let useSep = false; + for (let i = 0; i < array.length; i++) { + let link; + const separator = document.createTextNode(` | `); + const keys = Object.keys(array[i]); + + // Test to see if there was a problem with the key + for (let j = 0; j < keys.length; j++) { + if (["FS", "text", "updateSlave", "update", "note", "disabled"].includes(keys[j])) { + continue; + } else { + array[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY"; + console.log("Trash found while generateRows() was running: " + keys[j] + ": " + array[i][keys[j]]); + break; + } + } + // Some items will never be in App.Data.slaveWear, especially "none" if it falls in between harsh and nice data sets. Trying to look it up would cause an error, which is what access check works around. + let unlocked = false; + if (accessCheck === true) { + if (category === "chastity") { + let text = array[i].text.toLowerCase(); // Yucky. Category name does not match for chastity (since it sets multiple kinds of chastity at once). Compare using a lowercase name instead. + unlocked = isItemAccessible.entry(text, category, slave); + } else { + unlocked = isItemAccessible.entry(array[i].updateSlave[category], category, slave); + } + } + if (accessCheck === false || unlocked) { + if (i < array.length && i !== 0 && useSep === true) { // start with separator (after first loop); can't after since the last loop may not have any text. + row.appendChild(separator); + } + useSep = true; // First item may not appear and if it doesn't we don't want the second to start with a '|' + // is it just text? + if (array[i].disabled) { + link = App.UI.DOM.disabledLink(array[i].text, [array[i].disabled]); + } else if (typeof unlocked === 'string') { + link = App.UI.DOM.disabledLink(array[i].text, [unlocked]); + } else { + link = document.createElement('span'); + + // Set up the link + link.appendChild( + App.UI.DOM.link( + `${array[i].text} `, + () => { click(array[i]); }, + ) + ); + + if (array[i].FS) { + let FS = App.UI.DOM.disabledLink(`FS`, [FutureSocieties.displayAdj(array[i].FS)]); + FS.style.fontStyle = "italic"; + link.appendChild(FS); + } + + // add a note node if required + if (array[i].note) { + link.appendChild(App.UI.DOM.makeElement('span', ` ${array[i].note}`, 'note')); + } + } + row.appendChild(link); + } + } + + return row; + + /** @param {RowItem} arrayOption */ + function click(arrayOption) { + if (arrayOption.updateSlave) { + for (const slaveProperty in arrayOption.updateSlave) { + _.set(slave, slaveProperty, arrayOption.updateSlave[slaveProperty]); + } + } + if (arrayOption.update) { + Object.assign(V, arrayOption.update); + } + if (typeof refresh === "function") { + refresh(); + } else { + App.UI.Wardrobe.refreshAll(slave); + App.UI.SlaveInteract.refreshAll(slave); + } + } +}; + +App.UI.SlaveInteract.refreshAll = function(slave) { + App.UI.SlaveInteract.custom(slave); + App.UI.SlaveInteract.work(slave); +}; diff --git a/src/interaction/slaveInteract.js b/src/interaction/slaveInteract.js index 5bfcc38d6da81811e1acf8f2214f0a0ecd80a276..f6851c1be55d9fcb81d8c75b25fd14c65241efbe 100644 --- a/src/interaction/slaveInteract.js +++ b/src/interaction/slaveInteract.js @@ -1,30 +1,4 @@ -/* eslint-disable no-unused-vars */ // TODO: remove after testing -/** Find the previous and next slaves' IDs based on the current sort order - * @param {App.Entity.SlaveState} slave - * @returns {[number, number]} - previous and next slave ID - */ -App.UI.SlaveInteract.placeInLine = function(slave) { - const useSlave = assignmentVisible(slave) ? ((s) => assignmentVisible(s)) : ((s) => slave.assignment === s.assignment); - const slaveList = V.slaves.filter(useSlave); - SlaveSort.slaves(slaveList); - const curSlaveIndex = slaveList.findIndex((s) => s.ID === slave.ID); - - let nextIndex; - if (curSlaveIndex + 1 > slaveList.length - 1) { - nextIndex = 0; // wrap around to first slave - } else { - nextIndex = curSlaveIndex + 1; - } - let prevIndex; - if (curSlaveIndex - 1 < 0) { - prevIndex = slaveList.length - 1; // wrap around to last slave - } else { - prevIndex = curSlaveIndex - 1; - } - - return [slaveList[prevIndex].ID, slaveList[nextIndex].ID]; -}; /** * @param {App.Entity.SlaveState} slave @@ -930,8 +904,6 @@ App.UI.SlaveInteract.useSlaveDisplay = function(slave) { return el; }; - - App.UI.SlaveInteract.custom = (function() { let el; let label; @@ -1790,128 +1762,3 @@ App.UI.SlaveInteract.custom = (function() { return el; } })(); - -/** @typedef RowItem - * @type {object} - * @property {string} [FS] - FS requirement, if any - * @property {string} [text] - link text - * @property {object} [updateSlave] - properties to be merged onto the slave - * @property {object} [update] - properties to be merged into global state - * @property {string} [disabled] - text indicating why the option is unavailable - * @property {string} [note] - */ - -/** Append a simple row of choices with a label to a container, if there are choices to be made. - * @param {Node} parent - * @param {string} label - * @param {RowItem[]} array - * @param {App.Entity.SlaveState} slave - * @param {Function} [refresh] - */ -App.UI.SlaveInteract.appendLabeledChoiceRow = function(parent, label, array, slave, refresh) { - if (array.length > 0) { - let links = document.createElement('div'); - links.append(`${label}: `); - links.appendChild(App.UI.SlaveInteract.generateRows(array, slave, "", false, refresh)); - links.className = "choices"; - return parent.appendChild(links); - } -}; - -/** Generate a row of choices - * @param {RowItem[]} array - * @param {App.Entity.SlaveState} slave - * @param {string} [category] - should be in the form of slave.category, the thing we want to update. - * @param {boolean} [accessCheck=false] - * @param {Function} [refresh] - * @returns {HTMLSpanElement} - */ -App.UI.SlaveInteract.generateRows = function(array, slave, category, accessCheck = false, refresh) { - let row = document.createElement('span'); - let useSep = false; - for (let i = 0; i < array.length; i++) { - let link; - const separator = document.createTextNode(` | `); - const keys = Object.keys(array[i]); - - // Test to see if there was a problem with the key - for (let j = 0; j < keys.length; j++) { - if (["FS", "text", "updateSlave", "update", "note", "disabled"].includes(keys[j])) { - continue; - } else { - array[i].text += " ERROR, THIS SCENE WAS NOT ENTERED CORRECTLY"; - console.log("Trash found while generateRows() was running: " + keys[j] + ": " + array[i][keys[j]]); - break; - } - } - // Some items will never be in App.Data.slaveWear, especially "none" if it falls in between harsh and nice data sets. Trying to look it up would cause an error, which is what access check works around. - let unlocked = false; - if (accessCheck === true) { - if (category === "chastity") { - let text = array[i].text.toLowerCase(); // Yucky. Category name does not match for chastity (since it sets multiple kinds of chastity at once). Compare using a lowercase name instead. - unlocked = isItemAccessible.entry(text, category, slave); - } else { - unlocked = isItemAccessible.entry(array[i].updateSlave[category], category, slave); - } - } - if (accessCheck === false || unlocked) { - if (i < array.length && i !== 0 && useSep === true) { // start with separator (after first loop); can't after since the last loop may not have any text. - row.appendChild(separator); - } - useSep = true; // First item may not appear and if it doesn't we don't want the second to start with a '|' - // is it just text? - if (array[i].disabled) { - link = App.UI.DOM.disabledLink(array[i].text, [array[i].disabled]); - } else if (typeof unlocked === 'string') { - link = App.UI.DOM.disabledLink(array[i].text, [unlocked]); - } else { - link = document.createElement('span'); - - // Set up the link - link.appendChild( - App.UI.DOM.link( - `${array[i].text} `, - () => { click(array[i]); }, - ) - ); - - if (array[i].FS) { - let FS = App.UI.DOM.disabledLink(`FS`, [FutureSocieties.displayAdj(array[i].FS)]); - FS.style.fontStyle = "italic"; - link.appendChild(FS); - } - - // add a note node if required - if (array[i].note) { - link.appendChild(App.UI.DOM.makeElement('span', ` ${array[i].note}`, 'note')); - } - } - row.appendChild(link); - } - } - - return row; - - /** @param {RowItem} arrayOption */ - function click(arrayOption) { - if (arrayOption.updateSlave) { - for (const slaveProperty in arrayOption.updateSlave) { - _.set(slave, slaveProperty, arrayOption.updateSlave[slaveProperty]); - } - } - if (arrayOption.update) { - Object.assign(V, arrayOption.update); - } - if (typeof refresh === "function") { - refresh(); - } else { - App.UI.Wardrobe.refreshAll(slave); - App.UI.SlaveInteract.refreshAll(slave); - } - } -}; - -App.UI.SlaveInteract.refreshAll = function(slave) { - App.UI.SlaveInteract.custom(slave); - App.UI.SlaveInteract.work(slave); -};