리버티게임:게임 목록: 두 판 사이의 차이
둘러보기로 이동
검색으로 이동
리버티게임>BANIP 잔글편집 요약 없음 |
리버티게임>BANIP 잔글편집 요약 없음 |
||
1번째 줄: | 1번째 줄: | ||
{{사문편가}} | |||
{{빠른이동|0}} | {{빠른이동|0}} | ||
* {{/링크|어드벤처 게임}} | * {{/링크|어드벤처 게임}} |
2023년 8월 3일 (목) 09:16 판
BANIP" data-doc="틀:빠른이동/app.js" data-url="https://dev.libertygame.work/index.php?title=%ED%8B%80:%EB%B9%A0%EB%A5%B8%EC%9D%B4%EB%8F%99/app.js&action=raw&ctype=text/javascript" data-rev-id=18049 data-rev-timestamp=20230803010144 data-rev-user=/BANIP>(function(){ // 프리로딩 가능한 링크 최고 갯수 var previewLimit = 5; // 링크로 해당 문서 컨텐츠와 타이틀을 가져오는 프로미스 획득 var getParsedDocumentPromise = (function(){ var mwApi = new mw.Api(); return function(option){ var {href, fullPagename} = option; var searchParams = new URL(href).searchParams; var searchParamsObject = {}; searchParams.forEach(function(value, key){ // title 파라미터는 제외 if(key === "title") return; searchParamsObject[key] = value; }); // href에서 searchParams 추출 return new Promise(function(resolve, reject){ var apiParams = { action: 'parse', page: fullPagename, formatversion: 2, }; var requestOption = Object.assign(apiParams,searchParamsObject); mwApi.get(requestOption).then(function(data){ var title = data.parse.title; var text = data.parse.text; //text내에 #title-meta 요소가 포함되어 있으면 해당 컨텐츠를 title로 변경(제목틀 호환) var $titleMeta = $(text).find("#title-meta"); if( $titleMeta.length > 0 ){ title = $titleMeta.html(); } resolve({ title:title, text:text }); }, function(e){ reject(e); }); }); }; })(); var setLoading = (function(){ // 로딩창 표시 여부 플래그 var timers = []; return function(isSetShow){ // 이미 로딩 완료된 작업의 경우 로딩창을 표시하지 않기 위해 // 로딩창 표시 작업시 예약 플래그를 설정하고 약간의 텀을 두기. if(isSetShow){ setLoading.showFlag = true; var timer = setTimeout(function(){ if(setLoading.showFlag){ $("#loading").fadeIn(200); // 타이머에서 제거 timers.splice(timers.indexOf(timer), 1); } }, 50); timers.push(timer); } else { // 로딩창 삭제 작업시 표시작업이 예약되어있으면 같이 삭제 setLoading.showFlag = false; $("#loading").fadeOut(200); timers.forEach(function(timer){ clearTimeout(timer); }); timers = []; } }; })(); var toast = function(message){ // 화면 오른쪽 하단에서 메세지 표시, 2초 후 사라짐 var $toast = $("<div>").addClass("toast").css({ position:"fixed", bottom: "20px", right: "20px", padding: "10px 20px", background: "#000", color: "#fff", opacity: 0.8, boxShadow: "0 0 10px rgba(0,0,0,0.3)", zIndex: 9999, display: "none" }); $toast.text(message).appendTo("body").fadeIn(200); setTimeout(function(){ $toast.fadeOut(200, function(){ $toast.remove(); }); }, 2000); }; // 선행로딩된 페이지들 var documentPromiseMap = {}; var namespace = mw.config.get('wgFormattedNamespaces')[ mw.config.get('wgNamespaceNumber')] || ""; function getPagenameFromUrl(rawUrl){ var url = new URL(rawUrl, location.origin); // url의 searchParams에 title 파라미터가 있을 경우 해당 파라미터로 docname 지정 var fullPagename = url.searchParams.get("title") || ""; if(!fullPagename){ var matchedUrl = decodeURI(url.pathname).match(/[^\/]+\/(.*)/); if(matchedUrl){ // 문서명 파싱 성공시 문서명 지정 fullPagename = matchedUrl[1]; } else { // 문서명 파싱 실패시 모든 링크명 지정 fullPagename = decodeURI(url.pathname) } } // fullPagename에 ":"이 없을 경우 스트링 처음위치에 삽입 fullPagename = fullPagename.indexOf(":") === -1 ? `:${fullPagename}` : fullPagename; // :를 기준으로 네임스페이스와 문서명 분리 var [namespace, pagename] = fullPagename.split(":"); return { namespace, pagename, fullPagename, } } function preloadDocument($doc){ // 해당 링크의 action, title, oldid 파라미터가 없는 링크만 가져오기 var targetLinkItems = $doc.find("a").not(".new") // 대상이 되는 링크들만 필터링 .filter(function() { var href = this.href; if(href === "" || href.match(/^\#/) !== null) return false; // href가 없는 경우 제외 // 링크에서 가져온 url var url = new URL(href); var searchParams = url.searchParams; // 현재 url var nowUrl = new URL(location.href); // 동일한 도메인이 아닌 경우 제외 if(url.origin !== nowUrl.origin) return false; // 수정/리비전 확인 링크는 제외 if( ["action", "oldid"].some(function(key){ return searchParams.has(key); })) return false; return true; }) // 필터링된 링크에 문서명 정보를 추가 .toArray().map(function(el) { var { namespace, pagename, fullPagename } = getPagenameFromUrl(el.href); return { el, href: el.href, namespace, pagename, fullPagename } }) // 동일한 네임스페이스만 이동되게 필터링 .filter(({namespace:thisNamespace}) => thisNamespace === namespace ) // 필터된게 previewLimit 갯수 이상이면 동작 x, 프로미스맵에 클릭 시 로딩 필요함을 명시 if(targetLinkItems.length > previewLimit){ targetLinkItems.forEach(({href}) => { documentPromiseMap[href] ||= null }); } else { // 필터링된게 프로미스맵에 없는 경우 사전 프리로딩 프로미스 추가 targetLinkItems.forEach(({href, pagename, namespace}) => { documentPromiseMap[href] ||= getParsedDocumentPromise({href, fullPagename: `${namespace}:${pagename}`}) }); } // 가져온 링크로 전체 작업 targetLinkItems.forEach(function(linkItem){ // 문서명 파싱 실패시 해당 링크 제외 if(!linkItem) return; $(linkItem.el) .click(function(e){ e.preventDefault(); replaceBodyContent(this.href); }); }) }; async function replaceBodyContent(url, {urlChange = true} = {}){ var fullPagename = getPagenameFromUrl(url).fullPagename; // 프리로드 불필요한 경우(네임스페이스가 다를때, 편집/리비전확인 링크일때) url 영구이동 if(documentPromiseMap[url] === undefined){ return location.href = url; } // 프리로드되지 않은 이동 가능한 링크면 로딩창 표시 후 해당 페이지 로딩 if(documentPromiseMap[url] === null){ documentPromiseMap[url] = getParsedDocumentPromise({href:url, fullPagename}); } // 프로미스가 아직 안끝났으면 로딩창 표시 setLoading(true); // 링크 프로미스에 문제가 있을 시 다시 내용 확인, 성공시 문서 프로미스에 저장, 오류시 에러메세지 documentPromiseMap[url].then(function({title, text}){ // 프리로드 프로미스가 정상적으로 불러왔을 경우 let $thisDoc = $(text) // 사전로딩된 내용에서 프리로드 분석 재실행 preloadDocument( $thisDoc ); $("#bodyContent").fadeOut(100, function(){ // 문서내용 교체 후 페이드 인 $("#firstHeading").html(title); // .vector-article-toolbar 내용물 링크 변경 필요 $(".mw-article-toolbar-container").find("a").each(function(){ try{ var $this = $(this); var href = $this.attr("href"); var url = new URL(href); url.searchParams.set("title", title); $this.attr("href", url.href); } catch (e){ } }) // 현재 url 변경 if(urlChange){ history.pushState(null, null, url); } $("#bodyContent").html($thisDoc); $("#bodyContent").fadeIn(100); }) }).catch(function(e){ console.error(e) // 에러 발생 시 실패한 페이지 다시 프로미스에 저장 시도 documentPromiseMap[url] = null; // 에러메세지 표시 toast('페이지 로딩에 실패했습니다. 다시 시도해주세요.'); }).finally(function(){ // 로딩창 삭제 setLoading(false); }); } (function main(){ // #enable-preload div 없으면 동작 x if(!$(".mw-parser-output .enable-preload").length) return; //enable-preload의 data-preload-limit가 있으면 previewLimit에 설정 let preloadLimit = $(".mw-parser-output .enable-preload").data("preload-limit"); // preloadLimit가 있고 0-10개일시만 설정 if(preloadLimit && preloadLimit >= 0 && preloadLimit <= 10){ previewLimit = preloadLimit; } // #bodyContent에 로딩창 추가 $("<div>").addClass("content-loading") .css({ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", background: "#fff", opacity: 0.8, zIndex: 9999, display: "none" }) .attr("id", "loading") .append($("<div>").css({ position: "absolute", top: "50%", left: "50%", transform: "translate(-50%,-50%)" }) .append($("<span>로딩중</span>"))) .appendTo("#bodyContent"); // 현재 페이지 프리로드, 함수 내부에서 재귀적으로 프리로드 실행 preloadDocument($("#mw-content-text > div.mw-parser-output")); // url 변경 시(일반적으로 뒤로가기) 프리로드된 문서가 있으면 해당 문서로 이동( 2023년 7월 9일 (일) 14:00 (KST)기준 iOS/파폭에서 동작하지 않음 ) function handleNavigate(e){ // 사용자가 url 변경시에만 동작 if(e.navigationType === "traverse"){ replaceBodyContent(e.destination.url, {urlChange:false}); } } navigation.removeEventListener("navigate", handleNavigate); // 이벤트 중복 등록 방지 navigation.addEventListener("navigate", handleNavigate); // 이벤트 등록 })(); })();