사용자:BANIP/낙서장

리버티게임, 모두가 만들어가는 자유로운 게임
< 사용자:BANIP
BANIP (토론 | 기여)님의 2023년 7월 8일 (토) 01:33 판 (사이트 정상작동 원인확인)

// 프리로딩 가능한 링크 최고 갯수 var previewLimit = 5 var getParsedDocumentPromise = (function(link){

   var mwApi = new mw.Api(); 
   return function(pagename){
       return new Promise(function(resolve, reject){
           mwApi .get({
               action: 'parse',
               page: pagename,
               formatversion: 2
           }).then(function(data){
               resolve(data.parse.displaytitle, data.parse.text);
           }, function(e){
               reject(e);
           }); 
                       
       });
   }

})();

var setLoading = function(boolean){

   // 이미 로딩 완료된 작업의 경우 로딩창을 표시하지 않기 위해
   // 로딩창 표시 작업시 예약 플래그를 설정하고 약간의 텀을 두기
   // 로딩창 삭제 작업시 표시작업이 예약되어있으면 같이 삭제

}

// 선행로딩된 페이지들 var documentPromiseMap = {};

var namespace = $("#firstHeading > span.mw-page-title-namespace").val() || "" // 해당 링크의 action, title, oldid 파라미터가 없는 링크만 가져오기

var targetLinks = $("#mw-content-text a").not(".external").filter(function() {

   return !this.href.match(/action=|title=|oldid=/);

}).toArray().map(function(el) {

   var [_, namespace, docname] = decodeURI(el.href).match(/[a-z]+\:\/\/[a-z\.]+\/[a-z\.]+\/([^\:]+)\:?(.*)/);
   if (docname === "") [namespace, docname] = [docname, namespace];
   [namespace, docname];
   
   return {
       el,
       link: el.href,
       title: el.title,
       namespace, docname
   }

}) // 동일한 네임스페이스만 이동되게 필터링 .filter(({namespace:thisNamespace}) => thisNamespace === namespace ) // 필터된게 previewLimit 갯수 이상이면 동작 x, 프로미스맵에 클릭 시 로딩 필요함을 명시 if(targetLinks.length > previewLimit){

   targetLinks.forEach(({link}) => documentPromiseMap[link] ||= null);

} else {

   // 필터링된게 프로미스맵에 없는 경우 사전 프리로딩 프로미스 추가
   targetLinks.forEach(({link, docname, namespace}) => {
       var pagename = docname === "" ? namespace : `${namespace}:${docname}`;
       documentPromiseMap[link] ||= getParsedDocumentPromise(pagename)
   });

}

// 가져온 링크로 전체 작업 targetLinks.forEach(function(this){

   var $link = $(this);
   // a링크 href를 #로 변경, 클릭 시 이벤트 바인딩
   var href = $link.attr("href");
   var documentPromise = documentPromiseMap[href];
   $link
       .attr("href", "#")
       .click(function(){
           // 프리로드 불필요한 경우(네임스페이스가 다를때, 편집/리비전확인 링크일때) url 영구이동
           if(documentPromise === undefined){
               return location.href = href; 
           }
           // 프리로드되지 않은 이동 가능한 링크면 로딩창 표시 후 해당 페이지 로딩
           if(documentPromise === null){
               documentPromise = getParsedDocumentPromise(href);
           }
           // 프로미스가 아직 안끝났으면 로딩창 표시
           setLoading(true);
           // 링크 프로미스에 문제가 있을 시 다시 내용 확인, 성공시 문서 프로미스에 저장, 오류시 에러메세지
           documentPromise.then(function(title, text){
               // 프리로드 프로미스가 정상적으로 불러왔을 경우
               // Promise.race1
                   // 문서내용 페이드 아웃, 
                   // 프로미스 내용으로 교체
                   // 문서내용 페이드 인
               // Promise.race2
                   // 사전로딩된 내용에서 프리로드 분석 재실행
           }).error(function(e){
               // 에러 발생 시 실패한 페이지 다시 프로미스에 저장 시도
               documentPromiseMap[href] = null;
               documentPromise = null;
               // 에러메세지 표시
               toast('페이지 로딩에 실패했습니다. 다시 시도해주세요.');
           }).finally(function(){
               // 로딩창 삭제
               setLoading(false);
           });
       });
   })

})