ผู้ใช้:Bebiezaza/dev/iScript/helper.js

จากวิกิพีเดีย สารานุกรมเสรี

หมายเหตุ: หลังเผยแพร่ คุณอาจต้องล้างแคชเว็บเบราว์เซอร์ของคุณเพื่อดูการเปลี่ยนแปลง

  • ไฟร์ฟอกซ์ / ซาฟารี: กด Shift ค้างขณะคลิก Reload หรือกด Ctrl-F5 หรือ Ctrl-R (⌘-R บนแมค)
  • กูเกิล โครม: กด Ctrl-Shift-R (⌘-Shift-R บนแมค)
  • อินเทอร์เน็ตเอกซ์พลอเรอร์ และ Edge: กด Ctrl ค้างขณะคลิก Refresh หรือกด Ctrl-F5
  • โอเปร่า: กด Ctrl-F5
// ==============================================================
// สคริปต์จัดให้: helper module
//
// Copyright (C) 2006-2021, Jutiphan Mongkolsuthree
// 2021, Bebiezaza
// Certain functions are copyrighted by their
// respective copyright holders.
//
// Created: 01/12/2006
// Rewritten: 20/10/2021
// Replaced: original helper
// ==============================================================
// Available functions => prerequisites of
//
// createElement            => addMenuItem, makeSidebox, addTab
// addMenuItem              => addMenu, addWPMenu
// addMenu                  => <main>(notify.js, notifyFiles.js, speedyAFD.js)
// addWPMenu                => <main>(projectMenu.js)
// makeSidebox              => Sidebox(iScript.js)
// addToolboxLink           => Sidebox(iScript.js)
// addBookmarkLink          => Sidebox(iScript.js)
// addTab                   => editSection0 & lastDiff (mainTabs.js), (admin.js), <main>(editor.js)
// 
// selectUploader           => addAFDRequest(speedyAFD.js), addFileTemplate(notifyFiles.js)
// getBEYear                => addTemplate(notify.js), addFileTemplate(notifyFiles.js)
// dynamicSort              => populateWPMenu(projectMenu.js)
// getSelText               => copyvioCheck & createRedirect(sidebox.js), replacetxt(editor.js)
// userIsInGroup            => <main>(admin.js)
// openInNewWindow
// ==============================================================
// Additional Credits Information:
// ==============================================================
// dynamicSort function
// Source: //stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value
// ==============================================================
/* <pre><nowiki> */

/* --------------- Anatomy --------------- */

/**
 * Better createElement, with the ability to add child element and attributes as you create the element
 * 
 * @param { String } nodename Required. The name of the element you want to create
 * @param { Array } child Child elements you want to put inside this element
 * @param { Object } attributes Styles, Classes, IDs, etc
 * @returns HTML Node
 */
function createElement(nodename, child, attributes) {
    var element = document.createElement(nodename);
    if (!(child instanceof Array)) child = [child];

    for (var i = 0; i < child.length; i++) {
        var childMembers = child[i];
        if (typeof childMembers == 'string') childMembers = document.createTextNode(childMembers);
        if (childMembers) element.appendChild(childMembers);
    }

    if (typeof attributes == 'object') {
        for (var k in attributes) {
            switch (k) {
                case 'class':
                    element.className = attributes[k];
                    break;
                default:
                    element.setAttribute(k, attributes[k]);
            }
        }
    }
    return element;
}

/**
 * Helps add functions to the action menu (top bar)
 * @param { String } menuID Required. ID of the dropdown menu, can be repeated; syntax should be p-<desc>
 * @param { String } menuTitle Required. Title of the dropdown menu, can be repeated
 * @param { String } itemTitle Required. Title of the individual item
 * @param { String } itemID ID of the individual item; default: <item_title>
 * @param { String } itemDesc Description of the individual item
 * @param { String } color Predefined colour codes: notice, growth, style, content, merge, serious, or "default"
 * @param { String } event The behaviour you want to execute; default: "#"
 * @param { boolean } limitHeight True if you want to limit the list to 10 and uses scroll, only applies to the first use of each menu_id; default: false
 * @returns Element in the menu. If declared for the first time, returns the new menu too
 */
