Module:Infobox: Difference between revisions
(Barebones functional infobox module, WIP) |
(WIP - everything except categories is done, but module is untested) |
||
Line 7: | Line 7: | ||
local editbutton = require('Module:Edit button') |
local editbutton = require('Module:Edit button') |
||
local edit = editbutton("'''?''' (edit)") |
local edit = editbutton("'''?''' (edit)") |
||
local pagename = mw.title.getCurrentTitle().fullText |
|||
local Infobox = {} |
local Infobox = {} |
||
Line 19: | Line 21: | ||
-- other fields are initialized in other functions |
-- other fields are initialized in other functions |
||
--]] |
--]] |
||
function Infobox.new( |
function Infobox.new(args, config) |
||
local obj = setmetatable({ |
local obj = setmetatable({ |
||
args_raw = args, -- parameters (uncleaned) |
args_raw = args, -- parameters (uncleaned) |
||
Line 27: | Line 29: | ||
param_names = {}, -- ordered param list |
param_names = {}, -- ordered param list |
||
params = {}, -- param definitions |
params = {}, -- param definitions |
||
max_buttons = 6, -- If there are more buttons than the max, the buttons will become a dropdown menu |
|||
default_version = 1, -- default version to populate the infobox |
default_version = 1, -- default version to populate the infobox |
||
versions = nil, -- number of versions |
versions = nil, -- number of versions |
||
version_names = {}, -- title of each version (for selection and SMW) |
version_names = {'INFOBOX_ERROR'}, -- title of each version (for selection and SMW); version_name[0] should not be used (base index should be 1) |
||
rtable = nil, -- infobox table to return at the end |
rtable = nil, -- infobox table to return at the end |
||
switch_datatable = nil, -- datatable for javascript for switch infoboxes |
switch_datatable = nil, -- datatable for javascript for switch infoboxes |
||
Line 35: | Line 38: | ||
}, |
}, |
||
Infobox) |
Infobox) |
||
obj:config(config) |
|||
obj.infobox_name = mw.ustring.gsub(infobox_name, '%s', '_') |
|||
obj:parse_versions() |
obj:parse_versions() |
||
obj:create() |
obj:create() |
||
Line 41: | Line 44: | ||
end |
end |
||
function Infobox:config(...) |
|||
for k, v in pairs(...) do |
|||
if k == 'infobox_name' then |
|||
self.infobox_name = mw.ustring.gsub(v, '%s', '_') |
|||
elseif k == 'max_buttons' then |
|||
self.max_buttons = tonumber(v) |
|||
end |
|||
end |
|||
if self.infobox_name == nil then |
|||
table.insert(self.errors, 'infobox_name needs to be defined in Infobox.new()\'s config!') |
|||
end |
|||
return self |
|||
end |
|||
--[[ |
--[[ |
||
Line 74: | Line 91: | ||
end |
end |
||
self:parse_params() |
self:parse_params() |
||
--self:parse_categories() |
|||
return self |
return self |
||
end |
end |
||
Line 98: | Line 116: | ||
if self.args_raw['default_version'] then |
if self.args_raw['default_version'] then |
||
self.default_version = tonumber(self.args_raw['default_version']) |
self.default_version = tonumber(self.args_raw['default_version']) |
||
if self.default_version > self.versions then -- Make sure the default version exists |
|||
self.default_version = 1 |
|||
end |
|||
end |
end |
||
end |
end |
||
-- Value is not defined if "action=edit" exists in string, otherwise |
|||
-- value is defined if not nil and non-empty string |
|||
function Infobox.is_value_defined(value) |
|||
if value == nil then |
|||
return false |
|||
end |
|||
if type(value) ~= 'string' then |
|||
return true |
|||
end |
|||
if value:find('action=edit') then |
|||
return false |
|||
end |
|||
if value:find('%S') then |
|||
return true |
|||
end |
|||
return false |
|||
end |
|||
--[[ |
|||
Checks to see if a param is defined. |
|||
Returns 0 if param is never defined. Returns 1 if param is defined for some versions. Returns 2 if param is defined for all versions. |
|||
-- param: a table generated from Infobox:param(), Infobox:raw_param() or Infobox:smw_param() |
|||
]] |
|||
function Infobox:is_param_defined(param) |
|||
local undefined = 0 |
|||
local defined = 0 |
|||
for version = 1, self.versions do |
|||
local value = self:get_param(param, version) |
|||
if self.is_value_defined(value) then |
|||
defined = 1 |
|||
else |
|||
undefined = 1 |
|||
end |
|||
end |
|||
return 1 + defined - undefined |
|||
end |
|||
--[[ |
--[[ |
||
Line 156: | Line 213: | ||
-- Calculate the param value for all params and all versions |
-- Calculate the param value for all params and all versions |
||
for _, param_name in ipairs(self.param_names) do |
for _, param_name in ipairs(self.param_names) do |
||
for version=0,self.versions do |
for version=0, self.versions do |
||
if version == 0 then |
if version == 0 then |
||
version = '' -- default version |
version = '' -- default version |
||
Line 163: | Line 220: | ||
if self.args_raw[param_name..version] then |
if self.args_raw[param_name..version] then |
||
self.args_parsed[param_name..version] = self:parse_param(param_name, version, false) |
self.args_parsed[param_name..version] = self:parse_param(param_name, version, false) |
||
-- Only get the smw value if smw_property is defined |
|||
if self.params[param_name].smw_property then |
if self.params[param_name].smw_property then |
||
self.args_smw[param_name..version] = self:parse_param(param_name, version, true) |
self.args_smw[param_name..version] = self:parse_param(param_name, version, true) |
||
Line 171: | Line 229: | ||
end |
end |
||
function Infobox:store_smw() |
|||
-- Abort if not in mainspace |
|||
if mw.title.getCurrentTitle().namespace ~= 0 then |
|||
return false |
|||
end |
|||
-- Store a subobject for each version |
|||
for version=1, self.versions do |
|||
-- Reminder - subobject name cannot have a . in the first 5 characters |
|||
local subobject_name = 'Infobox.'..pagename..'#'..self.version_names[version] |
|||
local subobject = {} |
|||
-- Store each param that has smw_property defined and has a defined value |
|||
for _, param_name in ipairs(self.param_names) do |
|||
local property = self.params[param_name].smw_property |
|||
if property then |
|||
value = self:get_param(self.smw_param(param_name), version) |
|||
if self.is_value_defined(value) then |
|||
subobject[property] = value |
|||
end |
|||
end |
|||
end |
|||
local result = mw.smw.subobject(subobject, subobject_name) |
|||
if result ~= true then |
|||
table.insert(self.errors, 'SMW error: '..result.error) |
|||
end |
|||
end |
|||
return true |
|||
end |
|||
function Infobox.param(param_name) |
function Infobox.param(param_name) |
||
Line 199: | Line 285: | ||
-- Table -- |
-- Table -- |
||
----------- |
----------- |
||
function Infobox:buttons() |
|||
if self.versions < 2 then |
|||
return |
|||
end |
|||
local buttons = self.rtable:tag('caption') |
|||
:tag('div') |
|||
:addClass('infobox-buttons') |
|||
:attr('data-default-version', self.default_version) |
|||
-- Dropdown list instead of buttons |
|||
if self.versions > self.max_buttons then |
|||
buttons:addClass('infobox-buttons-select') |
|||
end |
|||
for version=1, self.versions do |
|||
buttons:tag('span') |
|||
:attr('data-switch-index', version) |
|||
:attr('data-switch-anchor', '#'..self.version_names[version]) |
|||
:addClass('button') |
|||
:wikitext(self.version_names[version]) |
|||
end |
|||
end |
|||
function Infobox:create() |
function Infobox:create() |
||
-- Create infobox table |
-- Create infobox table |
||
Line 214: | Line 322: | ||
self.switch_datatable:tag('span'):wikitext('Versions: '..self.versions) |
self.switch_datatable:tag('span'):wikitext('Versions: '..self.versions) |
||
self.switch_datatable:tag('span'):wikitext('Default version: '..self.default_version) |
self.switch_datatable:tag('span'):wikitext('Default version: '..self.default_version) |
||
self:buttons() |
|||
end |
end |
||
return self |
return self |
||
end |
end |
||
--[[ |
|||
Add parameters functions |
|||
All parameters should be tables |
|||
The first parameter defines the type of cell to create |
|||
-- tag = 'th' or 'td' |
|||
The second parameter defines what is inside the tag |
|||
-- content = string or Infobox.param |
|||
Additional named parameters can be used to add any styling or attributes |
|||
-- attr : mw.html:attr({ arg1 = '1', ... }) |
|||
-- css : mw.html:css({ arg1 = '1', ...) |
|||
-- class : mw.html:addClass('arg') |
|||
---- class also supports a table of values, even though mw.html:addClass() does not |
|||
-- rowspan : mw.html:attr('rowspan',arg) |
|||
-- colspan : mw.html:attr('colspan',arg) |
|||
-- title : mw.html:attr('title',arg) |
|||
Example: |
|||
ipsobox:addRow( { 'th' , 'Header', title = 'Title' }, |
|||
{ 'argh', 'arg1', class = 'parameter' } }) |
|||
produces: |
|||
<tr><th title="Title">Header</th><th class="parameter">args.arg1</th></tr> |
|||
adding it to the infobox table of ipsobox |
|||
Cells defined as 'argh' and 'argd' will automatically have data-attr-param="" added, and defined as the passed argument if the infobox in creation is defined as a switch infobox |
|||
The row itself may be modified with metadata using the named index "addClass' |
|||
-- addClass : mw.html:addClass('arg') |
|||
-- this function currently only supports a single string |
|||
--]] |
|||
function Infobox:add_switch_data(content) |
function Infobox:add_switch_data(content) |
||
Line 269: | Line 349: | ||
end |
end |
||
-- Let's build the datatable |
-- Let's build the datatable |
||
-- Prepend raw__ or smw$ |
-- Prepend raw__ or smw$__ if not a parsed argument |
||
local name = content.param_name |
local name = content.param_name |
||
if content.property == 'args_raw' then |
if content.property == 'args_raw' then |
||
Line 290: | Line 370: | ||
end |
end |
||
--[[ |
|||
Add parameters functions |
|||
All parameters should be tables |
|||
The first parameter defines the type of cell to create |
|||
-- tag = 'th' or 'td' |
|||
The second parameter defines what is inside the tag |
|||
-- content = string or Infobox.param |
|||
Additional named parameters can be used to add any styling or attributes |
|||
-- attr : mw.html:attr({ arg1 = '1', ... }) |
|||
-- css : mw.html:css({ arg1 = '1', ...) |
|||
-- class : mw.html:addClass('arg') (common class: infobox-subheader) |
|||
---- class also supports a table of values, even though mw.html:addClass() does not |
|||
-- rowspan : mw.html:attr('rowspan',arg) |
|||
-- colspan : mw.html:attr('colspan',arg) |
|||
-- title : mw.html:attr('title',arg) |
|||
Example: |
|||
ipsobox:addRow( { 'th' , 'Header', title = 'Title' }, |
|||
{ 'argh', 'arg1', class = 'parameter' } }) |
|||
produces: |
|||
<tr><th title="Title">Header</th><th class="parameter">args.arg1</th></tr> |
|||
adding it to the infobox table of ipsobox |
|||
Cells defined as 'argh' and 'argd' will automatically have data-attr-param="" added, and defined as the passed argument if the infobox in creation is defined as a switch infobox |
|||
The row itself may be modified with metadata using the named index "addClass' |
|||
-- addClass : mw.html:addClass('arg') |
|||
-- this function currently only supports a single string |
|||
--]] |
|||
function Infobox:add_row(...) |
function Infobox:add_row(...) |
||
-- New row to add |
-- New row to add |
||
Line 349: | Line 458: | ||
end |
end |
||
return self |
|||
end |
|||
--[[ |
|||
-- adds a blank row of padding spanning the given number of columns |
|||
--]] |
|||
function Infobox:pad(colspan, class) |
|||
local tr = self:tag('tr') |
|||
:tag('td'):attr('colspan', colspan or 1):addClass('infobox-padding') |
|||
if class then |
|||
tr:addClass(class) |
|||
end |
|||
return self |
|||
end |
|||
-- addClass |
|||
function Infobox:addClass(arg) |
|||
self.rtable:addClass(arg) |
|||
return self |
return self |
||
end |
end |
Revision as of 22:05, 25 March 2024
Creating a template step-by-step
Import Module:Infobox and Module:Param Parse
local Infobox = require('Module:Infobox')
local parse = require('Module:Param Parse')
Unpack the frame arguments from the Template
local p = {}
function p.main(frame)
local args = frame:getParent().args
...
Setup the Module config settings
local config = {
infobox_name = 'Scenery',
class = {Infobox.smw_param('episode')}, -- Add css class with episode name to colorize Infobox
}
Map your arguments to parsing functions
Use the params in Module:Param Parse to validate and format the data - feel free to create your own new params in Module:Param Parse.
local params = {
parse.name,
parse.image,
{name = 'description', func = parse.has_content, smw_property = 'Description'}, -- Custom param
parse.episode,
...
}
Define an Infobox object
local infobox = Infobox.new(config, params, args)
Create your table
infobox
:add_row{
{tag='th', content=Infobox.param('name'), class='infobox-header', colspan='20'},
}
:add_row{
{tag='td', content=Infobox.param('image'), class='infobox-image', colspan='20'},
}
:pad("20")
:add_row{
{tag='td', content='Info', class='infobox-subheader', colspan='20'},
}
:pad("20")
:add_row{
{tag='th', content='Description', colspan="6"},
{tag='td', content=Infobox.param('description'), colspan="14"},
}
:add_row{
{tag='th', content='[[Episode]]', colspan="6"},
{tag='td', content=Infobox.param('episode'), colspan="14"},
}
...
You're done!
return infobox
end
return p
Functions
Special params
You don't need to do anything about these special parameters, but they may be used as parameters within the Template:
param | explanation |
---|---|
version1, version2, version3 | Button label and SMW name for each switch version of the infobox |
default_version | The default version to display when the page is loaded |
version | If there is only a single version, you can use version to set the SMW name (default SMW name is "DEFAULT") |
Referring to params
Each parameter can have a different value for each version. In addition, there are 3 different representations of each value. Therefore, a parameter must be accessed via one of the 3 helper functions:
helper function | example | explanation |
---|---|---|
Infobox.raw_param(name) | "1000" | Raw value as passed by the Template |
Infobox.param(name) | "1,000" | Value formatted for display in the Infobox |
Infobox.smw_param(name) | 1000 | Value formatted to be saved as an SMW property |
Infobox.new(config, params, args)
Creates a new infobox. Automatically parses the arguments, creates SMW subobjects and adds categories.
local infobox = Infobox.new(config, params, args)
config
There are only 3 parameters for config
local config = {
infobox_name = 'Scenery', -- mandatory unique identifier for css
class = {'CustomClass', Infobox.smw_param('episode')} -- optional, defaults to {}. Adds css classes to infobox table: {'infobox-CustomClass', 'infobox-[default version parameter's value]'}
max_buttons = 6, -- optional, defaults to 6, max number of switch buttons before using a dropdown list instead
}
params
A list of parameters to be processed by the Infobox module
local params = {
{ name = <param>, func = <func>, ... },
...
}
key | value | ||||
---|---|---|---|---|---|
name | parameter name as used in the Template | ||||
func | A function in Module:Param Parse to validate and process the Template argument. You can also use a local function, but this is not recommended.
If func is a function, will call func(Infobox.raw_param(name)): {name = <param>, func = <func>, ... },
If func is a table, it takes the following parameters: {name = <param>, func = { name = <func>, params = <func_params>}, ... },
| ||||
empty (optional) | text to display in the infobox if func returns nil; defaults to "? (edit)" | ||||
category_never (optional) | category to add if func returns nil for all versions | ||||
category_partial (optional) | category to add if func returns nil for some versions, but a value for other versions | ||||
category_incomplete (optional) | category to add if func returns nil for at least 1 version (i.e. category_never and category_partial combined) | ||||
category_complete (optional) | category to add if func returns a value for all versions | ||||
smw_property (optional) | if this string is defined, the parameter will be saved into SMW | ||||
smw_func (optional) | function to validate and process the Template argument to save into SMW. func is used by default if smw_func is not defined |
args
Arguments passed via the Template
local args = frame:getParent().args
infobox:is_param_defined(param)
Used to conditionally display a line in the infobox
infobox:add_row{
{tag='th', content=Infobox.param('name'), class='infobox.subheader', colspan='2'},
}
if infobox:is_param_defined(Infobox.param('owner')) > 0 then
infobox:add_row{
{tag='td', content='[[Owner]]'},
{tag='td', content=Infobox.param('owner')},
}
end
param | a parameter referenced via Infobox.raw_param(name), Infobox.param(name) or Infobox.smw_param(name) |
Returns | 0 if param is never defined
1 if param is defined for a fraction of the versions 2 if param is defined for all versions |
Infobox:add_row(...)
Adds a row to the infobox table. Parameter should be a table of cells:
infobox:add_row{
{tag='td', content='[[Cell1]]', ...},
{tag='td', content=Infobox.param('param'), ...},
{tag='td', content='[[Cell3]]', ...},
...
addClass = 'row-class'
}
Each cell should have a set of key-values, of which only the tag and content are mandatory:
key | value |
---|---|
tag | 'td' or 'th' |
content | a string or Infobox.param(name), Infobox.raw_param(name), Infobox.smw_param(name) |
attr (optional) | a table of attributes to add to the cell
mw.html:attr({ arg1 = '1', ... }) |
css (optional) | a table of css to add to the cell
mw.html:css({ arg1 = '1', ... }) |
class (optional) | a string with a class to add, or a table of classes to add. infobox-header, infobox-subheader and infobox-image are commonly used.
mw.html:addClass(...) |
rowspan (optional) | Set the cell rowspan
mw.html:attr('rowspan',arg) |
rowspan (optional) | Set the cell colspan
mw.html:attr('colspan',arg) |
title (optional) | Set the cell title
mw.html:attr('title',arg) |
Infobox:pad(colspan, class)
Adds a blank row of padding spanning the given number of columns. Will always add the class infobox-padding, but can optionally add another class:
infobox:pad("10", class=<class>)
Infobox:addClass(class)
Adds a class to the entire table
infobox:addClass(class)
Infobox:dump()
Logs all the values into the Debug console for debugging purposes. You can also dump all the values in an Infobox template by setting a template parameter "__dump = Yes".
--[=[
-- For documentation, see [[Module:Infobox/doc]]
--]=]
-- <nowiki>
-- Edit button for unknown params
local editbutton = require('Module:Edit button')
local edit = editbutton("'''?''' (edit)")
local pagename = mw.title.getCurrentTitle().fullText
local Infobox = {}
Infobox.__index = Infobox
--[[
Infobox class
-- infobox_name: the name of the infobox
-- args : parameters from frame to pass through
-- Special args: version, default_version
-- Sets a meta table and creates a <div> tag wrapper
-- other fields are initialized in other functions
--]]
function Infobox.new(args, config)
local obj = setmetatable({
args_raw = args, -- parameters (uncleaned)
args_parsed = {}, -- parsed parameters
args_smw = {}, -- parameters parsed for smw
infobox_name = nil, -- template name
param_names = {}, -- ordered param list
params = {}, -- param definitions
max_buttons = 6, -- If there are more buttons than the max, the buttons will become a dropdown menu
default_version = 1, -- default version to populate the infobox
versions = nil, -- number of versions
version_names = {'INFOBOX_ERROR'}, -- title of each version (for selection and SMW); version_name[0] should not be used (base index should be 1)
rtable = nil, -- infobox table to return at the end
switch_datatable = nil, -- datatable for javascript for switch infoboxes
errors = {}, -- list of errors
},
Infobox)
obj:config(config)
obj:parse_versions()
obj:create()
return obj
end
function Infobox:config(...)
for k, v in pairs(...) do
if k == 'infobox_name' then
self.infobox_name = mw.ustring.gsub(v, '%s', '_')
elseif k == 'max_buttons' then
self.max_buttons = tonumber(v)
end
end
if self.infobox_name == nil then
table.insert(self.errors, 'infobox_name needs to be defined in Infobox.new()\'s config!')
end
return self
end
--[[
Function for defining parameters
-- name : parameter name
-- func : function to define param, defaults to looking at blanks
DO NOT DEFINE VERSION HERE
USE :maxVersion()
Can be used any number of times for efficient definition
--]]
function Infobox:define_params(...)
for _, v in ipairs(...) do
-- For every parameter, store its corresponding function to self.params
if v.name then
local param = {}
-- Copy the function
if type(v.func) == 'function' or type(v.func) == 'table' then
param.func = v.func
end
-- If smw_property is defined, then use smw_func, or default to func if it is not defined
if v.smw_property then
param.smw_property = v.smw_property
if type(v.smw_func) == 'function' or type(v.smw_func) == 'table' then
param.smw_func = v.smw_func
else
param.smw_func = param.func
end
end
self.params[v.name] = param
table.insert(self.param_names, v.name)
end
end
self:parse_params()
--self:parse_categories()
return self
end
--[[
Counts the number of versions in the infobox, and populates version_names
--]]
function Infobox:parse_versions()
-- Count the versions
local i = 1
while self.args_raw['version'..i] do
table.insert(self.version_names, self.args_raw['version'..i])
i = i + 1
end
self.versions = i - 1
-- Handle the no version case - might have a custom version_name
if self.versions == 0 then
table.insert(self.version_names, self.args_raw['version'] or 'DEFAULT')
end
if self.versions == 1 then
table.insert(self.errors, 'There should be multiple versions or no versions. If defining a custom version name for a single entry, use "version=Name" instead of "version1=Name".')
self.versions = 0
end
if self.args_raw['default_version'] then
self.default_version = tonumber(self.args_raw['default_version'])
if self.default_version > self.versions then -- Make sure the default version exists
self.default_version = 1
end
end
end
-- Value is not defined if "action=edit" exists in string, otherwise
-- value is defined if not nil and non-empty string
function Infobox.is_value_defined(value)
if value == nil then
return false
end
if type(value) ~= 'string' then
return true
end
if value:find('action=edit') then
return false
end
if value:find('%S') then
return true
end
return false
end
--[[
Checks to see if a param is defined.
Returns 0 if param is never defined. Returns 1 if param is defined for some versions. Returns 2 if param is defined for all versions.
-- param: a table generated from Infobox:param(), Infobox:raw_param() or Infobox:smw_param()
]]
function Infobox:is_param_defined(param)
local undefined = 0
local defined = 0
for version = 1, self.versions do
local value = self:get_param(param, version)
if self.is_value_defined(value) then
defined = 1
else
undefined = 1
end
end
return 1 + defined - undefined
end
--[[
Fetches a param value. If the value is nil, will return the default value instead
-- arg: a table generated from Infobox:param(), Infobox:raw_param() or Infobox:smw_param(), or else
-- version: '' for default, or else a number
--]]
function Infobox:get_param(arg, version)
if version == 0 then
version = ''
end
if type(arg) == 'table' then
local value = self[arg.property][arg.param_name..version]
if value == nil then -- Try to get default value if it exists
value = self[arg.property][arg.param_name]
end
return value
end
-- Other (int, string)
return arg
end
--[[
Calculates the parsed value of a param
-- param_name : string, name of the param
-- version : 0/'' for default, or else a number
-- smw : boolean, whether to use the smw function or default function
--]]
function Infobox:parse_param(param_name, version, smw)
if version == 0 then
version = ''
end
-- use func or smw_func depending on smw argument
local param = self.params[param_name]
local func = smw and param.smw_func or param.func
-- call functions by passing the param_name
if type(func) == 'function' then
return func(self:get_param(self.raw_param(param_name), version))
-- call tables by grabbing the function and reading the param arguments
elseif type(func) == 'table' then
local func_name = func.name
local func_params = func.params
local func_fetched_params = {}
for _, func_param in ipairs(func_params) do
table.insert(func_fetched_params, self:get_param(func_param, version))
end
return func_name(unpack(func_fetched_params))
else
table.insert(self.errors, 'Invalid param definition for '..param_name)
end
end
function Infobox:parse_params()
-- Calculate the param value for all params and all versions
for _, param_name in ipairs(self.param_names) do
for version=0, self.versions do
if version == 0 then
version = '' -- default version
end
-- Only get the parsed value if the raw value is defined
if self.args_raw[param_name..version] then
self.args_parsed[param_name..version] = self:parse_param(param_name, version, false)
-- Only get the smw value if smw_property is defined
if self.params[param_name].smw_property then
self.args_smw[param_name..version] = self:parse_param(param_name, version, true)
end
end
end
end
end
function Infobox:store_smw()
-- Abort if not in mainspace
if mw.title.getCurrentTitle().namespace ~= 0 then
return false
end
-- Store a subobject for each version
for version=1, self.versions do
-- Reminder - subobject name cannot have a . in the first 5 characters
local subobject_name = 'Infobox.'..pagename..'#'..self.version_names[version]
local subobject = {}
-- Store each param that has smw_property defined and has a defined value
for _, param_name in ipairs(self.param_names) do
local property = self.params[param_name].smw_property
if property then
value = self:get_param(self.smw_param(param_name), version)
if self.is_value_defined(value) then
subobject[property] = value
end
end
end
local result = mw.smw.subobject(subobject, subobject_name)
if result ~= true then
table.insert(self.errors, 'SMW error: '..result.error)
end
end
return true
end
function Infobox.param(param_name)
param = {
property = 'args_parsed',
param_name = param_name,
}
return param
end
function Infobox.raw_param(param_name)
param = {
property = 'args_raw',
param_name = param_name,
}
return param
end
function Infobox.smw_param(param_name)
param = {
property = 'args_smw',
param_name = param_name,
}
return param
end
-----------
-- Table --
-----------
function Infobox:buttons()
if self.versions < 2 then
return
end
local buttons = self.rtable:tag('caption')
:tag('div')
:addClass('infobox-buttons')
:attr('data-default-version', self.default_version)
-- Dropdown list instead of buttons
if self.versions > self.max_buttons then
buttons:addClass('infobox-buttons-select')
end
for version=1, self.versions do
buttons:tag('span')
:attr('data-switch-index', version)
:attr('data-switch-anchor', '#'..self.version_names[version])
:addClass('button')
:wikitext(self.version_names[version])
end
end
function Infobox:create()
-- Create infobox table
self.rtable = mw.html.create('table')
:addClass('plainlinks')
:addClass('infobox')
:addClass('infobox-'..self.infobox_name)
-- Add necessary class if switch infobox
if self.versions > 1 then
self.rtable:addClass('infobox-switch')
self.switch_datatable = mw.html.create('div')
:addClass('infobox-switch-resources')
:addClass('infobox-resources-'..self.infobox_name)
:addClass('hidden')
self.switch_datatable:tag('span'):wikitext('Versions: '..self.versions)
self.switch_datatable:tag('span'):wikitext('Default version: '..self.default_version)
self:buttons()
end
return self
end
function Infobox:add_switch_data(content)
-- Only check for params if there are multiple versions
if self.versions <= 1 then
return false
end
if type(content) ~= 'table' then
return false
end
-- Only if the data varies between the different versions
local first_value = self:get_param(cell_params.content, 1)
local all_same = true
for version=2, self.versions do
if first_value ~= self:get_param(cell_params.content, version) then
all_same = false
break
end
end
if all_same then
return false
end
-- Let's build the datatable
-- Prepend raw__ or smw$__ if not a parsed argument
local name = content.param_name
if content.property == 'args_raw' then
name = 'raw__' + name
end
if content.property == 'args_smw' then
name = 'smw__' + name
end
data_param = self.switch_datatable:tag('span'):attr('data-attr-param', name)
-- Add each version to the datatable
for version=1, self.versions do
text = self:get_param(content, version)
if text == nil then
text = edit
end
data_param:tag('span'):attr('data-attr-index', version):wikitext(text)
end
-- return the 'data-attr-param' name
return name
end
--[[
Add parameters functions
All parameters should be tables
The first parameter defines the type of cell to create
-- tag = 'th' or 'td'
The second parameter defines what is inside the tag
-- content = string or Infobox.param
Additional named parameters can be used to add any styling or attributes
-- attr : mw.html:attr({ arg1 = '1', ... })
-- css : mw.html:css({ arg1 = '1', ...)
-- class : mw.html:addClass('arg') (common class: infobox-subheader)
---- class also supports a table of values, even though mw.html:addClass() does not
-- rowspan : mw.html:attr('rowspan',arg)
-- colspan : mw.html:attr('colspan',arg)
-- title : mw.html:attr('title',arg)
Example:
ipsobox:addRow( { 'th' , 'Header', title = 'Title' },
{ 'argh', 'arg1', class = 'parameter' } })
produces:
<tr><th title="Title">Header</th><th class="parameter">args.arg1</th></tr>
adding it to the infobox table of ipsobox
Cells defined as 'argh' and 'argd' will automatically have data-attr-param="" added, and defined as the passed argument if the infobox in creation is defined as a switch infobox
The row itself may be modified with metadata using the named index "addClass'
-- addClass : mw.html:addClass('arg')
-- this function currently only supports a single string
--]]
function Infobox:add_row(...)
-- New row to add
local args = ...
local _row = self.rtable:tag('tr')
-- For each member of tags
for _, v in ipairs(args) do
local _cell = _row:tag(v.tag)
-- mw.html:attr() and mw.html:css() both accept table input
-- colspan, rowspan, title will be quick ways to access attr
-- these functions also do all the necessary work
if v.attr then
_cell:attr(v.attr)
end
if v.colspan then
_cell:attr('colspan',v.colspan)
end
if v.rowspan then
_cell:attr('rowspan',v.rowspan)
end
if v.title then
_cell:attr('title',v.title)
end
if v.css then
_cell:css(v.css)
end
-- if class is a string, it can be added directly
-- if a table, add every value
-- mw.html:addClass() doesn't function with tables
-- so iterate over the class names here and add them individually
if v.class then
if type(v.class) == 'string' then
_cell:addClass(v.class)
elseif type(v.class) == 'table' then
for _, w in ipairs(v.class) do
_cell:addClass(w)
end
end
end
local content = Infobox:get_param(v.content, self.default_version)
if content == nil then
content = edit
end
_cell:wikitext(content)
-- Add the switch data if multiple values exist
data_attr_param = self:add_switch_data(v.content)
if data_attr_param then
_cell:attr('data-attr-param', data_attr_param)
end
end
-- allow classes to be defined on the whole row
if args.addClass then
_row:addClass(args.addClass)
end
return self
end
--[[
-- adds a blank row of padding spanning the given number of columns
--]]
function Infobox:pad(colspan, class)
local tr = self:tag('tr')
:tag('td'):attr('colspan', colspan or 1):addClass('infobox-padding')
if class then
tr:addClass(class)
end
return self
end
-- addClass
function Infobox:addClass(arg)
self.rtable:addClass(arg)
return self
end
-- Override tostring
function Infobox:tostring()
error_text = ''
if #self.errors > 0 then
for _, v in ipairs(self.errors) do
error_text = error_text..'<span class="mw-message-box-error">'..v..'</span>'
end
end
return tostring(self.rtable) .. tostring(self.switch_datatable) .. tostring(error_text)
end
function Infobox:dump()
mw.log(mw.dumpObject(self))
mw.log(tostring(self))
end
return Infobox