Wikipedia:User scripts/Guide: Difference between revisions

Content deleted Content added
No edit summary
Line 28:
To make a [[Hello world]] program, insert the following code into your ''User:YourUserName/common.js'' file:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">importScript('User:YourUserName/hello-world.js');</syntaxhighlight>
 
Next, create the page ''User:YourUserName/hello-world.js'', and insert this code:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">$('#bodyContent').prepend('<p>Hello world!</p>');</syntaxhighlight>
 
This will write "Hello world!" on every page, below the title, until you remove the code. User scripts are written in [[JavaScript]], and both of the above code snippets are in JavaScript. The second snippet uses [[JQuery]], a JavaScript library that specializes in manipulating [[HTML]]. <code>$</code> is a JQuery [[Function (computer programming)|function]] that lets us target the [[HTML]] element we want. <code>#bodyContent</code> is a string in [[CSS selector]] syntax, and means target the HTML element with property <code>id="bodyContent"</code> . <code>prepend</code> is a JQuery function that inserts HTML code as a child of the <code>#bodyContent</code> element. <code><nowiki><p>Hello world!</p></nowiki></code> is the HTML code to be inserted.
Line 39:
We will be writing a user script by modifying your common.js. For the purpose of this tutorial, we will write a simple version of the [[Wikipedia:WikiProject User scripts/Scripts/Quick wikify|Quick wikify]] module, which adds the <code><nowiki>{{Wikify}}</nowiki></code> maintenance template to the top of an article when you click a link called "Wikify" in the "More" menu. To begin, change <code>MODULE_NAME</code> in the module template to "Qwikify". Your template should look like this:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Qwikify
$( document ).ready( function () {
Line 52:
Altogether, your new function should look like this:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Make sure the utilities module is loaded (will only load if not already)
mw.loader.using( 'mediawiki.util', function () {
Line 69:
Now, we must write our actual <code>doQwikify()</code> function. It will edit the edit box, so we need to get the name of that and its form. Viewing the source of the page shows that the form is named <code>editform</code> and the textbox is named <code>wpTextbox1</code>, meaning that the actual text is <code>document.editform.wpTextbox1.value</code>. To add {{tl|wikify}} (and two new lines), we simply do:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
document.editform.wpTextbox1.value = "{" + "{wikify}}\n\n" + document.editform.wpTextbox1.value;
</syntaxhighlight>
Line 77:
Finally, we want to submit the form for the user. Luckily, JavaScript has a built-in function just for this named <code>submit()</code>. To submit our editing form, use <code>document.editform.submit()</code>. Your code should now look something like this:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
function doQwikify() {
document.editform.wpTextbox1.value = "{" + "{wikify}}\n\n" + document.editform.wpTextbox1.value;
Line 86:
And that's it! Combine it all together and it should look like this:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Make sure the utilities module is loaded (will only load if not already)
mw.loader.using( 'mediawiki.util', function () {
Line 132:
The best and most recommended way to load a JavaScript file during development is from your local web server (see below for an easy way to install a web server). Put this string in your [[Special:Mypage/common.js|/common.js]]:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
mw.loader.load( 'https://localhost/wikipediatest.js' );
</syntaxhighlight>
 
In some environment, you need write this like<ref>https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content</ref>:
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
mw.loader.load( 'http://127.0.0.1/wikipediatest.js' );
</syntaxhighlight>
Line 201:
One option is <code>[//api.jquery.com/ready/ .ready()]</code> from [[jQuery]].
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Define our main function
function myScript() {
Line 215:
 
Since the function is called only once, many users prefer to shorten this code with an [[anonymous function]]:
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
$( document ).ready( function () {
// ... code ...
Line 239:
Code that works with page content and avoids the aforementioned pitfalls may look like this:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
mw.hook( 'wikipage.content' ).add( function ( $content ) {
const $target = $content.find( '.targetClass' );
Line 256:
</syntaxhighlight>
 
If your code works with page content and adds event handlers to DOM elements, then, instead of hooking to <code>'wikipage.content'</code> and looking for elements to attach event listeners to when it is fired, you may attach one event listener to an element outside of the content area or the whole <code>document</code> but filter events by a selector (see [https://api.jquery.com/on/#on-events-selector-data-handler jQuery's documentation]). That is, instead of writing <syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%" inline>$content.find( '.targetClass' ).on( 'click', ... )</syntaxhighlight> you can write <syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%" inline>$( document ).on( 'click', '.targetClass', ... )</syntaxhighlight>.
 
=== Finding elements ===
Every [[HTML]] element is a node in a [[Document Object Model|DOM]] model allowing scripts to access the element, for example, on the following HTML page.
 
<syntaxhighlight lang="html" copy style="min-width:fit-content; max-width: 40%">
<form name="frmname" id="frmid">
<textarea name="txtname" id="txtid"></textarea>
Line 283:
Many scripts are supposed to work only on some pages. You can check:
 
* The page type<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
if ( mw.config.get( 'wgAction' ) === 'history' ) { // Continue only on history pages.
</syntaxhighlight>
* [[:mw:Manual:Interface/JavaScript#mw.config|<kbd>wg</kbd> (Wikimedia global) variables]]; many of them have the same meaning as [[Help:Magic words|Magic words]]<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
if ( mw.config.get( 'wgCanonicalNamespace' ) === 'User_talk') { // Continue only on User_talk pages.
</syntaxhighlight><syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
if ( mw.config.get( 'wgPageName' ) === 'Article_name' ) { // Continue only for the article "Article name".
</syntaxhighlight>
 
* Presence of elements (only in second and third parts of the script)<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
function func_start() {
if ( $( '#editForm' ).length == 0 ) return; //No edit form ? exit
Line 324:
 
==== Portlet structure ====
<syntaxhighlight lang="html" copy style="min-width:fit-content; max-width: 40%">
<div id="p-myname" class="portlet">
<h5>Header</h5>
Line 349:
* <code>nextNode</code> (optional) – element that this will be added in front of
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Several examples of portlet links
 
Line 368:
Or you can use JQuery. Simply attach it in another place with <code>.append()</code>, <code>.prepend()</code>, <code>.before()</code>, or <code>.after()</code>. [https://www.w3schools.com/jquery/jquery_dom_add.asp][https://javascript.info/article/modifying-document/before-prepend-append-after.svg]. Warning: This is fragile. You may get it working on a couple skins, but a couple other skins may look broken.
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Add a clickable button on the edit article page, above the edit summary.
$('.editOptions').prepend('<button type="button" id="my-custom-button">Do Things</button>');
Line 382:
To hide an element, you can use JQuery's [//api.jquery.com/hide/ <code>.hide()</code>] function.
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Example: remove special characters toolbar from edit page
$( '#editpage-specialchars' ).hide();
Line 410:
The most important element on the edit page is a <kbd><textarea></kbd> with the article text inside. You can reference it with
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
var $textbox = $( '#wpTextbox1' );
</syntaxhighlight>
 
You can manipulate it using the [https://doc.wikimedia.org/mediawiki-core/master/js/jQueryPlugins.html#.textSelection jquery.textSelection] ResourceLoader module.
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
var $textbox = $( '#wpTextbox1' );
$textbox.textSelection( 'setContents', 'This is bold!' );
Line 425:
Or you can grab <code><textbox></code>'s text, create a [[string (computer science)|string]], modify it, then write it back. Note; other editing tools might not recognise your changes or cause conflicts if you use this methodology instead of the textSelection api.
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Get value.
let value = $('#wpTextbox1').val();
Line 462:
You may want to place the following code at the top and bottom of your user script, in a comment. This will help prevent bugs, such as <code><nowiki>~~~~</nowiki></code> turning into your hard-coded signature when you save the page.
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">//<nowiki>
 
Your code here.
Line 474:
Do not declare named functions in the global namespace. For example, this is bad:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">function submitEdit() {/* do stuff */}
 
$(function(){/* main code here */});</syntaxhighlight>
Line 480:
What if another of your user scripts also declares a <code><nowiki>submitEdit()</nowiki></code> function? This can lead to [[race conditions]] and hard-to-trace bugs. Instead, use classes named after your script, or place all your functions inside of an [[immediately invoked function expression]] (IIFE) such as <code><nowiki>$(function {});</nowiki></code>. JavaScript allows [[Nested function|nested functions]].
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">$(function(){
function submitEdit() {/* do stuff */}
Line 502:
===== Using module <code>mediawiki.api</code>=====
Note: make sure to add <code>mediawiki.api</code> to your dependencies!
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
function doSomethingWithText( wikitext ) {
/* .. */
Line 531:
 
===== Using jQuery $.getJSON =====
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
$.getJSON(
mw.util.wikiScript('api'),
Line 558:
 
===== Using jQuery $.ajax =====
Fetching a page content can be done using jQuery <code>$.ajax</code>, which does an HTTP [[GET (HTTP)|GET]] request.<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
$.ajax({
url: mw.util.getUrl( 'Wikipedia:Sandbox' )
Line 576:
===== Using module <code>mediawiki.api</code>=====
Note: make sure to add <code>mediawiki.api</code> to your dependencies!
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Edit page via the mw.Api module.
// postWithEditToken( {} ) may be used instead of postWithToken("csrf", {} )
Line 607:
 
===== Using plain jQuery =====
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
// Edit page (must be done through POST)
// the line "text: info.text," will cause the call
Line 651:
Security warning: Do not load Wikipedia pages that do not end in .js into your script using this method, because anybody can edit those pages.
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">let title = "User:YourName/YourScript.js";
mw.loader.load( "https://en.wikipedia.org/w/index.php?title="+title+"&action=raw&ctype=text/javascript" );</syntaxhighlight>
 
Line 660:
Careful with <code>ctype</code>. Set it to <code>raw</code> for normal Wiki pages, and <code>application/json</code> for pages where a template editor or admin has set the [https://www.mediawiki.org/wiki/Help:ChangeContentModel Content Model] to JSON.
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">let jsonData;
let title = "User:YourName/YourData.json";
$.getJSON(mw.config.get('wgScriptPath')+'/index.php?action=raw&ctype=application/json&title='+title, function(data){
Line 679:
An alternative way is to put this line in your Javascript file instead:
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
mw.loader.load( 'http://localhost/wikipediatest.css', 'text/css' );
</syntaxhighlight>
Line 687:
Once you have finished the CSS code, you either need to paste it into your <kbd>/vector.css</kbd> if it is only for personal use. Or if it is for use by others then you should upload it to for instance [[Special:Mypage/yourscript.css|User:Yourname/yourscript.css]]. Then other users can import it by putting the following line in their <kbd>/common.js</kbd> file. Note, that is in their ".js", not their ".css".
 
<syntaxhighlight lang="javascript" copy style="min-width:fit-content; max-width: 40%">
importStylesheet( 'User:Yourname/yourscript.css' );
</syntaxhighlight>