|
|
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
| | importScript('MediaWiki:NewsForm.js'); |
| 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 */ |