Module:Mw.html extension
This module is a helper module to be used by other modules; it may not designed to be invoked directly. See RuneScape:Lua/Helper modules for a full list and more information. For a full list of modules using this helper click here
Function | Type | Use |
---|---|---|
addClassIf(cond, class) | boolean, string | If cond = true it behaves the same as the normal addClass function, otherwise it's a no-op. Ex.: mw.html.create('div'):addClassIf(true, 'align-left-1') |
attrIf(cond, name, value) | boolean, string/table, string/nil | Similar to addClassIf |
cssIf(cond, name, value) | boolean, string/table, string/nil | Similar to addClassIf |
doneIf(cond) | boolean | Similar to addClassIf |
tagIf(cond, tag) | boolean, string | Similar to addClassIf |
wikitextIf(cond, text) | boolean, string | Similar to addClassIf |
na() | N/A | Shortcut for :tag('td'):attr('data-sort-value', 0):attr('class','table-na'):wikitext('<small>N/A</small>'):done() |
naIf(cond) | boolean | Similar to addClassIf |
tr([settings]) | table/nil | Shortcut for :tag('tr') but also auto closes the previous 'tr', 'th' or 'td' tag (so you don't need to add :done() before it). settings is a table with keys:
|
th([settings]) | string/table/nil | Shortcut for :tag('th'):wikitext(settings) if settings is a string. Also auto closes the previous 'th' or 'td' tag. settings can also be a table with keys:
|
td([settings]) | string/table/nil | Same as :th() . Example:
local tbl = mw.html.create('table')
tbl:tr{ class='sortable' }
:th{'foo', attr={'data-sort-type', 'number'}}
:th('bar')
:tr()
:td('buz')
:attr('data-sort-value', 10)
:td{'N/A', class='table-na'}
|
IF(cond) | boolean | Allows for if-blocks without breaking the chain. If the condition is true it is a no-op, if false everything inside the balanced IF-END block will be ignored. Can be nested. Ex.:
mw.html.create('div')
:IF(true)
:wikitext('Conditional text')
:END()
:...
Note: This only prevents elements from being added to your html object, it does not protect against statements that throw errors. I.e mw.html.create('div')
:IF(false)
:wikitext(5 * nil) -- This will still throw an error
:END()
|
ELSEIF(cond) | boolean | Used together with IF() . |
ELSE() | N/A | Used together with IF() . |
END() | N/A | Used together with IF() . Make sure the IF-END tags are balanced, it wont throw an error if they are not. |
exec(func, ...) | function, any | Call a function without breaking the chain. See module docs for more info. |
addFunction(func, name) | function, string | Add a function to the mw.html class that can then be used on mw.html object. See module docs for more info. |
Usage
For all functions other than addFunction()
all you need to do is simply require this module:
require('Module:Mw.html extension')
local p = {}
function p.main()
...
local tbl = mw.html.create('div')
:IF(true)
:wikitext('Conditional text')
:ELSE()
:wikitext('something else')
:END()
:addClassIf(true, 'wikitable')
:tag('span)'
:wikitext('normal wikitext')
:done()
...
end
return p
You can mix the normal old functions with the newly added ones.
attrIf
This accepts either a name-value pair or a table
:attrIf(true, 'data-sort-value', '0')
:attrIf(true, {'data-sort-value' = '0', ...})
cssIf
This accepts either a name-value pair or a table similar to attrIf
exec
The first parameter of the function will have the current state of the mw.html object passed into it, usually we call this parameter self
, the rest of the parameters can be anything you want. To not break the chaining the function must also return a mw.html object. Example:
local function repNa(self, times)
for i = 1,times do
self:na()
end
return self
end
This function can then be used as follows
mw.html.create('div'):exec(repNa, 5)
addFunction
The function you want to add has to be of the same structure as in exec()
. Example:
local htmlExtension = require('Module:Mw.html extension')
local p = {}
local function repNa(self, times)
for i = 1,times do
self:na()
end
return self
end
htmlExtension.addFunction(repNa, 'repNaName')
function p.main()
...
local tbl = mw.html.create('div'):repNaName(5)
...
end
return p
tr, th and td
The following three tables are the same:
local tbl = mw.html.create('table')
tbl:tr{ class='sortable' }
:th{'foo', attr={['data-sort-type']='number'}} -- or attr={'data-sort-type', 'number'}
:th('bar')
:IF(expression)
:addClass('table-na')
:END()
:tr()
:td('buz')
:td{'N/A', class='table-na'}
local tbl2 = mw.html.create('table')
tbl2:tag('tr')
:addClass('sortable')
:tag('th')
:attr('data-sort-type', 'number')
:wikitext('foo')
:done()
:tag('th')
:wikitext('bar')
:IF(expression)
:addClass('table-na')
:END()
:done() -- This is needed because "tag('tr')" is used after this instead of "tr()"
:done()
:tag('tr')
:tag('td')
:wikitext('buz')
:done()
:tag('td')
:wikitext('N/A')
:addClass('table-na')
local tbl3 = mw.html.create('table')
tbl3:tag('tr')
:addClass('sortable')
:tag('th')
:attr('data-sort-type', 'number')
:wikitext('foo')
:th('bar')
:IF(expression)
:addClass('table-na')
:END()
:done()
:done()
:tag('tr')
:td('buz')
:td('N/A')
:addClass('table-na')
-- <nowiki>
local p = {}
local checkType = require( 'libraryUtil' ).checkType
local mwHtml = getmetatable( mw.html.create() ).__index -- Trick to get acces to the mw.html class
local stack = {} -- Used to keep track of nested IF-END tags
local noOp = {} -- This object is returned by IF(false) tag
function mwHtml:addClassIf( cond, class )
if cond then
return self:addClass( class )
else
return self
end
end
function mwHtml:tagIf( cond, tagname )
if cond then
return self:tag( tagname )
else
return self
end
end
function mwHtml:wikitextIf( cond, text )
if cond then
return self:wikitext( text )
else
return self
end
end
function mwHtml:doneIf( cond )
if cond then
return self:done()
else
return self
end
end
function mwHtml:attrIf( cond, name, value )
if cond then
return self:attr( name, value )
else
return self
end
end
function mwHtml:cssIf( cond, name, value )
if cond then
return self:css( name, value )
else
return self
end
end
function mwHtml:na()
return self:tag( 'td' )
:attr( 'data-sort-value', 0 )
:attr( 'class', 'table-na' )
:wikitext( '<small>N/A</small>' )
:done()
end
function mwHtml:naIf( cond )
if cond then
return self:na()
else
return self
end
end
local function addValues( self, settings )
-- wikitext and addClass are no-ops when their argument is nil
self:wikitext( settings[1] or settings.wikitext )
self:addClass( settings.class or settings.addClass )
if settings.attr then
if settings.attr[1] and settings.attr[2] then
self:attr( settings.attr[1], settings.attr[2] )
else
self:attr( settings.attr )
end
end
if settings.css then
if settings.css[1] and settings.css[2] then
self:css( settings.css[1], settings.css[2] )
else
self:css( settings.css )
end
end
if settings.cssText then
self:cssText( settings.cssText )
end
end
function mwHtml:tr( settings )
if self.tagName == 'tr' then
self = self:done():tag( 'tr' )
elseif self.tagName == 'th' or self.tagName == 'td' then
self = self:done():done():tag( 'tr' )
else
self = self:tag( 'tr' )
end
if type( settings ) == 'table' then
addValues( self, settings )
end
return self
end
function mwHtml:th( settings )
if self.tagName == 'th' or self.tagName == 'td' then
self = self:done():tag( 'th' )
else
self = self:tag( 'th' )
end
if type( settings ) == 'table' then
addValues( self, settings )
else
self = self:wikitext( settings )
end
return self
end
function mwHtml:td( settings )
if self.tagName == 'th' or self.tagName == 'td' then
self = self:done():tag( 'td' )
else
self = self:tag( 'td' )
end
if type( settings ) == 'table' then
addValues( self, settings )
else
self = self:wikitext( settings )
end
return self
end
function mwHtml:IF( cond )
if cond then
table.insert( stack, { obj=noOp, trueCaseCompleted=true } )
return self
else
table.insert( stack, { obj=self, trueCaseCompleted=false } )
return noOp
end
end
function mwHtml:ELSEIF( cond )
if #stack == 0 then error( 'Missing IF tag', 2 ) end
local last = stack[#stack]
if cond and not last.trueCaseCompleted then
last.trueCaseCompleted = true
local res = last.obj
last.obj = noOp
return res
else
if self ~= noOp then
last.obj = self
end
return noOp
end
end
function mwHtml:ELSE()
return self:ELSEIF( true )
end
function mwHtml:END()
if #stack == 0 then error( 'Missing IF tag', 2 ) end
local res = table.remove( stack ) -- Pop element from the end
if res.obj == noOp then
return self
else
return res.obj
end
end
function mwHtml:exec( func, ... )
checkType( 'exec', 1, func, 'function' )
return func( self, ... )
end
function p.addFunction( func, name )
checkType( 'addFunction', 1, func, 'function' )
checkType( 'addFunction', 2, name, 'string' )
if mwHtml[name] then
error( 'Function "' .. name .. '" already exists', 2 )
end
mwHtml[name] = func
end
noOp.IF = mwHtml.IF
noOp.ELSEIF = mwHtml.ELSEIF
noOp.ELSE = mwHtml.ELSE
noOp.END = mwHtml.END
setmetatable( noOp, {
__index = function( self )
return self
end,
__call = function( self )
return self
end,
__tostring = function()
error( 'Attempting to convert no-op object into a string. Check for unbalanced IF-END tags', 2 )
end,
__concat = function()
error( 'Attempting to concatenate a no-op object. Check for unbalanced IF-END tags', 2 )
end
} )
return p
-- </nowiki>