Restore tabs with spaces

This commit is contained in:
Ethan O'Brien 2026-01-17 12:40:06 -06:00
parent 47d02438f0
commit 4955877370

View File

@ -6371,323 +6371,323 @@ class EmulatorJS {
}
createCheatsMenu() {
const body = this.createPopup("Cheats", {
"Add Cheat": () => {
const popups = this.createSubPopup();
this.cheatMenu.appendChild(popups[0]);
popups[1].classList.add("ejs_cheat_parent");
popups[1].style.width = "100%";
const popup = popups[1];
const header = this.createElement("div");
header.classList.add("ejs_cheat_header");
const title = this.createElement("h2");
title.innerText = this.localization("Add Cheat Code");
title.classList.add("ejs_cheat_heading");
const close = this.createElement("button");
close.classList.add("ejs_cheat_close");
header.appendChild(title);
header.appendChild(close);
popup.appendChild(header);
this.addEventListener(close, "click", (e) => {
popups[0].remove();
});
"Add Cheat": () => {
const popups = this.createSubPopup();
this.cheatMenu.appendChild(popups[0]);
popups[1].classList.add("ejs_cheat_parent");
popups[1].style.width = "100%";
const popup = popups[1];
const header = this.createElement("div");
header.classList.add("ejs_cheat_header");
const title = this.createElement("h2");
title.innerText = this.localization("Add Cheat Code");
title.classList.add("ejs_cheat_heading");
const close = this.createElement("button");
close.classList.add("ejs_cheat_close");
header.appendChild(title);
header.appendChild(close);
popup.appendChild(header);
this.addEventListener(close, "click", (e) => {
popups[0].remove();
});
let cheatDB = {};
const systemKey = this.getCore(true);
const cleanRomTags = (name) => {
return name
.replace(/\([^)]+\)/g, "")
.replace(/\[[^\]]+\]/g, "")
.trim();
};
let cheatDB = {};
const systemKey = this.getCore(true);
const cleanRomTags = (name) => {
return name
.replace(/\([^)]+\)/g, "")
.replace(/\[[^\]]+\]/g, "")
.trim();
};
const normalizeAndConvertNumerals = (name) => {
let normalized = name.toLowerCase();
normalized = normalized.replace(/ iv/g, " 4");
normalized = normalized.replace(/ iii/g, " 3");
normalized = normalized.replace(/ ii/g, " 2");
normalized = normalized.replace(/ v/g, " 5");
normalized = normalized.replace(/ i/g, " 1");
const normalizeAndConvertNumerals = (name) => {
let normalized = name.toLowerCase();
normalized = normalized.replace(/ iv/g, " 4");
normalized = normalized.replace(/ iii/g, " 3");
normalized = normalized.replace(/ ii/g, " 2");
normalized = normalized.replace(/ v/g, " 5");
normalized = normalized.replace(/ i/g, " 1");
return normalized.replace(/[^a-z0-9]/g, "");
};
return normalized.replace(/[^a-z0-9]/g, "");
};
const createSelect = (labelText) => {
const div = this.createElement("div");
const label = this.createElement("strong");
label.innerText = this.localization(labelText);
div.appendChild(label);
div.appendChild(this.createElement("br"));
const select = this.createElement("select");
select.style.width = "100%";
select.classList.add("ejs_cheat_code");
div.appendChild(select);
return { container: div, select: select };
};
const createSelect = (labelText) => {
const div = this.createElement("div");
const label = this.createElement("strong");
label.innerText = this.localization(labelText);
div.appendChild(label);
div.appendChild(this.createElement("br"));
const select = this.createElement("select");
select.style.width = "100%";
select.classList.add("ejs_cheat_code");
div.appendChild(select);
return { container: div, select: select };
};
const importDiv = this.createElement("div");
importDiv.classList.add("ejs_cheat_main");
importDiv.style.borderBottom = "1px solid #555";
importDiv.style.paddingBottom = "10px";
importDiv.style.display = "none";
const importDiv = this.createElement("div");
importDiv.classList.add("ejs_cheat_main");
importDiv.style.borderBottom = "1px solid #555";
importDiv.style.paddingBottom = "10px";
importDiv.style.display = "none";
const importTitle = this.createElement("h3");
importTitle.innerText =
this.localization("Import from Database") +
(systemKey ? ` (${systemKey.toUpperCase()})` : "");
importTitle.style.marginTop = "0px";
importDiv.appendChild(importTitle);
const importTitle = this.createElement("h3");
importTitle.innerText =
this.localization("Import from Database") +
(systemKey ? ` (${systemKey.toUpperCase()})` : "");
importTitle.style.marginTop = "0px";
importDiv.appendChild(importTitle);
const gameSelectUI = createSelect("Game");
const cheatSelectUI = createSelect("Cheat");
const gameSelectUI = createSelect("Game");
const cheatSelectUI = createSelect("Cheat");
importDiv.appendChild(gameSelectUI.container);
importDiv.appendChild(cheatSelectUI.container);
importDiv.appendChild(gameSelectUI.container);
importDiv.appendChild(cheatSelectUI.container);
popup.appendChild(importDiv);
popup.appendChild(importDiv);
const main = this.createElement("div");
main.classList.add("ejs_cheat_main");
const header3 = this.createElement("strong");
header3.innerText = this.localization(
"Manual Entry - Code"
);
main.appendChild(header3);
main.appendChild(this.createElement("br"));
const main = this.createElement("div");
main.classList.add("ejs_cheat_main");
const header3 = this.createElement("strong");
header3.innerText = this.localization(
"Manual Entry - Code"
);
main.appendChild(header3);
main.appendChild(this.createElement("br"));
const manualCodeTextarea = this.createElement("textarea");
manualCodeTextarea.classList.add("ejs_cheat_code");
manualCodeTextarea.style.width = "100%";
manualCodeTextarea.style.height = "80px";
main.appendChild(manualCodeTextarea);
main.appendChild(this.createElement("br"));
const manualCodeTextarea = this.createElement("textarea");
manualCodeTextarea.classList.add("ejs_cheat_code");
manualCodeTextarea.style.width = "100%";
manualCodeTextarea.style.height = "80px";
main.appendChild(manualCodeTextarea);
main.appendChild(this.createElement("br"));
const header2 = this.createElement("strong");
header2.innerText = this.localization(
"Manual Entry - Description"
);
main.appendChild(header2);
main.appendChild(this.createElement("br"));
const header2 = this.createElement("strong");
header2.innerText = this.localization(
"Manual Entry - Description"
);
main.appendChild(header2);
main.appendChild(this.createElement("br"));
const manualDescriptionInput = this.createElement("input");
manualDescriptionInput.type = "text";
manualDescriptionInput.classList.add("ejs_cheat_code");
manualDescriptionInput.style.width = "100%";
main.appendChild(manualDescriptionInput);
main.appendChild(this.createElement("br"));
popup.appendChild(main);
const manualDescriptionInput = this.createElement("input");
manualDescriptionInput.type = "text";
manualDescriptionInput.classList.add("ejs_cheat_code");
manualDescriptionInput.style.width = "100%";
main.appendChild(manualDescriptionInput);
main.appendChild(this.createElement("br"));
popup.appendChild(main);
const loadCheatList = (gameName) => {
cheatSelectUI.select.innerHTML = "";
const loadCheatList = (gameName) => {
cheatSelectUI.select.innerHTML = "";
const defaultOpt = this.createElement("option");
defaultOpt.value = "";
defaultOpt.innerText =
"--- " +
this.localization("Select a Cheat") +
" ---";
cheatSelectUI.select.appendChild(defaultOpt);
const defaultOpt = this.createElement("option");
defaultOpt.value = "";
defaultOpt.innerText =
"--- " +
this.localization("Select a Cheat") +
" ---";
cheatSelectUI.select.appendChild(defaultOpt);
manualCodeTextarea.value = "";
manualDescriptionInput.value = "";
manualCodeTextarea.value = "";
manualDescriptionInput.value = "";
if (!gameName || !cheatDB[gameName]) return;
if (!gameName || !cheatDB[gameName]) return;
const cheats = cheatDB[gameName];
cheats.forEach((cheat) => {
const opt = this.createElement("option");
opt.value = cheat.desc;
opt.innerText = cheat.desc;
cheatSelectUI.select.appendChild(opt);
});
const cheats = cheatDB[gameName];
cheats.forEach((cheat) => {
const opt = this.createElement("option");
opt.value = cheat.desc;
opt.innerText = cheat.desc;
cheatSelectUI.select.appendChild(opt);
});
if (cheats.length > 0) {
cheatSelectUI.select.value = cheats[0].desc;
manualCodeTextarea.value = cheats[0].code;
manualDescriptionInput.value = cheats[0].desc;
}
};
if (cheats.length > 0) {
cheatSelectUI.select.value = cheats[0].desc;
manualCodeTextarea.value = cheats[0].code;
manualDescriptionInput.value = cheats[0].desc;
}
};
const loadCheatDatabase = async (system) => {
gameSelectUI.select.innerHTML = "";
cheatSelectUI.select.innerHTML = "";
const loadCheatDatabase = async (system) => {
gameSelectUI.select.innerHTML = "";
cheatSelectUI.select.innerHTML = "";
const defaultGameOpt = this.createElement("option");
defaultGameOpt.value = "";
defaultGameOpt.innerText =
"--- " +
this.localization("Select a Game") +
" ---";
gameSelectUI.select.appendChild(defaultGameOpt);
const defaultGameOpt = this.createElement("option");
defaultGameOpt.value = "";
defaultGameOpt.innerText =
"--- " +
this.localization("Select a Game") +
" ---";
gameSelectUI.select.appendChild(defaultGameOpt);
if (!this.config.cheatPath) {
if (this.debug)
console.error(
"Cheat file load error: EJS_cheatPath is not configured."
);
importDiv.style.display = "none";
return;
}
if (!this.config.cheatPath) {
if (this.debug)
console.error(
"Cheat file load error: EJS_cheatPath is not configured."
);
importDiv.style.display = "none";
return;
}
const url = this.config.cheatPath + system + ".json";
const url = this.config.cheatPath + system + ".json";
try {
const res = await this.downloadFile(
url,
null,
true,
{ responseType: "text", method: "GET" }
);
try {
const res = await this.downloadFile(
url,
null,
true,
{ responseType: "text", method: "GET" }
);
let data;
if (res === -1) {
throw new Error(
"Cheat JSON not found. Create a file at: " +
url
);
} else if (typeof res.data === "string") {
try {
data = JSON.parse(res.data);
} catch (e) {
throw new Error(
"Failed to parse cheat JSON: " +
e.message
);
}
} else {
data = res.data;
}
let data;
if (res === -1) {
throw new Error(
"Cheat JSON not found. Create a file at: " +
url
);
} else if (typeof res.data === "string") {
try {
data = JSON.parse(res.data);
} catch (e) {
throw new Error(
"Failed to parse cheat JSON: " +
e.message
);
}
} else {
data = res.data;
}
cheatDB = data;
importDiv.style.display = "";
cheatDB = data;
importDiv.style.display = "";
const gameNames = Object.keys(cheatDB).sort();
gameNames.forEach((name) => {
const opt = this.createElement("option");
opt.value = name;
opt.innerText = name;
gameSelectUI.select.appendChild(opt);
});
const gameNames = Object.keys(cheatDB).sort();
gameNames.forEach((name) => {
const opt = this.createElement("option");
opt.value = name;
opt.innerText = name;
gameSelectUI.select.appendChild(opt);
});
let currentFileBaseName =
this.getBaseFileName(true);
currentFileBaseName = currentFileBaseName.replace(
/\.[^/.]+$/,
""
);
const cleanedFileName =
cleanRomTags(currentFileBaseName);
const normalizedFile =
normalizeAndConvertNumerals(cleanedFileName);
let matchedGameName = null;
if (
this.config.gameName &&
gameNames.includes(this.config.gameName)
) {
matchedGameName = this.config.gameName;
}
let currentFileBaseName =
this.getBaseFileName(true);
currentFileBaseName = currentFileBaseName.replace(
/\.[^/.]+$/,
""
);
const cleanedFileName =
cleanRomTags(currentFileBaseName);
const normalizedFile =
normalizeAndConvertNumerals(cleanedFileName);
let matchedGameName = null;
if (
this.config.gameName &&
gameNames.includes(this.config.gameName)
) {
matchedGameName = this.config.gameName;
}
if (!matchedGameName) {
for (const name of gameNames) {
if (
normalizeAndConvertNumerals(name) ===
normalizedFile
) {
matchedGameName = name;
break;
}
}
}
if (!matchedGameName) {
for (const name of gameNames) {
if (
normalizeAndConvertNumerals(name) ===
normalizedFile
) {
matchedGameName = name;
break;
}
}
}
if (matchedGameName) {
gameSelectUI.select.value = matchedGameName;
}
if (matchedGameName) {
gameSelectUI.select.value = matchedGameName;
}
loadCheatList(gameSelectUI.select.value);
} catch (e) {
if (this.debug)
console.error(
"Cheat file load error:",
e.message
);
importDiv.style.display = "none";
cheatDB = {};
loadCheatList(null);
}
};
loadCheatList(gameSelectUI.select.value);
} catch (e) {
if (this.debug)
console.error(
"Cheat file load error:",
e.message
);
importDiv.style.display = "none";
cheatDB = {};
loadCheatList(null);
}
};
gameSelectUI.select.addEventListener("change", () => {
loadCheatList(gameSelectUI.select.value);
});
gameSelectUI.select.addEventListener("change", () => {
loadCheatList(gameSelectUI.select.value);
});
cheatSelectUI.select.addEventListener("change", () => {
const game = gameSelectUI.select.value;
const cheatDesc = cheatSelectUI.select.value;
cheatSelectUI.select.addEventListener("change", () => {
const game = gameSelectUI.select.value;
const cheatDesc = cheatSelectUI.select.value;
if (!game || !cheatDesc) {
manualCodeTextarea.value = "";
manualDescriptionInput.value = "";
return;
}
if (!game || !cheatDesc) {
manualCodeTextarea.value = "";
manualDescriptionInput.value = "";
return;
}
const cheat = cheatDB[game].find(
(c) => c.desc === cheatDesc
);
if (cheat) {
manualCodeTextarea.value = cheat.code;
manualDescriptionInput.value = cheat.desc;
}
});
const cheat = cheatDB[game].find(
(c) => c.desc === cheatDesc
);
if (cheat) {
manualCodeTextarea.value = cheat.code;
manualDescriptionInput.value = cheat.desc;
}
});
if (systemKey) {
loadCheatDatabase(systemKey).catch((e) => {
if (this.debug)
console.error("Initial cheat load failed:", e);
});
} else {
importDiv.style.display = "none";
}
if (systemKey) {
loadCheatDatabase(systemKey).catch((e) => {
if (this.debug)
console.error("Initial cheat load failed:", e);
});
} else {
importDiv.style.display = "none";
}
const footer = this.createElement("footer");
const submit = this.createElement("button");
const closeButton = this.createElement("button");
submit.innerText = this.localization("Submit");
closeButton.innerText = this.localization("Close");
submit.classList.add("ejs_button_button");
closeButton.classList.add("ejs_button_button");
submit.classList.add("ejs_popup_submit");
closeButton.classList.add("ejs_popup_submit");
submit.style["background-color"] =
"rgba(var(--ejs-primary-color),1)";
footer.appendChild(submit);
const span = this.createElement("span");
span.innerText = " ";
footer.appendChild(span);
footer.appendChild(closeButton);
popup.appendChild(footer);
const footer = this.createElement("footer");
const submit = this.createElement("button");
const closeButton = this.createElement("button");
submit.innerText = this.localization("Submit");
closeButton.innerText = this.localization("Close");
submit.classList.add("ejs_button_button");
closeButton.classList.add("ejs_button_button");
submit.classList.add("ejs_popup_submit");
closeButton.classList.add("ejs_popup_submit");
submit.style["background-color"] =
"rgba(var(--ejs-primary-color),1)";
footer.appendChild(submit);
const span = this.createElement("span");
span.innerText = " ";
footer.appendChild(span);
footer.appendChild(closeButton);
popup.appendChild(footer);
this.addEventListener(submit, "click", (e) => {
if (
!manualCodeTextarea.value.trim() ||
!manualDescriptionInput.value.trim()
)
return;
popups[0].remove();
this.cheats.push({
code: manualCodeTextarea.value,
desc: manualDescriptionInput.value,
checked: false,
});
this.updateCheatUI();
this.saveSettings();
});
this.addEventListener(closeButton, "click", (e) => {
popups[0].remove();
});
},
Close: () => {
this.cheatMenu.style.display = "none";
},
}, true);
this.addEventListener(submit, "click", (e) => {
if (
!manualCodeTextarea.value.trim() ||
!manualDescriptionInput.value.trim()
)
return;
popups[0].remove();
this.cheats.push({
code: manualCodeTextarea.value,
desc: manualDescriptionInput.value,
checked: false,
});
this.updateCheatUI();
this.saveSettings();
});
this.addEventListener(closeButton, "click", (e) => {
popups[0].remove();
});
},
Close: () => {
this.cheatMenu.style.display = "none";
},
}, true);
this.cheatMenu = body.parentElement;
this.cheatMenu.getElementsByTagName("h4")[0].style["padding-bottom"] = "0px";
const msg = this.createElement("div");