function addMenuItem(menuID, menuTitle, itemTitle, itemID, itemDesc, color, event, limitHeight) {
    // colour handler thingy
    switch (color) {
        case 'notice': color = '#1e90ff'; break; // light blue; default
        case 'growth': color = '#228b22'; break; // green
        case 'style': color = '#f4c430'; break; // yellow
        case 'content': color = '#f28500'; break; // orange
        case 'merge': color = '#9932cc'; break; // purple
        case 'serious': color = '#b22222'; break; // dark red
        default: color = '#1e90ff'; // light blue; default
    }
    // helps cleanup any missing var
    if (!event) event = "#";
    if (!itemID) itemID = "p-" + itemTitle;
    if (!limitHeight) limitHeight = false;
    // continue to each skin's function
    if (mw.config.get('skin') == "vector") addMenuItem__Vector(menuID, menuTitle, itemTitle, itemID, itemDesc, color, event, limitHeight);
    else addMenuItem__Monobook(menuID, menuTitle, itemTitle, itemID, itemDesc, color, event, limitHeight);
}
function addMenuItem__Monobook(menuID, menuTitle, itemTitle, itemID, itemDesc, color, event, limitHeight) {
    var menu = document.getElementById(menuID);
    if (menu) var menuBox = menu; // checks if the element has been repeated
    else {
        menuTitle += "▼";
        var dropdownList = createElement('ul', "", {
            'class': "iScript-monobook-menu-content-list"
        });
        if (limitHeight) dropdownList.classList.add("iScript-monobook-menu-dropdown-limit-height");
        var menuBox = createElement('li', [menuTitle, dropdownList], {
            'id': menuID,
            'class': "iScript-monobook-menu-dropdown"
        });
        var navParent = document.getElementById("ca-view").parentNode;
        navParent.appendChild(menuBox);
    }
    var itemTitle_span = createElement('span', itemTitle, "");
    var dropdownLink = createElement('a', itemTitle_span, {
        'href': event,
        'title': itemDesc
    });
    var dropdownItem = createElement('li', dropdownLink, {
        'id': itemID,  
        'style': "border-left: 10px solid " + color + ";"
    });
    return menuBox.lastChild.appendChild(dropdownItem);
}
function addMenuItem__Vector(menuID, menuTitle, itemTitle, itemID, itemDesc, color, event, limitHeight) {
    var menu = document.getElementById(menuID);
    if (menu) var menuBox = menu; // checks if the element has been repeated
    else {
        var dropdownList = createElement('ul', "", {
            'class': "vector-menu-content-list"
        });
        if (limitHeight) dropdownList.classList.add("iScript-vector-menu-dropdown-limit-height");
        var dropdownDiv = createElement('div', dropdownList, {
            'class': "vector-menu-content"
        });
        var menuHeader_span = createElement('span', menuTitle, "");
        var menuHeader = createElement('h3', menuHeader_span, {
            'id': menuID + "-label",
            'class': "vector-menu-heading"
        });
        var menuCheckbox = createElement('input', "", {
            'type': "checkbox",
            'id': menuID + "-checkbox",
            'class': "vector-menu-checkbox",
            'aria-labelledby': menuID + "-label",
            'role': "button",
            'aria-haspopup': "true",
            'data-event-name': "ui.dropdown-" + menuID
        });
        var menuBox = createElement('nav', [menuCheckbox, menuHeader, dropdownDiv], {
            'id': menuID,
            'class': "mw-portlet mw-portlet-cactions vector-menu-dropdown-noicon vector-menu vector-menu-dropdown",
            'aria-labelledby': menuID + "-label",
            'role': "navigation",
            'title': "From iScript"
        });
        var navParent = document.getElementById("p-cactions").parentNode;
        var searchBox = document.getElementById("p-search");
        if (searchBox.parentNode == navParent) navParent.insertBefore(menuBox, searchBox); // old vector
        else navParent.appendChild(menuBox); // new vector
    }
    var itemTitle_span = createElement('span', itemTitle, "");
    var dropdownLink = createElement('a', itemTitle_span, {
        'href': event,
        'title': itemDesc
    });
    var dropdownItem = createElement('li', dropdownLink, {
        'id': itemID,
        'class': "mw-list-item",
        'style': "border-left: 10px solid " + color + ";"
    });
    return menuBox.lastChild.firstChild.appendChild(dropdownItem);
}

/**
 * For adding iScript notify function to the top bar
 * @param { String } itemTitle Required. Title of the individual item
 * @param { String } itemID ID of the individual item; default: <item_title>
 * @param { String } itemDesc Description of the individual item
 * @param { String } color Predefined colour codes: notice, growth, style, content, merge, serious, or "default"
 * @param { String } event The behaviour you want to execute; default: "#"
 * @returns Element in the menu. If declared for the first time, returns the new menu too
 */
function addMenu(itemTitle, itemID, itemDesc, color, event) {
    return addMenuItem("p-iScript-notify", "แจ้ง", itemTitle, itemID, itemDesc, color, event, false);
}

/**
 * For adding iScript add Wikiprojects function to the top bar
 * @param { String } itemTitle Required. Title of the individual item
 * @param { String } itemID ID of the individual item; default: <item_title>
 * @param { String } itemDesc Description of the individual item
 * @param { String } event The behaviour you want to execute; default: "#"
 * @returns Element in the menu. If declared for the first time, returns the new menu too
 */
