Jump to content

ICT:Documentation:JavaScript in Asset v2

From Costa Sano MediaWiki

Explanation of JavaScript Usage in Asset v2

This page documents the role, purpose, and strict limitations of the JavaScript used in Asset v2.

It is intended as long-term reference documentation and is written to remain understandable years after the implementation.


Purpose of This Document

JavaScript in MediaWiki systems often becomes problematic because:

  • it runs in the browser, not on the server
  • it can be bypassed
  • it depends on UI behavior
  • it is easy to give it too much authority

This document explains exactly what JavaScript is allowed to do in Asset v2, and just as importantly, what it must NEVER do.


Big Picture

In Asset v2, JavaScript is used only as a form assistant.

JavaScript:

  • helps the user
  • reacts to user input
  • fills form fields automatically
  • improves usability

JavaScript does NOT:

  • define identity
  • create or rename pages
  • rename files
  • write to Cargo
  • enforce immutability
  • guarantee correctness

JavaScript is never authoritative.


Where the JavaScript Lives

The JavaScript code is stored in:

MediaWiki:Asset.js

It is loaded explicitly by the Asset form using:

mw.loader.load(
  mw.util.getUrl(
    'MediaWiki:Asset.js',
    { action: 'raw', ctype: 'text/javascript' }
  )
);

This means:

  • The script runs only on pages that include it
  • It is not globally injected into the wiki

When the Script Runs

The script starts with:

$(document).ready(function () {
    ...
});

This means:

  • The script runs after the form HTML is fully loaded
  • All form fields already exist in the DOM

This avoids race conditions.


Helper Function for Form Fields

function f(name) {
    return $("[name='Asset[" + name + "]']");
}

What this does:

  • Provides a short way to access form fields
  • Maps template parameter names to HTML input elements

Example:

  • f("Chapter") returns the Chapter field input

This is purely a convenience function.


Detecting Create Mode

function isCreateMode() {
    return $("input[name='pfFormPageName']").val() === "Asset:DRAFT";
}

What this does:

  • Detects whether the user is creating a new Asset
  • Prevents logic from running on existing Assets

Why this is critical:

  • Existing Assets must never be renumbered
  • Editing an Asset must never regenerate identifiers

This guard is essential for immutability.


The generate() Function

The core logic lives in:

function generate() {
    if (!isCreateMode()) return;
    ...
}

What this means:

  • All generation logic is disabled unless we are creating a new Asset
  • JavaScript cannot affect existing Assets

Reading User Input

const ch = f("Chapter").val();
const pl = f("Place").val();
const org = f("Organisation").val();

What this does:

  • Reads current user selections
  • Does not modify them
  • Does not validate beyond basic presence checks

Basic Input Validation

if (!ch || (pl && org) || (!pl && !org)) return;

What this does:

  • Ensures Chapter is selected
  • Ensures exactly one context is selected
  • Silently stops if conditions are not met

Important: This is only a UI convenience check. The authoritative validation happens in Lua.


Calling the Lua Module

new mw.Api().get({
    action: "scribunto-console",
    title: "Module:AssetID",
    question:
        "return require('Module:AssetID').generate{" +
        "Chapter='" + ch + "'," +
        "Place='" + pl + "'," +
        "Organisation='" + org + "'}"
});

What this does:

  • Calls the Lua module on the server
  • Passes current form values
  • Receives computed data

Why Lua is called from JS:

  • JavaScript cannot query Cargo safely
  • Lua runs server-side
  • Lua is deterministic

Handling the Lua Response

const r = JSON.parse(data.return);

What this does:

  • Parses the JSON returned by Lua
  • Allows structured access to values

If an error exists:

if (r.error) {
    alert(r.error);
    return;
}

This displays a message to the user but does not force behavior.


Writing Values Back to the Form

f("Label").val(r.identifier);
f("Sequence").val(r.sequence);
$("input[name='pfFormPageName']").val(r.identifier);

What this does:

  • Displays the generated identifier
  • Displays the sequence number
  • Sets the final page name

Important: This does NOT create the page. The page is only created when Save is clicked.


Capturing the Original Filename

$("input[type='file']").on("change", function () {
    if (this.files[0]) {
        f("OriginalFilename").val(this.files[0].name);
    }
});

What this does:

  • Listens for file selection
  • Reads the local filename
  • Stores it in a readonly field

Why this is done in JavaScript:

  • Only the browser knows the local filename
  • The server never sees it otherwise

This value is informational only.


What JavaScript Must NEVER Do

In Asset v2, JavaScript must never:

  • rename files
  • move pages
  • reserve identifiers
  • enforce immutability
  • decide final truth
  • write directly to Cargo

Any logic placed in JavaScript must be safe to bypass.


Failure Tolerance

If JavaScript fails completely:

  • The form still works
  • The user can still save
  • Asset v1-style behavior is possible
  • No data corruption occurs

This is intentional.


Mental Model to Keep

You can safely remember:

  • JavaScript = assistant
  • Lua = calculator
  • Cargo = storage
  • PHP extension = enforcement
  • Browser logic is never trusted

Status

This document is stable reference documentation.

It exists to support long-term understanding and memory retention.