ผู้ใช้:Bebiezaza/iScript/helper.js
< ผู้ใช้:Bebiezaza | iScript
หมายเหตุ: หลังเผยแพร่ คุณอาจต้องล้างแคชเว็บเบราว์เซอร์ของคุณเพื่อดูการเปลี่ยนแปลง
- ไฟร์ฟอกซ์ / ซาฟารี: กด Shift ค้างขณะคลิก Reload หรือกด Ctrl-F5 หรือ Ctrl-R (⌘-R บนแมค)
- กูเกิล โครม: กด Ctrl-Shift-R (⌘-Shift-R บนแมค)
- อินเทอร์เน็ตเอกซ์พลอเรอร์ และ Edge: กด Ctrl ค้างขณะคลิก Refresh หรือกด Ctrl-F5
- โอเปร่า: กด Ctrl-F5
// ==============================================================
// สคริปต์จัดให้: helper module
//
// Copyright (C) 2006-2022, Jutiphan Mongkolsuthree
// 2021-2023, Bebiezaza
// Certain functions are copyrighted by their
// respective copyright holders.
//
// Created: 01/12/2006
// Rewritten: 20/10/2021
// Replaced:
// ==============================================================
// 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 => revert.js
// ==============================================================
// 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 'none': color = 'none'; break; // no 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 (TODO: no color should be 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-2022") addMenuItem__Vector2022(menuID, menuTitle, itemTitle, itemID, itemDesc, color, event, limitHeight);
else 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("p-cactions").getElementsByTagName("ul")[0];
navParent.appendChild(menuBox);
}
var itemTitle_span = createElement('span', itemTitle, "");
var dropdownLink = createElement('a', itemTitle_span, {
'href': event,
'title': itemDesc
});
var dropdownColor;
if (color === "none") dropdownColor = "";
else dropdownColor = "border-left: 10px solid " + color + ";"
var dropdownItem = createElement('li', dropdownLink, {
'id': itemID,
'style': dropdownColor
});
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 vector-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);
}
function addMenuItem__Vector2022(menuID, menuTitle, itemTitle, itemID, itemTooltip, color, href, limitHeight) {
var menu = document.getElementById(menuID);
if (!menu) { // ofc, make the menu
var dropdownList = createElement('ul', "", {
'class': "vector-menu-content-list"
});
if (limitHeight) dropdownList.classList.add("iScript-vector2022-menu-limit-height");
var dropdown = createElement('div', [dropdownList], {
'class': "vector-menu-content"
})
menu = createElement('div', dropdown, {
'id': menuID,
'class': "vector-menu mw-portlet mw-portlet-" + menuID,
'title': "เครื่องมือของสคริปต์จัดให้"
});
var menuHolder = createElement('div', menu, {
'class': "vector-dropdown-content",
'style': "padding: 0"
});
var menuHeader = createElement('label', createElement('span', menuTitle, { 'class': "vector-menu-heading-label" }), {
'id': menuID + "-dropdown-label",
'class': "vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet",
'for': menuID + "-dropdown-checkbox",
'aria-hidden': "true"
});
var menuCheckbox = createElement('input', "", {
'type': "checkbox",
'id': menuID + "-dropdown-checkbox",
'class': "vector-dropdown-checkbox",
'role': "button",
'data-event-name': "ui.dropdown-" + menuID + '-dropdown',
'aria-label': menuTitle,
'aria-expanded': "false",
'aria-haspopup': "true"
});
var menuDropdownHandle = createElement('div', [menuCheckbox, menuHeader, menuHolder], {
'id': menuID + "-dropdown",
'class': "vector-dropdown vector-page-tools-dropdown",
});
var menuLandmark = createElement('nav', menuDropdownHandle, {
'aria-label': "เครื่องมือของสคริปต์จัดให้"
});
var rightGroup = document.getElementById("right-navigation");
rightGroup.appendChild(menuLandmark);
}
var itemLink = createElement('a', createElement('span', itemTitle, ""), '');
if (href) itemLink.href = href;
if (itemTooltip) itemLink.title = itemTooltip;
var dropdownColor;
if (color !== "none") dropdownColor = "border-left: 10px solid " + color + ";";
var item = createElement('li', itemLink, {
'id': itemID,
// mw-list-item-js distinguishes portlet links added via javascript and the server
'class': "mw-list-item mw-list-item-js",
'style': dropdownColor + " margin-bottom: 0;"
});
menu.lastChild.firstChild.appendChild(item);
return item;
}
/**
* 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 = document.getElementById("mw-panel").lastElementChild.id;
// continue to each skin's function
if (mw.config.get('skin') === "vector-2022") makeSidebox__Vector2022(sidebarTitle, sidebarID, insertAfter);
else 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"
});
if (insertAfterID && insertAfterID.nextElementSibling && insertAfterID.nextElementSibling.parentNode === sidebarBox) {
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"
});
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"
});
if (insertAfterID.nextSibling.parentNode === sidebarBox) {
return sidebarBox.insertBefore(sidebarNav, insertAfterID.nextSibling);
}
}
function makeSidebox__Vector2022(title, id, insertAfter) {
var sidebar = document.getElementById("mw-panel");
if (!insertAfter) insertAfter = sidebar.lastElementChild.previousElementSibling.id;
else if (insertAfter === "p-tb") insertAfter = "p-interaction";
var insertAfterElement = document.getElementById(insertAfter).nextSibling;
var sideboxHeader = createElement('div', title, { 'class': "vector-menu-heading" });
var sideboxList = createElement('ul', "", { 'class': "vector-menu-content-list" });
var sideboxDiv = createElement('div', sideboxList, {
'class': "vector-menu-content"
});
var sidebox = createElement('div', [sideboxHeader, sideboxDiv], {
'id': id,
'class': "vector-menu mw-portlet mw-portlet-" + id
});
try {
sidebar.firstElementChild.firstElementChild.insertBefore(sidebox, insertAfterElement);
} catch (e) {
console.error("Could not create new sidebar navigation group due to unexpected DOM.");
}
return sidebox;
}
/**
* 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-2022") addTab__Vector2022(href, itemTitle, itemID, itemDesc, nextnodeid);
else 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': "vector-tab-noicon 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);
}
}
function addTab__Vector2022(href, title, id, tooltip, nextnode) {
var itemLink = createElement('a', createElement('span', title, ""), "");
if (href) itemLink.href = href;
if (tooltip) itemLink.title = tooltip;
var item = createElement('li', itemLink, {
// mw-list-item-js distinguishes portlet links added via javascript and the server
'id': id, 'class': "vector-tab-noicon mw-list-item mw-list-item-js"
});
if (!nextnode) {
var parent = document.getElementById("p-cactions").lastElementChild.lastElementChild;
parent.appendChild(item);
} else {
var parent = nextnode.parentNode;
item.classList.add("collapsible");
parent.insertBefore(item, nextnode);
}
return item;
}
/* --------------- 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> */