Module:Infobox: Difference between revisions

WIP - everything except categories is done, but module is untested
(Barebones functional infobox module, WIP)
(WIP - everything except categories is done, but module is untested)
Line 7:
local editbutton = require('Module:Edit button')
local edit = editbutton("'''?''' (edit)")
 
local pagename = mw.title.getCurrentTitle().fullText
 
local Infobox = {}
Line 19 ⟶ 21:
-- other fields are initialized in other functions
--]]
function Infobox.new(infobox_nameargs, argsconfig)
local obj = setmetatable({
args_raw = args, -- parameters (uncleaned)
Line 27 ⟶ 29:
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
Line 35 ⟶ 38:
},
Infobox)
obj:config(config)
obj.infobox_name = mw.ustring.gsub(infobox_name, '%s', '_')
obj:parse_versions()
obj:create()
Line 41 ⟶ 44:
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 ⟶ 91:
end
self:parse_params()
--self:parse_categories()
return self
end
Line 98 ⟶ 116:
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
 
--[[
Line 156 ⟶ 213:
-- 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
Line 163 ⟶ 220:
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)
Line 171 ⟶ 229:
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)
Line 199 ⟶ 285:
-- 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
Line 214 ⟶ 322:
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
 
--[[
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)
Line 269 ⟶ 349:
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
Line 290 ⟶ 370:
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
Line 349 ⟶ 458:
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