function addWPMenu(itemTitle, itemID, itemDesc, event) {
    return addMenuItem("p-iScript-wpProjects", "แจ้งอยู่ในโครงการ", itemTitle, itemID, itemDesc, 'notice', event, true);
}

/**
 * Helps create new sidebar group
 * @param { String } sidebarTitle Required. The name you want the header of the section to appear
 * @param { String } sidebarID ID of the sidebar group
 * @param { String } insertAfter ID of the sidebar group you want to place after; default: "p-lang"
 * @returns New sidebar group
 */
function makeSidebox(sidebarTitle, sidebarID, insertAfter) {
    // cleanup missing var
    if (!sidebarID) sidebarID = "p-" + sidebarTitle;
    if (!insertAfter) insertAfter = "p-lang";
    // continue to each skin's function
    if (mw.config.get('skin') == "vector") makeSidebox__Vector(sidebarTitle, sidebarID, insertAfter);
    else makeSidebox__Monobook(sidebarTitle, sidebarID, insertAfter);
}
function makeSidebox__Monobook(sidebarTitle, sidebarID, insertAfter) {
    var sidebarBox = document.getElementById("sidebar");
    var insertAfterID = document.getElementById(insertAfter);
    var sidebarHeader = createElement('h3', sidebarTitle, {
        'id': sidebarID + "-label"
    });
    var sidebarList = createElement('ul', "", "");
    var sidebarDiv = createElement('div', sidebarList, {
        'class': "pBody"
    });
    var sidebarNav = createElement('nav', [sidebarHeader, sidebarDiv], {
        'id': sidebarID,
        'class': "portlet mw-portlet mw-portlet-tb",
        'aria-labelledby': sidebarID + "-label",
        'role': "navigation"
    });
    return sidebarBox.insertBefore(sidebarNav, insertAfterID.nextSibling);
}
function makeSidebox__Vector(sidebarTitle, sidebarID, insertAfter) {
    var sidebarBox = document.getElementById("mw-panel");
    var insertAfterID = document.getElementById(insertAfter);
    var sidebarTitle_span = createElement('span', sidebarTitle, "");
    var sidebarHeader = createElement('h3', sidebarTitle_span, {
        'id': sidebarID + "-label",
        'aria-label': "",
        class: "vector-menu-heading"
    });
    var sidebarList = createElement('ul', "", {
        'class': "vector-menu-content-list"
    });
    var sidebarDiv = createElement('div', sidebarList, {
        'class': "vector-menu-content body" // body ใช้ใน <1.36 ซึ่งเหลือแค่ uncyclopedia ที่ยังใช้อยู่
    });
    var sidebarNav = createElement('nav', [sidebarHeader, sidebarDiv], {
        'id': sidebarID,
        'class': "mw-portlet mw-portlet-tb vector-menu vector-menu-portal portal",
        'aria-labelledby': sidebarID + "-label",
        'role': "navigation"
    });
    return sidebarBox.insertBefore(sidebarNav, insertAfterID.nextSibling);
}

/**
 * Add links to iScript's toolbox
 * @param { String } href Required. Link URL
 * @param { String } itemText Required. Link text
 * @param { String } itemID Required. ID of the list item, should be unique
 * @param { String } itemDesc Text to show when hovering over the link, without accesskey suffix
 * @returns Element in the iScript toolbox
 */
function addToolboxLink(href, itemText, itemID, itemDesc) {
    return mw.util.addPortletLink("p-iScriptTools", href, itemText, itemID, itemDesc);
}

/**
 * Add bookmarks to iScript's bookmark
 * @param { String } href Required. Link URL
 * @param { String } itemText Required. Link text
 * @param { String } itemID Required. ID of the list item, should be unique
 * @param { String } itemDesc Text to show when hovering over the link, without accesskey suffix
 * @returns Element in the iScript bookmark
 */
function addBookmarkLink(href, itemText, itemID, itemDesc) {
    return mw.util.addPortletLink("p-iBookmarks", href, itemText, itemID, itemDesc);
}

/**
 * Helps add functions to the main action tab (top bar)
 * @param { String } itemTitle Required. The name you want the tab to appear
 * @param { String } itemID Required. ID of the tab, should be unique
 * @param { String } itemDesc Required. Text to show when hovering over the link, without accesskey suffix
 * @param { String } href Required. Link URL
 * @param { Node } nextnodeid HTML Node of the tab you want to place before
 * @param { Boolean } childOf Only applied to monobook skin. True if new tab should be sticked together with parent.
 * @returns Element in the main action tab
 */
