From 5161f16c3dcdb4be59bb72e9ffad4663f76c0540 Mon Sep 17 00:00:00 2001
From: bananarama92 <bananarama921@outlook.com>
Date: Wed, 18 Sep 2024 17:32:20 +0200
Subject: [PATCH] BUG: Use `Element.get/setAttribute` over directly accessing
 aria properties

---
 .../Character/FriendList/FriendList.js        |  2 +-
 .../Screens/Online/ChatRoom/ChatRoom.js       | 16 +++---
 BondageClub/Screens/Room/Crafting/Crafting.js | 20 +++----
 BondageClub/Scripts/Element.js                | 57 ++++++++++---------
 BondageClub/Scripts/Layering.js               |  2 +-
 5 files changed, 51 insertions(+), 46 deletions(-)

diff --git a/BondageClub/Screens/Character/FriendList/FriendList.js b/BondageClub/Screens/Character/FriendList/FriendList.js
index 128a5e224b..6e5ee7067e 100644
--- a/BondageClub/Screens/Character/FriendList/FriendList.js
+++ b/BondageClub/Screens/Character/FriendList/FriendList.js
@@ -957,7 +957,7 @@ function FriendListChangeSortingMode(sortingMode) {
  * @this {HTMLButtonElement}
  */
 function FriendListToggleAutoRefresh() {
-	Player.OnlineSettings.FriendListAutoRefresh = this.ariaChecked === "true";
+	Player.OnlineSettings.FriendListAutoRefresh = this.getAttribute("aria-checked") === "true";
 	ServerAccountUpdate.QueueData({ OnlineSettings: Player.OnlineSettings });
 }
 //#endregion
diff --git a/BondageClub/Screens/Online/ChatRoom/ChatRoom.js b/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
index e84e191775..4991aa3a82 100644
--- a/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
+++ b/BondageClub/Screens/Online/ChatRoom/ChatRoom.js
@@ -862,7 +862,7 @@ var ChatRoomSep = {
 	 * @type {(this: HTMLButtonElement, event: MouseEvent | TouchEvent) => Promise<void>}
 	 */
 	_ClickCollapse: async function _ClickCollapse(event) {
-		const mode = this.ariaExpanded === "true" ? "Collapse" : "Uncollapse";
+		const mode = this.getAttribute("aria-expanded") === "true" ? "Collapse" : "Uncollapse";
 		const roomSep = /** @type {HTMLDivElement} */(this.parentElement.parentElement);
 		if (event.shiftKey) {
 			// (un)collapse all separators if the `shift` key is held down while clicking
@@ -965,7 +965,7 @@ var ChatRoomSep = {
 	 */
 	IsCollapsed: function IsCollapsed(roomSep) {
 		const button = /** @type {HTMLButtonElement} */(roomSep?.querySelector(".chat-room-sep-collapse"));
-		return !!button && button.ariaExpanded === "false";
+		return !!button && button.getAttribute("aria-expanded") === "false";
 	},
 
 	/**
@@ -974,11 +974,11 @@ var ChatRoomSep = {
 	 */
 	Uncollapse: async function Uncollapse(roomSep) {
 		const button = /** @type {HTMLButtonElement} */(roomSep?.querySelector(".chat-room-sep-collapse"));
-		if (!button || button.ariaExpanded === "true") {
+		if (!button || button.getAttribute("aria-expanded") === "true") {
 			return;
 		}
 
-		button.ariaExpanded = "true";
+		button.setAttribute("aria-expanded", "true");
 		button.innerText = "Ë…";
 		let sibbling = /** @type {null | HTMLElement} */(roomSep.nextSibling);
 		while (sibbling && !sibbling.classList.contains("chat-room-sep")) {
@@ -999,11 +999,11 @@ var ChatRoomSep = {
 	 */
 	Collapse: async function Collapse(roomSep) {
 		const button = /** @type {HTMLButtonElement} */(roomSep?.querySelector(".chat-room-sep-collapse"));
-		if (!button || button.ariaExpanded === "false") {
+		if (!button || button.getAttribute("aria-expanded") === "false") {
 			return;
 		}
 
-		button.ariaExpanded = "false";
+		button.setAttribute("aria-expanded", "false");
 		button.innerText = "˃";
 		let sibbling = /** @type {null | HTMLElement} */(roomSep.nextSibling);
 		while (sibbling && !sibbling.classList.contains("chat-room-sep")) {
@@ -1085,8 +1085,8 @@ function ChatRoomCreateElement() {
 						ElementButton.Create(
 							"chat-room-buttons-collapse",
 							function() {
-								const displayState = this.ariaExpanded === "true" ? "none" : "";
-								this.ariaExpanded = displayState ? "false" : "true";
+								const displayState = this.getAttribute("aria-expanded") === "true" ? "none" : "";
+								this.setAttribute("aria-expanded", displayState ? "false" : "true");
 								this.innerText = displayState ? "<" : ">";
 								const elements = /** @type {NodeListOf<HTMLElement>} */(document.querySelectorAll("#chat-room-buttons > *"));
 								elements.forEach(b => {
diff --git a/BondageClub/Screens/Room/Crafting/Crafting.js b/BondageClub/Screens/Room/Crafting/Crafting.js
index e5448bca20..e0f777c894 100644
--- a/BondageClub/Screens/Room/Crafting/Crafting.js
+++ b/BondageClub/Screens/Room/Crafting/Crafting.js
@@ -461,7 +461,7 @@ var CraftingEventListeners = {
 	 * @type {(this: HTMLButtonElement, ev: Event) => void}
 	 */
 	_ClickExpand: function _ClickExpand() {
-		if (this.ariaExpanded !== "true") {
+		if (this.getAttribute("aria-expanded") !== "true") {
 			return;
 		}
 
@@ -488,7 +488,7 @@ var CraftingEventListeners = {
 	 * @type {(this: HTMLButtonElement, ev: Event) => void}
 	 */
 	_ClickPadlock: function _ClickPadlock() {
-		const newLock = this.ariaChecked === "true" ? AssetGet("Female3DCG", "ItemMisc", this.dataset.asset) : null;
+		const newLock = this.getAttribute("aria-checked") === "true" ? AssetGet("Female3DCG", "ItemMisc", this.dataset.asset) : null;
 		const needsRefresh = (!newLock && CraftingSelectedItem.Lock) || (newLock && !CraftingSelectedItem);
 		CraftingSelectedItem.Lock = newLock;
 		if (needsRefresh) {
@@ -542,7 +542,7 @@ var CraftingEventListeners = {
 		document.querySelectorAll(`#${CraftingID.propertyGrid} [data-property]`).forEach(e => {
 			const propertyType = /** @type {CraftingPropertyType} */(e.getAttribute("data-property"));
 			const callback = CraftingPropertyMap.get(propertyType);
-			e.ariaDisabled = propertyType === "Normal" || (callback && CraftingSelectedItem.Assets.some(a => callback(a))) ? "false" : "true";
+			e.setAttribute("aria-disabled", propertyType === "Normal" || (callback && CraftingSelectedItem.Assets.some(a => callback(a))) ? "false" : "true");
 		});
 
 		// Set the item property, falling back to `Normal` of an invalid property is selected
@@ -571,9 +571,9 @@ var CraftingEventListeners = {
 
 		// Disable the lock buttons if none of the items supports any lock
 		if (allowLock) {
-			document.querySelectorAll(`#${CraftingID.padlockGrid} [data-asset]`).forEach(e => e.ariaDisabled = "false");
+			document.querySelectorAll(`#${CraftingID.padlockGrid} [data-asset]`).forEach(e => e.setAttribute("aria-disabled", "false"));
 		} else {
-			document.querySelectorAll(`#${CraftingID.padlockGrid} [data-asset]`).forEach(e => e.ariaDisabled = "true");
+			document.querySelectorAll(`#${CraftingID.padlockGrid} [data-asset]`).forEach(e => e.setAttribute("aria-disabled", "true"));
 		}
 
 		CraftingUpdatePreview();
@@ -599,7 +599,7 @@ var CraftingEventListeners = {
 		const searchInput = sidePannel.querySelector("input[type='search']");
 		searchInput?.dispatchEvent(new Event("input"));
 
-		if (this.ariaChecked === "true") {
+		if (this.getAttribute("aria-checked") === "true") {
 			controlButton.innerHTML = this.innerHTML;
 			return;
 		} else {
@@ -627,7 +627,7 @@ var CraftingEventListeners = {
 		searchResultCandidates?.querySelectorAll("button.button").forEach(button => {
 			const label = button.querySelector(".button-label");
 			if (label) {
-				const displayStyle = (button.ariaChecked === "true" || label.textContent.toUpperCase().includes(query)) ? "" : "none";
+				const displayStyle = (button.getAttribute("aria-checked") === "true" || label.textContent.toUpperCase().includes(query)) ? "" : "none";
 				/** @type {HTMLButtonElement} */(button).style.display = displayStyle;
 			}
 		});
@@ -1660,11 +1660,11 @@ function CraftingExitResetElements() {
 
 	// Select the `Normal` property and disable all others
 	document.querySelector(`#${CraftingID.propertyGrid} [data-property='Normal'][aria-checked='false']`)?.dispatchEvent(new Event("click"));
-	document.querySelectorAll(`#${CraftingID.propertyGrid} [data-property]:not([data-property='Normal'])`).forEach(e => e.ariaDisabled = "true");
+	document.querySelectorAll(`#${CraftingID.propertyGrid} [data-property]:not([data-property='Normal'])`).forEach(e => e.setAttribute("aria-disabled", "true"));
 
 	// Deselect the active lock and disable them all
 	document.querySelector(`#${CraftingID.padlockGrid} [data-asset][aria-checked='true']`)?.dispatchEvent(new Event("click"));
-	document.querySelectorAll(`#${CraftingID.padlockGrid} [data-asset]`).forEach(e => e.ariaDisabled = "true");
+	document.querySelectorAll(`#${CraftingID.padlockGrid} [data-asset]`).forEach(e => e.setAttribute("aria-disabled", "true"));
 
 	// Deselect the asset and disable the accept button
 	const assetSelected = document.querySelector(`#${CraftingID.assetGrid} [aria-checked='true']`);
@@ -1678,7 +1678,7 @@ function CraftingExitResetElements() {
 	assetControlButton.innerHTML = "";
 	ElementButton._ParseLabel(assetControlButton.id, TextGet("SelectItem"), "bottom", { parent: assetControlButton });
 	ElementButton._ParseImage(assetControlButton.id, "./Icons/NoCraft.png", { parent: assetControlButton });
-	if (assetControlButton.ariaChecked === "false") {
+	if (assetControlButton.getAttribute("aria-checked") === "false") {
 		assetControlButton.dispatchEvent(new Event("click"));
 	}
 
diff --git a/BondageClub/Scripts/Element.js b/BondageClub/Scripts/Element.js
index 0375270c21..80c5b658a1 100644
--- a/BondageClub/Scripts/Element.js
+++ b/BondageClub/Scripts/Element.js
@@ -812,7 +812,7 @@ var ElementButton = {
 			case " ":
 				ev.preventDefault();
 
-				if (this.disabled || this.ariaDisabled === "true") {
+				if (this.disabled || this.getAttribute("aria-disabled") === "true") {
 					ev.stopImmediatePropagation();
 					return;
 				} else if (!ev.repeat) {
@@ -835,7 +835,7 @@ var ElementButton = {
 		switch (ev.key) {
 			case "Enter":
 			case " ":
-				if (this.disabled || this.ariaDisabled === "true") {
+				if (this.disabled || this.getAttribute("aria-disabled") === "true") {
 					ev.stopImmediatePropagation();
 					return;
 				}
@@ -849,7 +849,7 @@ var ElementButton = {
 	 * @type {(this: HTMLButtonElement, ev: MouseEvent | TouchEvent) => void}
 	 */
 	_Click: function _Click(ev) {
-		if (this.ariaDisabled === "true") {
+		if (this.getAttribute("aria-disabled") === "true") {
 			ev.stopImmediatePropagation();
 		}
 	},
@@ -902,11 +902,11 @@ var ElementButton = {
 		}
 
 		// Ensure that `radio` buttons to switch the tabindex of the active radio to 0, while `menuitemradio` buttons do not
-		if (this.ariaChecked === "true") {
-			if (parent.ariaRequired === "true") {
+		if (this.getAttribute("aria-checked") === "true") {
+			if (parent.getAttribute("aria-required") === "true") {
 				ev.stopImmediatePropagation();
 			} else {
-				this.ariaChecked = "false";
+				this.setAttribute("aria-checked", "false");
 				if (isRadio) {
 					/** @type {(e: Element) => boolean} */
 					const filter = (e) => e.role === "radiogroup" || !ElementCheckVisibility(e);
@@ -916,8 +916,8 @@ var ElementButton = {
 						first.value.setAttribute("tabindex", "0");
 					}
 				}
-				if (this.ariaExpanded === "true") {
-					this.ariaExpanded = "false";
+				if (this.getAttribute("aria-expanded") === "true") {
+					this.setAttribute("aria-expanded", "false");
 				}
 			}
 		} else {
@@ -931,22 +931,22 @@ var ElementButton = {
 			}
 
 			if (prev.value) {
-				prev.value.ariaChecked = "false";
-				if (prev.value.ariaExpanded === "true") {
-					prev.value.ariaExpanded = "false";
+				prev.value.setAttribute("aria-checked", "false");
+				if (prev.value.getAttribute("aria-expanded") === "true") {
+					prev.value.setAttribute("aria-expanded", "false");
 				}
 				if (isRadio) {
 					prev.value.setAttribute("tabindex", "-1");
 				}
 			}
 
-			if (this.ariaExpanded === "false") {
-				this.ariaExpanded = "true";
+			if (this.getAttribute("aria-expanded") === "false") {
+				this.setAttribute("aria-expanded", "true");
 			}
 			if (isRadio) {
 				this.tabIndex = 0;
 			}
-			this.ariaChecked = "true";
+			this.setAttribute("aria-checked", "true");
 		}
 	},
 
@@ -996,16 +996,16 @@ var ElementButton = {
 	 * @type {(this: HTMLButtonElement, ev: Event) => void}
 	 */
 	_ClickCheckbox: function _ClickCheckbox(ev) {
-		if (this.ariaChecked === "true") {
-			if (this.ariaExpanded === "true") {
-				this.ariaExpanded = "false";
+		if (this.getAttribute("aria-checked") === "true") {
+			if (this.getAttribute("aria-expanded") === "true") {
+				this.setAttribute("aria-expanded", "false");
 			}
-			this.ariaChecked = "false";
+			this.setAttribute("aria-checked", "false");
 		} else {
-			if (this.ariaExpanded === "false") {
-				this.ariaExpanded = "true";
+			if (this.getAttribute("aria-expanded") === "false") {
+				this.setAttribute("aria-expanded", "true");
 			}
-			this.ariaChecked = "true";
+			this.setAttribute("aria-checked", "true");
 		}
 	},
 
@@ -1216,18 +1216,23 @@ var ElementButton = {
 			case "radio":
 			case "menuitemradio":
 				elem.addEventListener("click", this._ClickRadio);
-				elem.ariaChecked ??= "false";
+				if (!elem.getAttribute("aria-checked")) {
+					elem.setAttribute("aria-checked", "false");
+				}
+
 				if (role === "radio") {
 					elem.addEventListener("keydown", this._KeyDownRadio);
 					if (elem.getAttribute("tabindex") == null) {
-						elem.tabIndex = elem.ariaChecked === "true" ? 0 : -1;
+						elem.tabIndex = elem.getAttribute("aria-checked") === "true" ? 0 : -1;
 					}
 				}
 				break;
 			case "checkbox":
 			case "menuitemcheckbox":
 				elem.addEventListener("click", this._ClickCheckbox);
-				elem.ariaChecked ||= "false";
+				if (!elem.getAttribute("aria-checked")) {
+					elem.setAttribute("aria-checked", "false");
+				}
 				break;
 		}
 
@@ -1351,7 +1356,7 @@ var ElementMenu = {
 			}
 			case "ArrowUp":
 			case "ArrowDown": {
-				if (this.ariaHasPopup !== "true" && this.ariaHasPopup !== "menu") {
+				if (this.getAttribute("aria-haspopup") !== "true" && this.getAttribute("aria-haspopup") !== "menu") {
 					return;
 				}
 
@@ -1436,7 +1441,7 @@ var ElementMenu = {
 			// Ensure that disabled buttons use `aria-disabled` in order to keep them focusable
 			if (menuitem instanceof HTMLButtonElement && menuitem.disabled) {
 				menuitem.disabled = false;
-				menuitem.ariaDisabled = "true";
+				menuitem.setAttribute("aria-disabled", "true");
 			}
 		});
 		return elem;
diff --git a/BondageClub/Scripts/Layering.js b/BondageClub/Scripts/Layering.js
index 428a3a0f86..43c04e6746 100644
--- a/BondageClub/Scripts/Layering.js
+++ b/BondageClub/Scripts/Layering.js
@@ -282,7 +282,7 @@ var Layering = {
 	 */
 	_ShowLayersClickListener(ev) {
 		const elements = Array.from(document.querySelectorAll("[data-layer-priority]"));
-		if (this.ariaChecked === "true") {
+		if (this.getAttribute("aria-checked") === "true") {
 			const typeRecord = Layering.Item.Property?.TypeRecord;
 			const layers = elements.map(e => {
 				const asset = Layering.Asset;
-- 
GitLab