Tags: Mobile edit Mobile web edit Advanced mobile edit |
Tags: Mobile edit Mobile web edit Advanced mobile edit |
(15 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 toggle = document.createElement("button"); |
| | toggle.id = "delta-toggle"; |
| | Object.assign(toggle.style, { |
| | position: "fixed", |
| | bottom: "20px", |
| | right: "20px", |
| | padding: "0", |
| | background: "#2b2b2b", |
| | 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"); |
| function saveSettings() { | | icon.src = "https://files.catbox.moe/uodscw.png"; |
| localStorage.setItem("mahitoMenuSettings", JSON.stringify(settings)); | | icon.alt = "Delta"; |
| }
| | Object.assign(icon.style, { |
| | width: "48px", |
| | height: "48px", |
| | borderRadius: "12px", |
| | 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", |
| | marginBottom: "10px", |
| | userSelect: "text", |
| | cursor: "default", |
| | }); |
|
| |
|
| const rightIcon = document.createElement("img"); | | const textarea = document.createElement("textarea"); |
| rightIcon.src = settings.iconURL; | | textarea.placeholder = "Enter JavaScript..."; |
| rightIcon.width = settings.iconSize; | | Object.assign(textarea.style, { |
| rightIcon.height = settings.iconSize; | | width: "100%", |
| | height: "120px", |
| | background: "#1e1e1e", |
| | color: "#fff", |
| | border: "none", |
| | borderRadius: "6px", |
| | padding: "10px", |
| | resize: "none", |
| | boxSizing: "border-box", |
| | cursor: "auto", |
| | userSelect: "text", |
| | }); |
|
| |
|
| titleWrap.appendChild(leftIcon);
| | const runBtn = document.createElement("button"); |
| titleWrap.appendChild(title);
| | runBtn.textContent = "Run Code"; |
| titleWrap.appendChild(rightIcon);
| | Object.assign(runBtn.style, { |
| | | marginTop: "10px", |
| const minimizeBtn = document.createElement("button"); | | width: "100%", |
| minimizeBtn.textContent = "–"; | | padding: "10px", |
| Object.assign(minimizeBtn.style, { | | background: "#4caf50", |
| background: settings.buttonColor, | | color: "#fff", |
| border: "none", | | border: "none", |
| color: settings.textColor, | | borderRadius: "6px", |
| cursor: "pointer", | | cursor: "pointer", |
| borderRadius: "5px",
| |
| width: "25px",
| |
| height: "25px"
| |
| }); | | }); |
|
| |
|
| header.appendChild(titleWrap); | | runBtn.onclick = () => { |
| header.appendChild(minimizeBtn);
| | try { |
| | eval(textarea.value); |
| | } catch (e) { |
| | alert("Error: " + e.message); |
| | } |
| | }; |
|
| |
|
| const minimizedIcon = document.createElement("img"); | | function makeDraggable(element, excludeElements = [], onClick) { |
| minimizedIcon.src = settings.iconURL;
| | let isDragging = false; |
| Object.assign(minimizedIcon.style, {
| | let dragStartX = 0; |
| position: "fixed", | | let dragStartY = 0; |
| top: "20px", | | let elemStartLeft = 0; |
| right: "20px", | | let elemStartTop = 0; |
| zIndex: "99999", | | let moved = false; |
| display: "none",
| | |
| cursor: "pointer",
| | function onDragStart(x, y, target) { |
| borderRadius: "6px",
| | if (excludeElements.includes(target)) return false; |
| width: settings.minimizedSize + "px",
| | isDragging = true; |
| height: settings.minimizedSize + "px"
| | moved = false; |
| });
| | dragStartX = x; |
| | dragStartY = y; |
| | const rect = element.getBoundingClientRect(); |
| | elemStartLeft = rect.left; |
| | elemStartTop = rect.top; |
| | return true; |
| | } |
|
| |
|
| minimizedIcon.addEventListener("click", () => {
| | function onDragMove(x, y) { |
| minimizedIcon.style.display = "none";
| | if (!isDragging) return; |
| menu.style.display = "block";
| | const dx = x - dragStartX; |
| });
| | const dy = y - dragStartY; |
| | if (Math.abs(dx) > 3 || Math.abs(dy) > 3) moved = true; |
|
| |
|
| minimizeBtn.addEventListener("click", () => {
| | let newLeft = elemStartLeft + dx; |
| menu.style.display = "none";
| | let newTop = elemStartTop + dy; |
| minimizedIcon.style.display = "block";
| | [newLeft, newTop] = constrainPosition( |
| });
| | newLeft, |
| | newTop, |
| | element.offsetWidth, |
| | element.offsetHeight |
| | ); |
| | element.style.left = newLeft + "px"; |
| | element.style.top = newTop + "px"; |
| | element.style.bottom = "auto"; |
| | element.style.right = "auto"; |
| | } |
|
| |
|
| makeDraggable(minimizedIcon);
| | function onDragEnd() { |
| | if (!isDragging) return; |
| | isDragging = false; |
| | if (!moved && typeof onClick === "function") { |
| | onClick(); |
| | } |
| | } |
|
| |
|
| function makeButton(text, action) {
| | element.addEventListener("mousedown", (e) => { |
| const btn = document.createElement("button"); | | if (!onDragStart(e.clientX, e.clientY, e.target)) return; |
| btn.textContent = text;
| | e.preventDefault(); |
| btn.onclick = action;
| |
| Object.assign(btn.style, {
| |
| marginBottom: "6px",
| |
| width: "100%",
| |
| cursor: "pointer",
| |
| background: settings.buttonColor,
| |
| color: settings.textColor, | |
| border: "none",
| |
| padding: "5px 10px",
| |
| borderRadius: "5px"
| |
| }); | | }); |
| return btn; | | document.addEventListener("mousemove", (e) => onDragMove(e.clientX, e.clientY)); |
| }
| | document.addEventListener("mouseup", onDragEnd); |
|
| |
|
| const btnUndo = makeButton("Mass undo", () => {
| | element.addEventListener("touchstart", (e) => { |
| navigator.clipboard.writeText( | | if (!e.touches || !e.touches[0]) return; |
| "mw.loader.load('//en.wikipedia.org/w/index.php?title=User:Alexis_Jazz/Kill-It-With-Fire.js&action=raw&ctype=text/javascript');" | | if (!onDragStart(e.touches[0].clientX, e.touches[0].clientY, e.target)) return; |
| | e.preventDefault(); |
| | }); |
| | document.addEventListener( |
| | "touchmove", |
| | (e) => { |
| | if (!e.touches || !e.touches[0]) return; |
| | onDragMove(e.touches[0].clientX, e.touches[0].clientY); |
| | }, |
| | { passive: false } |
| ); | | ); |
| alert("Go to your common.js and paste what was just copied!"); | | document.addEventListener("touchend", onDragEnd); |
| }); | | document.addEventListener("touchcancel", onDragEnd); |
| | } |
|
| |
|
| const btnExplain = makeButton("Open Explanation", () => { | | function toggleMenu() { |
| alert("This would explain how Mahito works. You can hook this later."); | | menu.style.display = menu.style.display === "none" ? "block" : "none"; |
| });
| | } |
| | |
| const btnEncouragement = makeButton("Encouragement", () => {
| |
| 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();
| |
| });
| |
| | |
| 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;
| | makeDraggable(toggle, [], toggleMenu); |
| if (newIcon) settings.iconURL = newIcon;
| | makeDraggable(menu, [textarea, runBtn]); |
| if (newBg) settings.backgroundColor = newBg;
| |
| if (newBtn) settings.buttonColor = newBtn;
| |
| if (newTxt) settings.textColor = newTxt;
| |
| if (newBorder) settings.borderColor = newBorder;
| |
|
| |
|
| saveSettings();
| | menu.appendChild(title); |
| alert("Changes saved! Refresh to apply.");
| | menu.appendChild(textarea); |
| });
| | menu.appendChild(runBtn); |
| | | document.body.appendChild(toggle); |
| 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();
| |
| });
| |
| | |
| const ytContainer = document.createElement("div");
| |
| 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);
| |
| | |
| // Add buttons to menu
| |
| menu.appendChild(header); | |
| menu.appendChild(btnUndo); | |
| menu.appendChild(btnExplain); | |
| menu.appendChild(btnEncouragement); | |
| menu.appendChild(btnYujify);
| |
| menu.appendChild(btnCustomize);
| |
| menu.appendChild(btnReset);
| |
| | |
| // Add everything to page
| |
| document.body.appendChild(menu); | | document.body.appendChild(menu); |
| document.body.appendChild(minimizedIcon);
| |
| document.body.appendChild(ytContainer);
| |
|
| |
| // 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"
| |
| });
| |
| document.body.appendChild(watermark);
| |
| })(); | | })(); |