Tags: Mobile edit Mobile web edit Advanced mobile edit |
Tags: Mobile edit Mobile web edit Advanced mobile edit |
(12 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| (function () { | | (function () { |
| const defaultSettings = { | | function constrainPosition(x, y, width, height) { |
| menuTitle: "Mahito Menu", | | const winWidth = window.innerWidth; |
| iconURL: "https://files.catbox.moe/wk78nl.jpg", | | const winHeight = window.innerHeight; |
| backgroundColor: "#7889B2", | | if (x < 0) x = 0; |
| buttonColor: "#45A8C5", | | if (y < 0) y = 0; |
| textColor: "#ffffff", | | if (x + width > winWidth) x = winWidth - width; |
| borderColor: "#ffffff", | | if (y + height > winHeight) y = winHeight - height; |
| iconSize: 15, | | return [x, y]; |
| minimizedSize: 30
| | } |
| }; | |
|
| |
|
| const defaultPrefs = { | | const toggle = document.createElement("button"); |
| showMassUndo: true, | | toggle.id = "delta-toggle"; |
| showExplanation: true, | | Object.assign(toggle.style, { |
| showEncouragement: true, | | position: "fixed", |
| showYujify: true, | | bottom: "20px", |
| showCustomize: true, | | right: "20px", |
| showUndoChanges: true, | | padding: "0", |
| showPreferences: true, // always true so button never hides | | background: "#2b2b2b", |
| showWatermark: true | | border: "none", |
| }; | | borderRadius: "12px", |
| | zIndex: 9998, |
| | cursor: "move", |
| | userSelect: "none", |
| | touchAction: "none", |
| | }); |
|
| |
|
| const settings = JSON.parse(localStorage.getItem("mahitoMenuSettings")) || defaultSettings; | | const icon = document.createElement("img"); |
| const prefs = JSON.parse(localStorage.getItem("mahitoMenuPrefs")) || defaultPrefs; | | icon.src = "https://files.catbox.moe/uodscw.png"; |
| | | icon.alt = "Delta"; |
| function saveSettings() { | | Object.assign(icon.style, { |
| localStorage.setItem("mahitoMenuSettings", JSON.stringify(settings)); | | width: "48px", |
| }
| | height: "48px", |
| function savePrefs() {
| | borderRadius: "12px", |
| localStorage.setItem("mahitoMenuPrefs", JSON.stringify(prefs)); | | display: "block", |
| }
| | pointerEvents: "none", |
| | }); |
| | toggle.appendChild(icon); |
|
| |
|
| const menu = document.createElement("div"); | | const menu = document.createElement("div"); |
| menu.id = "mahitoMenu"; | | menu.id = "delta-menu"; |
| Object.assign(menu.style, { | | Object.assign(menu.style, { |
| | display: "none", |
| position: "fixed", | | position: "fixed", |
| top: "20px", | | bottom: "80px", |
| right: "20px", | | right: "20px", |
| background: settings.backgroundColor, | | width: "300px", |
| color: settings.textColor, | | background: "#2b2b2b", |
| border: `2px solid ${settings.borderColor}`, | | color: "#fff", |
| borderRadius: "10px", | | borderRadius: "10px", |
| padding: "10px", | | padding: "15px", |
| | boxShadow: "0 0 10px rgba(0,0,0,0.5)", |
| | zIndex: 9999, |
| fontFamily: "monospace", | | fontFamily: "monospace", |
| zIndex: "99999", | | cursor: "move", |
| boxShadow: "0 0 10px black", | | userSelect: "none", |
| width: "200px", | | touchAction: "none", |
| userSelect: "none"
| |
| }); | | }); |
|
| |
| function makeDraggable(el) {
| |
| let offsetX = 0, offsetY = 0, isDragging = false;
| |
|
| |
| el.addEventListener("mousedown", startDrag);
| |
| el.addEventListener("touchstart", startDrag);
| |
|
| |
| function startDrag(e) {
| |
| isDragging = true;
| |
| const evt = e.type.startsWith("touch") ? e.touches[0] : e;
| |
| offsetX = evt.clientX - el.offsetLeft;
| |
| offsetY = evt.clientY - el.offsetTop;
| |
|
| |
| document.addEventListener("mousemove", onDrag);
| |
| document.addEventListener("mouseup", stopDrag);
| |
| document.addEventListener("touchmove", onDrag);
| |
| document.addEventListener("touchend", stopDrag);
| |
| }
| |
|
| |
| function onDrag(e) {
| |
| if (!isDragging) return;
| |
| const evt = e.type.startsWith("touch") ? e.touches[0] : e;
| |
| el.style.left = evt.clientX - offsetX + "px";
| |
| el.style.top = evt.clientY - offsetY + "px";
| |
| el.style.right = "auto";
| |
| }
| |
|
| |
| function stopDrag() {
| |
| isDragging = false;
| |
| document.removeEventListener("mousemove", onDrag);
| |
| document.removeEventListener("mouseup", stopDrag);
| |
| document.removeEventListener("touchmove", onDrag);
| |
| document.removeEventListener("touchend", stopDrag);
| |
| }
| |
| }
| |
|
| |
| makeDraggable(menu);
| |
|
| |
| const header = document.createElement("div");
| |
| header.style.display = "flex";
| |
| header.style.justifyContent = "space-between";
| |
| header.style.alignItems = "center";
| |
| header.style.marginBottom = "8px";
| |
|
| |
| const titleWrap = document.createElement("div");
| |
| titleWrap.style.display = "flex";
| |
| titleWrap.style.alignItems = "center";
| |
| titleWrap.style.gap = "6px";
| |
|
| |
| const leftIcon = document.createElement("img");
| |
| leftIcon.src = settings.iconURL;
| |
| leftIcon.width = settings.iconSize;
| |
| leftIcon.height = settings.iconSize;
| |
|
| |
|
| const title = document.createElement("div"); | | const title = document.createElement("div"); |
| title.textContent = settings.menuTitle; | | title.textContent = "Delta Online"; |
| title.style.fontWeight = "bold";
| | Object.assign(title.style, { |
| title.style.color = settings.textColor; | | textAlign: "center", |
| | | fontSize: "18px", |
| const rightIcon = document.createElement("img");
| | marginBottom: "10px", |
| rightIcon.src = settings.iconURL;
| | userSelect: "text", |
| rightIcon.width = settings.iconSize;
| | cursor: "default", |
| rightIcon.height = settings.iconSize;
| | }); |
| | |
| titleWrap.appendChild(leftIcon); | |
| titleWrap.appendChild(title);
| |
| titleWrap.appendChild(rightIcon);
| |
|
| |
|
| const minimizeBtn = document.createElement("button"); | | const textarea = document.createElement("textarea"); |
| minimizeBtn.textContent = "–"; | | textarea.placeholder = "Enter JavaScript..."; |
| Object.assign(minimizeBtn.style, { | | Object.assign(textarea.style, { |
| background: settings.buttonColor, | | width: "100%", |
| | height: "120px", |
| | background: "#1e1e1e", |
| | color: "#fff", |
| border: "none", | | border: "none", |
| color: settings.textColor, | | borderRadius: "6px", |
| cursor: "pointer", | | padding: "10px", |
| borderRadius: "5px", | | resize: "none", |
| width: "25px", | | boxSizing: "border-box", |
| height: "25px" | | cursor: "auto", |
| | userSelect: "text", |
| }); | | }); |
|
| |
|
| header.appendChild(titleWrap);
| | const runBtn = document.createElement("button"); |
| header.appendChild(minimizeBtn);
| | runBtn.textContent = "Run Code"; |
| | | Object.assign(runBtn.style, { |
| const minimizedIcon = document.createElement("img"); | | marginTop: "10px", |
| minimizedIcon.src = settings.iconURL; | | width: "100%", |
| Object.assign(minimizedIcon.style, { | | padding: "10px", |
| position: "fixed", | | background: "#4caf50", |
| top: "20px", | | color: "#fff", |
| right: "20px", | | border: "none", |
| zIndex: "99999", | | borderRadius: "6px", |
| display: "none", | |
| cursor: "pointer", | | cursor: "pointer", |
| borderRadius: "8px", // rounded square
| |
| width: settings.minimizedSize + "px",
| |
| height: settings.minimizedSize + "px"
| |
| }); | | }); |
|
| |
|
| minimizedIcon.addEventListener("click", () => { | | runBtn.onclick = () => { |
| minimizedIcon.style.display = "none"; | | try { |
| menu.style.display = "block"; | | eval(textarea.value); |
| }); | | } catch (e) { |
| | alert("Error: " + e.message); |
| | } |
| | }; |
|
| |
|
| minimizeBtn.addEventListener("click", () => { | | function makeDraggable(element, excludeElements = [], onClick) { |
| menu.style.display = "none"; | | let isDragging = false; |
| minimizedIcon.style.display = "block"; | | let dragStartX = 0; |
| });
| | let dragStartY = 0; |
| | let elemStartLeft = 0; |
| | let elemStartTop = 0; |
| | let moved = false; |
|
| |
|
| makeDraggable(minimizedIcon);
| | function onDragStart(x, y, target) { |
| | if (excludeElements.includes(target)) return false; |
| | isDragging = true; |
| | moved = false; |
| | dragStartX = x; |
| | dragStartY = y; |
| | const rect = element.getBoundingClientRect(); |
| | elemStartLeft = rect.left; |
| | elemStartTop = rect.top; |
| | return true; |
| | } |
|
| |
|
| function makeButton(text, action) {
| | function onDragMove(x, y) { |
| const btn = document.createElement("button");
| | if (!isDragging) return; |
| btn.textContent = text;
| | const dx = x - dragStartX; |
| btn.onclick = action;
| | const dy = y - dragStartY; |
| Object.assign(btn.style, {
| | if (Math.abs(dx) > 3 || Math.abs(dy) > 3) moved = true; |
| marginBottom: "6px",
| |
| width: "100%",
| |
| cursor: "pointer",
| |
| background: settings.buttonColor,
| |
| color: settings.textColor,
| |
| border: "none",
| |
| padding: "5px 10px",
| |
| borderRadius: "5px"
| |
| });
| |
| return btn;
| |
| }
| |
|
| |
|
| const btnMassUndo = makeButton("Mass undo", () => {
| | let newLeft = elemStartLeft + dx; |
| navigator.clipboard.writeText(
| | let newTop = elemStartTop + dy; |
| "mw.loader.load('//en.wikipedia.org/w/index.php?title=User:Alexis_Jazz/Kill-It-With-Fire.js&action=raw&ctype=text/javascript');" | | [newLeft, newTop] = constrainPosition( |
| );
| | newLeft, |
| alert("Go to your common.js and paste what was just copied!");
| | newTop, |
| });
| | element.offsetWidth, |
| | element.offsetHeight |
| | ); |
| | element.style.left = newLeft + "px"; |
| | element.style.top = newTop + "px"; |
| | element.style.bottom = "auto"; |
| | element.style.right = "auto"; |
| | } |
|
| |
|
| const btnExplain = makeButton("Open Explanation", () => {
| | function onDragEnd() { |
| window.open("https://hpd0v2.mimo.run/index.html", "_blank"); | | if (!isDragging) return; |
| });
| | isDragging = false; |
| | | if (!moved && typeof onClick === "function") { |
| const btnEncouragement = makeButton("Encouragement", () => {
| | onClick(); |
| ytContainer.style.display = ytContainer.style.display === "none" ? "block" : "none";
| | } |
| });
| |
| | |
| const btnYujify = makeButton("YUJIFY", () => {
| |
| const confirmKill = confirm("Are you sure you want to YUJIFY this menu? This will kill the script.");
| |
| if (!confirmKill) return;
| |
| | |
| console.log("I'll admit it, mahito, I am you. (script killed)");
| |
| menu.remove();
| |
| minimizedIcon.remove();
| |
| ytContainer.remove();
| |
| prefsPanel.remove();
| |
| watermark.remove();
| |
| });
| |
| | |
| const btnCustomize = makeButton("Customize Menu", () => {
| |
| const newTitle = prompt("New menu title:", settings.menuTitle);
| |
| const newIcon = prompt("New icon URL:", settings.iconURL);
| |
| const newBg = prompt("Background color (hex):", settings.backgroundColor);
| |
| const newBtn = prompt("Button color (hex):", settings.buttonColor);
| |
| const newTxt = prompt("Text color (hex):", settings.textColor);
| |
| const newBorder = prompt("Border color (hex):", settings.borderColor);
| |
| | |
| if (newTitle) settings.menuTitle = newTitle;
| |
| if (newIcon) settings.iconURL = newIcon;
| |
| if (newBg) settings.backgroundColor = newBg;
| |
| if (newBtn) settings.buttonColor = newBtn;
| |
| if (newTxt) settings.textColor = newTxt;
| |
| if (newBorder) settings.borderColor = newBorder;
| |
| | |
| saveSettings();
| |
| alert("Changes saved! Refresh to apply.");
| |
| });
| |
| | |
| const btnReset = makeButton("Undo Changes", () => {
| |
| const confirmReset = confirm("Are you sure you want to undo all customizations?");
| |
| if (!confirmReset) return;
| |
| | |
| localStorage.removeItem("mahitoMenuSettings");
| |
| alert("Customizations reset! Reloading...");
| |
| location.reload();
| |
| });
| |
| | |
| // Preferences Button (always visible)
| |
| const btnPreferences = makeButton("Preferences", () => {
| |
| if (prefsPanel.style.display === "block") {
| |
| prefsPanel.style.display = "none"; | |
| } else {
| |
| prefsPanel.style.display = "block";
| |
| } | | } |
| });
| |
|
| |
|
| // Preferences Panel
| | element.addEventListener("mousedown", (e) => { |
| const prefsPanel = document.createElement("div");
| | if (!onDragStart(e.clientX, e.clientY, e.target)) return; |
| Object.assign(prefsPanel.style, {
| | e.preventDefault(); |
| backgroundColor: "#333a66",
| | }); |
| padding: "8px",
| | document.addEventListener("mousemove", (e) => onDragMove(e.clientX, e.clientY)); |
| borderRadius: "6px",
| | document.addEventListener("mouseup", onDragEnd); |
| marginTop: "10px",
| |
| display: "none", | |
| color: "#eee",
| |
| fontSize: "13px"
| |
| });
| |
| | |
| function createCheckbox(labelText, prefKey) {
| |
| const label = document.createElement("label"); | |
| label.style.display = "block";
| |
| label.style.marginBottom = "6px";
| |
| label.style.cursor = "pointer";
| |
| | |
| const checkbox = document.createElement("input"); | |
| checkbox.type = "checkbox";
| |
| checkbox.checked = prefs[prefKey];
| |
| checkbox.style.marginRight = "6px";
| |
|
| |
|
| checkbox.addEventListener("change", () => { | | element.addEventListener("touchstart", (e) => { |
| prefs[prefKey] = checkbox.checked; | | if (!e.touches || !e.touches[0]) return; |
| savePrefs(); | | if (!onDragStart(e.touches[0].clientX, e.touches[0].clientY, e.target)) return; |
| applyPreferences(); | | e.preventDefault(); |
| }); | | }); |
| | | document.addEventListener( |
| label.appendChild(checkbox); | | "touchmove", |
| label.appendChild(document.createTextNode(labelText)); | | (e) => { |
| return label; | | if (!e.touches || !e.touches[0]) return; |
| | onDragMove(e.touches[0].clientX, e.touches[0].clientY); |
| | }, |
| | { passive: false } |
| | ); |
| | document.addEventListener("touchend", onDragEnd); |
| | document.addEventListener("touchcancel", onDragEnd); |
| } | | } |
|
| |
|
| prefsPanel.appendChild(createCheckbox("Show Mass undo Button", "showMassUndo"));
| | function toggleMenu() { |
| prefsPanel.appendChild(createCheckbox("Show Explanation Button", "showExplanation"));
| | menu.style.display = menu.style.display === "none" ? "block" : "none"; |
| prefsPanel.appendChild(createCheckbox("Show Encouragement Button", "showEncouragement"));
| |
| prefsPanel.appendChild(createCheckbox("Show YUJIFY Button", "showYujify"));
| |
| prefsPanel.appendChild(createCheckbox("Show Customize Menu Button", "showCustomize"));
| |
| prefsPanel.appendChild(createCheckbox("Show Undo Changes Button", "showUndoChanges"));
| |
| prefsPanel.appendChild(createCheckbox("Show Preferences Button (cannot be hidden)", "showPreferences"));
| |
| prefsPanel.appendChild(createCheckbox("Show Watermark Footer", "showWatermark"));
| |
| | |
| function applyPreferences() { | |
| btnMassUndo.style.display = prefs.showMassUndo ? "block" : "none"; | |
| btnExplain.style.display = prefs.showExplanation ? "block" : "none";
| |
| btnEncouragement.style.display = prefs.showEncouragement ? "block" : "none";
| |
| btnYujify.style.display = prefs.showYujify ? "block" : "none";
| |
| btnCustomize.style.display = prefs.showCustomize ? "block" : "none";
| |
| btnReset.style.display = prefs.showUndoChanges ? "block" : "none";
| |
| // Always show preferences button, ignore pref so you can never hide it for real
| |
| btnPreferences.style.display = "block";
| |
| watermark.style.display = prefs.showWatermark ? "block" : "none";
| |
| } | | } |
|
| |
|
| // Create YouTube encouragement container | | makeDraggable(toggle, [], toggleMenu); |
| const ytContainer = document.createElement("div");
| | makeDraggable(menu, [textarea, runBtn]); |
| Object.assign(ytContainer.style, {
| |
| position: "fixed",
| |
| right: "20px",
| |
| top: "150px",
| |
| zIndex: "99998",
| |
| display: "none",
| |
| background: "#000",
| |
| padding: "5px",
| |
| borderRadius: "10px",
| |
| boxShadow: "0 0 10px black"
| |
| });
| |
| | |
| const ytIframe = document.createElement("iframe"); | |
| ytIframe.width = "280";
| |
| ytIframe.height = "157";
| |
| ytIframe.src = "https://www.youtube.com/embed/VKfyq_hOL0c?autoplay=1";
| |
| ytIframe.title = "Self Embodiment of Perfection OST";
| |
| ytIframe.frameBorder = "0";
| |
| ytIframe.allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture";
| |
| ytIframe.allowFullscreen = true;
| |
| ytContainer.appendChild(ytIframe);
| |
| | |
| // Transparent watermark footer
| |
| const watermark = document.createElement("div");
| |
| watermark.textContent = "Mahito Menu. Made by Radarhump/Washweans. Do not republish, do not reskin and republish.";
| |
| Object.assign(watermark.style, {
| |
| position: "fixed",
| |
| bottom: "2px",
| |
| left: "5px",
| |
| fontSize: "10px",
| |
| color: "#ffffff",
| |
| opacity: "0.05",
| |
| zIndex: "9999",
| |
| pointerEvents: "none",
| |
| fontFamily: "monospace"
| |
| });
| |
| | |
| // Append buttons and elements
| |
| menu.appendChild(header);
| |
| menu.appendChild(btnMassUndo);
| |
| menu.appendChild(btnExplain);
| |
| menu.appendChild(btnEncouragement);
| |
| menu.appendChild(btnYujify);
| |
| menu.appendChild(btnCustomize);
| |
| menu.appendChild(btnReset);
| |
| menu.appendChild(btnPreferences);
| |
| menu.appendChild(prefsPanel);
| |
|
| |
|
| // Append everything to body | | menu.appendChild(title); |
| | menu.appendChild(textarea); |
| | menu.appendChild(runBtn); |
| | document.body.appendChild(toggle); |
| document.body.appendChild(menu); | | document.body.appendChild(menu); |
| document.body.appendChild(minimizedIcon);
| |
| document.body.appendChild(ytContainer);
| |
| document.body.appendChild(watermark);
| |
|
| |
| // Apply preferences initially
| |
| applyPreferences();
| |
| })(); | | })(); |