function addTab(href, itemTitle, itemID, itemDesc, nextnodeid, childOf) {
    // cleanup missing var
    if (!itemID) itemID = "ca-" + itemTitle;
    if (!href) href = "#";
    // continue to each skin's function
    if (mw.config.get("skin") == "vector") addTab__Vector(href, itemTitle, itemID, itemDesc, nextnodeid);
    else addTab__Monobook(href, itemTitle, itemID, itemDesc, nextnodeid, childOf);
}
function addTab__Monobook(href, itemTitle, itemID, itemDesc, nextnodeid, childOf) {
    var itemLink = createElement('a', itemTitle, {
        'href': href,
        'title': itemDesc
    });
    var tab = createElement('li', itemLink, {
        'id': itemID,
        'class': "mw-list-item"
    });
    
    if (!nextnodeid || nextnodeid == "") {
        var parent = document.getElementById("ca-watch").parentNode;
        return parent.appendChild(tab);
    } else {
        var parent = nextnodeid.parentNode;
        if (childOf) nextnodeid.previousSibling.classList.add("istalk");
        return parent.insertBefore(tab, nextnodeid);
    }
}
function addTab__Vector(href, itemTitle, itemID, itemDesc, nextnodeid) {
    var itemTitle_span = createElement('span', itemTitle, "");
    var itemLink = createElement('a', itemTitle_span, {
        'href': href,
        'title': itemDesc
    });
    var tab = createElement('li', itemLink, {
        'id': itemID,
        'class': "mw-list-item"
    });

    if (!nextnodeid || nextnodeid == "") {
        var parent = document.getElementById("p-cactions").childNodes[5].childNodes[1];
        return parent.appendChild(tab);
    } else {
        tab.classList.add("collapsible");
        var parent = nextnodeid.parentNode;
        return parent.insertBefore(tab, nextnodeid);
    }
}

/* --------------- Physiology --------------- */

/**
 * Get file's uploader name you want
 * @param { String } pageName Required. Page name of targeted page 
 * @returns Selected uploader's name as String
 */
function selectUploader(pageName) {
    var uploaders = iScriptAPI.getUploaders(pageName);
    var uploadersNew = [];
    
    var number = 0, uploaderList = "";
    for (var count in uploaders) {
        if (uploaderList.indexOf(uploaders[count]) == -1) {
            if (number > 0) uploaderList += "; ";
            uploaderList += number + " => " + uploaders[count];
            uploadersNew.push(uploaders[count]);
            number++;
        }
    }

    var uploaderNum = parseInt(window.prompt("กรุณาเลือกชื่อผู้ใช้ที่ต้องการจะแจ้ง\n" + uploaderList, ""));
    if (isNaN(uploaderNum) || uploaderNum < 0 || uploaderNum >= uploadersNew.length) {
        alert("ไม่มีชื่อผู้ใช้ที่เลือก หยุดการดำเนินการ");
        return null;
    }

    return uploadersNew[uploaderNum];
}

/**
 * get Bhuddhist Era Year
 * @returns Bhuddhist Era year (Number)
 */
function getBEYear() {
    var jsDate = new Date();
    var year = jsDate.getFullYear() + 543;
    return year;
}

/**
 * Dynamic sort function that sorts objects by their value that you pass; use with Array.sort()
 * @param {*} property property inside object inside array
 * @returns sort order
 */
function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        /* next line works with strings and numbers, 
         * and you may want to customize it to your needs */
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

/**
 * Get selected text
 * @returns Selected text
 */
function getSelText() {
    var a = "";
    if (window.getSelection && window.getSelection().toString() && $(window.getSelection()).attr('type') != "Caret") {
        a = window.getSelection().toString();
        return a
    } else if (document.getSelection && document.getSelection().toString() && $(document.getSelection()).attr('type') != "Caret") {
        a = document.getSelection().toString();
        return a
    } else {
        var b = document.selection && document.selection.createRange();
        if (!(typeof b === "undefined") && b.text && b.text.toString()) {
            a = b.text;
            return a
        }
    }
    if (window.getSelection) {
        selText = window.getSelection()
    } else if (document.getSelection) {
        selText = document.getSelection()
    } else if (document.selection) {
        selText = document.selection.createRange();
        selText = selText.text
    } else {
        return ""
    }
}

/**
 * Check if the user is in a local user group
 * @param { String } userGroup local user group you are trying to find
 * @returns Boolean
 */
function userIsInGroup(userGroup) {
    for (var i = 0; i < mw.config.get('wgUserGroups').length; i++) {
        if (mw.config.get('wgUserGroups')[i] == userGroup) return true;
    }
    return false;
}

/**
 * Opens a new browser window, or a new tab, depending on your browser settings and the parameter values.
 * @param { String } a Specifies the URL of the page to open. If no URL is specified, a new window/tab with about:blank is opened
 * @param { String } b Specifies the target attribute or the name of the window; default = _blank
 */
function openInNewWindow(a, b) {
    if (!b) {
        b = '_blank'
    }
    window.open(a, b);
}

$(document).ready(function() {
    // for test cases
});

/* </nowiki></pre> */