<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mwiki.costasano.club/index.php?action=history&amp;feed=atom&amp;title=ICT%3ADocumentation%3AJavaScript_in_Asset_v2</id>
	<title>ICT:Documentation:JavaScript in Asset v2 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mwiki.costasano.club/index.php?action=history&amp;feed=atom&amp;title=ICT%3ADocumentation%3AJavaScript_in_Asset_v2"/>
	<link rel="alternate" type="text/html" href="https://mwiki.costasano.club/index.php?title=ICT:Documentation:JavaScript_in_Asset_v2&amp;action=history"/>
	<updated>2026-07-23T00:11:25Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://mwiki.costasano.club/index.php?title=ICT:Documentation:JavaScript_in_Asset_v2&amp;diff=1219&amp;oldid=prev</id>
		<title>Mngr: Created page with &quot;= 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 * i...&quot;</title>
		<link rel="alternate" type="text/html" href="https://mwiki.costasano.club/index.php?title=ICT:Documentation:JavaScript_in_Asset_v2&amp;diff=1219&amp;oldid=prev"/>
		<updated>2026-02-20T13:22:11Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;= 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 * i...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Explanation of JavaScript Usage in Asset v2 =&lt;br /&gt;
&lt;br /&gt;
This page documents the role, purpose, and strict limitations of the&lt;br /&gt;
JavaScript used in Asset v2.&lt;br /&gt;
&lt;br /&gt;
It is intended as long-term reference documentation and is written&lt;br /&gt;
to remain understandable years after the implementation.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Purpose of This Document ==&lt;br /&gt;
&lt;br /&gt;
JavaScript in MediaWiki systems often becomes problematic because:&lt;br /&gt;
&lt;br /&gt;
* it runs in the browser, not on the server&lt;br /&gt;
* it can be bypassed&lt;br /&gt;
* it depends on UI behavior&lt;br /&gt;
* it is easy to give it too much authority&lt;br /&gt;
&lt;br /&gt;
This document explains exactly what JavaScript is allowed to do in Asset v2,&lt;br /&gt;
and just as importantly, what it must NEVER do.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Big Picture ==&lt;br /&gt;
&lt;br /&gt;
In Asset v2, JavaScript is used only as a &amp;#039;&amp;#039;&amp;#039;form assistant&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
JavaScript:&lt;br /&gt;
&lt;br /&gt;
* helps the user&lt;br /&gt;
* reacts to user input&lt;br /&gt;
* fills form fields automatically&lt;br /&gt;
* improves usability&lt;br /&gt;
&lt;br /&gt;
JavaScript does NOT:&lt;br /&gt;
&lt;br /&gt;
* define identity&lt;br /&gt;
* create or rename pages&lt;br /&gt;
* rename files&lt;br /&gt;
* write to Cargo&lt;br /&gt;
* enforce immutability&lt;br /&gt;
* guarantee correctness&lt;br /&gt;
&lt;br /&gt;
JavaScript is never authoritative.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Where the JavaScript Lives ==&lt;br /&gt;
&lt;br /&gt;
The JavaScript code is stored in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MediaWiki:Asset.js&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is loaded explicitly by the Asset form using:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mw.loader.load(&lt;br /&gt;
  mw.util.getUrl(&lt;br /&gt;
    &amp;#039;MediaWiki:Asset.js&amp;#039;,&lt;br /&gt;
    { action: &amp;#039;raw&amp;#039;, ctype: &amp;#039;text/javascript&amp;#039; }&lt;br /&gt;
  )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means:&lt;br /&gt;
&lt;br /&gt;
* The script runs only on pages that include it&lt;br /&gt;
* It is not globally injected into the wiki&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== When the Script Runs ==&lt;br /&gt;
&lt;br /&gt;
The script starts with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    ...&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This means:&lt;br /&gt;
&lt;br /&gt;
* The script runs after the form HTML is fully loaded&lt;br /&gt;
* All form fields already exist in the DOM&lt;br /&gt;
&lt;br /&gt;
This avoids race conditions.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Helper Function for Form Fields ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function f(name) {&lt;br /&gt;
    return $(&amp;quot;[name=&amp;#039;Asset[&amp;quot; + name + &amp;quot;]&amp;#039;]&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does:&lt;br /&gt;
&lt;br /&gt;
* Provides a short way to access form fields&lt;br /&gt;
* Maps template parameter names to HTML input elements&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
* &amp;lt;code&amp;gt;f(&amp;quot;Chapter&amp;quot;)&amp;lt;/code&amp;gt; returns the Chapter field input&lt;br /&gt;
&lt;br /&gt;
This is purely a convenience function.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Detecting Create Mode ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function isCreateMode() {&lt;br /&gt;
    return $(&amp;quot;input[name=&amp;#039;pfFormPageName&amp;#039;]&amp;quot;).val() === &amp;quot;Asset:DRAFT&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does:&lt;br /&gt;
&lt;br /&gt;
* Detects whether the user is creating a new Asset&lt;br /&gt;
* Prevents logic from running on existing Assets&lt;br /&gt;
&lt;br /&gt;
Why this is critical:&lt;br /&gt;
&lt;br /&gt;
* Existing Assets must never be renumbered&lt;br /&gt;
* Editing an Asset must never regenerate identifiers&lt;br /&gt;
&lt;br /&gt;
This guard is essential for immutability.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== The generate() Function ==&lt;br /&gt;
&lt;br /&gt;
The core logic lives in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function generate() {&lt;br /&gt;
    if (!isCreateMode()) return;&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means:&lt;br /&gt;
&lt;br /&gt;
* All generation logic is disabled unless we are creating a new Asset&lt;br /&gt;
* JavaScript cannot affect existing Assets&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Reading User Input ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const ch = f(&amp;quot;Chapter&amp;quot;).val();&lt;br /&gt;
const pl = f(&amp;quot;Place&amp;quot;).val();&lt;br /&gt;
const org = f(&amp;quot;Organisation&amp;quot;).val();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does:&lt;br /&gt;
&lt;br /&gt;
* Reads current user selections&lt;br /&gt;
* Does not modify them&lt;br /&gt;
* Does not validate beyond basic presence checks&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Basic Input Validation ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (!ch || (pl &amp;amp;&amp;amp; org) || (!pl &amp;amp;&amp;amp; !org)) return;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does:&lt;br /&gt;
&lt;br /&gt;
* Ensures Chapter is selected&lt;br /&gt;
* Ensures exactly one context is selected&lt;br /&gt;
* Silently stops if conditions are not met&lt;br /&gt;
&lt;br /&gt;
Important:&lt;br /&gt;
This is only a UI convenience check.&lt;br /&gt;
The authoritative validation happens in Lua.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Calling the Lua Module ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
new mw.Api().get({&lt;br /&gt;
    action: &amp;quot;scribunto-console&amp;quot;,&lt;br /&gt;
    title: &amp;quot;Module:AssetID&amp;quot;,&lt;br /&gt;
    question:&lt;br /&gt;
        &amp;quot;return require(&amp;#039;Module:AssetID&amp;#039;).generate{&amp;quot; +&lt;br /&gt;
        &amp;quot;Chapter=&amp;#039;&amp;quot; + ch + &amp;quot;&amp;#039;,&amp;quot; +&lt;br /&gt;
        &amp;quot;Place=&amp;#039;&amp;quot; + pl + &amp;quot;&amp;#039;,&amp;quot; +&lt;br /&gt;
        &amp;quot;Organisation=&amp;#039;&amp;quot; + org + &amp;quot;&amp;#039;}&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does:&lt;br /&gt;
&lt;br /&gt;
* Calls the Lua module on the server&lt;br /&gt;
* Passes current form values&lt;br /&gt;
* Receives computed data&lt;br /&gt;
&lt;br /&gt;
Why Lua is called from JS:&lt;br /&gt;
&lt;br /&gt;
* JavaScript cannot query Cargo safely&lt;br /&gt;
* Lua runs server-side&lt;br /&gt;
* Lua is deterministic&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Handling the Lua Response ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const r = JSON.parse(data.return);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does:&lt;br /&gt;
&lt;br /&gt;
* Parses the JSON returned by Lua&lt;br /&gt;
* Allows structured access to values&lt;br /&gt;
&lt;br /&gt;
If an error exists:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (r.error) {&lt;br /&gt;
    alert(r.error);&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This displays a message to the user but does not force behavior.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Writing Values Back to the Form ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
f(&amp;quot;Label&amp;quot;).val(r.identifier);&lt;br /&gt;
f(&amp;quot;Sequence&amp;quot;).val(r.sequence);&lt;br /&gt;
$(&amp;quot;input[name=&amp;#039;pfFormPageName&amp;#039;]&amp;quot;).val(r.identifier);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does:&lt;br /&gt;
&lt;br /&gt;
* Displays the generated identifier&lt;br /&gt;
* Displays the sequence number&lt;br /&gt;
* Sets the final page name&lt;br /&gt;
&lt;br /&gt;
Important:&lt;br /&gt;
This does NOT create the page.&lt;br /&gt;
The page is only created when Save is clicked.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Capturing the Original Filename ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$(&amp;quot;input[type=&amp;#039;file&amp;#039;]&amp;quot;).on(&amp;quot;change&amp;quot;, function () {&lt;br /&gt;
    if (this.files[0]) {&lt;br /&gt;
        f(&amp;quot;OriginalFilename&amp;quot;).val(this.files[0].name);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this does:&lt;br /&gt;
&lt;br /&gt;
* Listens for file selection&lt;br /&gt;
* Reads the local filename&lt;br /&gt;
* Stores it in a readonly field&lt;br /&gt;
&lt;br /&gt;
Why this is done in JavaScript:&lt;br /&gt;
&lt;br /&gt;
* Only the browser knows the local filename&lt;br /&gt;
* The server never sees it otherwise&lt;br /&gt;
&lt;br /&gt;
This value is informational only.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== What JavaScript Must NEVER Do ==&lt;br /&gt;
&lt;br /&gt;
In Asset v2, JavaScript must never:&lt;br /&gt;
&lt;br /&gt;
* rename files&lt;br /&gt;
* move pages&lt;br /&gt;
* reserve identifiers&lt;br /&gt;
* enforce immutability&lt;br /&gt;
* decide final truth&lt;br /&gt;
* write directly to Cargo&lt;br /&gt;
&lt;br /&gt;
Any logic placed in JavaScript must be safe to bypass.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Failure Tolerance ==&lt;br /&gt;
&lt;br /&gt;
If JavaScript fails completely:&lt;br /&gt;
&lt;br /&gt;
* The form still works&lt;br /&gt;
* The user can still save&lt;br /&gt;
* Asset v1-style behavior is possible&lt;br /&gt;
* No data corruption occurs&lt;br /&gt;
&lt;br /&gt;
This is intentional.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Mental Model to Keep ==&lt;br /&gt;
&lt;br /&gt;
You can safely remember:&lt;br /&gt;
&lt;br /&gt;
* JavaScript = assistant&lt;br /&gt;
* Lua = calculator&lt;br /&gt;
* Cargo = storage&lt;br /&gt;
* PHP extension = enforcement&lt;br /&gt;
* Browser logic is never trusted&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Status ==&lt;br /&gt;
&lt;br /&gt;
This document is stable reference documentation.&lt;br /&gt;
&lt;br /&gt;
It exists to support long-term understanding and memory retention.&lt;/div&gt;</summary>
		<author><name>Mngr</name></author>
	</entry>
</feed>