Help:Widgets

From Guild Wars 2 Wiki
Jump to navigationJump to search

The Widgets extension allows the creation of raw HTML pages that can be embedded (similarly to templates) in normal wiki pages. You do this by creating pages in the Widget namespace. They avoid the security problems of raw HTML in editable wiki pages because the privilege to edit in the Widget namespace is managed.

MediaWiki Extension:Widgets

Overview[edit]

General[edit]

  • As mentioned above, only widget editors and sysops can edit widgets to prevent malicious code from being added.
  • Widgets run at the same time as the asyncronous ResourceLoader modules, e.g. jQuery, and will have to wait for the document to be ready before trying to use ResourceLoader dependencies.
  • Parameters can be passed to widgets using SmartySyntax. For example, you could pass a parameter named "clear" to a widget by including the following within the widget code: <!--{$clear|default:both|escape:'html'}-->, which would be replaced with the value left for example if used like {{#Widget:widget name|clear=left}}.
    • Parameter names cannot contain spaces. A viable alternative is to use underscores instead. Wrapping a parameter name containing spaces with quotes won't work either.
  • Use a counter to ensure that scripts and styles defined by the widget will only be included once, even if the widget is used multiple times on a single page.
  • An invalid widget will return a red error string along the lines of "Error in Widget:Widget name." Some smarty parameters will have to be escaped in order to produce a valid widget. Likewise invalid code will produce the same message.
  • After editing a widget page, it will need to be purged to generate the latest scripts.

How to fix widgets? Purge![edit]

Did you find a page which should have an API check? Or a timetable with the wrong date? You have probably found a page with a bugged widget. How to fix it? Purge!

Purge the page on which you are experiencing the bug (not the widget page).

  • How to purge?
    • Click the clock (top right) and wait for the page to reload.
    • Logged in users can click the purge button at the top of the page.
    • Add ?action=purge to the end of the page url.

If this does not fix your widget you can try editing and saving the page without changes (called a NULL edit). If this does not work either you can leave a comment on the talk page.

Technical points[edit]

  • The widget extension effectively converts a widget page into a php template file that lives in the compiled_templates folder.
  • If there are any errors within the widget template, they will manifest themselves as PHP errors. That error will be added to the log.
  • The PHP error may not be visible to regular users since the live wiki operates with PHP errors hidden by default, however if you were to copy the exact widget code onto a fresh installation of MediaWiki, you would see PHP errors plastered in amongst the widget results.
  • In April 2020 there was an issue identified (a bug in the underlying template engine "smarty"), which had lead to the PHP error log file becoming so large that all the wiki disk space was exhausted, preventing files from being uploaded. Additionally widgets could not be recompiled after purging, leaving broken widgets everywhere. In order to avoid a repeat of this event, it is important that all smarty syntax is carefully checked for the following:
    • Empty parameter handling
      • Does the template use <!--{if isset($varname1) && isset($varname2)}--><!--{else}--><!--{/if}--> at the start for any required parameters?
      • Do user-exposed parameters have default values defined using the default: modifier?
    • User input validation
      • Are bad parameter inputs escaped to avoid malicious usage of widgets using the escape: modifier? (javascript/html/htmlall)
    • Good practice example: <!--{$varname1|default:''|escape:'javascript'}-->
  • Smarty "counters" is currently subject to a bug where the first counter on a page may not initialise to 1. Due to this, in December 2022, all widgets in the mainspace were rewritten to remove smarty counter checks for the first occurrence on a page; such a check should now either be implemented with javascript (see example below) or at template level with variables.

API specific notes[edit]

  • If the language token, i.e. &lang=en, is not specified, it uses the browser's language. All widgets should use a language token to prevent unexpected results.
  • Queries made by wiki widgets also have &wiki=1, which does nothing but theoretically could allow ArenaNet to figure out how much traffic the API receives from wiki pages.
  • Results are not cached, but widget code is cached.

Typical widget page layout[edit]

<noinclude>
== Description ==
This widget performs function X Y Z. The widget is used by [[Template:Widget name ABC]].

=== Parameters ===
; wikiparameter1
: wikiparameter1 description

== Example ==
{{#Widget:Widget name|wikiparameter1=value1}}

[[Category:Widgets]]

</noinclude><includeonly>
<!-- HTML to be inserted by widget -->
<div class="widgetcontainer"><!--{$wikiparameter1|default:'Is it me you are looking for?'|escape:'htmlall'}--></div>

<style>/* Custom CSS rules for the widget */</style>
<script>/* Custom JavaScript code for the widget */</script>
</includeonly>

Code to wait for the document to be ready[edit]

// defer script execution until the mediawiki loader and jQuery are available

// DEFER LOADING SCRIPT UNTIL JQUERY IS READY. WAIT 40MS BETWEEN ATTEMPTS.
function defer(method) {
    if (window.jQuery && mw && mw.loader) { // can remove the mw portion if not using mediawiki functions
        method();
    } else {
        setTimeout(function() { defer(method) }, 40);
    }
}

// INITIALISATION
defer(function () {
    console.log('mw.loader and jQuery are available now', $);

    // to load external scripts (here to load User:Example/common.js)
    mw.loader.load('//wiki.guildwars2.com/index.php?action=raw&ctype=text/javascript&title=User:Example/common.js');

    // to depend on other mediawiki modules
    mw.loader.using('mediawiki.api.parse', function () {
        var api = new mw.Api();
        api.parse('[[Sandbox]]').done(function (result) {
            console.log('Parsed HTML', result);
        });
    });
});

Code to check if a widget's script has already been loaded on the current page[edit]

// Verify this is the first time this script is being loaded.
if (typeof widget_AccountOutfits_counter === 'undefined') {
    var widget_AccountOutfits_counter = 1;
    
    (function() {
    
        // Main widget code here
    
    })();

} else {
    console.log('Only one instance of [[Widget:Account outfits]] can be called per page. Further occurrences have been ignored.');
}

Widgets on this wiki[edit]

See also: Category:Widgets

Notes[edit]