imported>Senouis |
|
(사용자 4명의 중간 판 49개는 보이지 않습니다) |
1번째 줄: |
1번째 줄: |
| | /* -- 전역 상수 선언 -- */ |
| | // 미디어위키 폴더명 url 다뤄야되는 함수들에서 사용됨, 메인터넌스 거친 후 w 혹은 wiki로 변경 예정, |
| | var wgScriptPath = "index.php"; |
| /* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */ | | /* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */ |
| /*<source lang="javascript"><nowiki>*/
| |
|
| |
| /** [[틀:USERNAME]]에서 사용하는 바꿔치기 함수
| |
| * 작성자: [[사용자:Peremen]]
| |
| */
| |
|
| |
| function UserNameReplace() {
| |
| if (typeof(disableUsernameReplace) != 'undefined' && disableUsernameReplace) return;
| |
| if (!document.getElementById('pt-userpage')) return;
| |
| $("span.insertusername").each(function(i) {
| |
| $(this).text(mw.config.get("wgUserName"))
| |
| })
| |
| };
| |
| $(UserNameReplace);
| |
|
| |
| /** 플러그인이 작동하지 않을 때 나타나는 내용 | | /** 플러그인이 작동하지 않을 때 나타나는 내용 |
| * js: noPlugin('(이름)'); | | * js: noPlugin('(이름)'); |
34번째 줄: |
22번째 줄: |
| @param {object} location 획득할 로케이션 객체, 비어있으면 window.location을 참조 | | @param {object} location 획득할 로케이션 객체, 비어있으면 window.location을 참조 |
| 원작성자: [[사용자:BANIP|BANIP]] | | 원작성자: [[사용자:BANIP|BANIP]] |
| | 현 편집자: [[사용자:hsl0|hsl0]] |
| */ | | */ |
| | |
| function geturlSearch(location) { | | function geturlSearch(location) { |
| location = location || window.location; | | if(!location) location = window.location; |
| var result = {}; | | else if(typeof location === 'string') location = new URL(location); |
| if(location.search) decodeURIComponent(location.search)
| | var result = {}; |
| .substring(1)
| | if (location.search) |
| .split("&")
| | location.search.substring(1).replace(/\+/g, ' ').split("&").map(function(v) { |
| .map(function(v) { return v.split("=") })
| | return v.split("="); |
| .forEach(function(v) { result[v[0]] = v[1] });
| | }).forEach(function(v) { |
| return result;url.hash = encodeURIComponent(hash);
| | result[decodeURIComponent(v[0])] = decodeURIComponent(v[1]); |
| | }); |
| | return result; |
| } | | } |
| | |
|
| |
|
| /* 객체형태로 된 SearchParam을 받아 string형태로 반환 | | /* 객체형태로 된 SearchParam을 받아 string형태로 반환 |
75번째 줄: |
68번째 줄: |
| } | | } |
| }); | | }); |
|
| |
| /** [[틀:제목]]에서 사용하는 제목 바꿔치기 함수
| |
| * 작성자: [[사용자:Peremen|Peremen]]
| |
| */
| |
| /*
| |
| function rewriteTitle() {
| |
| if (typeof(disableTitleRewrite) != 'undefined' && disableTitleRewrite) return;
| |
| if (!document.getElementById('title-meta')) return;
| |
| $('h1.firstHeading').each(function(i) {
| |
| $(this).html($("#title-meta").html()).css('text-align', $("#title-align").text());
| |
| });
| |
| }
| |
| $(rewriteTitle);
| |
| */
| |
| /* from en: */
| |
| var hasClass = (function() {
| |
| var reCache = {};
| |
| return function(element, className) {
| |
| return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
| |
| };
| |
| })();
| |
|
| |
| /* ([[위키백과:관리자 요청/2007년 5월#스크립트 추가 요청]]) */
| |
| /** Collapsible tables *********************************************************
| |
| *
| |
| * Description: Allows tables to be collapsed, showing only the header. See
| |
| * Wikipedia:NavFrame.
| |
| * Maintainers: User:R. Koot
| |
| */
| |
|
| |
| //var autoCollapse = 2;
| |
| //var collapseCaption = "hide";
| |
| //var expandCaption = "show";
| |
|
| |
| function collapseTable(tableIndex) {
| |
| var Button = document.getElementById("collapseButton" + tableIndex);
| |
| var Table = document.getElementById("collapsibleTable" + tableIndex);
| |
|
| |
| if (!Table || !Button) {
| |
| return false;
| |
| }
| |
|
| |
| var Rows = Table.getElementsByTagName("tr");
| |
|
| |
| if (Button.firstChild.data == collapseCaption) {
| |
| for (var i = 1; i < Rows.length; i++) {
| |
| Rows[i].style.display = "none";
| |
| }
| |
| Button.firstChild.data = expandCaption;
| |
| } else {
| |
| for (var i = 1; i < Rows.length; i++) {
| |
| Rows[i].style.display = Rows[0].style.display;
| |
| }
| |
| Button.firstChild.data = collapseCaption;
| |
| }
| |
| }
| |
|
| |
| function createCollapseButtons() {
| |
| var tableIndex = 0;
| |
| var NavigationBoxes = new Object();
| |
| var Tables = document.getElementsByTagName("table");
| |
|
| |
| for (var i = 0; i < Tables.length; i++) {
| |
| if (hasClass(Tables[i], "collapsible")) {
| |
| NavigationBoxes[tableIndex] = Tables[i];
| |
| Tables[i].setAttribute("id", "collapsibleTable" + tableIndex);
| |
|
| |
| var Button = document.createElement("span");
| |
| var ButtonLink = document.createElement("a");
| |
| var ButtonText = document.createTextNode(collapseCaption);
| |
|
| |
| Button.style.styleFloat = "right";
| |
| Button.style.cssFloat = "right";
| |
| Button.style.fontWeight = "normal";
| |
| Button.style.textAlign = "right";
| |
| Button.style.width = "6em";
| |
|
| |
| ButtonLink.setAttribute("id", "collapseButton" + tableIndex);
| |
| ButtonLink.setAttribute("href", "javascript:collapseTable(" + tableIndex + ");");
| |
| ButtonLink.appendChild(ButtonText);
| |
|
| |
| Button.appendChild(document.createTextNode("["));
| |
| Button.appendChild(ButtonLink);
| |
| Button.appendChild(document.createTextNode("]"));
| |
|
| |
| var Header = Tables[i].getElementsByTagName("tr")[0].getElementsByTagName("th")[0];
| |
| /* only add button and increment count if there is a header row to work with */
| |
| if (Header) {
| |
| Header.insertBefore(Button, Header.childNodes[0]);
| |
| tableIndex++;
| |
| }
| |
| }
| |
| }
| |
|
| |
| for (var i = 0; i < tableIndex; i++) {
| |
| if (hasClass(NavigationBoxes[i], "collapsed") || (tableIndex >= autoCollapse && hasClass(NavigationBoxes[i], "autocollapse"))) {
| |
| collapseTable(i);
| |
| }
| |
| }
| |
| }
| |
|
| |
| $(createCollapseButtons);
| |
|
| |
| /** ([[위키백과:관리자 요청/2007년 5월#스크립트 추가 요청]])
| |
| * 이 스크립트는 위키백과 펌이므로, 위키백과 라이선스인 CCL BY-SA가 적용됩니다.
| |
| */
| |
| /** Dynamic Navigation Bars (experimental) *************************************
| |
| *
| |
| * Description: See [[:en:Wikipedia:NavFrame]].
| |
| * Maintainers: UNMAINTAINED
| |
| */
| |
|
| |
| // set up the words in your language
| |
| var autoCollapse = 2;
| |
| var collapseCaption = "숨기기";
| |
| var expandCaption = "보이기";
| |
| var NavigationBarHide = '[' + collapseCaption + ']';
| |
| var NavigationBarShow = '[' + expandCaption + ']';
| |
|
| |
| // set up max count of Navigation Bars on page,
| |
| // if there are more, all will be hidden
| |
| // NavigationBarShowDefault = 0; // all bars will be hidden
| |
| // NavigationBarShowDefault = 1; // on pages with more than 1 bar all bars will be hidden
| |
| var NavigationBarShowDefault = autoCollapse;
| |
|
| |
|
| |
| // shows and hides content and picture (if available) of navigation bars
| |
| // Parameters:
| |
| // indexNavigationBar: the index of navigation bar to be toggled
| |
| function toggleNavigationBar(indexNavigationBar) {
| |
| var NavToggle = document.getElementById("NavToggle" + indexNavigationBar);
| |
| var NavFrame = document.getElementById("NavFrame" + indexNavigationBar);
| |
|
| |
| if (!NavFrame || !NavToggle) {
| |
| return false;
| |
| }
| |
|
| |
| // if shown now
| |
| if (NavToggle.firstChild.data == NavigationBarHide) {
| |
| for (
| |
| var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling
| |
| ) {
| |
| if (hasClass(NavChild, 'NavPic')) {
| |
| NavChild.style.display = 'none';
| |
| }
| |
| if (hasClass(NavChild, 'NavContent')) {
| |
| NavChild.style.display = 'none';
| |
| }
| |
| }
| |
| NavToggle.firstChild.data = NavigationBarShow;
| |
|
| |
| // if hidden now
| |
| } else if (NavToggle.firstChild.data == NavigationBarShow) {
| |
| for (
| |
| var NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling
| |
| ) {
| |
| if (hasClass(NavChild, 'NavPic')) {
| |
| NavChild.style.display = 'block';
| |
| }
| |
| if (hasClass(NavChild, 'NavContent')) {
| |
| NavChild.style.display = 'block';
| |
| }
| |
| }
| |
| NavToggle.firstChild.data = NavigationBarHide;
| |
| }
| |
| }
| |
|
| |
| // adds show/hide-button to navigation bars
| |
| function createNavigationBarToggleButton() {
| |
| var indexNavigationBar = 0;
| |
| // iterate over all < div >-elements
| |
| var divs = document.getElementsByTagName("div");
| |
| for (var i = 0; NavFrame = divs[i]; i++) {
| |
| // if found a navigation bar
| |
| if (hasClass(NavFrame, "NavFrame")) {
| |
|
| |
| indexNavigationBar++;
| |
| var NavToggle = document.createElement("a");
| |
| NavToggle.className = 'NavToggle';
| |
| NavToggle.setAttribute('id', 'NavToggle' + indexNavigationBar);
| |
| NavToggle.setAttribute('href', 'javascript:toggleNavigationBar(' + indexNavigationBar + ');');
| |
|
| |
| var NavToggleText = document.createTextNode(NavigationBarHide);
| |
| NavToggle.appendChild(NavToggleText);
| |
| // Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked)
| |
| for (
| |
| var j = 0; j < NavFrame.childNodes.length; j++
| |
| ) {
| |
| if (hasClass(NavFrame.childNodes[j], "NavHead")) {
| |
| NavFrame.childNodes[j].appendChild(NavToggle);
| |
| }
| |
| }
| |
| NavFrame.setAttribute('id', 'NavFrame' + indexNavigationBar);
| |
| }
| |
| }
| |
| // if more Navigation Bars found than Default: hide all
| |
| if (NavigationBarShowDefault < indexNavigationBar) {
| |
| for (
| |
| var i = 1; i <= indexNavigationBar; i++
| |
| ) {
| |
| toggleNavigationBar(i);
| |
| }
| |
| }
| |
|
| |
| }
| |
|
| |
| $(createNavigationBarToggleButton);
| |
|
| |
| /** 대문의 탭을 "프로젝트"->"대문"으로 바꾸는 함수.
| |
| * 작성자: [[사용자:Peremen|Peremen]]
| |
| */
| |
|
| |
| function MainPageRenameNamespaceTab() {
| |
| var hasMainPageTab = document.getElementsByClassName("hasMainPageTab");
| |
| if (hasMainPageTab[0] !== undefined) {
| |
| $('#ca-nstab-project a').text("대문");
| |
| }
| |
| var title = mw.config.get('wgPageName');
| |
| var hasGameListTab = (title == '백괴게임:게임_목록' || title == '백괴게임토론:게임_목록');
| |
| if (hasGameListTab) {
| |
| $('#ca-nstab-project a').text("게임 목록");
| |
| }
| |
| $('#ca-nstab-main a').text("게임");
| |
| }
| |
| $(MainPageRenameNamespaceTab);
| |
|
| |
| /** 임베드 플래시 무비
| |
| * 문서에 플래시 파일을 넣을 수 있게 합니다. [[틀:플래시]]를 참고하십시오.
| |
| * 원작성자: [[:en:User:Olipro|Olipro]]
| |
| */
| |
| function useFlash() {
| |
| var flashOk;
| |
| var contentTempHolder;
| |
| $(embedFlashCheck);
| |
| }
| |
|
| |
| function embedFlashMovie(flashOk) {
| |
| mainbody = document.getElementById('bodyContent');
| |
| mainbody.innerHTML = contentTempHolder;
| |
| spancheck = document.getElementsByTagName('span');
| |
| for (i = 0; i < spancheck.length; i++) {
| |
| if (spancheck[i].getAttribute('id') != 'embedFlashDoc') {
| |
| continue;
| |
| }
| |
| obj = spancheck[i].innerHTML.split('@');
| |
| flwidth = obj[0];
| |
| flheight = obj[1];
| |
| flfile = obj[2].replace('fullurl://', 'https://');
| |
| showFlash = ' ';
| |
| if (flashOk) {
| |
| showFlash = '<object width="' + flwidth + '" height="' + flheight + '"';
| |
| showFlash += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"';
| |
| showFlash += 'codebase="http://fpdownload.macromedia.com/pub/';
| |
| showFlash += 'shockwave/cabs/flash/swflash.cab#version=8,0,0,0">';
| |
| showFlash += '<param name="movie" value="' + flfile + '" />';
| |
| showFlash += '<embed src="' + flfile + '" width="' + flwidth + '" height=';
| |
| showFlash += '"' + flheight + '" type="application/x-shockwave-flash" ';
| |
| showFlash += 'pluginspage="http://www.macromedia.com/go/getflashplayer" />';
| |
| showFlash += '</object>';
| |
| } else {
| |
| showFlash = '<a class="plainlinks" href="javascript:embedFlashMovie(true)" onClick="embedFlashMovie(true)">' + flfile + '</a> (신뢰하는 경우 보려면 클릭하십시오.)';
| |
| }
| |
| spancheck[i].innerHTML = showFlash;
| |
| spancheck[i].style.display = 'inline';
| |
| }
| |
| }
| |
|
| |
| function embedFlashCheck() {
| |
| if (!document.getElementById('embedFlashDoc')) {
| |
| return;
| |
| }
| |
| mainbody = document.getElementById('bodyContent');
| |
| contentTempHolder = mainbody.innerHTML;
| |
| if (typeof displayFlashOverride != 'undefined') {
| |
| embedFlashMovie(displayFlashOverride);
| |
| return;
| |
| }
| |
| askmessage = '<div align="center" id="askflash">이 게임에는 ';
| |
| askmessage += '<a href="/wiki/백괴:플래시" class="plainlinks">플래시</a>가 들어있습니다.<br />';
| |
| askmessage += '컴퓨터에 해를 끼칠 수 있으므로 신뢰하는 경우에만 여십시오.<br />';
| |
| askmessage += '플래시가 포함된 게임을 보시겠습니까?<br><b> ';
| |
| askmessage += '<a href="javascript:embedFlashMovie(true)" ';
| |
| askmessage += 'onClick="embedFlashMovie(true)">예</a> | <a ';
| |
| askmessage += 'href="https://libertygame.miraheze.org/">아니오</a>';
| |
| mainbody.innerHTML = askmessage;
| |
| }
| |
| $(useFlash);
| |
|
| |
|
| /* userAgent */ | | /* userAgent */ |
378번째 줄: |
84번째 줄: |
|
| |
|
| if (M[1] === 'Chrome') { | | if (M[1] === 'Chrome') { |
| tem = ua.match(/\bOPR\/(\d+)/) | | tem = ua.match(/\bOPR\/(\d+)/); |
| if (tem != null) { | | if (tem != null) { |
| return { | | return { |
400번째 줄: |
106번째 줄: |
| } | | } |
|
| |
|
| /** DB기능 초기화
| |
| * [[틀:DB]]를 사용 가능하게 해 줍니다.
| |
| * 원작성자: [[사용자:BANIP|BANIP]]
| |
| */
| |
|
| |
| function enableLocalStorage() {
| |
| // 문서 미리보기 상태일 시 종료
| |
| var searchParams = geturlSearch(location);
| |
| var isNormalMode =
| |
| searchParams.action === undefined &&
| |
| searchParams.curid === undefined &&
| |
| searchParams.oldid === undefined &&
| |
| searchParams.direction === undefined &&
| |
| searchParams.printable === undefined &&
| |
| searchParams.diff === undefined ;
| |
| if (!(isNormalMode)) return "";
| |
|
| |
| //플러그인의 모든 키 순회
| |
| function forEach(object, callback) {
| |
| for (var key in object) {
| |
| var variable = object[key];
| |
| callback(variable, key);
| |
| }
| |
| }
| |
|
| |
| function setLocalStorage(parentKey, datas) {
| |
| var stringKeys = JSON.stringify(Object.keys(datas));
| |
| localStorage.setItem(parentKey + "/__keys__", stringKeys);
| |
| forEach(datas, function(v, i) {
| |
| if (i === "action") return;
| |
| localStorage.setItem(parentKey + "/" + i, v);
| |
| });
| |
| }
| |
|
| |
|
| |
| function getLocalStorage(parentKey) {
| |
| var datas = {};
| |
| var stringKeys = localStorage.getItem(parentKey + "/__keys__");
| |
| if (stringKeys === null) return null;
| |
| var keys = JSON.parse(stringKeys);
| |
| keys.forEach(function(key) {
| |
| datas[key] = localStorage.getItem(parentKey + "/" + key);
| |
| })
| |
| return datas;
| |
| }
| |
|
| |
| function clearLocalStorage(parentKey) {
| |
| var datas = {};
| |
| var stringKeys = localStorage.getItem(parentKey + "/__keys__");
| |
| if (stringKeys === null) return null;
| |
| var keys = JSON.parse(stringKeys);
| |
| keys.forEach(function(key) {
| |
| datas[key] = localStorage.removeItem(parentKey + "/" + key);
| |
| })
| |
| }
| |
|
| |
| function getSearch() {
| |
| return geturlSearch();
| |
| }
| |
|
| |
| function searchParamToString(searchParamsObj){
| |
| var params = "?" + Object.entries(searchParamsObj)
| |
| .map(function(v){ return v.join("=") })
| |
| .join("&");
| |
| return encodeURI(params);
| |
| }
| |
|
| |
| function setSearch(datas) {
| |
| var searchParams = getSearch();
| |
| forEach(datas, function(v, i) {
| |
| searchParams[i] = v;
| |
| });
| |
| location.search = searchParamToString(searchParams);
| |
| }
| |
|
| |
| function hasSearch() {
| |
| return !(location.search === "");
| |
| }
| |
|
| |
| $(".controlLocalStorage").each(function() {
| |
| var parentKey = $(this).data("key");
| |
| var behavior = $(this).data("behavior");
| |
| switch (behavior) {
| |
| case "세이브":
| |
| if (!hasSearch()) return;
| |
| var datas = getSearch();
| |
| clearLocalStorage(parentKey);
| |
| setLocalStorage(parentKey, datas);
| |
| break;
| |
| case "로드":
| |
| if (hasSearch()) return;
| |
| var datas = getLocalStorage(parentKey, datas);
| |
| if (datas === null) return;
| |
| setSearch(datas);
| |
| break;
| |
| case "초기화":
| |
| clearLocalStorage(parentKey);
| |
| break;
| |
| }
| |
| })
| |
|
| |
|
| |
| }
| |
| $(enableLocalStorage);
| |
|
| |
| /* DB기능 초기화 끝 */
| |
|
| |
| /** [[틀:CGI2]] 변수 구문 해석기
| |
| * 작성자: [[사용자:Gustmd7410]]
| |
| **/
| |
| var CGI2Parser = (function() {
| |
| function CGI2Parser(actions) {
| |
| // new 키워드 미사용시
| |
| if(!(this instanceof CGI2Parser)) {
| |
| console.warn("CGI2Parser 객체를 new 키워드 없이 생성했습니다");
| |
| return new CGI2Parser(actions);
| |
| }
| |
|
| |
| if(typeof actions === "object") this.actions = actions;
| |
| else if(actions === undefined) this.actions = {};
| |
| else throw new TypeError("생성자 CGI2Parser의 첫번째 변수가 객체가 아닙니다");
| |
| }
| |
| CGI2Parser.prototype.parse = function parse(origin, params, useStrict) {
| |
| var actions = this.actions;
| |
|
| |
| JSON.parse(params.replace(/\,\s*\]/, "]")).forEach(function(command, useStrict) {
| |
| var wrapper = Object.entries(command)[0];
| |
| var action = actions[wrapper[0]];
| |
| var arg = wrapper[1];
| |
|
| |
| if(typeof action === "function") {
| |
| origin = actions[wrapper[0]].apply(origin, Array.isArray(arg)? arg : [arg]) || origin;
| |
| } else if(!useStrict) {
| |
| return;
| |
| } else if(action === undefined) {
| |
| origin = new TypeError('동작 "' + wrapper[0] + '"이(가) 존재하지 않습니다');
| |
| origin.name = "ActionNoExistError";
| |
| throw origin;
| |
| } else {
| |
| origin = new TypeError('동작 "' + wrapper[0] + '"은(는) 유효하지 않는 타입(' + typeof action + ') 입니다');
| |
| origin.name = "ActionWrongTypeError";
| |
| throw origin;
| |
| }
| |
| });
| |
|
| |
| return origin;
| |
| };
| |
| return CGI2Parser;
| |
| })();
| |
|
| |
| /* [[틀:CGI2]] 변수 구문 해석기 끝 */
| |
|
| |
| /** [[틀:CGI2|CGI2]]를 사용 가능하게 만드는 jquery 구문
| |
| * 원작성자: [[사용자:BANIP|BANIP]]
| |
| * 2차 작성자: [[사용자:Gustmd7410|Gustmd7410]]
| |
| **/
| |
| function useCGI2() {
| |
| $(".cgilink").each(function() {
| |
| // CGI2의 page속성과 data속성을 가져옴
| |
| var page = $(this).data("page").split('#');
| |
| var variables = $(this).data("var");
| |
| // 가져온 page데이터 속성을 조합해 url인스턴스 생성
| |
| var pagename = page.shift() || mw.config.get('wgPageName');
| |
| var hash = page.join('#');
| |
| var urlstr = window.location.origin;
| |
| var url = new URL(urlstr);
| |
| var searchParam = geturlSearch();
| |
| // 엄격모드 사용여부 결정
| |
| if(typeof useCGI2.useStrict !== "boolean") {
| |
| useCGI2.useStrict = (searchParam.debug === "true" || searchParam.debug == 1)? true : false;
| |
| }
| |
| // 가져온 var속성으로 url 인스턴스의 searchparams를 씹고 뜯고 맛보고 즐기고
| |
| var enabledKey = null;
| |
| try {
| |
| searchParam = new CGI2Parser({
| |
| set: function(key, value) {
| |
| this[key.trim()] = value.trim();
| |
| },
| |
| "default": function(key, value) {
| |
| key = key.trim();
| |
| this[key] = this[key] || value.trim();
| |
| },
| |
| del: function(key) {
| |
| delete this[key.trim()];
| |
| },
| |
| restrict: function(key) {
| |
| if(!enabledKey) enabledKey = [];
| |
| enabledKey.push(key);
| |
| }
| |
| }).parse(searchParam, variables, useCGI2.useStrict);
| |
|
| |
| if(enabledKey) Object.keys(searchParam).forEach(function(key) {
| |
| if(!enabledKey.includes(key)) delete searchParam[key];
| |
| });
| |
| } catch(error) {
| |
| $(this).html($("<span class='error' />").text(error.message));
| |
| return;
| |
| }
| |
| // url 경로 조정
| |
| if(Object.keys(searchParam).length > 0) {
| |
| url.pathname = "/w/index.php";
| |
| searchParam.title = pagename;
| |
| } else url.pathname = "/wiki/" + mw.util.wikiUrlencode(pagename);
| |
| url.search = searchParamToString(searchParam);
| |
| url.hash = mw.util.escapeIdForLink(hash);
| |
| // cgilink에 a태그 추가
| |
| var children = $(this).html();
| |
| $(this).html("<a href='" + url.href.replace("'", "'") + "'>" + children + "</a>");
| |
| });
| |
| }
| |
| /*
| |
| true = 항상 엄격모드
| |
| null = 디버그 모드 (debug=true) 에 엄격모드 자동 전환
| |
| false = 엄격모드 사용 안함
| |
| */
| |
| useCGI2.useStrict = null;
| |
| $(useCGI2);
| |
|
| |
| /* [[틀:CGI2|CGI2]]를 사용 가능하게 만드는 jquery 구문 끝 */
| |
|
| |
| /** mediawiki api를 통해 간단하게 문서들을 수집, 변경하는 함수.
| |
| * 플러그인 코어에서 사용하기 위해 만들었습니다.
| |
| * 원작성자: [[사용자:BANIP|BANIP]], 수정자: [[사용자:Bd3076|Bd3076]]
| |
| * 사용방법
| |
| *: var api = MediaWikiAPI(); .changeDocument()
| |
| *: api.changeDocument(변경할 문서의 타이틀, 편집 요약, 변경할 문서의 내용) => 문서의 내용을 변경합니다.
| |
| *: api.addDocument(변경할 문서의 타이틀, 편집 요약, 추가할 문서의 내용) => 문서에 새로운 내용을 추가합니다.
| |
| *: api.getDocument(가져올 문서의 타이틀) => 문서의 모든 텍스트를 읽어옵니다.
| |
| *: api.readDocument(가져올 문서의 타이틀) => 문서의 모든 텍스트를 jquery 객체로 읽어옵니다.
| |
| * 영 좋지 않은 목적으로 사용 하면 안드로메다 경찰관이 잡아간다!
| |
| */
| |
|
| |
| function MediaWikiAPI() {
| |
| var token;
| |
| var getToken = function() {
| |
| if (token !== undefined) return token;
| |
| $.ajax({
| |
| url: "/w/api.php?action=query&meta=tokens",
| |
| success: function(v, i) {
| |
| var datas = JSON.parse($(v).find("pre").text());
| |
| token = datas["query"]["tokens"]["csrftoken"];
| |
| },
| |
| async: false
| |
| });
| |
| return token;
| |
| };
| |
|
| |
| function changeDocument(title, summary, content, isUnReload, minor) {
| |
| mw.loader.using( ['mediawiki.util','mediawiki.Title'] ).then( function () {
| |
| $.ajax({
| |
| url: mw.util.wikiScript("api"),
| |
| data: {
| |
| format: 'json',
| |
| action: 'edit',
| |
| title: title,
| |
| summary: summary,
| |
| text: content,
| |
| minor: minor,
| |
| token: getToken(),
| |
| },
| |
| dataType: 'json',
| |
| type: 'POST',
| |
| success: function(data) {
| |
| if (data && data.edit && data.edit.result == 'Success') {
| |
| if (!isUnReload) window.location.reload(); // reload page if edit was successful
| |
| } else if (data && data.error) {
| |
| alert('Error: API returned error code "' + data.error.code + '": ' + data.error.info);
| |
| } else {
| |
| alert('Error: Unknown result from API.');
| |
| }
| |
| },
| |
| error: function(xhr) {
| |
| alert('Error: Request failed.');
| |
| }
| |
| });
| |
| } );
| |
| }
| |
|
| |
| function addDocument(title, summary, content, isUnReload, minor) {
| |
| originContent = getDocument(title);
| |
| changeDocument(title, summary, originContent + content, isUnReload, minor);
| |
| }
| |
|
| |
| function getDocument(title) {
| |
| function entityDecode(doc) {
| |
| return $('<p></p>').html(doc).text();
| |
| }
| |
|
| |
| var originContent;
| |
| $.ajax({
| |
| url: "/w/index.php?title=" + title + "&action=edit",
| |
| success: function ajaxSucess(data) {
| |
| originContent = $(data).find("textarea").html();
| |
| },
| |
| async: false
| |
| });
| |
| return entityDecode(originContent);
| |
| }
| |
|
| |
| function readDocument(title) {
| |
| var doc;
| |
| $.ajax({
| |
| url: "/wiki/" + title,
| |
| success: function ajaxSucess(data) {
| |
| doc = $(data).find("#mw-content-text");
| |
| },
| |
| async: false
| |
| });
| |
| return doc;
| |
| }
| |
|
| |
|
| |
| return {
| |
| getToken: getToken,
| |
| changeDocument: changeDocument,
| |
| addDocument: addDocument,
| |
| getDocument: getDocument,
| |
| readDocument: readDocument,
| |
| };
| |
| }
| |
|
| |
| /* DB 기능 초기화 끝 */
| |
|
| |
| /** [[틀:플러그인]]을 사용 가능하게 해 줍니다. 사용자의 허락을 맡고 사용자의 commonjs 편집을 허가 할 수 있는 문서입니다.
| |
| * 작성자: [[사용자:BANIP|BANIP]]
| |
| * [[백괴게임:관리자 요청/2018년 1월]]에서 BANIP님 요청으로 퍼왔습니다.
| |
| */
| |
| function pluginCore() {
| |
| // 사용자의 commonjs의 문서 이름을 획득
| |
| var commonjs = "사용자:" + mw.config.get("wgUserName") + "/common.js";
| |
| var plugins = {},
| |
| docPlugins = {},
| |
| uninstalledPlugins = {},
| |
| unupdatedPlugins = {};
| |
| var preloadedplugins = [],
| |
| needPlugins = [];
| |
| var api = MediaWikiAPI();
| |
| var jsdoc = api.getDocument(commonjs);
| |
|
| |
| //commonjs에서 특정 플러그인 제거
| |
| function removePluginByDoc(pluginTitle, doc) {
| |
| var reg = new RegExp("\\/\\*\\* 플러그인 " + pluginTitle + "([\\s\\S]*)\\/\\* " + pluginTitle + " 끝 \\*\\/", "g");
| |
| doc = doc.replace(reg, "");
| |
| return doc
| |
| }
| |
|
| |
| // 플러그인이 비어있는지 확인
| |
| function isPluginsEmpty(plugins) {
| |
| return Object.keys(plugins).length === 0;
| |
| }
| |
|
| |
| //플러그인의 모든 키 순회
| |
| function forEach(object, callback) {
| |
| for (var key in object) {
| |
| var variable = object[key];
| |
| callback(variable, key);
| |
| }
| |
| }
| |
|
| |
| // 문서에서 사용하는 플러그인들을 체크합니다. use-script클래스를 가진 모든 돔 요소를 조사하고
| |
| // 그 돔에 내장된 플러그인 데이터를 docPlugins에 추가합니다.
| |
| var checkDocPlugin = (function(docPlugins) {
| |
| function getPluginData($this) {
| |
| return {
| |
| name: $this.attr("data-name"), // 플러그인 이름
| |
| descript: $this.attr("data-descript"), // 플러그인 내용
| |
| version: $this.attr("data-version"), // 플러그인 이름
| |
| local: ($this.attr("data-local") === "true") ? true : false,
| |
| creat: $this.attr("data-creat"),
| |
| state: $this.attr("data-state"),
| |
| link: $this.attr("data-link"),
| |
| executable: $this.attr("data-executable") === "true" ? true : false,
| |
| };
| |
| }
| |
|
| |
| function getAllPluginsName(plugins) {
| |
| var pluginNames = [];
| |
| forEach(plugins, function(plugin) {
| |
| var pluginName = plugin.name;
| |
| pluginNames.push(pluginName);
| |
| })
| |
|
| |
| return pluginNames;
| |
| }
| |
|
| |
| var loadAllPlugins = (function(docPlugins) {
| |
| $(".use-script").each(function() {
| |
| const plugin = getPluginData($(this));
| |
| docPlugins[plugin.name] = plugin;
| |
| })
| |
| })(docPlugins)
| |
|
| |
| var loadAllPlugins = (function(docPlugins) {
| |
| if (!isPluginsEmpty(docPlugins)) {
| |
| var subTitle = " " + getAllPluginsName(docPlugins).join(", ") + " 플러그인 가동중";
| |
| $("#siteSub").text(function(i, v) {
| |
| return v + subTitle
| |
| });
| |
| }
| |
| })(docPlugins)
| |
| })(docPlugins);
| |
|
| |
| // 사용자가 가지고 있는 플러그인들을 체크합니다.
| |
| var checkHavePlugin = (function() {
| |
| function getUserPlugins(jsdoc) {
| |
| var userplugins = [];
| |
| // plugins.---가 있는지 체크하는 정규식
| |
| var pluginreg = /JSON \=\> ([\S]+) = (\{.*\})/g;
| |
| var nameMatch = pluginreg.exec(jsdoc);
| |
| while (nameMatch) {
| |
| userplugins.push(JSON.parse(nameMatch[2]));
| |
| nameMatch = pluginreg.exec(jsdoc);
| |
| }
| |
| return userplugins;
| |
| }
| |
|
| |
| function isSamePlugin(pluginFirst, pluginSecond) {
| |
| return pluginFirst.name == pluginSecond.name
| |
| }
| |
|
| |
| function isSameVersionPlugin(pluginFirst, plugiSecond) {
| |
| return pluginFirst.version == plugiSecond.version
| |
| }
| |
|
| |
| function addNeedPlugins(targetPlugins) {
| |
| //global docPlugins, needPlugins
| |
| for (var key in targetPlugins) {
| |
| var pluginName = docPlugins[key].name;
| |
| needPlugins.push(pluginName);
| |
| }
| |
| }
| |
|
| |
| if (!isPluginsEmpty(docPlugins)) {
| |
| preloadedplugins = getUserPlugins(jsdoc);
| |
| forEach(docPlugins, function(docplugin) {
| |
| var isHavePlugin = false;
| |
| forEach(preloadedplugins, function(myplugin) {
| |
| if (!isSamePlugin(docplugin, myplugin)) return;
| |
| if (!isSameVersionPlugin(docplugin, myplugin)) {
| |
| unupdatedPlugins[docplugin.name] = docplugin;
| |
| }
| |
| isHavePlugin = true;
| |
| });
| |
|
| |
| if (!isHavePlugin) {
| |
| uninstalledPlugins[docplugin.name] = docplugin;
| |
| }
| |
| });
| |
| addNeedPlugins(uninstalledPlugins);
| |
| addNeedPlugins(unupdatedPlugins);
| |
| }
| |
| })();
| |
|
| |
| function onPluginInstall() {
| |
| function getPluginCode(plugin) {
| |
| // html로 구성된 코드를 텍스트로
| |
| function entityDecode(doc) {
| |
| return $('<p></p>').html(doc).text();
| |
| }
| |
|
| |
| function getDocHead(plugin) {
| |
| var docHead = "";
| |
| var toJSONPlugin = Object.assign({}, plugin);
| |
| toJSONPlugin.code = undefined;
| |
| toJSONPlugin.link = undefined;
| |
| docHead += "\n"
| |
| docHead += "\n/** 플러그인 " + plugin["name"] + "***************************\n";
| |
| docHead += "* " + plugin["descript"] + "\n";
| |
| docHead += "* 버전 => " + plugin["version"] + "\n";
| |
| docHead += "* 작성자 : [[사용자:" + plugin["creat"] + "|" + plugin["creat"] + "]] \n";
| |
| docHead += "* JSON => " + plugin["name"] + " = " + JSON.stringify(toJSONPlugin) + "; \n";
| |
| docHead += "*/ \n";
| |
| docHead += "function plugin_" + plugin["name"] + "(){\n";
| |
| if (plugin.local) docHead += " if($(\"[data-name='" + plugin["name"] + "']\").length >= 1){\n";
| |
| return docHead;
| |
| }
| |
|
| |
| function getDocFoot(plugin) {
| |
| var docFoot = "";
| |
| if (plugin.local) docFoot += "\n }\n";
| |
| docFoot += "\n}\n";
| |
| if (plugin.executable) docFoot += "$( plugin_" + plugin["name"] + " );\n";
| |
| docFoot += "/* " + plugin["name"] + " 끝 */\n\n";
| |
| return docFoot;
| |
| }
| |
|
| |
| var docHead = getDocHead(plugin),
| |
| docFoot = getDocFoot(plugin);
| |
| return entityDecode(docHead + plugin["code"] + docFoot);
| |
| }
| |
|
| |
| $(".install-button").text("설치중..");
| |
| $(".install-button").off("click");
| |
|
| |
| var doc = "";
| |
| forEach(needPlugins, function(pluginName) {
| |
| var plugin = docPlugins[pluginName];
| |
| jsdoc = removePluginByDoc(pluginName, jsdoc);
| |
| doc += getPluginCode(plugin);
| |
| });
| |
| api.changeDocument(commonjs, "플러그인 " + needPlugins + "설치", jsdoc + doc);
| |
| }
| |
|
| |
| var checkinstalledPlugin = function() {
| |
| function appendBox(plugin, status) {
| |
| var pluginName = plugin.name;
| |
| var box = $(".cloneable.p-box").clone().removeClass("cloneable");
| |
| var code = api.readDocument(plugin.state).find("pre.script").html();
| |
| docPlugins[pluginName].code = code;
| |
| box.find(".p-status").html(status);
| |
| box.find(".p-code").html(code.replace(/\s{1,}$/, ""));
| |
| box.find(".p-name").text(pluginName);
| |
| box.find(".p-descript").text(plugin["descript"]);
| |
| if (status == "버전업") {
| |
| var thisVersion;
| |
| for (var key in preloadedplugins) {
| |
| if (preloadedplugins[key].name == plugin["name"]) {
| |
| thisVersion = preloadedplugins[key].version;
| |
| }
| |
| }
| |
| box.find(".p-version").text(thisVersion + " => " + plugin["version"]);
| |
| } else {
| |
| box.find(".p-version").text(plugin["version"]);
| |
| }
| |
| box.find(".p-local").text(plugin["local"] == true ? "일부 문서만" : "문서 전체");
| |
| box.find(".p-creat").text(plugin["creat"]);
| |
| $.ajax({
| |
| url: "/w/api.php?action=query&prop=revisions&rvdir=older&titles=" + plugin.state,
| |
| success: function(v, i) {
| |
| var datas = JSON.parse($(v).find("pre").text());
| |
| var titleKey = Object.keys(datas["query"]["pages"])[0];
| |
| var lastModified = datas["query"]["pages"][titleKey]["revisions"][0]["user"] + "(" + datas["query"]["pages"][titleKey]["revisions"][0]["timestamp"] + ")";
| |
| box.find(".p-last").text(lastModified);
| |
| },
| |
| async: false
| |
| })
| |
| $(".box-article").append(box);
| |
| }
| |
|
| |
| if (isPluginsEmpty(docPlugins) || (isPluginsEmpty(unupdatedPlugins) && isPluginsEmpty(uninstalledPlugins))) return;
| |
| var doc = $("#mw-content-text");
| |
| var setupMeta = api.readDocument("틀:플러그인/setup");
| |
| doc.html(setupMeta);
| |
| forEach(uninstalledPlugins, function(uninstalledPlugin) {
| |
| appendBox(uninstalledPlugin, "설치");
| |
| });
| |
| forEach(unupdatedPlugins, function(unupdatedPlugin) {
| |
| appendBox(unupdatedPlugin, "버전업");
| |
| });
| |
| $(".install-button").on("click", onPluginInstall);
| |
| }
| |
|
| |
| var showPluginTemplet = (function() {
| |
| if (isPluginsEmpty(needPlugins)) {
| |
| return;
| |
| }
| |
|
| |
| if ($(".plugin-install").length >= 1) {
| |
| $(".plugin-install").eq(0).closest("table").show();
| |
| $(".plugin-name").eq(0).text(needPlugins);
| |
| $(".plugin-install").on("click", checkinstalledPlugin);
| |
| } else {
| |
| checkinstalledPlugin();
| |
| }
| |
| })();
| |
| }
| |
| $(pluginCore)
| |
|
| |
| /** paramtest 함수
| |
| * [[틀:CGI2|CGI2]] 등에 적용되는 searchParams 메소드 지원 여부를 판단하는 함수
| |
| * 작성자: [[사용자:Manymaster|manymaster]]
| |
| */
| |
|
| |
| function paramtest() {
| |
| var test_code;
| |
| var Params = new URL(document.location).searchParams;
| |
| if (Params === undefined) {
| |
| test_code = 0;
| |
| } else {
| |
| test_code = 1;
| |
| }
| |
| return test_code;
| |
| }
| |
|
| |
| /** paraminfo 함수
| |
| * paramtest의 부속 함수로 searchParams 메소드 지원시 지정한 메시지를 숨길 수 있게 해주는 함수
| |
| * 메시지는 searchparam_test 클래스로 지정하여 숨길 수 있습니다. */
| |
| function paraminfo() {
| |
| var test_code = paramtest();
| |
| if (test_code == 0) {
| |
| return;
| |
| } else {
| |
| for (var i = 0; i < document.getElementsByClassName("searchparam_test").length; i++) {
| |
| document.getElementsByClassName("searchparam_test")[i].style.display = "none";
| |
| }
| |
| }
| |
| }
| |
|
| |
| $(paraminfo);
| |
| /* paramtest 및 부속 함수 끝 */
| |
|
| |
| /** [[틀:편집불가]] 재 리뉴얼용 함수
| |
| * [[틀:편집불가]]의 브라우저 및 모니터 차별, 3대 원칙 위반 가능 요소 포함 등으로 리뉴얼을 했으나, 리뉴얼한 틀을 소화 못하는 게임이 많아보이는 관계로 재 리뉴얼 합니다.
| |
| * 작성자: [[사용자:Manymaster|manymaster]]
| |
| */
| |
|
| |
| function editprevent() {
| |
| var caprevent = document.getElementsByClassName("edit-prevent");
| |
| var cahisprevent = document.getElementsByClassName("history-prevent");
| |
| if (caprevent[0] === undefined || caprevent[0] === null) {
| |
| return;
| |
| } else {
| |
| if (cahisprevent[0] === undefined || cahisprevent[0] === null) {
| |
| cahisprevent = document.getElementsByClassName("edit-prevent");
| |
| }
| |
| var caedit = document.getElementById('ca-edit');
| |
| var cahistory = document.getElementById('ca-history');
| |
| var caviewsource = document.getElementById('ca-viewsource');
| |
| if (caedit !== null && caedit !== undefined){
| |
| caedit.innerHTML = caprevent[0].innerHTML;
| |
| cahistory.innerHTML = cahisprevent[0].innerHTML;
| |
| } else {
| |
| caviewsource.innerHTML = caprevent[0].innerHTML;
| |
| cahistory.innerHTML = cahisprevent[0].innerHTML;
| |
| }
| |
| }
| |
| return;
| |
| }
| |
| $( editprevent );
| |
| /* [[틀:편집불가]] 재 리뉴얼용 함수 끝 */
| |
|
| |
| /** [[틀:복붙 상자]]용 함수
| |
| * [[틀:자동저장|자동저장 시스템]]이 자동 인증 사용자 전용인 관계로 자동저장 시스템을 사용하지 못하거나 안 하는 사용자를 위해 쉽게 내용을 복붙할 수 있도록 도와주는 함수입니다.
| |
| * 작성자: [[사용자:Manymaster|manymaster]]
| |
| */
| |
| function cvbox() {
| |
|
| |
| var i
| |
| var cvdata = [];
| |
| var box = [];
| |
| var cvbox = [];
| |
|
| |
| /* 틀 사용 여부 확인 */
| |
| for(i = 0;
| |
| document.getElementsByClassName("cvdata")[i] !== undefined &&
| |
| document.getElementsByClassName("box_locator")[i] !== undefined; i++)
| |
| {
| |
|
| |
| /* 복붙 상자에 넣을 내용을 불러오고 문제가 되는 문자열 치환 */
| |
| cvdata.push(document.getElementsByClassName("cvdata")[i].innerHTML);
| |
| cvdata[i] = cvdata[i].replace(/(<([^>]+)>)/ig, "");
| |
| cvdata[i] = cvdata[i].replace(/\n+/gi, "\n");
| |
|
| |
| /* 지정한 위치에 복붙 상자를 만들어 내용 넣기 */
| |
| box.push(document.getElementsByClassName("box_locator")[i]);
| |
| box[i].innerHTML = '<textarea class="ctrlcvbox" onclick="this.focus();this.select()" title="클릭 후 Ctrl+C 등으로 \'복사\'하시면 클립보드에 내용이 저장됩니다." readonly>' + cvdata[i] + '</textarea>';
| |
|
| |
| /* 복붙 상자 크기 조정 */
| |
| cvbox.push(document.getElementsByClassName("ctrlcvbox")[i]);
| |
| cvbox[i].style.height = (2+cvbox[i].scrollHeight)+"px";
| |
| }
| |
| return;
| |
| }
| |
| $( cvbox );
| |
|
| |
| /* [[틀:복붙 상자]]용 함수 끝 */
| |
|
| |
| /** 스크립트의 함수를 실행시키는 링크 만들기
| |
| * $('(객체)').each(function() {
| |
| scriptLink(this);
| |
| $(this).click(function () {
| |
| (함수)
| |
| });
| |
| });
| |
| * 작성자: [[사용자:Gustmd7410|Gustmd7410]] */
| |
|
| |
| function scriptLink(element) {
| |
| $(element).html('<a>' + $(element).html() + '</a>');
| |
| }
| |
|
| |
| /** [[틀:고급 넘겨주기]]에서 사용하는 넘겨주기 함수
| |
| * id="advredirect" data-url="(문서명)"
| |
| * 작성자: [[사용자:Gustmd7410|Gustmd7410]] */
| |
|
| |
| $('#advredirect').each(function() {
| |
| location.replace(location.origin + $(this).data('url'));
| |
| });
| |
|
| |
|
| |
| /** [[틀:비밀링크]]에서 사용하는 리다이렉트 링크 함수
| |
| * class="clearlink" data-url="(문서명)"
| |
| * 작성자: [[사용자:Gustmd7410|Gustmd7410]] */
| |
|
| |
| $('.clearlink').each(function() {
| |
| scriptLink(this);
| |
| $(this).click(function() {
| |
| location.replace(location.origin + $(this).data('url'));
| |
| });
| |
| });
| |
|
| |
|
| |
| /** [[틀:뒤로]], [[틀:새로고침]], [[틀:앞으로]]에서 사용하는 방문기록 이동 함수
| |
| * class="historygo" data-url="(문서명)"
| |
| * 작성자: [[사용자:Gustmd7410|Gustmd7410]] */
| |
|
| |
| $('.historygo').each(function() {
| |
| scriptLink(this);
| |
| $(this).click(function() {
| |
| history.go($(this).data('page'));
| |
| });
| |
| });
| |
|
| |
| /** [[특수:올리기]]에 파일 정보 틀 자동 로드
| |
| * [[w:특수:고유링크/20640234]] 이 스크립트는 위키백과 펌이므로, 위키백과 라이선스인 CCL BY-SA가 적용됩니다.
| |
| */
| |
|
| |
| function uploadPreload() {
| |
| // 새 버전 올리기일 때 동작 안 함
| |
| if (mw.util.getParamValue('wpForReUpload') !== null) return;
| |
|
| |
| // 설명란이 있고 비어있을 때 내용 변경
| |
| var desc = document.getElementById('wpUploadDescription');
| |
| if(desc !== null && desc.value === '' ) {
| |
| desc.value = '{\{파일 정보\n|설명 = \n|출처 = \n|날짜 = \n}}\n';
| |
| }
| |
| }
| |
| jQuery( document ).ready(uploadPreload);
| |
|
| |
| /* [[특수:올리기]]에 파일 정보 틀 자동 로드 끝 */
| |
|
| |
|
| |
| /** [[틀:로고 바꾸기]]용 함수 V 1.1
| |
| * 작성자: [[사용자:Manymaster|manymaster]],
| |
| * 1.1 업데이트: [[사용자:BANIP|BANIP]]
| |
| */
| |
| function logochange() {
| |
| // 허용 확장자 및 url 패턴
| |
| var allwedURLPattern = ["i.uncyclopedia.kr/game/","i.uncyclopedia.kr/pedia/","upload.wikimedia.org/wikipedia/commons/"]
| |
| var allowedExt = ["gif","png","jpg","jpeg","svg"]
| |
|
| |
| const logoElement = document.getElementsByClassName("changelogo123");
| |
| /* .changelogo 요소가 없으면 종료 */
| |
| if (logoElement.length === 0) {
| |
| return;
| |
|
| |
| }
| |
|
| |
| var logoTest = logoElement[0].innerHTML.toLowerCase();
| |
| //이미지 url이 주어진 조건에 맞는지 검사
| |
| var isSafeURL = allwedURLPattern.some( function(middleURL){
| |
| var reg = new RegExp("//" + middleURL)
| |
| return ( logoTest.match(reg) != null)
| |
| })
| |
| var isSafeExt = allowedExt.some( function(ext){
| |
| var reg = new RegExp("\." + ext + "$")
| |
| return ( logoTest.match(reg) != null)
| |
| })
| |
|
| |
| // URL패턴과 확장자의 조건이 맞지 않으면 종료
| |
| if ( !(isSafeURL && isSafeExt) ) {
| |
| return;
| |
| }
| |
|
| |
| /* 로고 교체 */
| |
| var orglogoElement = document.querySelector("#p-logo a");
| |
| orglogoElement.style.backgroundImage = "url('" + logoElement[0].innerHTML + "')";
| |
| /* 사이즈 교체 */
| |
| var widthElement = document.querySelector(".changelogowidth");
| |
| widthElement.innerHTML = widthElement === null ? "160px" : widthElement.innerHTML;
| |
| var heightElement = document.querySelector(".changelogoheight");
| |
| heightElement.innerHTML = heightElement === null ? "160px" : heightElement.innerHTML;
| |
| orglogoElement.style.backgroundSize = widthElement.innerHTML + " " + heightElement.innerHTML;
| |
|
| |
| }
| |
| $(logochange);
| |
| /* [[틀:로고 바꾸기]]용 함수 끝 */
| |
|
| |
| /**
| |
| * [[백괴게임:댸문]]문서의 일부 링크를 낚시문서로 바꿔치기
| |
| * 원작성자: [[사용자:BANIP|BANIP]]
| |
| */
| |
| $(function(){
| |
| var gate = document.getElementsByClassName("fakegate");
| |
| if (gate[0] === undefined || gate[0] === null) {
| |
| return;
| |
| } else{
| |
| var targetLink = "https://libertygame.miraheze.org/wiki/"+gate[0].innerHTML;
| |
| $("#bodyContent a").attr("href",targetLink);
| |
| }
| |
| })
| |
| /* [[백괴게임:댸문]]문서의 일부 링크를 낚시문서로 바꿔치기 끝 */
| |
|
| |
|
| |
| /**
| |
| * pluginX Core
| |
| * pluginX 시스템이 제대로 돌아가게 해 줍니다.
| |
| * 작성자: [[사용자:Bd3076|Bd3076]]
| |
| */
| |
|
| |
| function pluginXCore() {
| |
| var api = MediaWikiAPI();
| |
| var ipUser = false;
| |
|
| |
| if(mw.config.get("wgUserName") === null) ipUser = true;
| |
|
| |
| var script_list = [];
| |
| var pluginExist = false;
| |
| var neededPluginExist = false;
| |
| var html_before;
| |
| var jsonDoc = "사용자:" + mw.config.get("wgUserName") + "/pluginX.json";
| |
| var jsonData = JSON.parse(api.getDocument(jsonDoc));
| |
|
| |
| /// 플러그인의 정보가 담긴 데이터를 만듭니다.
| |
| var generateScriptData = function(_url, _name, _creator, _doc, _script, _revid){
| |
| return {
| |
| url: _url,
| |
| name: _name,
| |
| creator: _creator,
| |
| doc: _doc,
| |
| script: _script,
| |
| revid: _revid
| |
| };
| |
| };
| |
|
| |
| /// 플러그인 목록을 만들어서 script_list[]에 담습니다.
| |
| var getPluginList = function(){
| |
| $(".c_pluginX").each(function() {
| |
| pluginExist = true;
| |
| var url = $(this).attr('data-url');
| |
| var name = $(this).attr('data-name');
| |
| var creator = $(this).attr('data-creator');
| |
| var doc = $(this).attr('data-doc');
| |
| var revid = $(this).attr('data-revid');
| |
|
| |
| var script = api.getDocument(doc);
| |
|
| |
| script_list.push(generateScriptData(url, name, creator, doc, script, revid));
| |
|
| |
| if(jsonData[doc] === undefined || jsonData[doc] !== revid){
| |
| console.log(name);
| |
| neededPluginExist = true;
| |
| }
| |
| });
| |
| };
| |
|
| |
| /// 플러그인을 실행합니다.
| |
| var executePlugins = function(){
| |
| script_list.forEach(function(data){
| |
| var link = data.url;
| |
| var revid = data.revid;
| |
| var doc = data.doc;
| |
|
| |
| if(neededPluginExist){
| |
| jsonData[doc] = revid;
| |
| }
| |
|
| |
| $.getScript(link);
| |
| });
| |
|
| |
| ///자동 인증된 사용자가 플러그인을 실행할 경우 json을 갱신합니다.
| |
| var userGroups = mw.config.get('wgUserGroups');
| |
| var autocheck = 0;
| |
| if (userGroups) {
| |
| for (var i = 0; i < userGroups.length; i++) {
| |
| if (userGroups[i] === 'autoconfirmed') {
| |
| autocheck++;
| |
| }
| |
| }
| |
| }
| |
| if(neededPluginExist && !(autocheck == 0) ){
| |
| api.changeDocument(jsonDoc, "pluginX - 새로운 플러그인", JSON.stringify(jsonData));
| |
| }
| |
| };
| |
|
| |
| /// 플러그인을 실행하지 않습니다.
| |
| var doNotExecutePlugins = function(){
| |
| document.getElementById('mw-content-text').innerHTML = html_before;
| |
| };
| |
|
| |
| /// 알림 창을 만듭니다.
| |
| var showWindow = function(){
| |
| html_before = document.getElementById('mw-content-text').innerHTML;
| |
| $('#mw-content-text').html(api.readDocument("틀:PluginX/setup"));
| |
| var script = "";
| |
|
| |
| script_list.forEach(function(data){
| |
| var addingCode;
| |
| addingCode = '<div class="px-code"><pre>';
| |
| addingCode = addingCode.concat(((data.script.replace(/&/g, '&')).replace(/</g, '<')).replace(/>/g, '>'));
| |
| addingCode = addingCode.concat('</pre> </div> <div class="px-codeinfo"> <ul> <li> 플러그인 이름: ');
| |
| addingCode = addingCode.concat(data.name);
| |
| addingCode = addingCode.concat('</li> <li> 플러그인 제작자: ');
| |
| addingCode = addingCode.concat(data.creator);
| |
| addingCode = addingCode.concat('</li> </ul> </div>');
| |
|
| |
| // 위험 코드 탐지 시작
| |
| var pattern;
| |
| var nscode = data.script.replace(/\r?\n|\r/g, ' ');
| |
|
| |
| // 패턴 1. document.innerHTML 사용 (위험도: 심각)
| |
| pattern = new RegExp("^.*document *\. *innerHTML.*$");
| |
|
| |
| if(pattern.test(nscode)){
| |
| addingCode = addingCode.concat('<div class="px-critical">이 플러그인은 문서 열람 시 지장을 줄 수 있습니다.<br>플러그인 제작자를 신뢰할 수 있는 경우에만 실행하시기 바랍니다.</div>');
| |
| }
| |
|
| |
| // 패턴 2. document.write 사용 (위험도: 심각)
| |
| pattern = new RegExp("^.*document *\. *write.*$");
| |
|
| |
| if(pattern.test(nscode)){
| |
| addingCode = addingCode.concat('<div class="px-critical">이 플러그인은 문서 내용을 왜곡시킬 수 있습니다.<br>플러그인 제작자를 신뢰할 수 있는 경우에만 실행하시기 바랍니다.</div>');
| |
| }
| |
|
| |
| // 패턴 3. "wgUserName" 사용 (위험도: 안내)
| |
| pattern = new RegExp('^.*"wgUserName".*$');
| |
|
| |
| if(pattern.test(nscode)){
| |
| addingCode = addingCode.concat('<div class="px-notice">이 플러그인은 당신의 사용자 이름을 수집합니다.<br>이를 원치 않으시면 플러그인을 실행하지 마시기 바랍니다.</div>');
| |
| }
| |
|
| |
| //패턴 4. MediaWikiAPI.changeDocument 사용(위험도: 경고)
| |
| pattern = new RegExp('^.*MediaWikiAPI.*changeDocument.*$');
| |
|
| |
| if(pattern.test(nscode)){
| |
| addingCode = addingCode.concat('<div class="px-warning">이 플러그인은 다른 문서를 편집합니다.<br>이 게임이 계정 생성형 게임일 가능성이 높습니다.<br>플러그인 제작자를 신뢰할 수 있는 경우에만 실행하시기 바랍니다.</div>');
| |
| }
| |
|
| |
| script += addingCode;
| |
| });
| |
|
| |
| document.getElementById('px-script').innerHTML = script;
| |
|
| |
| $('#px-button').on('click', executePlugins);
| |
| $('#px-button2').on('click', doNotExecutePlugins);
| |
| };
| |
|
| |
| getPluginList();
| |
|
| |
| if(pluginExist === false) return;
| |
|
| |
| if(neededPluginExist === false){
| |
| executePlugins();
| |
| return;
| |
| }
| |
| else{
| |
| showWindow();
| |
| return;
| |
| }
| |
| }
| |
| $(pluginXCore);
| |
|
| |
| /* pluginX Core 끝 */
| |
|
| |
| /** 플러그인 inputform
| |
| * 완전한 입력기를 구현합니다. (베타)
| |
| * 작성자 : [[사용자:Gustmd7410|Gustmd7410]]
| |
| */
| |
| function plugin_inputform(){
| |
| // 이부분에 코드 입력 //
| |
| mw.loader.using('oojs-ui-core').done(function () {
| |
| function toBool(value) {
| |
| switch (value) {
| |
| case undefined: return false;
| |
| case '': return true;
| |
| }
| |
| }
| |
| function toArray(value) {
| |
| if (value)
| |
| return value.split(' ');
| |
| else
| |
| return undefined;
| |
| }
| |
| function InpTable(table) {
| |
| this["case"] = {};
| |
| this["default"] = Object.assign({
| |
| prefix: '',
| |
| value: undefined,
| |
| suffix: '',
| |
| replace: [],
| |
| sub: [0]
| |
| }, table["default"]);
| |
| if (table["case"]) {
| |
| for (var value in table["case"]) {
| |
| this["case"][value] = Object.assign({}, this["default"], { value: this["default"].value || value }, table["case"][value]);
| |
| }
| |
| }
| |
| }
| |
| $('.input-form').each(function () {
| |
| var container = this;
| |
| $(this).html(new $('<form />', {
| |
| "class": $(this).data('class'),
| |
| id: $(this).data('id'),
| |
| style: $(this).data('style'),
| |
| 'accept-charset': 'UTF-8',
| |
| autocomplete: toBool($(this).data('autocomplete')),
| |
| novalidate: toBool($(this).data('novalidate')),
| |
| html: $(this).html()
| |
| }));
| |
| $(this).children('form').submit(function (event) {
| |
| event.preventDefault();
| |
| var action = new URL('/w/index.php', location);
| |
| if (toBool($(container).data('pass')))
| |
| action.search = location.search;
| |
| if ($(container).data('get'))
| |
| new URLSearchParams($(container).data('get')).forEach(function (value, key) {
| |
| action.searchParams.set(key, value);
| |
| });
| |
| action.searchParams.set('title', $(container).data('title'));
| |
| $(this).children('.input-field').each(function () {
| |
| if (typeof ($(this).data('table')) == 'object') {
| |
| var name = $(this).data('name');
| |
| var rawval = $(this).find('input').val();
| |
| var table = new InpTable($(this).data('table'));
| |
| var cvttbl = table["case"][rawval] || table["default"];
| |
| var cvtval = (cvttbl.value || rawval).slice(cvttbl.sub[0], cvttbl.sub[1]);
| |
| cvttbl.replace.forEach(function (reparr) {
| |
| var regex = reparr[0].substr(1).split('/');
| |
| regex.pop();
| |
| regex = regex.join('/');
| |
| var flag = reparr[0].substr(1).split('/').reverse()[0];
| |
| cvtval = cvtval.replace(new RegExp(regex, flag), reparr[1]);
| |
| });
| |
| action.searchParams.set(name, cvttbl.prefix + cvtval + cvttbl.suffix);
| |
| }
| |
| else
| |
| action.searchParams.set($(this).data('name'), $(this).find('input').val());
| |
| });
| |
| location.href = action.href;
| |
| });
| |
| });
| |
| $('.input-field').each(function () {
| |
| $(this).html(new OO.ui.TextInputWidget({
| |
| accessKey: $(this).data('accessKey'),
| |
| autocomplete: toBool($(this).data('autocomplete')),
| |
| autofocus: toBool($(this).data('autofocus')),
| |
| classes: toArray($(this).data('classes')),
| |
| disabled: toBool($(this).data('disabled')),
| |
| flags: toArray($(this).data('flags')),
| |
| icon: $(this).data('icon'),
| |
| iconTitle: $(this).data('iconTitle'),
| |
| id: $(this).data('id'),
| |
| indicator: $(this).data('indicator'),
| |
| indicatorTitle: $(this).data('indicatorTitle'),
| |
| inputId: $(this).data('inputId'),
| |
| maxLength: Number($(this).data('maxLength')),
| |
| name: $(this).data('name'),
| |
| placeholder: $(this).data('placeholder'),
| |
| readOnly: toBool($(this).data('readOnly')),
| |
| required: toBool($(this).data('required')),
| |
| spellcheck: toBool($(this).data('spellcheck')),
| |
| tabIndex: Number($(this).data('tabIndex')),
| |
| text: $(this).data('text'),
| |
| title: $(this).data('title'),
| |
| type: $(this).data('type'),
| |
| validate: (function(container) {
| |
| if ($(container).data('validatetype') == 'RegExp') {
| |
| var value = $(container).data('validate').substr(1).split('/');
| |
| return RegExp(value[0], value[1]);
| |
| }
| |
| else
| |
| return $(container).data('validate');
| |
| })(this),
| |
| value: this.dataset.value || ''
| |
| }).$element);
| |
|
| |
| if(toBool($(this).data('inline'))) $(this).find('*').css({
| |
| display: 'inline',
| |
| width: 'auto'
| |
| });
| |
| });
| |
| $('.input-button').each(function () {
| |
| $(this).html(new OO.ui.ButtonInputWidget({
| |
| accessKey: $(this).data('accessKey'),
| |
| classes: toArray($(this).data('classes')),
| |
| disabled: toBool($(this).data('disabled')),
| |
| flags: toArray($(this).data('flags')),
| |
| framed: toBool($(this).data('framed')),
| |
| icon: $(this).data('icon'),
| |
| iconTitle: $(this).data('iconTitle'),
| |
| id: $(this).data('id'),
| |
| indicator: $(this).data('indicator'),
| |
| indicatorTitle: $(this).data('indicatorTitle'),
| |
| inputId: $(this).data('inputId'),
| |
| label: $(this).data('label'),
| |
| name: $(this).data('name'),
| |
| tabIndex: Number($(this).data('tabIndex')),
| |
| text: $(this).data('text'),
| |
| title: $(this).data('title'),
| |
| type: $(this).data('type'),
| |
| value: $(this).data('value')
| |
| }).$element);
| |
| });
| |
| noPlugin('input');
| |
| });
| |
| }
| |
| $( plugin_inputform );
| |
| /* inputform 끝 */
| |
|
| |
| /** [[틀:SCGI]]에서 사용하는 링크 리다이렉트 함수
| |
| * class="scgi-use"
| |
| * 작성자: [[사용자:Gustmd7410|Gustmd7410]]
| |
| **/
| |
| $(function useSCGI() {
| |
| if(!URLSearchParams) return;
| |
|
| |
| $('.scgi-use a').each(function() {
| |
| var href = new URL(this.href);
| |
| var params = new URLSearchParams(location.search);
| |
|
| |
| if(
| |
| location.host === href.host && (
| |
| location.pathname === '/w/index.php' && params.get('title') ||
| |
| location.pathname.startsWith('/wiki/') && location.pathname.replace('/wiki/', '')
| |
| ) === (
| |
| href.pathname === '/w/index.php' && params.searchParams.get('title') ||
| |
| href.pathname.startsWith('/wiki/') && href.pathname.replace('/wiki/', '')
| |
| ) && params.get('action') === href.searchParams.get('action')
| |
| ) $(this).click(function(event) {
| |
| event.preventDefault();
| |
| location.replace(event.currentTarget.href);
| |
| });
| |
| });
| |
| });
| |
|
| |
| /* [[틀:SCGI]]에서 사용하는 링크 리다이렉트 함수 끝 */
| |
|
| |
|
| /** 편집 저장시 다른 문서나 CGI로 넘겨주기 | | /** 편집 저장시 다른 문서나 CGI로 넘겨주기 |
1,560번째 줄: |
141번째 줄: |
|
| |
|
| /* 편집 저장시 다른 문서나 CGI로 넘겨주기 끝 */ | | /* 편집 저장시 다른 문서나 CGI로 넘겨주기 끝 */ |
|
| |
| /** JSON 편집을 편리하게 해 주는 기능.
| |
| * [[틀:JSON수정]]을 위한 플러그인입니다.
| |
| * 작성자: [[사:Bd3076|Bd3076]]
| |
| */
| |
|
| |
| function uncy_jsonEdit(){
| |
| var mp = new Map();
| |
| var api = MediaWikiAPI();
| |
|
| |
| $('.uncy-jsonedit').each(function() {
| |
| var jsonDoc = $(this).attr("data-title");
| |
| if (jsonDoc.indexOf("/pluginX.json") !== -1) {
| |
| console.log("사용자의 pluginX JSON은 안돼요!");
| |
| return;
| |
| }
| |
| var jsonData;
| |
| if(mp.get(jsonDoc) === undefined){
| |
| jsonData = JSON.parse(api.getDocument(jsonDoc));
| |
| }
| |
| else{
| |
| jsonData = JSON.parse(mp.get(jsonDoc));
| |
| }
| |
| var variable = $(this).attr("data-var");
| |
| var value = $(this).attr("data-val");
| |
| var reset = $(this).attr("data-reset");
| |
|
| |
| if(reset === "1") jsonData = {};
| |
| else jsonData[variable] = value;
| |
|
| |
| mp.set(jsonDoc, JSON.stringify(jsonData));
| |
| console.log(jsonDoc);
| |
| console.log(JSON.stringify(jsonData));
| |
| });
| |
|
| |
| mp.forEach(function(value, key) {
| |
| if(key === undefined){
| |
| console.log("error: document name is undefined");
| |
| return;
| |
| }
| |
| if(value === undefined){
| |
| console.log("error: variable or value is wrong");
| |
| return;
| |
| }
| |
| api.changeDocument(key, "JSON 데이터 수정", value, 1, 1);
| |
| mw.loader.using( ['mediawiki.notify','mediawiki.Title'] ).then( function () {
| |
| mw.notify('JSON 데이터가 수정되었습니다.');
| |
| });
| |
| });
| |
| }
| |
| $(uncy_jsonEdit);
| |
|
| |
| /* JSON 편집을 편리하게 해 주는 기능 끝 */
| |
|
| |
|
|
| |
|
1,697번째 줄: |
225번째 줄: |
| /* [[틀:자동저장]]용 문서 미리 비워놓기 끝 */ | | /* [[틀:자동저장]]용 문서 미리 비워놓기 끝 */ |
|
| |
|
| /** 진동 구현 | | |
| * 작성자: 사용자:아라 | | /** mediawiki api를 통해 간단하게 문서들을 수집, 변경하는 함수. |
| | * @deprecated |
| | * 이 기능은 사용을 권장하지 않습니다. 대신 mw.Api를 사용해 주세요. (참조: https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api) |
| | * 동기 XHR은 정보를 가져오는 동안 페이지를 멈춰 현저한 성능 저하를 야기하여 WHATWG 표준에서 제외되었고, 이에 따라 최신 브라우저에서 작동하지 않게 되었습니다. |
| | * MediaWikiAPI는 동기 XHR 기능에 의존하도록 설계되었고, 이 기능을 사용하는 모든 기능들은 작동을 보장할 수 없게 되었습니다. |
| | * |
| | * 플러그인 코어에서 사용하기 위해 만들었습니다. |
| | * 원작성자: [[사용자:BANIP|BANIP]], 수정자: [[사용자:Bd3076|Bd3076]] |
| | * 사용방법 |
| | *: var api = MediaWikiAPI(); .changeDocument() |
| | *: api.changeDocument(변경할 문서의 타이틀, 편집 요약, 변경할 문서의 내용) => 문서의 내용을 변경합니다. |
| | *: api.addDocument(변경할 문서의 타이틀, 편집 요약, 추가할 문서의 내용) => 문서에 새로운 내용을 추가합니다. |
| | *: api.getDocument(가져올 문서의 타이틀) => 문서의 모든 텍스트를 읽어옵니다. |
| | *: api.readDocument(가져올 문서의 타이틀) => 문서의 모든 텍스트를 jquery 객체로 읽어옵니다. |
| | * 영 좋지 않은 목적으로 사용 하면 안드로메다 경찰관이 잡아간다! |
| */ | | */ |
|
| |
|
| function Vibration(duration) { | | function MediaWikiAPI() { |
| if (!document.getElementById('vibrate')) return; | | console.warn('권장하지 않는 MediaWikiAPI를 사용하고 있습니다. 대신 mw.Api를 사용해 주세요.'); |
| if (!duration) duration = 100; | | |
| if (duration > 1000) duration = 1000; | | var token; |
| navigator.vibrate(duration); | | var getToken = function() { |
| } | | if (token !== undefined) return token; |
| $(function() { | | $.ajax({ |
| Vibration(100);
| | url: "/api.php?action=query&meta=tokens", // Note: URL은 서버 디렉토리 설정에 따라 바꾸어야 합니다. |
| }); | | success: function(v, i) { |
| /* 진동 구현 끝 */ | | var datas = JSON.parse($(v).find("pre").text()); |
| | token = datas.query.tokens.csrftoken; |
| | }, |
| | async: false |
| | }); |
| | return token; |
| | }; |
| | |
| | function changeDocument(title, summary, content, isUnReload, minor) { |
| | mw.loader.using( ['mediawiki.util','mediawiki.Title'] ).then( function () { |
| | $.ajax({ |
| | url: mw.util.wikiScript("api"), |
| | data: { |
| | format: 'json', |
| | action: 'edit', |
| | title: title, |
| | summary: summary, |
| | text: content, |
| | minor: minor, |
| | token: getToken(), |
| | }, |
| | dataType: 'json', |
| | type: 'POST', |
| | success: function(data) { |
| | if (data && data.edit && data.edit.result == 'Success') { |
| | if (!isUnReload) window.location.reload(); // reload page if edit was successful |
| | } else if (data && data.error) { |
| | alert('Error: API returned error code "' + data.error.code + '": ' + data.error.info); |
| | } else { |
| | alert('Error: Unknown result from API.'); |
| | } |
| | }, |
| | error: function(xhr) { |
| | alert('Error: Request failed.'); |
| | } |
| | }); |
| | } ); |
| | } |
| | |
| | function addDocument(title, summary, content, isUnReload, minor) { |
| | originContent = getDocument(title); |
| | changeDocument(title, summary, originContent + content, isUnReload, minor); |
| | } |
| | |
| | function getDocument(title) { |
| | function entityDecode(doc) { |
| | return $('<p></p>').html(doc).text(); |
| | } |
| | |
| | var originContent; |
| | $.ajax({ |
| | url: "/" + wgScriptPath + "?title=" + title + "&action=edit", |
| | success: function ajaxSucess(data) { |
| | originContent = $(data).find("textarea").html(); |
| | }, |
| | async: false |
| | }); |
| | return entityDecode(originContent); |
| | } |
| | |
| | function readDocument(title) { |
| | var doc; |
| | $.ajax({ |
| | url: "/" + wgScriptPath + "/" + title, |
| | success: function ajaxSucess(data) { |
| | doc = $(data).find("#mw-content-text"); |
| | }, |
| | async: false |
| | }); |
| | return doc; |
| | } |
|
| |
|
| /** 게임 컨트롤러 진동 구현
| |
| * 작성자: 사용자:아라 (사용자 공대여자 소스 참조)
| |
| */
| |
| function GamepadVibration(idx, duration) {
| |
| if (!document.getElementById('vibrate')) return;
| |
| var gamepads = navigator.getGamepads();
| |
| if (!idx) idx = 0;
| |
| if (!gamepads[idx]) return;
| |
| var pad = gamepads[idx];
| |
| if (!duration) duration = 100;
| |
| if (duration > 1000) duration = 1000;
| |
| pad.vibrationActuator.playEffect(pad.vibrationActuator.type, {
| |
| startDelay: 0,
| |
| duration: duration,
| |
| weakMagnitude: 0.5,
| |
| strongMagnitude: 1
| |
| });
| |
| }
| |
| $(function() {
| |
| GamepadVibration(0, 100);
| |
| });
| |
| /* 게임 컨트롤러 진동 구현 끝 */
| |
|
| |
|
| /** TTS 지원
| | return { |
| * class="speech" (lang="") (data-pitch="") (data-rate="") (data-volume="")
| | getToken: getToken, |
| * 제작자: [[사용자:hsl0]]
| | changeDocument: changeDocument, |
| **/
| | addDocument: addDocument, |
| var voiceSettings = {};
| | getDocument: getDocument, |
| voiceSettings.default = {
| | readDocument: readDocument, |
| voice: null,
| | }; |
| pitch: 1,
| |
| rate: 1,
| |
| volume: 1
| |
| };
| |
| function speakSpeech() {
| |
| var ssu, setting;
| |
|
| |
| if(!('notts' in geturlSearch() || window.disableTTS)) Array.from(document.getElementsByClassName('speech')).forEach(function(elem) {
| |
| ssu = new SpeechSynthesisUtterance(elem.innerText);
| |
|
| |
| ssu.lang = elem.lang;
| |
| setting = Object.assign({}, voiceSettings.default, voiceSettings[ssu.lang]);
| |
| if(setting.voice) ssu.voice = setting.voice;
| |
| if(!isNaN(elem.dataset.pitch)) ssu.pitch = setting.pitch * elem.dataset.pitch;
| |
| if(!isNaN(elem.dataset.rate)) ssu.rate = setting.rate * elem.dataset.rate;
| |
| if(!isNaN(elem.dataset.volume)) ssu.volume = setting.volume * elem.dataset.volume;
| |
|
| |
| speechSynthesis.speak(ssu);
| |
| });
| |
| } | | } |
| $(speakSpeech);
| |
| /* TTS 끝 */
| |
|
| |
| /**
| |
| * punycode.js - 퓨니코드 처리 라이브러리
| |
| * DB2에서 미디어위키 옵션 저장소 키의 문자열 제한 우회를 위해 사용중
| |
| * 제작자: bestiejs - https://github.com/bestiejs/punycode.js
| |
| * 라이선스: MIT 라이선스
| |
| * 출처: CDNJS - https://cdnjs.cloudflare.com/ajax/libs/punycode/1.4.1/punycode.min.js
| |
| **/
| |
| !function(e){function o(e){throw new RangeError(T[e])}function n(e,o){for(var n=e.length,r=[];n--;)r[n]=o(e[n]);return r}function r(e,o){var r=e.split("@"),t="";r.length>1&&(t=r[0]+"@",e=r[1]),e=e.replace(S,".");var u=e.split("."),i=n(u,o).join(".");return t+i}function t(e){for(var o,n,r=[],t=0,u=e.length;u>t;)o=e.charCodeAt(t++),o>=55296&&56319>=o&&u>t?(n=e.charCodeAt(t++),56320==(64512&n)?r.push(((1023&o)<<10)+(1023&n)+65536):(r.push(o),t--)):r.push(o);return r}function u(e){return n(e,function(e){var o="";return e>65535&&(e-=65536,o+=P(e>>>10&1023|55296),e=56320|1023&e),o+=P(e)}).join("")}function i(e){return 10>e-48?e-22:26>e-65?e-65:26>e-97?e-97:b}function f(e,o){return e+22+75*(26>e)-((0!=o)<<5)}function c(e,o,n){var r=0;for(e=n?M(e/j):e>>1,e+=M(e/o);e>L*C>>1;r+=b)e=M(e/L);return M(r+(L+1)*e/(e+m))}function l(e){var n,r,t,f,l,s,d,a,p,h,v=[],g=e.length,w=0,m=I,j=A;for(r=e.lastIndexOf(E),0>r&&(r=0),t=0;r>t;++t)e.charCodeAt(t)>=128&&o("not-basic"),v.push(e.charCodeAt(t));for(f=r>0?r+1:0;g>f;){for(l=w,s=1,d=b;f>=g&&o("invalid-input"),a=i(e.charCodeAt(f++)),(a>=b||a>M((x-w)/s))&&o("overflow"),w+=a*s,p=j>=d?y:d>=j+C?C:d-j,!(p>a);d+=b)h=b-p,s>M(x/h)&&o("overflow"),s*=h;n=v.length+1,j=c(w-l,n,0==l),M(w/n)>x-m&&o("overflow"),m+=M(w/n),w%=n,v.splice(w++,0,m)}return u(v)}function s(e){var n,r,u,i,l,s,d,a,p,h,v,g,w,m,j,F=[];for(e=t(e),g=e.length,n=I,r=0,l=A,s=0;g>s;++s)v=e[s],128>v&&F.push(P(v));for(u=i=F.length,i&&F.push(E);g>u;){for(d=x,s=0;g>s;++s)v=e[s],v>=n&&d>v&&(d=v);for(w=u+1,d-n>M((x-r)/w)&&o("overflow"),r+=(d-n)*w,n=d,s=0;g>s;++s)if(v=e[s],n>v&&++r>x&&o("overflow"),v==n){for(a=r,p=b;h=l>=p?y:p>=l+C?C:p-l,!(h>a);p+=b)j=a-h,m=b-h,F.push(P(f(h+j%m,0))),a=M(j/m);F.push(P(f(a,0))),l=c(r,w,u==i),r=0,++u}++r,++n}return F.join("")}function d(e){return r(e,function(e){return F.test(e)?l(e.slice(4).toLowerCase()):e})}function a(e){return r(e,function(e){return O.test(e)?"xn--"+s(e):e})}var p="object"==typeof exports&&exports&&!exports.nodeType&&exports,h="object"==typeof module&&module&&!module.nodeType&&module,v="object"==typeof global&&global;v.global!==v&&v.window!==v&&v.self!==v||(e=v);var g,w,x=2147483647,b=36,y=1,C=26,m=38,j=700,A=72,I=128,E="-",F=/^xn--/,O=/[^\x20-\x7E]/,S=/[\x2E\u3002\uFF0E\uFF61]/g,T={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},L=b-y,M=Math.floor,P=String.fromCharCode;if(g={version:"1.4.1",ucs2:{decode:t,encode:u},decode:l,encode:s,toASCII:a,toUnicode:d},"function"==typeof define&&"object"==typeof define.amd&&define.amd)define("punycode",function(){return g});else if(p&&h)if(module.exports==p)h.exports=g;else for(w in g)g.hasOwnProperty(w)&&(p[w]=g[w]);else e.punycode=g}(this);
| |
| //# sourceMappingURL=./punycode.min.js.map
| |
| /* punycode.js 끝 */
| |
|
| |
|
| /** @function fetchScript | | /** @function fetchScript |
1,799번째 줄: |
357번째 줄: |
| }); | | }); |
| } : $.getScript; | | } : $.getScript; |
| | | /** |
| /** [[틀:DB2]]
| | * API 에러가 반환될 경우 알려주는 함수 |
| * 제작자: [[사용자:hsl0]] | | * 저작자: [[사용자:hsl0|hsl0]] |
| | **/ |
| | function notifyApiError(msg, option, code, object) { |
| | option = option || {}; |
| | mw.notification.notify( |
| | code === 'http'? |
| | $('<span />') |
| | .append($('<p />', {class: 'api-errmsg'}).text(object.xhr.responseText).html(option.additionalMessage || '')) |
| | .append($('<code />', {class: 'api-errcode'}).text('HTTP ' + object.xhr.status)) : |
| | $('<span />') |
| | .append($('<p />', {class: 'api-errmsg'}).text(object.error.info).html(option.additionalMessage || '')) |
| | .append($('<code />', {class: 'api-errcode'}).text(code)), |
| | { |
| | title: msg, |
| | type: 'error', |
| | tag: option.tag, |
| | autoHideSeconds: 'long' |
| | } |
| | ); |
| | } |
| | /** 링크경고 |
| | * 자바스크립트로 링크에 경고를 넣을 수 있습니다. |
| | * 제작자: [[사용자:hsl0|hsl0]] |
| **/ | | **/ |
| mw.loader.using([
| | function linkWarn(element, msg, msgClass) { |
| 'mediawiki.notification',
| | return $(element) |
| 'oojs-ui-core'
| | .addClass('linkwarn tooltip') |
| ]);
| | .append($('<span class="tooltip-msg" />').append(msg).addClass(msgClass || 'messagebox')); |
| function enableDB2() {
| | } |
| var title = mw.config.get('wgPageName').split('/')[0].split(':');
| |
| title = title[0].replace(/talk|토론/gi, '') + ':' + title[1];
| |
| var noti;
| |
| var currentUrl = new mw.Title(mw.config.get('wgPageName')).getUrl(geturlSearch());
| |
|
| |
|
| /* option key 인코딩
| | /** |
| 퓨니코드 + url인코딩
| | * [[리버티게임:오락실/2023년_8월#사이드바 '임의의 게임으로' 기능 관련]] |
| % = _
| | * --[[사용자:BANIP|BANIP]] ([[사용자토론:BANIP|토론]]) 2023년 8월 14일 (월) 10:36 (KST) |
| _ = __
| | */ |
| */
| | $(function(){ |
| function encode(key) {
| | var triggered = false; |
| return encodeURIComponent(punycode.toASCII(key))
| | var $linkwrapper = $("#n-randompage, .move-randompage").find("a"); |
| .replace(/\./g, '%2E')
| | //[[틀:임의_게임]] 구현, 사이드바 임의게임으로 링크 바인딩 |
| .replace(/!/g, '%21')
| | $linkwrapper.on("click",function(e){ |
| .replace(/~/g, '%7E')
| | var category = $(this).closest(".move-randompage").data("category") || undefined |
| .replace(/\*/g, '%2A')
| | e.preventDefault(); |
| .replace(/'/g, '%27')
| | if(triggered) return; |
| .replace(/\(/g, '%28')
| | triggered = true; |
| .replace(/\)/g, '%29')
| |
| .replace(/_/g, '__')
| |
| .replace(/%/g, '_'); | |
| }
| |
| function decode(key) {
| |
| return punycode.toUnicode(decodeURIComponent(key.replace(/_(?=[a-zA-Z0-9]{2})/g, '%').replace(/__/g, '_'))); | |
| }
| |
|
| |
|
| function parseJSON(json) {
| | (new mw.Api()).get({ |
| try {
| | action: 'parse', |
| return JSON.parse(json);
| | page: '리버티게임:임의 게임', |
| } catch(e) {
| | formatversion: 2, |
| return;
| | category:category |
| }
| | }).then(function(res){ |
| }
| | var page = $(res.parse.text).find(".redirect-random-page").text().trim(); |
| | location.href = mw.util.getUrl(page); |
| | }).catch(function(){ |
| | location.href = mw.util.getUrl("리버티게임:임의 게임",{category:category}); |
| | }); |
| | }).attr("rel","nofollow"); |
|
| |
|
| // hybridStorage 서브셋 생성
| | //[[리버티게임:임의_게임]] 구현 |
| window.setStoragePrefix = function(storage, prefix, except, needEncode) {
| | if($("#content .redirect-random-page").length){ |
| if(mw.user.isAnon()) needEncode = false;
| | history.replaceState(null, null, mw.util.getUrl($("#content .redirect-random-page").text().trim())); |
| | location.reload(); |
| | } |
| | }); |
|
| |
|
| var spp = new Proxy(storage, {
| | /** |
| get: function(target, prop, receiver) {
| | * 리버티게임 인기 게임 순위 정렬 |
| function keys() {
| | * ver 1.2.1 --{{사용자:Senouis/서명}} 2024년 9월 15일 (일) 16:43 (KST) |
| return Object.keys(target).filter(function(key) {
| | */ |
| return key.startsWith(prefix);
| | $(function (){ |
| });
| | var sectionRatings = document.getElementsByClassName("section-ratings"); |
| }
| | var sectionRatings_param = "4"; |
|
| | if (sectionRatings.length === 0) return; |
| return Reflect.get(Object.assign({
| | if (document.getElementById("sectionRatings-parameter")) sectionRatings_param = document.getElementById("sectionRatings-parameter").innerText; |
| length: (prop === 'length') && keys().length,
| | for (var i = 0; i < sectionRatings.length; i++){ |
| getItem: function getItem(key) {
| | var param1 = sectionRatings.item(i).innerText; |
| return target.getItem(prefix + (needEncode? encode(key) : key));
| | fetch("https://libertyga.me/rest.php/sectionratings/v0/ratings/"+param1+"/" + sectionRatings_param).then(function (result){return result.json();}).then(function (result){ |
| },
| | if (result.result !== "SUCCESS") return; |
| key: function key(index) {
| | if (!result.category) return; |
| return decode(keys()[index].slice(prefix.length));
| | var sectionRatings = document.getElementsByClassName("section-ratings"); |
| },
| | if (Object.keys(result.gameList).length === 0){ |
| removeItem: function removeItem(key) {
| | for (var k = 0; k < sectionRatings.length; k++){ |
| return target.removeItem(prefix + (needEncode? encode(key) : key)).then(function() {
| | if (sectionRatings.item(k).innerText === result.category){ |
| return spp;
| | sectionRatings.item(k).innerText = "\n\n\n\n\n\n"; |
| });
| | break; |
| },
| | } |
| setItem: function setItem(key, value) {
| | } |
| return target.setItem(prefix + (needEncode? encode(key) : key), value).then(function() {
| | return; |
| return spp;
| | } |
| });
| | var tempElement = document.createElement("div"); |
| }
| | tempElement.innerHTML = result.parseResult; |
| }, except), prop, receiver) || target.getItem(prefix + (needEncode? encode(prop) : prop));
| | for (var j = 0; j < sectionRatings.length; j++ ){ |
| },
| | if (sectionRatings.item(j).innerText === result.category){ |
| set: function(target, prop, value) {
| | sectionRatings.item(j).innerText = ""; |
| return target.setItem(prefix + (needEncode? encode(prop) : prop), value);
| | var elemlist = tempElement.querySelectorAll(".gamecard"); |
| },
| | for (var idx = 0; idx < elemlist.length; idx++){ |
| deleteProperty: function(target, prop) {
| | try{ |
| return target.removeItem(prefix + (needEncode? encode(prop) : prop));
| | var elem = elemlist.item(idx); |
| },
| | sectionRatings.item(j).appendChild(elem); |
| has: function(target, prop) {
| | } catch (e) { |
| Reflect.has(target, prefix + (needEncode? encode(prop) : prop));
| | continue; |
| },
| | } |
| ownKeys: function(target) {
| | } |
| return Reflect.ownKeys(target).filter(function(key) {
| | break; // 작업 종료 |
| return key.startsWith(prefix);
| | } |
| }).map(function(key) {
| | } |
| return decode(key.slice(prefix.length));
| | }).catch(function(e){console.log(e);}); |
| });
| | } |
| }
| | }); |
| });
| |
| return spp;
| |
| };
| |
|
| |
|
| /*
| | /** |
| anon = localStorage[*]
| | * DisucussionTools가 알림 상자 틀을 망가뜨리는 문제 해결을 위한 스크립트(작동 중지) |
| user = mw.user.options[userjs-*]
| | * --[[사용자:Senouis|Senouis]] ([[사용자토론:Senouis|토론]]) 2024년 8월 30일 (금) 11:47 (KST) |
| */
| | */ |
| window.hybridStorage = (function() {
| |
| var action;
| |
| var api = new mw.Api();
| |
| var storage, action;
| |
| var saveOption = (function() {
| |
| var options = {};
| |
| var deferred = new $.Deferred();
| |
| var timeout = null;
| |
|
| |
| return function saveOption(key, value) {
| |
| if(timeout) clearTimeout(timeout);
| |
| options[key] = value;
| |
| timeout = setTimeout(function() {
| |
| api.saveOptions(options).then(deferred.resolve, deferred.reject);
| |
|
| |
| options = {};
| |
| timeout = null;
| |
| deferred = new $.Deferred();
| |
| }, 100);
| |
| return deferred.promise();
| |
| };
| |
| })();
| |
| if(mw.user.isAnon()) {
| |
| storage = new Proxy(localStorage, {
| |
| get: function(target, prop, receiver) {
| |
| var value = Reflect.get({
| |
| length: target.length,
| |
| getItem: target.getItem,
| |
| key: target.key,
| |
| removeItem: function removeItem(key) {
| |
| return Promise.resolve(target.removeItem(key));
| |
| },
| |
| setItem: function setItem(key, value) {
| |
| return Promise.resolve(target.setItem(key, value));
| |
| },
| |
| refresh: function refresh() {
| |
| return Promise.resolve(storage);
| |
| },
| |
| needRefresh: false
| |
| }, prop, receiver) || target.getItem(prop);
| |
| return (value === null)? undefined : value;
| |
| },
| |
| set: function(target, prop, value, receiver) {
| |
| return Promise.resolve(target.setItem(prop, value));
| |
| },
| |
| deleteProperty: function(target, prop) {
| |
| return Promise.resolve(target.removeItem(prop));
| |
| }
| |
| });
| |
| } else {
| |
| action = {
| |
| removeItem: function removeItem(key) {
| |
| if(key) return saveOption("userjs-" + key, null);
| |
| else throw new TypeError("Failed to execute 'removeItem' on 'Storage': 1 argument required, but only 0 present.");
| |
| },
| |
| setItem: function setItem(key, value) {
| |
| if(key) return saveOption("userjs-" + key, value);
| |
| else throw new TypeError("Failed to execute 'removeItem' on 'Storage': 1 argument required, but only 0 present.");
| |
| },
| |
| refresh: (function() {
| |
| var deferred = new $.Deferred();
| |
| var timeout = null;
| |
|
| |
| return function refresh() {
| |
| if(timeout) clearTimeout(timeout);
| |
| timeout = setTimeout(function() {
| |
| api.get({
| |
| action: 'query',
| |
| meta: 'userinfo',
| |
| uiprop: 'options'
| |
| }, {
| |
| cache: false
| |
| }).then(function(response) {
| |
| mw.user.options.values = response.query.userinfo.options;
| |
| return storage;
| |
| }).then(deferred.resolve, deferred.reject);
| |
|
| |
| timeout = null;
| |
| deferred = new $.Deferred();
| |
| }, 100);
| |
| return deferred.promise();
| |
| };
| |
| })()
| |
| };
| |
| storage = new Proxy(mw.user.options, {
| |
| get: function(target, prop, receiver) {
| |
| function keys() {
| |
| return Object.keys(target.values).filter(function(key) {
| |
| return key.startsWith('userjs-');
| |
| });
| |
| }
| |
|
| |
| return Reflect.get({
| |
| length: prop === 'length' && keys().length,
| |
| getItem: function getItem(key) {
| |
| if(key) return target.get("userjs-" + key);
| |
| else throw new TypeError("Failed to execute 'getItem' on 'Storage': 1 argument required, but only 0 present.");
| |
| },
| |
| key: function key(index) {
| |
| return keys()[index].slice(7);
| |
| },
| |
| removeItem: function removeItem(key) {
| |
| if(!target.exists("userjs-" + key)) return Promise.resolve();
| |
| return action.removeItem(key).then(function() {
| |
| Reflect.deleteProperty(target.values, "userjs-" + key);
| |
| });
| |
| },
| |
| setItem: function setItem(key, value) {
| |
| if(target.get("userjs-" + key) === value) return Promise.resolve();
| |
| return action.setItem(key, value).then(function() {
| |
| target.set("userjs-" + key, value);
| |
| });
| |
| },
| |
| refresh: action.refresh,
| |
| needRefresh: true
| |
| }, prop, receiver) || Reflect.get(target.values, "userjs-" + prop, receiver);
| |
| },
| |
| set: function(target, prop, value, receiver) {
| |
| if(Reflect.get(target.values, "userjs-" + prop, receiver) === value) return Promise.resolve();
| |
| return action.setItem(prop, value).then(function() {
| |
| Reflect.set(target.values, "userjs-" + prop, value, receiver);
| |
| });
| |
| },
| |
| deleteProperty: function(target, prop) {
| |
| if(!Reflect.has(target.values, "userjs-" + prop)) return Promise.resolve();
| |
| return action.removeItem(prop).then(function() {
| |
| Reflect.deleteProperty(target.values, "userjs-" + prop);
| |
| });
| |
| },
| |
| has: function(target, prop) {
| |
| return Reflect.has(target.values, "userjs-" + prop);
| |
| },
| |
| ownKeys: function(target) {
| |
| return Reflect.ownKeys(target.values).filter(function(key) {
| |
| return key.startsWith("userjs-");
| |
| }).map(function(key) {
| |
| return key.slice(7);
| |
| });
| |
| }
| |
| });
| |
| }
| |
| return storage;
| |
| })();
| |
| // local + global 슈퍼셋 (hybridStorage[gamedb-*])
| |
| var rootGameDB = setStoragePrefix(hybridStorage, 'gamedb-', {
| |
| refresh: function() {
| |
| return hybridStorage.refresh().then(function() {
| |
| return rootGameDB;
| |
| });
| |
| },
| |
| needRefresh: hybridStorage.needRefresh
| |
| }, true);
| |
| // 게임별로 할당되는 영역 (rootGameDB[{게임}/*])
| |
| window.localGameDB = setStoragePrefix(rootGameDB, title + '/', {
| |
| refresh: function() {
| |
| return rootGameDB.refresh().then(function() {
| |
| return localGameDB;
| |
| });
| |
| },
| |
| needRefresh: rootGameDB.needRefresh
| |
| });
| |
| // 모든 게임이 공유하는 영역 (rootGameDB[#*])
| |
| window.globalGameDB = setStoragePrefix(rootGameDB, '#', {
| |
| refresh: function() {
| |
| return rootGameDB.refresh().then(function() {
| |
| return globalGameDB;
| |
| });
| |
| },
| |
| needRefresh: rootGameDB.needRefresh
| |
| });
| |
|
| |
|
| function DataChange(href) {
| | $(function (){ |
| this.params = geturlSearch(new URL(href, location));
| | var amboces = document.getElementsByClassName("template-ambox"); |
| this.local = {};
| | if (amboces.length === 0) return; |
| this.global = {};
| | for (var i in amboces) { |
| this.root = {};
| | var problemistic = amboces.item(i).querySelector("div div span:first-child"); |
| this.refresh = false;
| | if (problemistic.id.substring(0,2) === "c-") { |
| this.paramChanged = false;
| | problemistic.style.display = "none"; |
| }
| | } |
| DataChange.prototype.control = function control(element) {
| | } |
| var base, key, storage, params, val, paramChanged;
| | }); |
| var data = element.dataset;
| |
|
| |
| /* 저장할 키
| |
| local: 키 지정
| |
| global: 전역 키 지정
| |
| local global: 키 지정
| |
| (없음): 기본 키
| |
| */
| |
| if('local' in data && 'global' in data) {
| |
| throw new TypeError('전역키와 일반키가 동시에 지정되었습니다');
| |
| } else if('local' in data) {
| |
| storage = localGameDB;
| |
| base = this.local;
| |
| key = data.local;
| |
| } else if('global' in data) {
| |
| storage = globalGameDB;
| |
| base = this.global;
| |
| key = data.global;
| |
| } else {
| |
| storage = rootGameDB;
| |
| base = this.root;
| |
| key = title;
| |
| }
| |
|
| |
| switch(data.action) {
| |
| // 호환
| |
| case '저장':
| |
| case 'save':
| |
| /*
| |
| create: 새 키를 생성할 때만 저장
| |
| */
| |
| if(!('create' in data && key in base) && location.search) base[key] = JSON.stringify(geturlSearch());
| |
| break;
| |
|
| |
|
| case '로드':
| | /** |
| case 'load':
| | * 일반 이름공간 내에 있는 특정 분류의 문서 갯수를 가져오는 API 요청 |
| /*
| | * v1.3--{{사용자:Senouis/서명}} 2024년 9월 19일 (목) 01:25 (KST) |
| safe: 파라미터가 있으면 불러오지 않음
| | */ |
| fill: 없는 파라미터만 불러옴
| | $(function () { |
| */
| | var categorylist = document.getElementsByClassName("pagecount"); |
| if(!(location.search && 'safe' in data)) {
| | if (categorylist.length === 0) return; |
| Object.assign(this.params, parseJSON(storage.getItem(key)), 'fill' in data && this.params);
| | var parameter = []; |
| this.paramChanged = true;
| | for (var i in categorylist) { |
| }
| | var param = categorylist.item(i).innerText; // 이름공간을 제외하고 공백을 언더바(_)로 바꾼 분류 이름(예: 철도_교통_게임)을 파라미터로 함 |
| break;
| | parameter.push(param); // namespace 0번(일반 이름공간) 내 분류 갯수를 세도록 파라미터를 삽입한다. |
| | |
| // 기본
| |
| case '호출':
| |
| case 'get':
| |
| /*
| |
| else: 저장된 데이터가 없을 때의 대체 텍스트
| |
| */
| |
| if(key in storage || data.else) {
| |
| this.params[data.arg] = storage.getItem(key) || data.else;
| |
| this.paramChanged = true;
| |
| }
| |
| break;
| |
| | |
| case '수정':
| |
| case 'set':
| |
| /*
| |
| create: 새 키를 생성할 때만 저장
| |
| */
| |
| if(!('create' in data && key in base)) base[key] = data.arg;
| |
| break;
| |
| | |
| case '삭제':
| |
| case '제거':
| |
| case 'del':
| |
| base[key] = null;
| |
| break;
| |
| | |
| // JSON
| |
| case 'JSON':
| |
| case 'json':
| |
| /*
| |
| reset: 데이터 초기화
| |
| */
| |
| params = this.params;
| |
| val = JSON.stringify(new CGI2Parser({
| |
| get: function(args) {
| |
| var base = this;
| |
| if(typeof args === 'object') Object.pairs(args).forEach(function(pair) {
| |
| if(base[pair[1]]) {
| |
| params[pair[0]] = base[pair[1]];
| |
| paramChanged = true;
| |
| }
| |
| });
| |
| else Array.from(arguments).forEach(function(key) {
| |
| if(base[key]) {
| |
| params[key] = base[key];
| |
| paramChanged = true;
| |
| }
| |
| });
| |
| },
| |
| set: function(args) {
| |
| var base = this;
| |
| Object.pairs(args).forEach(function(pair) {
| |
| base[pair[0]] = pair[1];
| |
| });
| |
| },
| |
| del: function() {
| |
| var base = this;
| |
| Array.from(arguments).forEach(function(key) {
| |
| delete base[key];
| |
| });
| |
| },
| |
| def: function(args) {
| |
| var base = this;
| |
| Object.pairs(args).forEach(function(pair) {
| |
| if(!(pair[0] in base)) base[pair[0]] = pair[1];
| |
| });
| |
| },
| |
| sav: function(args) {
| |
| var base = this;
| |
| if(typeof args === 'object') Object.pairs(args).forEach(function(pair) {
| |
| base[pair[0]] = params[pair[1]];
| |
| });
| |
| else Array.from(arguments).forEach(function(key) {
| |
| base[key] = params[key];
| |
| });
| |
| }
| |
| }).parse(parseJSON('reset' in data? '' : storage.getItem(key)) || {}, '[' + data.arg + ']'));
| |
| if(val.length > 2) base[key] = val;
| |
| Object.assign(this.params, params);
| |
| if(paramChanged) this.paramChanged = true;
| |
| break;
| |
| | |
| default:
| |
| $(element).addClass('error').text(data.action? "'" + data.action + "'은(는) 올바른 동작이 아닙니다" : '올바른 동작을 입력하지 않았습니다');
| |
| }
| |
| };
| |
| | |
| /**
| |
| * DB 저장
| |
| * @function
| |
| * @param {DataChange} change
| |
| */
| |
| DataChange.prototype.save = function() {
| |
| var key, promise;
| |
| var yet = true;
| |
| var promises = [];
| |
| | |
| if(title in this.root) {
| |
| promises.push(rootGameDB.setItem(title, this.root[title]));
| |
| }
| |
| for(key in this.local) {
| |
| promises.push(localGameDB.setItem(key, this.local[key]));
| |
| }
| |
| for(key in this.global) {
| |
| promises.push(globalGameDB.setItem(key, this.global[key]));
| |
| }
| |
|
| |
| promise = $.when.apply(null, promises);
| |
| promise.then(function() {
| |
| yet = false;
| |
| });
| |
|
| |
| if(promises.length && !mw.user.isAnon()) setTimeout(function() {
| |
| if(yet) noti = mw.notification.notify('데이터를 저장하는 중입니다...', {
| |
| autoHide: false,
| |
| tag: 'gameDB',
| |
| type: 'pending'
| |
| });
| |
| }, 10);
| |
| | |
| return promise;
| |
| }
| |
| | |
| function handleError(code, object) {
| |
| mw.notification.notify(
| |
| code === 'http'?
| |
| $('<span />')
| |
| .append($('<p />', {class: 'gameDB-noti-errmsg'}).text(object.xhr.responseText))
| |
| .append($('<code />', {class: 'gameDB-noti-errcode'}).text('HTTP ' + object.xhr.status)) :
| |
| $('<span />')
| |
| .append($('<p />', {class: 'gameDB-noti-errmsg'}).text(object.error.info))
| |
| .append($('<code />', {class: 'gameDB-noti-errcode'}).text(code)),
| |
| {
| |
| title: '데이터 저장에 실패하였습니다.',
| |
| type: 'error',
| |
| tag: 'gameDB'
| |
| }
| |
| );
| |
| } | | } |
| | | fetch("https://libertyga.me/rest.php/sectionratings/v0/categorycounter/"+parameter.join("|")+"/0").then(function (result){return result.json();}).then(function (result) { |
| // 즉시
| | var categorylist2 = document.getElementsByClassName("pagecount"); |
| (function() {
| | for (var i in result.count) { |
| var instant = new DataChange(location.href);
| | for (var j in categorylist2){ |
| | | if (categorylist2.item(j).innerText === result.category[i]){ // 파라미터와 result.category가 같으면 치환 |
| $('.gameDB-control').each(function() {
| | categorylist2.item(j).innerText = result.count[i] === null ? 0 : result.count[i]; |
| instant.control(this);
| | categorylist2.item(j).style.display = "initial"; |
| });
| | break; |
| | | } |
| instant.save().then(function() {
| | } |
| var url = new mw.Title(instant.params.title || mw.config.get('wgPageName')).getUrl(instant.params) + location.hash;
| | } |
|
| | }); |
| if(currentUrl !== url && instant.paramChanged) location.href = url;
| | }); |
| else if(noti) noti.close();
| |
| }, handleError);
| |
| })();
| |
| | |
| // 링크
| |
| (function() {
| |
| function process(link, controllers, change) {
| |
| controllers.each(function() {
| |
| change.control(this);
| |
| });
| |
|
| |
| var url = new mw.Title(change.params.title || mw.config.get('wgPageName')).getUrl(change.params) + new URL(link.href).hash;
| |
| if(change.paramChanged) link.href = url;
| |
| else if(link.href === location.href) link.href = "";
| |
| }
| |
| | |
| $('.gameDB-container').not(':has(a, .gameDB-container)').each(function() {
| |
| var href;
| |
| | |
| /*
| |
| clear: 기존 파라미터 넘겨주지 않음
| |
| */
| |
| if('clear' in this.dataset) {
| |
| href = new URL(location.href);
| |
| href.search = '';
| |
| href = href.href;
| |
| } else href = location.href;
| |
| | |
| $(this).html($('<a />', {
| |
| href: href
| |
| }).text(this.innerText));
| |
| });
| |
|
| |
| $('.gameDB-container a').each(function() {
| |
| var change = new DataChange(this.href);
| |
| var controllers = $($(this).parents('.gameDB-container').get().reverse());
| |
| | |
| process(this, controllers, change);
| |
|
| |
| $(this).data('change', change);
| |
| $(this).addClass('gameDB-link');
| |
| });
| |
| | |
| $('.gameDB-link').on('click', function handler(event) {
| |
| var link = this;
| |
| | |
| if(!('done' in this.dataset)) {
| |
| event.preventDefault();
| |
| event.stopImmediatePropagation();
| |
| }
| |
| | |
| $(this).data('change').save().then(function() {
| |
| if(link.href !== location.href) {
| |
| link.dataset.done = '';
| |
| $(link).off('click', handler)[0].click();
| |
| } else mw.notification.notify('데이터가 저장되었습니다.', {
| |
| tag: 'gameDB'
| |
| });
| |
| }, handleError);
| |
| });
| |
| })();
| |
| } | |
| $(function() {
| |
| mw.loader.using([ | |
| 'mediawiki.notification',
| |
| 'oojs-ui-core'
| |
| ]).then(enableDB2)['catch'](console.error);
| |
| }) | |
| /* [[틀:DB2]] 끝 */
| |