Bikarhêner:Balyozxane/skrîpt/js/addSortKey.js
Xuyakirin
Zanibe: Piştî weşandinê, ji bo dîtina guhartinan dibe ku hewce be "cache"ya geroka xwe paqij bikî.
- Firefox / Safari: Pê li Shift û Reload bike an jî Ctrl-F5 an Ctrl-R bike (ji bo Mac: ⌘-R)
- Google Chrome: Pê li Ctrl-Shift-R (ji bo Mac: ⌘-Shift-R) bike
- Internet Explorer / Edge: Pê li Ctrl û Refresh bike, an jî Ctrl-F5 bike
- Opera: Pê li Ctrl-F5 bike.
$(document).ready(function() {
mw.loader.using(["mediawiki.api", "jquery.ui"]).done(function() {
function getCategoriesAndPagesInCategory(categoryName, callback) {
// Construct the API URL
const apiUrl = "https://ku.wikipedia.org/w/api.php";
const params = {
action: "query",
list: "categorymembers",
cmtitle: encodeURIComponent(categoryName),
cmlimit: "max", // To retrieve all members
format: "json"
};
const queryString = Object.keys(params).map(key => key + '=' + params[key]).join('&');
const fullUrl = apiUrl + '?' + queryString;
// Make a request to the API
fetch(fullUrl)
.then(response => response.json())
.then(data => {
// Extract category and page members from the response
if (data.query && data.query.categorymembers) {
const members = data.query.categorymembers.reduce((acc, member) => {
if (!acc[member.ns]) {
acc[member.ns] = [];
}
acc[member.ns].push(member.title);
return acc;
}, {});
callback(members);
} else {
callback({
0: [],
14: []
});
}
})
.catch(error => {
console.error("Error fetching categories and pages:", error);
callback({
0: [],
14: []
});
});
}
function displayModal(categoriesAndPages) {
const pageTitle = mw.config.get('wgPageName');
let sereke = pageTitle.replace(/_/g, " ").replace(/^Kategorî:/, "");
const firstPart = sereke.split(" ")[0];
let pattern = "^" + firstPart + " (.*?)$";
const categoryItems = categoriesAndPages[14] ? categoriesAndPages[14].map(category => `<div class="category-item">${category}</div>`).join('') : '';
const pageItems = categoriesAndPages[0] ? categoriesAndPages[0].map(page => `<div class="page-item">${page}</div>`).join('') : '';
const modalContent = `
<style>
.category-item.selected, .page-item.selected {
font-weight: bold;
background-color: #ffcc80; /* Orange highlight color */
}
</style>
<div>
<label for="pattern">Pattern:</label>
<input type="text" id="pattern" value="${pattern}">
</div>
<div>
<input type="radio" id="categoryRadio" name="content" value="category" checked>
<label for="categoryRadio">Categories</label>
<input type="radio" id="pageRadio" name="content" value="page">
<label for="pageRadio">Pages</label>
</div>
<div id="content-list">
${categoryItems}
</div>
<button id="selectAllButton">Select All</button>
<button id="invertSelectionButton">Invert</button>
<button id="saveButton">Save Changes</button>
`;
$('#modal-content').html(modalContent);
openModal();
$('#selectAllButton').on('click', function() {
$('.category-item, .page-item').addClass('selected');
});
$('#invertSelectionButton').on('click', function() {
$('.category-item, .page-item').toggleClass('selected');
});
$('#saveButton').on('click', function() {
const editedPattern = $('#pattern').val();
const editedItems = $('.category-item.selected, .page-item.selected').map(function() {
return $(this).text();
}).get();
// Update the pages with edited data
editPages(sereke, editedPattern, editedItems);
});
// Event listener for selecting items
$('#content-list').on('click', '.category-item, .page-item', function() {
$(this).toggleClass('selected');
});
// Event listener for radio button change
$('input[name="content"]').on('change', function() {
const contentType = $(this).val();
if (contentType === 'category') {
$('#content-list').html(categoryItems);
} else if (contentType === 'page') {
$('#content-list').html(pageItems);
}
});
}
// Ji [[:commons:MediaWiki:Gadget-Cat-a-lot.js#L-600]] hat girtin
function regexCatBuilder(category) {
var catname = "Kategorî";
// Build a regexp string for matching the given category:
// trim leading/trailing whitespace and underscores
category = category.replace(/^[\s_]+|[\s_]+$/g, '');
// escape regexp metacharacters (= any ASCII punctuation except _)
category = mw.util.escapeRegExp(category);
// any sequence of spaces and underscores should match any other
category = category.replace(/[\s_]+/g, '[\\s_]+');
// Make the first character case-insensitive:
var first = category.substr(0, 1);
if (first.toUpperCase() !== first.toLowerCase()) {
category = '[' + first.toUpperCase() + first.toLowerCase() + ']' + category.substr(1);
}
// Compile it into a RegExp that matches MediaWiki category syntax (yeah, it looks ugly):
// XXX: the first capturing parens are assumed to match the sortkey, if present, including the | but excluding the ]]
return new RegExp('\\[\\[[\\s_]*' + catname + '[\\s_]*:[\\s_]*' + category + '[\\s_]*(\\|[^\\]]*(?:\\][^\\]]+)*)?\\]\\]\\s*', 'g');
}
function editPages(sereke, editedPattern, editedItems) {
const promises = editedItems.map(item => {
const patterns_arr = [" ", "!", "+", "*"];
let sort_key;
if (patterns_arr.includes(editedPattern)) {
console.log("Using editedPattern as sort_key:", editedPattern);
sort_key = editedPattern;
} else {
console.log("Checking if editedPattern is a valid regex and matches sereke...");
const regexPattern = new RegExp(editedPattern);
const item_kat_removed = item.replace(/^Kategorî:/, "");
if (regexPattern.test(item_kat_removed)) {
console.log("Edited pattern is a valid regex and matches item:", editedPattern);
const match = item_kat_removed.match(regexPattern);
if (match && match[1]) {
sort_key = match[1]; // Extract the matching part of item
console.log("Extracted sort_key:", sort_key);
} else {
console.log("No match found for sort_key, skipping to the next item");
// If no match found for sort_key, skip to the next item
return Promise.resolve();
}
} else {
console.log("Edited pattern is not a valid regex or doesn't match item, skipping to the next item");
// If editedPattern is not a valid regex or doesn't match item, skip to the next item
return Promise.resolve();
}
}
// Fetch current content of the page
console.log("Fetching current content of the page:", item);
return fetch(`https://ku.wikipedia.org/w/api.php?action=query&titles=${encodeURIComponent(item)}&prop=revisions&rvprop=content&format=json`)
.then(response => response.json())
.then(data => {
const pages = data.query.pages;
const pageId = Object.keys(pages)[0];
let currentPageContent = pages[pageId].revisions[0]['*'];
// Build a RegExp to match sereke with sort_key
console.log("Building RegExp to match sereke with sort_key:", sereke, sort_key);
const regexBuilder = new RegExp(regexCatBuilder(sereke));
// Update the page content with the edited data
console.log("Replacing content in currentPageContent with sort_key:", sort_key);
const updatedContent = currentPageContent.replace(regexBuilder, `[[Kategorî:${sereke}|${sort_key}]]\n`);
// Get CSRF token
console.log("Fetching CSRF token...");
return fetch("https://ku.wikipedia.org/w/api.php?action=query&meta=tokens&type=csrf&format=json")
.then(response => response.json())
.then(data => {
const editToken = data.query.tokens.csrftoken;
// Construct edit parameters
console.log("Constructing edit parameters...");
const apiUrl = "https://ku.wikipedia.org/w/api.php";
const editParams = new URLSearchParams({
action: "edit",
title: item,
token: editToken,
summary: `Kilîda rêzkirinê li [[Kategorî:${sereke}]] hat zêdekirin ([[Bikarhêner:Balyozxane/skrîpt/js/addSortKey.js|addSortKey.js]])`,
text: updatedContent,
format: "json"
});
// Send POST request to edit the page
console.log("Sending POST request to edit the page...");
return fetch(apiUrl, {
method: "POST",
body: editParams
});
});
});
});
// Wait for all edit requests to complete
console.log("Waiting for all edit requests to complete...");
Promise.all(promises)
.then(responses => {
responses.forEach(response => {
if (response.ok) {
console.log("Content edited successfully");
mw.notify("Content edited successfully");
} else {
console.error("Failed to edit content:", response);
mw.notify("Failed to edit content", {
type: "error"
});
}
});
closeModal(); // Close the modal after content is edited
})
.catch(error => {
console.error("Error editing content:", error);
mw.notify("Error editing content", {
type: "error"
});
});
}
// Function to open the modal
function openModal() {
$('#myModal').dialog('open');
}
// Function to close the modal
function closeModal() {
$('#myModal').dialog('close');
}
// Create the modal dialog
const modal = $('<div>', {
id: 'myModal',
title: 'AddSortKey',
style: 'display: none;'
});
// Modal content area
const modalContent = $('<div>', {
id: 'modal-content'
});
modal.append(modalContent);
// Append modal to the document body
$(document.body).append(modal);
// Initialize the modal as a jQuery UI dialog
modal.dialog({
autoOpen: false,
modal: true,
width: 'auto', // Adjusted for responsiveness
close: function() {
// Remove the modal from the DOM when closed
$(this).dialog('destroy');
$(this).remove();
}
});
// Define the function to handle the click event
function handleTemplateDataClick(event) {
event.preventDefault(); // Prevent the default action of following the link
const categoryName = mw.config.get('wgPageName');
getCategoriesAndPagesInCategory(categoryName, function(categoriesAndPages) {
displayModal(categoriesAndPages);
});
}
if (mw.config.get('wgNamespaceNumber') === 14) {
// Create the link using mw.util.addPortletLink
var targetContainer = mw.config.get('skin') === 'vector-2022' ? 'p-cactions' : 'p-tb';
var link = mw.util.addPortletLink(targetContainer, '#', 'AddSortKey', 't-AddSortKey', 'AddSortKey');
// Attach an event listener to the link
link.addEventListener('click', handleTemplateDataClick);
}
});
});