// ==UserScript== // @name 아카라이브 미리보기 이미지, 모두 열기 // @namespace Violentmonkey Scripts // @version 1.04 // @icon https://www.google.com/s2/favicons?sz=64&domain=arca.live // @description Extract image URL from specific element and log it to console // @author You // @match https://arca.live/b/* // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_getValue // @grant GM_setValue // @downloadURL none // ==/UserScript== // 설정 변수 false로 비활성화 var config = { openAllButton: true, // 모두 열기 버튼 생성 thumbnail: true, // 미리보기 이미지 생성 thumbnailHover: true, // 미리보기 이미지 마우스 오버시 보이게 applyBlur: true, // 블러 효과를 적용할지 여부 blurAmount: '2px', // 블러 효과의 정도 originalThumbnail: true, // 개념글 썸네일 클릭 시 원본 이미지 불러오기 thumbnailHoverBest: true, // 개념글 미리보기 이미지 마우스 오버시 보이게 }; // 각 설정 변수에 대한 기본값 표시 var openAllButtonText = config.openAllButton ? 'Open All Button: On' : 'Open All Button: Off'; var thumbnailButtonText = config.thumbnail ? 'Thumbnail: On' : 'Thumbnail: Off'; var thumbnailHoverButtonText = config.thumbnailHover ? 'Thumbnail Hover: On' : 'Thumbnail Hover: Off'; var applyBlurButtonText = config.applyBlur ? 'Apply Blur: On' : 'Apply Blur: Off'; var originalThumbnailButtonText = config.originalThumbnail ? 'Original Thumbnail: On' : 'Original Thumbnail: Off'; var thumbnailHoverBestButtonText = config.thumbnailHoverBest ? 'Thumbnail Hover Best: On' : 'Thumbnail Hover Best: Off'; // 각 설정 변수에 대한 GM_registerMenuCommand 추가 var openAllButtonCommand = GM_registerMenuCommand(openAllButtonText, function() { config.openAllButton = !config.openAllButton; saveConfig(); recreateButtons(); refreshPage(); }); var thumbnailCommand = GM_registerMenuCommand(thumbnailButtonText, function() { config.thumbnail = !config.thumbnail; saveConfig(); recreateButtons(); refreshPage(); }); var thumbnailHoverCommand = GM_registerMenuCommand(thumbnailHoverButtonText, function() { config.thumbnailHover = !config.thumbnailHover; saveConfig(); recreateButtons(); refreshPage(); }); var applyBlurCommand = GM_registerMenuCommand(applyBlurButtonText, function() { config.applyBlur = !config.applyBlur; saveConfig(); recreateButtons(); refreshPage(); }); var setBlurAmountCommand = GM_registerMenuCommand('Set Blur Amount (' + config.blurAmount + ')', function() { var amount = prompt("Enter blur amount (e.g., '2'):", config.blurAmount.replace('px', '')); if (amount !== null) { amount = parseInt(amount); // 문자열을 정수로 변환 if (!isNaN(amount)) { config.blurAmount = amount + 'px'; // 픽셀 단위 추가 saveConfig(); recreateButtons(); refreshPage(); } else { alert("Invalid input! Please enter a valid number."); } } }); var originalThumbnailCommand = GM_registerMenuCommand(originalThumbnailButtonText, function() { config.originalThumbnail = !config.originalThumbnail; saveConfig(); recreateButtons(); refreshPage(); }); var thumbnailHoverBestCommand = GM_registerMenuCommand(thumbnailHoverBestButtonText, function() { config.thumbnailHoverBest = !config.thumbnailHoverBest; saveConfig(); recreateButtons(); refreshPage(); }); // 설정 값을 로컬 저장소에 저장 function saveConfig() { GM_setValue('openAllButton', config.openAllButton); GM_setValue('thumbnail', config.thumbnail); GM_setValue('thumbnailHover', config.thumbnailHover); GM_setValue('applyBlur', config.applyBlur); GM_setValue('blurAmount', config.blurAmount); GM_setValue('originalThumbnail', config.originalThumbnail); GM_setValue('thumbnailHoverBest', config.thumbnailHoverBest); } // 설정 값을 로컬 저장소에서 불러오기 function loadConfig() { config.openAllButton = GM_getValue('openAllButton', true); config.thumbnail = GM_getValue('thumbnail', true); config.thumbnailHover = GM_getValue('thumbnailHover', true); config.applyBlur = GM_getValue('applyBlur', true); config.blurAmount = GM_getValue('blurAmount', '2px'); config.originalThumbnail = GM_getValue('originalThumbnail', true); config.thumbnailHoverBest = GM_getValue('thumbnailHoverBest', true); } // 저장된 설정 값을 로드 loadConfig(); // 모든 버튼을 삭제하고 다시 생성하는 함수 function recreateButtons() { GM_unregisterMenuCommand(openAllButtonCommand); GM_unregisterMenuCommand(thumbnailCommand); GM_unregisterMenuCommand(thumbnailHoverCommand); GM_unregisterMenuCommand(applyBlurCommand); GM_unregisterMenuCommand(setBlurAmountCommand); GM_unregisterMenuCommand(originalThumbnailCommand); GM_unregisterMenuCommand(thumbnailHoverBestCommand); openAllButtonText = config.openAllButton ? 'Open All Button: On' : 'Open All Button: Off'; thumbnailButtonText = config.thumbnail ? 'Thumbnail: On' : 'Thumbnail: Off'; thumbnailHoverButtonText = config.thumbnailHover ? 'Thumbnail Hover: On' : 'Thumbnail Hover: Off'; applyBlurButtonText = config.applyBlur ? 'Apply Blur: On' : 'Apply Blur: Off'; originalThumbnailButtonText = config.originalThumbnail ? 'Original Thumbnail: On' : 'Original Thumbnail: Off'; thumbnailHoverBestButtonText = config.thumbnailHoverBest ? 'Thumbnail Hover Best: On' : 'Thumbnail Hover Best: Off'; openAllButtonCommand = GM_registerMenuCommand(openAllButtonText, function() { config.openAllButton = !config.openAllButton; saveConfig(); recreateButtons(); refreshPage(); }); thumbnailCommand = GM_registerMenuCommand(thumbnailButtonText, function() { config.thumbnail = !config.thumbnail; saveConfig(); recreateButtons(); refreshPage(); }); thumbnailHoverCommand = GM_registerMenuCommand(thumbnailHoverButtonText, function() { config.thumbnailHover = !config.thumbnailHover; saveConfig(); recreateButtons(); refreshPage(); }); applyBlurCommand = GM_registerMenuCommand(applyBlurButtonText, function() { config.applyBlur = !config.applyBlur; saveConfig(); recreateButtons(); refreshPage(); }); setBlurAmountCommand = GM_registerMenuCommand('Set Blur Amount (' + config.blurAmount + ')', function() { var amount = prompt("Enter blur amount (e.g., '2'):", config.blurAmount.replace('px', '')); if (amount !== null) { amount = parseInt(amount); // 문자열을 정수로 변환 if (!isNaN(amount)) { config.blurAmount = amount + 'px'; // 픽셀 단위 추가 saveConfig(); recreateButtons(); refreshPage(); } else { alert("Invalid input! Please enter a valid number."); } } }); originalThumbnailCommand = GM_registerMenuCommand(originalThumbnailButtonText, function() { config.originalThumbnail = !config.originalThumbnail; saveConfig(); recreateButtons(); refreshPage(); }); thumbnailHoverBestCommand = GM_registerMenuCommand(thumbnailHoverBestButtonText, function() { config.thumbnailHoverBest = !config.thumbnailHoverBest; saveConfig(); recreateButtons(); refreshPage(); }); } // 페이지 새로고침 함수 function refreshPage() { location.reload(); } // 모든 버튼 생성 recreateButtons(); // 모두 열기 버튼 생성 if (config.openAllButton) { var openAllButton = document.createElement('a'); openAllButton.className = 'btn btn-sm btn-primary float-left'; openAllButton.href = '#'; openAllButton.innerHTML = ' 모두 열기 '; openAllButton.addEventListener('click', function(event) { event.preventDefault(); document.querySelectorAll('a.vrow.column:not(.notice)').forEach(function(element) { var href = element.getAttribute('href'); var classes = element.className.split(' '); if (href && !classes.includes('filtered') && !classes.includes('filtered-keyword')) { window.open(href, '_blank'); } }); }); var targetElement = document.querySelector('.form-control.select-list-type'); targetElement.parentNode.insertBefore(openAllButton, targetElement); } // 페이지가 모두 로드된 후 실행 document.addEventListener('DOMContentLoaded', function() { // 미리보기 이미지 생성 if (config.thumbnail) { document.querySelectorAll('a.vrow.column:not(.notice)').forEach(function(element) { var vcolId = element.querySelector('.vrow-top .vcol.col-id'); var vcolTitle = element.querySelector('.vrow-top .vcol.col-title'); vcolId.style.width = '3rem'; var vcolThumb = document.createElement('span'); vcolThumb.className = 'vcol col-thumb'; vcolThumb.style.width = '5rem'; vcolTitle.parentNode.insertBefore(vcolThumb, vcolTitle); var vrowPreview = element.querySelector('.vrow-preview'); function createThumbnail(retryCount) { var imageElement = vrowPreview ? vrowPreview.querySelector('img') : null; if (!imageElement && retryCount < 3) { // 이미지 요소가 없는 경우이고, 재시도 횟수가 3보다 작은 경우, 1초 후에 다시 함수를 호출하여 재시도 setTimeout(function() { createThumbnail(retryCount + 1); // 재시도 횟수 증가하여 재호출 }, 100); // 0.1초 후에 다시 시도 } else if (!imageElement) { // 이미지 요소가 없는 경우이고, 재시도 횟수가 3인 경우에는 종료 console.log('Retry limit reached. Unable to find image element.'); } else { // 이미지 요소가 있는 경우에만 나머지 코드 실행 element.style.height = 'auto'; element.style.paddingTop = '3px'; element.style.paddingBottom = '3px'; var imageUrl = imageElement.getAttribute('src'); var image = document.createElement('img'); image.src = imageUrl; image.style.width = '5rem'; image.style.height = '5rem'; if (config.applyBlur) { image.style.filter = 'blur(' + config.blurAmount + ')'; // 흐림 효과 적용 // 마우스 이벤트 추가 image.addEventListener('mouseenter', function() { image.style.filter = 'none'; // 마우스가 요소 위에 있을 때 블러 효과 제거 }); image.addEventListener('mouseleave', function() { image.style.filter = 'blur(' + config.blurAmount + ')'; // 마우스가 요소를 벗어날 때 다시 블러 효과 적용 }); } vcolThumb.appendChild(image); vrowPreview.style.width = '30rem'; vrowPreview.style.height = 'auto'; vrowPreview.style.top = 'auto'; vrowPreview.style.left = '10rem'; vrowPreview.style.display = 'none'; if (config.thumbnailHover) { image.addEventListener('mouseenter', function() { imageElement.src = imageUrl.replace('&type=list', ''); vrowPreview.style.display = null; }); image.addEventListener('mouseleave', function() { vrowPreview.style.display = 'none'; }); } } } createThumbnail(0); // 함수 호출 및 재시도 횟수 초기값 설정 }); } }); // 썸네일 클릭 시 원본 이미지 불러오기 if (config.originalThumbnail) { document.querySelectorAll('a.title.preview-image').forEach(function(link) { link.addEventListener('click', function(event) { event.preventDefault(); // 기본 동작 방지 var imageUrl = link.querySelector('img').getAttribute('src').replace(/&type=list/g, ''); window.location.href = imageUrl; }); }); } // 개념글 미리보기 이미지 마우스 오버시 보이게 if (config.thumbnailHoverBest) { // 이미지 요소 선택 var imageElements = document.querySelectorAll('.vrow.hybrid .title.preview-image .vrow-preview img'); // 각 이미지 요소에 이벤트 추가 imageElements.forEach(function(imageElement) { // 이미지에 호버 이벤트 추가 imageElement.addEventListener('mouseenter', function() { // 이미지의 부모 요소 찾기 var parentDiv = imageElement.closest('.vrow.hybrid'); // 이미지 URL에서 &type=list 부분 제거 var imageUrl = imageElement.src.replace('&type=list', ''); // 복제된 이미지 요소 생성 var duplicateImageElement = document.createElement('img'); duplicateImageElement.src = imageUrl; // 복제된 이미지의 스타일 설정 duplicateImageElement.style.position = 'absolute'; duplicateImageElement.style.width = '30rem'; duplicateImageElement.style.height = 'auto'; duplicateImageElement.style.top = 'auto'; duplicateImageElement.style.left = '7.5rem'; // 오른쪽으로 10rem 이동 duplicateImageElement.style.zIndex = '1'; duplicateImageElement.style.padding = '5px'; duplicateImageElement.style.border = '1px solid'; duplicateImageElement.style.borderRadius = '5px'; duplicateImageElement.style.boxSizing = 'content-box'; duplicateImageElement.style.backgroundColor = '#fff'; // 배경색 duplicateImageElement.style.borderColor = '#bbb'; // 테두리 색상 // vrow hybrid 클래스에 align-items: center; 스타일 추가 parentDiv.classList.add('hybrid'); parentDiv.style.alignItems = 'center'; // 수직 가운데 정렬 // 복제된 이미지 요소를 기존 이미지 요소 다음에 추가 parentDiv.appendChild(duplicateImageElement); // 마우스를 이미지에서 떼었을 때 복제된 이미지 제거 imageElement.addEventListener('mouseleave', function() { duplicateImageElement.remove(); }); }); }); }