Wikipedia:User scripts/Guide: Difference between revisions
Content deleted Content added
→Built-in scripts: clarify |
Let's move "Running code on page load" to "Basic techniques". It's more in-depth than the surrounding sections. |
||
Line 83:
And that's it! Save the common.js and then do a hard refresh. Go and edit a page such as the [[Wikipedia:Sandbox|Sandbox]], and see what happens!<ref>This section originally written by [[User:Raylu|raylu]] <sup>[[User:raylu/monobook.js|my monobook.js]]</sup>
Thanks a ton to all the users who helped improve this tutorial!</ref> Note that syntax highlighting must be disabled for this to work.
== Built-in scripts ==
Line 237 ⟶ 173:
== Basic techniques ==
=== Running code on page load ===
The personal <code>user</code> module (built from /common.js, /common.css and optionally the skin-specific files for the current skin; see [[#Writing a script from scratch|above]]) and [[Wikipedia:Gadget|gadgets]] are loaded on all pages. Most scripts will want to manipulate elements on the page; to do so the page needs to be ready (which may not be the case at the time the modules are loaded). We can defer execution of code by using a special function.
==== <code>$(document).ready(...)</code> ====
One option is [//api.jquery.com/ready/ <code>.ready()</code>] from [[jQuery]].
<syntaxhighlight lang="javascript">
// Define our main function
function myScript() {
// ... code ...
};
// Schedule it to run after the HTML page is parsed
$( document ).ready( myScript );
// This shorthand is also valid
jQuery( myScript );
</syntaxhighlight>
Since the function is called only once, many users prefer to shorten this code with an [[anonymous function]]:
<syntaxhighlight lang="javascript">
$( document ).ready( function () {
// ... code ...
} );
// Or
jQuery( function () {
// ... code ...
} );
</syntaxhighlight>
'' '''Note:''' <code>$</code> and <code>jQuery</code> are the same object; choosing between them is purely a matter of opinion.''
Many scripts use this function simply to add some script interface, such as a link in a portlet. Then the main part of the code is executed after the user clicks on that link.
==== <code>mw.hook('wikipage.content').add(...)</code> ====
However, if your code works with the content part of the page (the <code>#mw-content-text</code> element), you should use the <code>[https://doc.wikimedia.org/mediawiki-core/master/js/Hooks.html#~event:'wikipage.content' 'wikipage.content']</code> [[Hooking|hook]] instead. This way your code will successfully reprocess the page when it is updated asynchronously and the hook is fired again. There are plenty of tools which do so, ranging from edit preview to watchlist autoupdate.
Be sure to only work with the descendants of the <code>$content</code> element that your handler function takes and not the whole page. Otherwise, you may end up running the same code for the same elements many times. Note that the <code>'wikipage.content'</code> hook may be fired ''really'' many times.
Be cautious about what comes in the <code>$content</code> argument of the handler function. You shouldn't assume it's the <code>#mw-content-text</code> element. It can be a small portion of the page, e.g. when it is previewed.
Code that works with page content and avoids the aforementioned pitfalls may look like this:
<syntaxhighlight lang="javascript">
mw.hook( 'wikipage.content' ).add( function ( $content ) {
const $target = $content.find( '.targetClass' );
if ( $target.length ) {
// Do things with $target
}
// Only perform some operations when it is #mw-content-text in the argument
if ( $content.is( '#mw-content-text' ) ) {
const $note = $( '<div>' )
.addClass( 'myScript-note' )
.text( 'MyScript has successfully processed the content!' );
$content.prepend( $note );
}
} );
</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" inline>$content.find( '.targetClass' ).on( 'click', ... )</syntaxhighlight> you can write <syntaxhighlight lang="javascript" inline>$( document ).on( 'click', '.targetClass', ... )</syntaxhighlight>.
=== Finding elements ===
|