Wikipedia:On-demand gadgets

Work in progress; comments welcome
 – Currently being discussed at MediaWiki talk:Common.js#Class-triggered gadgets

On-demand gadgets are gadgets that are loaded on pages with content meeting some specific condition.

Motivation edit

There are a lot of usecases for gadgets that load conditionally based on the content of a page. The condition could be the presence of a template, a category, a parser tag, or an HTML class attribute. We only need to support one kind of condition since anything that adds a template can be easily changed to also add a category or parser tag or a div with a class, and vice-versa.

Today, Kartographer and Graph extensions provide interactive maps and graphs in Wikipedia. We should empower the community to build more such interactive features. The on-demand gadget system provides an efficient way to load such gadgets only where required. Many features in MediaWiki are first tried out as local scripts or gadgets before they mature into extensions.

Existing solutions and limitations edit

  • Using a loader gadget – a very small gadget that just checks if the core gadget needs to load. A separate loader gadget is used for each feature gadget, which bloats the startup module registry, and each one has to perform some check which could be optimised into a single check when we use a centralised loader solution.
  • Loading scripts based on presence of some URL parameter. This typically requires the user to click some button which redirects to the same or different page with the URL param added. The click, page reload, the loss of position in the page, and the slowness make it unsuitable for use in mainspace.

Guidelines for use edit

When on-demand gadgets are used in mainspace, they:

  • Should be used only for progressive enhancement. They should not add or remove any content, and only add interactivity over existing content. Must have a no-JS fallback so that the page displays normally without looking odd when JS is disabled. There should not be any "hole" in the content when indexed by a no-JS client, such as a search crawler or while printing.
  • Should not depend on or modify the html provided by the skin, or other content outside the parser output. Should hence work across all skins.
  • Should not require any user rights or depend on any user-specific information. Should work for anons.

Implementation edit

This is proposed to be implemented with the following code in MediaWiki:Gadget-ondemand.js:

mw.hook('wikipage.content').add($content =>
    $content.find('.load-gadget').each((_, e) => 
        mw.loader.load('ext.gadget.ondemand-' + e.dataset.gadget)
    )
);

The above gadget is then registered as default in MediaWiki:Gadgets-definition:

* ondemand [ ResourceLoader | default | hidden ] | ondemand.js

The "hidden" qualifier can be also be skipped. Doing so enables a user to opt-out from all on-demand gadgets.

An equivalent snippet can also be used in MediaWiki:Common.js and MediaWiki:Mobile.js in lieu of adding a default gadget.

Usage edit

Sample usage (within a template, which can then be used on pages):

<div class=load-gadget data-gadget=xyz>
</div>

Presence of such an html element triggers the gadget with name ondemand-xyz to load.

The gadget ondemand-xyz should be registered as hidden to hide it from preferences:

* ondemand-xyz [ ResourceLoader | hidden ] | ondemand-xyz.js

This should not be marked default as it will be internally loaded via ondemand gadget.

Process edit

Pre-deployment review edit

New on-demand gadgets affecting mainspace content should have community consensus demonstrated through an RfC or a discussion at an appropriate village pump.

On-demand gadgets for use outside mainspace may be enabled after a consensus at a relevant project talk page or a broader discussion, depending on the nature of the gadget.

In ALL cases, code in on-demand gadgets MUST be reviewed by at least one user (other than the author) with js-3 or higher proficiency. The code reviewer should be familiar with typical JS vulnerabilities such as XSS and ReDoS, and have demonstrable experience with JavaScript.

Maintenance edit

Names of maintainers should be listed in the gadget header. Maintainers should ensure that the gadget continues to function despite the changes occurring in the core MediaWiki software and in browsers.

Inactive maintainers should be replaced with active ones. Gadgets that fail to attract new maintainers should be disabled.

Alternative implementations edit

  1. Extending the gadget definition spec to load the gadget only when a template or category is present (phab:T204201, phab:T63007).
    • Setting a load condition based on a template makes it harder to test changes to the template itself. The template and its sandbox may have identical content, but only the former causes the gadget to load.
    • Using categories as a load condition may be inconsistent with expectations of users, who don't expect "magic" to happen from adding a category, as they would for templates or parser tags. Coupling gadgets with categories seems like a fragile connection.
    • In both cases, renaming the template or category breaks things and requires an update to the gadget definition, which has a higher protection level.
  2. Adding support for a parser tag, eg. <gadget name="xyz"/> (phab:T241524). This is an ideal solution. It can also provide enhanced tracking capabilities (backlinks, tracking category). But the patch has been stuck in code review for years.