您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
모바일 요소 선택기
当前为
- // ==UserScript==
- // @name Mobile Element Selector
- // @author ZNJXL
- // @version 1.1.3
- // @namespace http://tampermonkey.net/
- // @description 모바일 요소 선택기
- // @description:en Mobile Element Selector (especially for cromium browsers)
- // @match *://*/*
- // @license MIT
- // @grant GM_setClipboard
- // ==/UserScript==
- (function() {
- 'use strict';
- let selecting = false;
- let selectedEl = null;
- let initialTouchedElement = null;
- let includeSiteName = true;
- let touchStartX = 0, touchStartY = 0;
- let touchMoved = false;
- const moveThreshold = 10;
- // 다국어 텍스트 정의
- const i18n = {
- ko: {
- blockerInfo: "선택된 요소:",
- blockerCopy: "복사",
- blockerToggleSite: (siteNameOn) => `사이트명: ${siteNameOn ? "ON" : "OFF"}`,
- blockerBlock: "미리보기",
- blockerCancel: "취소",
- blockerMode: "차단 모드",
- blockerSelecting: "선택 중...",
- blockerPreview: "미리보기",
- blockerRevert: "되돌리기",
- alertNoElement: "선택된 요소가 없습니다.",
- alertCopySuccess: "✅ 선택자가 복사되었습니다!",
- alertCopyFail: "❌ 클립보드 복사에 실패했습니다.",
- alertDirectCopy: "선택자를 직접 복사하세요:",
- },
- en: {
- blockerInfo: "Selected Element:",
- blockerCopy: "Copy",
- blockerToggleSite: (siteNameOn) => `Site Name: ${siteNameOn ? "ON" : "OFF"}`,
- blockerBlock: "Preview",
- blockerCancel: "Cancel",
- blockerMode: "Block Mode",
- blockerSelecting: "Selecting...",
- blockerPreview: "Preview",
- blockerRevert: "Revert",
- alertNoElement: "No element selected.",
- alertCopySuccess: "✅ Selector copied!",
- alertCopyFail: "❌ Failed to copy to clipboard.",
- alertDirectCopy: "Copy the selector manually:"
- }
- };
- // 언어 감지 및 선택 (기본값은 한국어)
- const lang = navigator.language.startsWith('ko') ? 'ko' : 'en';
- const t = i18n[lang];
- const style = document.createElement('style');
- style.textContent = `
- .mobile-block-ui { /* 스타일 내용은 동일 */ }
- #blocker-slider { /* 스타일 내용은 동일 */ }
- #blocker-slider::-webkit-slider-thumb { /* 스타일 내용은 동일 */ }
- #blocker-slider::-moz-range-thumb { /* 스타일 내용은 동일 */ }
- .selected-element { /* 스타일 내용은 동일 */ }
- #mobile-block-panel { /* 스타일 내용은 동일 */ }
- #mobile-block-toggleBtn { /* 스타일 내용은 동일 */ }
- .mb-btn { /* 스타일 내용은 동일 */ }
- #blocker-info-wrapper { /* 스타일 내용은 동일 */ }
- #blocker-info { /* 스타일 내용은 동일 */ }
- `;
- document.head.appendChild(style);
- const panel = document.createElement('div');
- panel.id = 'mobile-block-panel';
- panel.classList.add('mobile-block-ui', 'ui-ignore');
- panel.innerHTML = `
- <div id="blocker-info-wrapper">
- <span style="font-size: 12px; color: #ccc;">${t.blockerInfo}</span>
- <span id="blocker-info">없음</span>
- </div>
- <input type="range" id="blocker-slider" min="0" max="10" value="0" class="ui-ignore">
- <div class="button-grid">
- <button id="blocker-copy" class="mb-btn ui-ignore">${t.blockerCopy}</button>
- <button id="blocker-toggle-site" class="mb-btn ui-ignore">${t.blockerToggleSite(includeSiteName)}</button>
- <button id="blocker-block" class="mb-btn ui-ignore">${t.blockerBlock}</button>
- <button id="blocker-cancel" class="mb-btn ui-ignore">${t.blockerCancel}</button>
- </div>
- `;
- document.body.appendChild(panel);
- const toggleBtn = document.createElement('button');
- toggleBtn.id = 'mobile-block-toggleBtn';
- toggleBtn.classList.add('mobile-block-ui', 'ui-ignore');
- toggleBtn.textContent = t.blockerMode;
- document.body.appendChild(toggleBtn);
- function setBlockMode(enabled) {
- selecting = enabled;
- toggleBtn.textContent = enabled ? t.blockerSelecting : t.blockerMode;
- toggleBtn.classList.toggle('selecting', enabled);
- panel.style.display = enabled ? 'block' : 'none';
- if (!enabled && selectedEl) {
- selectedEl.classList.remove('selected-element');
- selectedEl = null;
- initialTouchedElement = null;
- }
- panel.querySelector('#blocker-slider').value = 0;
- updateInfo();
- }
- function updateInfo() {
- const infoSpan = panel.querySelector('#blocker-info');
- infoSpan.textContent = selectedEl ? generateSelector(selectedEl) : '없음';
- }
- function generateSelector(el) { /* generateSelector 함수는 그대로 유지 */ }
- const uiExcludeClass = '.ui-ignore';
- document.addEventListener('touchstart', e => {
- if (!selecting || e.target.closest(uiExcludeClass)) return;
- const touch = e.touches[0];
- touchStartX = touch.clientX; touchStartY = touch.clientY; touchMoved = false;
- }, { passive: true });
- document.addEventListener('touchmove', e => {
- if (!selecting || e.target.closest(uiExcludeClass) || !e.touches[0]) return;
- if (!touchMoved) {
- const touch = e.touches[0];
- const dx = touch.clientX - touchStartX, dy = touch.clientY - touchStartY;
- if (Math.sqrt(dx * dx + dy * dy) > moveThreshold) touchMoved = true;
- }
- }, { passive: true });
- document.addEventListener('touchend', e => {
- if (!selecting || e.target.closest(uiExcludeClass)) return;
- if (touchMoved) { touchMoved = false; return; }
- e.preventDefault(); e.stopImmediatePropagation();
- const touch = e.changedTouches[0];
- const targetEl = document.elementFromPoint(touch.clientX, touch.clientY);
- if (!targetEl || targetEl.closest(uiExcludeClass)) return;
- if (selectedEl) selectedEl.classList.remove('selected-element');
- selectedEl = targetEl;
- initialTouchedElement = targetEl;
- selectedEl.classList.add('selected-element');
- panel.querySelector('#blocker-slider').value = 0;
- updateInfo();
- }, { capture: true, passive: false });
- const slider = panel.querySelector('#blocker-slider');
- slider.addEventListener('input', handleSlider);
- function handleSlider(e) { /* handleSlider 함수는 그대로 유지 */ }
- panel.querySelector('#blocker-copy').addEventListener('click', () => {
- if (selectedEl) {
- const fullSelector = generateSelector(selectedEl);
- let finalSelector = "##" + fullSelector;
- if (includeSiteName) finalSelector = location.hostname + finalSelector;
- try {
- GM_setClipboard(finalSelector);
- alert(t.alertCopySuccess + '\n' + finalSelector);
- } catch (err) {
- console.error("클립보드 복사 실패:", err);
- alert(t.alertCopyFail);
- prompt(t.alertDirectCopy, finalSelector);
- }
- } else { alert(t.alertNoElement); }
- });
- panel.querySelector('#blocker-toggle-site').addEventListener('click', () => {
- includeSiteName = !includeSiteName;
- panel.querySelector('#blocker-toggle-site').textContent = t.blockerToggleSite(includeSiteName);
- });
- const blockBtn = panel.querySelector('#blocker-block');
- let isHidden = false;
- blockBtn.textContent = t.blockerPreview;
- blockBtn.addEventListener('click', () => {
- if (!selectedEl) {
- alert(t.alertNoElement);
- return;
- }
- if (!isHidden) {
- selectedEl.dataset._original_display = selectedEl.style.display || '';
- selectedEl.style.display = 'none';
- blockBtn.textContent = t.blockerRevert;
- isHidden = true;
- } else {
- selectedEl.style.display = selectedEl.dataset._original_display || '';
- blockBtn.textContent = t.blockerPreview;
- isHidden = false;
- }
- });
- panel.querySelector('#blocker-cancel').addEventListener('click', () => setBlockMode(false));
- toggleBtn.addEventListener('click', () => setBlockMode(!selecting));
- function makeDraggable(el) { /* makeDraggable 함수는 그대로 유지 */ }
- makeDraggable(panel);
- makeDraggable(toggleBtn);
- })();