|
|
1번째 줄: |
1번째 줄: |
|
| |
|
| // 프리로딩 가능한 링크 최고 갯수
| |
| 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);
| |
| });
| |
| });
| |
| })
| |
| })
| |