No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
// Check if we are adding or editing news | |||
if ( mw.config.get('wgAction') === 'formedit' || location.href.includes('Special:FormEdit/News') ) { | |||
// Setup save button to check for SEO mistakes before saving | |||
var saveButton = document.querySelector('[name="wpSave"'); | |||
saveButton.onclick = function(e){ | |||
var seoWarning = document.querySelector('.seo-warning'); | |||
if ( seoWarning ) { | |||
e.preventDefault(); | |||
var rect = seoWarning.getBoundingClientRect(); | |||
// Scroll the window to the top of the element | |||
window.scrollTo({ | |||
top: rect.top + window.scrollY, | |||
behavior: 'smooth' | |||
}); | |||
} | |||
}; | |||
var elements = Array.from(document.querySelectorAll('tbody th')); | |||
var keywordTr = elements.find(function (el) {return el.textContent.includes('SEO Keywords');}).closest('tr'); | |||
var keywordTd = keywordTr.querySelector('td'); | |||
var title = mw.config.get('wgTitle').split('/')[2]; | |||
var warningEl = function(text){ | |||
var warning = document.createElement('span'); | |||
warning.classList.add('seo-warning'); | |||
warning.style.textAlign = 'center'; | |||
warning.style.color = 'red'; | |||
warning.style.position = 'relative'; | |||
warning.style.zIndex = 11; | |||
warning.textContent = text; | |||
return warning; | |||
}; | |||
// SEO Title check | |||
var seoTitle = document.querySelector('[name="News[seo_title]"'); | |||
var seoTitleTd = seoTitle.closest('td'); | |||
var checkTitleLength = function() { | |||
var titleWarning = seoTitleTd.parentElement.querySelector('.seo-warning'); | |||
var titleLength = seoTitle.value.length; | |||
// If SEO Title too short | |||
if ( titleLength < 43 ) { | |||
if ( titleWarning ) { titleWarning.textContent = 'Title too short'; return;} | |||
seoTitleTd.parentNode.insertBefore(warningEl('Title too short'), seoTitleTd.nextSibling); | |||
} else if ( titleLength > 59 ) { | |||
if ( titleWarning ) { titleWarning.textContent = 'Title too long'; return;} | |||
seoTitleTd.parentNode.insertBefore(warningEl('Title too long'), seoTitleTd.nextSibling); | |||
} else if ( titleWarning ) { | |||
titleWarning.remove(); | |||
} | |||
}; | |||
seoTitle.onkeyup = checkTitleLength; | |||
// Check initial Title length | |||
checkTitleLength(); | |||
// SEO Description check | |||
var seoDescription = document.querySelector('[name="News[seo_description]"'); | |||
var seoDescriptionTd = seoDescription.closest('td'); | |||
var checkDescriptionLength = function() { | |||
if ( seoDescription.value.length == 0 ) return; | |||
var descriptionWarning = seoDescriptionTd.parentElement.querySelector('.seo-warning'); | |||
var descriptionLength = seoDescription.value.length; | |||
var errorText = ''; | |||
// If SEO Description too short | |||
if ( descriptionLength < 120 ) { | |||
errorText = 'Description too short'; | |||
} else if ( descriptionLength > 155 ) { | |||
errorText = 'Description too long'; | |||
} | |||
// Check if description contains keywords | |||
if ( !Array.from(keywordTd.querySelectorAll('.select2-match-entire')).find(function(el) { return seoDescription.value.includes(el.textContent); } ) ) { | |||
if ( errorText.length > 0 ) errorText += '. Does not contain Keywords'; | |||
else errorText = 'Does not contain Keywords'; | |||
} | |||
if ( errorText.length > 0 ) { | |||
if ( descriptionWarning ) descriptionWarning.textContent = errorText; | |||
else seoDescriptionTd.parentNode.insertBefore(warningEl(errorText), seoDescriptionTd.nextSibling); | |||
} else if ( descriptionWarning ) descriptionWarning.remove(); | |||
}; | |||
seoDescription.onkeyup = checkDescriptionLength; | |||
// Check initial Title length | |||
checkDescriptionLength(); | |||
//Content length check | |||
mw.hook('wikiEditor.toolbarReady').add(function ($textarea) { | |||
var content = document.querySelector('[name="News[content]"'); | |||
if ( !content ) return; | |||
var contentTd = content.closest('td'); | |||
content.style.overflowY = 'scroll'; | |||
var checkContentLength = function() { | |||
var value = content.value; | |||
if ( value.length == 0 ) return; | |||
var contentWarning = contentTd.parentElement.querySelector('.seo-warning'); | |||
var contentWords = value.split(' ').length; | |||
var contentErrorText = ''; | |||
// If SEO Description too short | |||
if ( contentWords < 300 ) { | |||
if ( contentErrorText.length > 0 ) contentErrorText += '. Content under 300 words'; | |||
contentErrorText = 'Content under 300 words'; | |||
} | |||
// Check if content has internal links | |||
if ( !value.includes('[[') ) { | |||
if ( contentErrorText.length > 0 ) contentErrorText += '. No internal links found'; | |||
else contentErrorText = 'No internal links founds'; | |||
} | |||
// Check if first paragraph has keywords | |||
var firstP = value.split('\n\n')[0]; | |||
if ( !Array.from(keywordTd.querySelectorAll('.select2-match-entire')).find(function(el) { return firstP.includes(el.textContent); } ) ) { | |||
if ( contentErrorText.length > 0 ) contentErrorText += '. First paragraph does not include Keywords'; | |||
else contentErrorText = 'First paragraph does not include Keywords'; | |||
} | |||
if ( contentErrorText.length > 0 ) { | |||
if ( contentWarning ) contentWarning.textContent = contentErrorText; | |||
else contentTd.parentNode.insertBefore(warningEl(contentErrorText), contentTd.nextSibling); | |||
} else if ( contentWarning ) contentWarning.remove(); | |||
}; | |||
content.onkeyup = checkContentLength; | |||
checkContentLength(); | |||
}); | |||
var keywordCheck = function (checkList) { | |||
var keywordWarning = keywordTr.querySelector('.keyword-warning'); | |||
var list = Array.from(checkList || []); | |||
if ( !list.find(function (el) {return title.includes( el.querySelector('.select2-match-entire').textContent ); }) ) { | |||
if (keywordWarning) return; | |||
keywordTr.insertBefore(warningEl('No keyword is present in the URL'), keywordTd.nextSibling); | |||
} else if (keywordWarning) { | |||
keywordWarning.remove(); | |||
} | |||
}; | |||
// Set up observer to check for keyword changes | |||
var observer = new MutationObserver(function (mutations) { | |||
// Check each mutation that occurred | |||
mutations.forEach(function (mutation) { | |||
// Check if the mutation was an addition of a node | |||
if ( | |||
mutation.target.nodeName === 'UL' && | |||
mutation.addedNodes.length > 0 && | |||
!mutation.addedNodes[0].classList.contains('select2-search') && | |||
mutation.type === 'childList' | |||
) { | |||
keywordCheck(mutation.addedNodes); | |||
} | |||
}); | |||
}); | |||
var config = { childList: true, subtree: true }; | |||
observer.observe(keywordTd, config); | |||
} | |||
// Check if we're editing a page and if we are, then add news search button to wikieditor | |||
if ( | |||
['edit', 'submit', 'formedit'].indexOf(mw.config.get('wgAction')) !== -1 || | |||
location.href.includes('Special:FormEdit') | |||
) { | |||
// Set up some variables for global use | |||
var caretPosition = 0; | |||
var lastKeyupTime = 0; | |||
var textarea; | |||
// Search function | |||
var search = function () { | |||
// Get the current timestamp | |||
var currentTime = new Date().getTime(); | |||
// Check if at least 2 seconds have passed since the last keyup event | |||
if (currentTime - lastKeyupTime > 2000 || lastKeyupTime === 0) { | |||
var searchInput = document.getElementById('search-input'); | |||
// Get the search phrase entered by the user | |||
var searchPhrase = searchInput.value.trim().toLowerCase() + '*'; | |||
// Do nothing unless at least 4 letters are entered (5 with our manual * at the end) | |||
if (searchPhrase.length < 5) return; | |||
var suggestionsContainer = document.getElementById('suggestions'); | |||
if (lastKeyupTime === 0) { | |||
suggestionsContainer.addEventListener('click', function (e) { | |||
if (e.target.classList.contains('newsForm-suggestion')) { | |||
searchInput.value = e.target.textContent; | |||
} | |||
}); | |||
} | |||
// Clear any existing suggestions | |||
suggestionsContainer.innerHTML = ''; | |||
var url = 'api.php'; | |||
params = new URLSearchParams({ | |||
action: 'query', | |||
list: 'search', | |||
srsearch: searchPhrase, | |||
format: 'json', | |||
srlimit: 5, | |||
// origin: location.origin | |||
origin: '*' | |||
}); | |||
fetch(url + '?' + params) | |||
.then(function (response) { | |||
return response.json(); | |||
}) | |||
.then(function (response) { | |||
// Loop through the suggestions and add matching items to the container | |||
var results = response.query.search; | |||
for (var i = 0; i < results.length; i++) { | |||
var result = results[i]; | |||
var suggestionItem = document.createElement('div'); | |||
suggestionItem.innerText = result.title; | |||
suggestionItem.classList.add('newsForm-suggestion'); | |||
suggestionsContainer.appendChild(suggestionItem); | |||
} | |||
}) | |||
.catch(function (error) { | |||
console.log(error); | |||
}); | |||
lastKeyupTime = currentTime; | |||
} | |||
}; | |||
// Create the modal for search | |||
var modal = document.createElement('div'); | |||
modal.id = 'newsForm'; | |||
modal.classList.add('newsForm'); | |||
var content = document.createElement('div'); | |||
content.classList.add('newsForm-content'); | |||
var close = document.createElement('span'); | |||
close.classList.add('newsForm-close'); | |||
close.innerHTML = '×'; | |||
var h2 = document.createElement('h2'); | |||
h2.innerHTML = 'Search'; | |||
var p = document.createElement('div'); | |||
p.innerHTML = 'Enter your search phrase:'; | |||
var input = document.createElement('input'); | |||
input.id = 'search-input'; | |||
var p2 = document.createElement('div'); | |||
p2.innerHTML = 'Results:'; | |||
var suggestions = document.createElement('div'); | |||
suggestions.id = 'suggestions'; | |||
var p3 = document.createElement('div'); | |||
p3.innerHTML = 'Displayed title'; | |||
var input2 = document.createElement('input'); | |||
input2.id = 'display-title'; | |||
var insert = document.createElement('button'); | |||
insert.innerHTML = 'Insert link'; | |||
insert.addEventListener('click', function () { | |||
var value = textarea.value; | |||
var link = '[[' + input.value + '|' + input2.value + ']]'; | |||
textarea.value = | |||
value.substring(0, caretPosition) + link + value.substring(caretPosition); | |||
input.value = ''; | |||
input2.value = ''; | |||
modal.style.display = 'none'; | |||
}); | |||
close.onclick = function () { | |||
modal.style.display = 'none'; | |||
}; | |||
input.addEventListener('keyup', search); | |||
content.append(close, h2, p, input, p3, input2, p2, suggestions, insert); | |||
modal.append(content); | |||
// Append the modal HTML to the body element | |||
document.body.appendChild(modal); | |||
// Add a hook handler. | |||
mw.hook('wikiEditor.toolbarReady').add(function ($textarea) { | |||
// Configure a new toolbar entry on the given $textarea jQuery object. | |||
$textarea.wikiEditor('addToToolbar', { | |||
section: 'secondary', | |||
group: 'default', | |||
tools: { | |||
dothing: { | |||
type: 'element', | |||
element: function (context) { | |||
// Note that the `context` object contains various useful references. | |||
var button = new OO.ui.ButtonInputWidget({ | |||
label: 'N', | |||
icon: 'linkSecure' | |||
}); | |||
textarea = document.querySelector('.wikiEditor-ui-text textarea'); | |||
// var wikieditorInstance = $( '.wikiEditor-ui-text textarea' ).wikieditor(); | |||
button.connect(null, { | |||
click: function (e) { | |||
modal.style.display = 'flex'; | |||
caretPosition = textarea.selectionStart; | |||
} | |||
}); | |||
return button.$element; | |||
} | |||
} | |||
} | |||
}); | |||
}); | |||
} | |||
/* Tournament team list */ | /* Tournament team list */ | ||
(function () { | (function () { |
Revision as of 17:45, 4 May 2023
/* Any JavaScript here will be loaded for all users on every page load. */
// Check if we are adding or editing news
if ( mw.config.get('wgAction') === 'formedit' || location.href.includes('Special:FormEdit/News') ) {
// Setup save button to check for SEO mistakes before saving
var saveButton = document.querySelector('[name="wpSave"');
saveButton.onclick = function(e){
var seoWarning = document.querySelector('.seo-warning');
if ( seoWarning ) {
e.preventDefault();
var rect = seoWarning.getBoundingClientRect();
// Scroll the window to the top of the element
window.scrollTo({
top: rect.top + window.scrollY,
behavior: 'smooth'
});
}
};
var elements = Array.from(document.querySelectorAll('tbody th'));
var keywordTr = elements.find(function (el) {return el.textContent.includes('SEO Keywords');}).closest('tr');
var keywordTd = keywordTr.querySelector('td');
var title = mw.config.get('wgTitle').split('/')[2];
var warningEl = function(text){
var warning = document.createElement('span');
warning.classList.add('seo-warning');
warning.style.textAlign = 'center';
warning.style.color = 'red';
warning.style.position = 'relative';
warning.style.zIndex = 11;
warning.textContent = text;
return warning;
};
// SEO Title check
var seoTitle = document.querySelector('[name="News[seo_title]"');
var seoTitleTd = seoTitle.closest('td');
var checkTitleLength = function() {
var titleWarning = seoTitleTd.parentElement.querySelector('.seo-warning');
var titleLength = seoTitle.value.length;
// If SEO Title too short
if ( titleLength < 43 ) {
if ( titleWarning ) { titleWarning.textContent = 'Title too short'; return;}
seoTitleTd.parentNode.insertBefore(warningEl('Title too short'), seoTitleTd.nextSibling);
} else if ( titleLength > 59 ) {
if ( titleWarning ) { titleWarning.textContent = 'Title too long'; return;}
seoTitleTd.parentNode.insertBefore(warningEl('Title too long'), seoTitleTd.nextSibling);
} else if ( titleWarning ) {
titleWarning.remove();
}
};
seoTitle.onkeyup = checkTitleLength;
// Check initial Title length
checkTitleLength();
// SEO Description check
var seoDescription = document.querySelector('[name="News[seo_description]"');
var seoDescriptionTd = seoDescription.closest('td');
var checkDescriptionLength = function() {
if ( seoDescription.value.length == 0 ) return;
var descriptionWarning = seoDescriptionTd.parentElement.querySelector('.seo-warning');
var descriptionLength = seoDescription.value.length;
var errorText = '';
// If SEO Description too short
if ( descriptionLength < 120 ) {
errorText = 'Description too short';
} else if ( descriptionLength > 155 ) {
errorText = 'Description too long';
}
// Check if description contains keywords
if ( !Array.from(keywordTd.querySelectorAll('.select2-match-entire')).find(function(el) { return seoDescription.value.includes(el.textContent); } ) ) {
if ( errorText.length > 0 ) errorText += '. Does not contain Keywords';
else errorText = 'Does not contain Keywords';
}
if ( errorText.length > 0 ) {
if ( descriptionWarning ) descriptionWarning.textContent = errorText;
else seoDescriptionTd.parentNode.insertBefore(warningEl(errorText), seoDescriptionTd.nextSibling);
} else if ( descriptionWarning ) descriptionWarning.remove();
};
seoDescription.onkeyup = checkDescriptionLength;
// Check initial Title length
checkDescriptionLength();
//Content length check
mw.hook('wikiEditor.toolbarReady').add(function ($textarea) {
var content = document.querySelector('[name="News[content]"');
if ( !content ) return;
var contentTd = content.closest('td');
content.style.overflowY = 'scroll';
var checkContentLength = function() {
var value = content.value;
if ( value.length == 0 ) return;
var contentWarning = contentTd.parentElement.querySelector('.seo-warning');
var contentWords = value.split(' ').length;
var contentErrorText = '';
// If SEO Description too short
if ( contentWords < 300 ) {
if ( contentErrorText.length > 0 ) contentErrorText += '. Content under 300 words';
contentErrorText = 'Content under 300 words';
}
// Check if content has internal links
if ( !value.includes('[[') ) {
if ( contentErrorText.length > 0 ) contentErrorText += '. No internal links found';
else contentErrorText = 'No internal links founds';
}
// Check if first paragraph has keywords
var firstP = value.split('\n\n')[0];
if ( !Array.from(keywordTd.querySelectorAll('.select2-match-entire')).find(function(el) { return firstP.includes(el.textContent); } ) ) {
if ( contentErrorText.length > 0 ) contentErrorText += '. First paragraph does not include Keywords';
else contentErrorText = 'First paragraph does not include Keywords';
}
if ( contentErrorText.length > 0 ) {
if ( contentWarning ) contentWarning.textContent = contentErrorText;
else contentTd.parentNode.insertBefore(warningEl(contentErrorText), contentTd.nextSibling);
} else if ( contentWarning ) contentWarning.remove();
};
content.onkeyup = checkContentLength;
checkContentLength();
});
var keywordCheck = function (checkList) {
var keywordWarning = keywordTr.querySelector('.keyword-warning');
var list = Array.from(checkList || []);
if ( !list.find(function (el) {return title.includes( el.querySelector('.select2-match-entire').textContent ); }) ) {
if (keywordWarning) return;
keywordTr.insertBefore(warningEl('No keyword is present in the URL'), keywordTd.nextSibling);
} else if (keywordWarning) {
keywordWarning.remove();
}
};
// Set up observer to check for keyword changes
var observer = new MutationObserver(function (mutations) {
// Check each mutation that occurred
mutations.forEach(function (mutation) {
// Check if the mutation was an addition of a node
if (
mutation.target.nodeName === 'UL' &&
mutation.addedNodes.length > 0 &&
!mutation.addedNodes[0].classList.contains('select2-search') &&
mutation.type === 'childList'
) {
keywordCheck(mutation.addedNodes);
}
});
});
var config = { childList: true, subtree: true };
observer.observe(keywordTd, config);
}
// Check if we're editing a page and if we are, then add news search button to wikieditor
if (
['edit', 'submit', 'formedit'].indexOf(mw.config.get('wgAction')) !== -1 ||
location.href.includes('Special:FormEdit')
) {
// Set up some variables for global use
var caretPosition = 0;
var lastKeyupTime = 0;
var textarea;
// Search function
var search = function () {
// Get the current timestamp
var currentTime = new Date().getTime();
// Check if at least 2 seconds have passed since the last keyup event
if (currentTime - lastKeyupTime > 2000 || lastKeyupTime === 0) {
var searchInput = document.getElementById('search-input');
// Get the search phrase entered by the user
var searchPhrase = searchInput.value.trim().toLowerCase() + '*';
// Do nothing unless at least 4 letters are entered (5 with our manual * at the end)
if (searchPhrase.length < 5) return;
var suggestionsContainer = document.getElementById('suggestions');
if (lastKeyupTime === 0) {
suggestionsContainer.addEventListener('click', function (e) {
if (e.target.classList.contains('newsForm-suggestion')) {
searchInput.value = e.target.textContent;
}
});
}
// Clear any existing suggestions
suggestionsContainer.innerHTML = '';
var url = 'api.php';
params = new URLSearchParams({
action: 'query',
list: 'search',
srsearch: searchPhrase,
format: 'json',
srlimit: 5,
// origin: location.origin
origin: '*'
});
fetch(url + '?' + params)
.then(function (response) {
return response.json();
})
.then(function (response) {
// Loop through the suggestions and add matching items to the container
var results = response.query.search;
for (var i = 0; i < results.length; i++) {
var result = results[i];
var suggestionItem = document.createElement('div');
suggestionItem.innerText = result.title;
suggestionItem.classList.add('newsForm-suggestion');
suggestionsContainer.appendChild(suggestionItem);
}
})
.catch(function (error) {
console.log(error);
});
lastKeyupTime = currentTime;
}
};
// Create the modal for search
var modal = document.createElement('div');
modal.id = 'newsForm';
modal.classList.add('newsForm');
var content = document.createElement('div');
content.classList.add('newsForm-content');
var close = document.createElement('span');
close.classList.add('newsForm-close');
close.innerHTML = '×';
var h2 = document.createElement('h2');
h2.innerHTML = 'Search';
var p = document.createElement('div');
p.innerHTML = 'Enter your search phrase:';
var input = document.createElement('input');
input.id = 'search-input';
var p2 = document.createElement('div');
p2.innerHTML = 'Results:';
var suggestions = document.createElement('div');
suggestions.id = 'suggestions';
var p3 = document.createElement('div');
p3.innerHTML = 'Displayed title';
var input2 = document.createElement('input');
input2.id = 'display-title';
var insert = document.createElement('button');
insert.innerHTML = 'Insert link';
insert.addEventListener('click', function () {
var value = textarea.value;
var link = '[[' + input.value + '|' + input2.value + ']]';
textarea.value =
value.substring(0, caretPosition) + link + value.substring(caretPosition);
input.value = '';
input2.value = '';
modal.style.display = 'none';
});
close.onclick = function () {
modal.style.display = 'none';
};
input.addEventListener('keyup', search);
content.append(close, h2, p, input, p3, input2, p2, suggestions, insert);
modal.append(content);
// Append the modal HTML to the body element
document.body.appendChild(modal);
// Add a hook handler.
mw.hook('wikiEditor.toolbarReady').add(function ($textarea) {
// Configure a new toolbar entry on the given $textarea jQuery object.
$textarea.wikiEditor('addToToolbar', {
section: 'secondary',
group: 'default',
tools: {
dothing: {
type: 'element',
element: function (context) {
// Note that the `context` object contains various useful references.
var button = new OO.ui.ButtonInputWidget({
label: 'N',
icon: 'linkSecure'
});
textarea = document.querySelector('.wikiEditor-ui-text textarea');
// var wikieditorInstance = $( '.wikiEditor-ui-text textarea' ).wikieditor();
button.connect(null, {
click: function (e) {
modal.style.display = 'flex';
caretPosition = textarea.selectionStart;
}
});
return button.$element;
}
}
}
});
});
}
/* Tournament team list */
(function () {
// If Participants team list with a toggle button is added, then make that button clickable
var myElement = document.getElementById('team-toggle');
if (myElement) {
myElement.addEventListener('click', function (e) {
if (e.target.innerHTML === 'Show Players')
e.target.innerHTML = 'Hide Players';
else e.target.innerHTML = 'Show Players';
document.querySelectorAll('.team-list .players').forEach(function (el) {
el.classList.toggle('show');
});
});
}
})();