Module:Infobox: Difference between revisions
WIP
No edit summary |
(WIP) |
||
Line 4:
-- <nowiki>
-- Edit button for unknown params
local editbutton = require('Module:Edit button')
local edit = editbutton("'''?''' (edit)")
local Infobox = {}
Line 11 ⟶ 13:
--[[
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(infobox_name, args)
local obj = setmetatable({
args_parsed = {}, -- parsed parameters
args_smw = {}, -- parameters parsed for smw
infobox_name = nil, -- template name
param_names = {}, -- ordered param list
params = {}, -- param definitions
default_version = 1, -- default version to populate the infobox
versions = nil, -- number of versions
version_names = {}, -- title of each version (for selection and SMW)
rtable = nil, -- infobox table to return at the end
switch_datatable = nil, -- datatable for javascript for switch infoboxes
errors = {}, -- list of errors
},
Infobox)
obj.infobox_name = mw.ustring.gsub(infobox_name, '%s', '_')
obj:parse_versions()
obj:create()
return obj
end
--[[
Line 55 ⟶ 61:
end
-- If smw_property is defined, then use smw_func, or default to func if it is not defined
if v.smw_property
param.smw_property = v.smw_property
if type(v.smw_func) == 'function' or type(v.smw_func) == 'table' then
Line 67 ⟶ 73:
end
end
self:parse_params()
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.
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'])
end
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)
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.param(
param = {
property = '
}
return param
end
function Infobox.raw_param(
param = {
property = '
}
return param
end
function Infobox.smw_param(param_name)
param = {
property = 'args_smw',
param_name = param_name,
}
return param
end
-----------
-- Table --
-----------
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)
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)
-- 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
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
-- Make sure that all params are only called from Infobox.param(), and not raw_param() nor smw_param()
if type(v.content) == 'table' and v.content.property ~= 'args_parsed' then
table.insert(table.errors, 'Only Infobox.param() can be used in addRow, not Infobox.raw_param() nor Infobox.smw_param()! '..mw.dumpObject(args))
end
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 = 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
-- Override tostring
function Infobox:tostring()
-- If not finished, finish
if not self.__finished then
self:finish()
end
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()
|