Home
Random
Log in
Settings
About Brighter Shores Wiki
Disclaimers
Search
Editing
Module:Infobox
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
--[=[ -- For documentation, see [[Module:Infobox/doc]] --]=] -- <nowiki> require('strict') local editbutton = require('Module:Edit button') local smwutils = require('Module:SMW Utils') local Infobox = {} Infobox.__index = Infobox --[[ Infobox class -- config: table containing configuration parameters -- params : definitions for each used value -- args : values passed from the Template ---- the following values are treated specially: default_version, version, version1, version2... --]] function Infobox.new(config, params, args) local obj = setmetatable({ args_raw = args, -- parameters (uncleaned) args_parsed = {}, -- parsed parameters args_smw = {}, -- parameters parsed for smw infobox_name = nil, -- template name classes = {}, -- list of classes to add, using the default_version 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 = {}, -- title of each version (for selection and SMW) rtable = nil, -- infobox table to return at the end switch_datatable = '', -- datatable for javascript for switch infoboxes categories = {}, -- set of categories errors = {}, -- list of errors __smw_debug = {}, -- debug data for smw subobjects }, Infobox) -- Step 1, setup config vars and count the versions obj:config(config) obj:parse_versions() -- Step 2, process the params obj:define_params(params) obj:parse_params() -- Table obj:table_header() obj:buttons() -- Misc obj:store_smw() obj:parse_categories() return obj end --[[ Refers to a param after being processed by the validating func Used in add_row(), define_params() and is_param_defined() --]] function Infobox.param(param_name) local param = { property = 'args_parsed', param_name = param_name, } return param end --[[ Refers to a param in raw form as passed from the Template Used in add_row(), define_params() and is_param_defined() --]] function Infobox.raw_param(param_name) local param = { property = 'args_raw', param_name = param_name, } return param end --[[ Refers to a param after being processed by the validating smw_func Used in add_row(), define_params() and is_param_defined() --]] function Infobox.smw_param(param_name) local param = { property = 'args_smw', param_name = param_name, } return param end --[[ Checks to see if a param is defined. -- param: Infobox.param(name), Infobox.raw_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 ]] 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 value ~= nil then defined = 1 else undefined = 1 end end return 1 + defined - undefined end --[[ Adds a row to the infobox table Parameter should be a table of cells, where each cell is a table with the following arguments: -- tag : 'td' or 'th' -- content : a string or Infobox.param(name), Infobox.raw_param(name), Infobox.smw_param(name) -- attr (optional) : mw.html:attr({ arg1 = '1', ... }) -- css (optional) : mw.html:css({ arg1 = '1', ...) -- class (optional) : mw.html:addClass('arg') ---- class also supports a table of values, even though mw.html:addClass() does not ---- common classes: infobox-subheader -- rowspan (optional) : mw.html:attr('rowspan',arg) -- colspan (optional) : mw.html:attr('colspan',arg) -- title (optional) : mw.html:attr('title',arg) The row itself may be assigned a single class by setting the value of the key addClass -- addClass : mw.html:addClass('arg') -- this function currently only supports a single string --]] function Infobox:add_row(...) local args = ... local _row = self.rtable:tag('tr') -- For each cell for _, v in ipairs(args) do local _cell = _row:tag(v.tag) -- Optional parameters 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 v.class then if type(v.class) == 'string' then _cell:addClass(v.class) -- mw.html:addClass() doesn't function with tables, add in a loop elseif type(v.class) == 'table' then for _, w in ipairs(v.class) do _cell:addClass(w) end end end -- Populate the cell contents local content = self:get_param(v.content, self.default_version) if content == nil then content = self.params[v.content.param_name].empty end _cell:wikitext(content) -- Add the switch data if multiple values exist local 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.rtable:tag('tr'):tag('td'):attr('colspan', colspan or 1):addClass('infobox-padding') if class then tr:addClass(class) end return self end --[[ Adds a class to the table as a whole --]] function Infobox:addClass(arg) self.rtable:addClass(arg) return self end --[[ Setup config values -- config: table containing configuration parameters ---- infobox_name = mandatory unique identifier for this infobox, used for css ---- max_buttons = max number of switch buttons before using a dropdown list instead --]] function Infobox:config(config) for k, v in pairs(config) do if k == 'infobox_name' then self.infobox_name = mw.ustring.gsub(v, '%s', '_') elseif k == 'max_buttons' then self.max_buttons = tonumber(v) elseif k == 'class' then if type(v) == 'string' then self.classes = {v} elseif type(v) == 'table' then self.classes = v end 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 --[[ Counts the number of versions in the infobox Populates Infobox.version_names Sets Infobox.default_version --]] function Infobox:parse_versions() local function insert_version_name(version_name) table.insert(self.version_names, version_name) if smwutils.valid_subobject_name(version_name) == false then table.insert(self.errors, 'Illegal version value: must not be "0" nor contain a "." in the first five characters') end end -- Count the versions and setup self.version_names local i = 1 while self.args_raw['version'..i] do insert_version_name(self.args_raw['version'..i]) i = i + 1 end self.versions = i - 1 -- Should either have 0 or 2+ versions 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".') end -- Handle the no version case - check for a custom version_name if self.versions == 0 then insert_version_name(self.args_raw['version'] or 'DEFAULT') self.versions = 1 end -- Check for a default_version 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 --[[ Define all used parameters (except for default_version/version) -- name : parameter name as used in the Template -- func : function to validate and process the Template argument -- If func is a function, will call func(Infobox.raw_param(name)) -- If func is a table, contains the following key-value pairs: ---- name : function ---- params : list of arguments to pass to the function (use Infobox.raw_param(), ---- Infobox.param() and Infobox.smw_param() to use arguments) -- empty (optional) : text to display in the infobox if func returns nil, defaults to "? (edit)" -- category_never : category to add if func returns nil for all versions -- category_partial : category to add if func returns nil for some versions, but a value for other versions -- category_incomplete : category to add if func returns nil for at least 1 version (i.e. category_never and category_partial combined) -- category_complete : 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 --]] function Infobox:define_params(...) -- For every parameter, store its corresponding function to self.params for _, v in ipairs(...) do 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 -- If empty is not defined, default message is "? (edit)" param.empty = v.empty or editbutton("'''?''' (edit)") -- Get the category names param.category_never = v.category_never param.category_partial = v.category_partial param.category_incomplete = v.category_incomplete param.category_complete = v.category_complete -- Store the param self.params[v.name] = param table.insert(self.param_names, v.name) end end return self end --[[ Fetches a param value. If the value is nil, will return the default value instead -- arg: a non-table value (string, number, etc), or Infobox.param(name), Infobox.raw_param(name), Infobox.smw_param(name) -- version: 0/'' for default, or else a number Returns arg if a constant param value (or default value) if Infobox.param(name), Infobox.raw_param(name), Infobox.smw_param(name) --]] function Infobox:get_param(arg, version) if version == 0 then version = '' end -- Handle Infobox.param(), Infobox.raw_param(), Infobox.smw_param() if type(arg) == 'table' then local value = self[arg.property][arg.param_name..version] -- If nil, grab default value (which could be nil as well) if value == nil then value = self[arg.property][arg.param_name] end return value end -- Everything else passes through unmodified (string, number, etc) return arg end --[[ Calculates the parsed value of a param -- param_name : param_name as a string -- version : 0/'' for default, or else a number -- smw : boolean, will use smw_func if true, or func is false --]] 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 = {} local i = 1 for _, func_param in ipairs(func_params) do func_fetched_params[i] = self:get_param(func_param, version) i = i + 1 end return func_name(unpack(func_fetched_params)) else table.insert(self.errors, 'Invalid param definition for '..param_name) end end --[[ Parses all the param values (args_parsed and args_smw) --]] 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 = '' end -- get the parsed value 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 --[[ Creates the table header --]] function Infobox:table_header() -- Create infobox table self.rtable = mw.html.create('table') :addClass('plainlinks') :addClass('infobox') :addClass('infobox-'..self.infobox_name) for _, class in ipairs(self.classes) do local class_name = self:get_param(class, self.default_version) if type(class_name) == 'string' then self.rtable:addClass('infobox-'..mw.ustring.gsub(class_name, '%s', '_')) end end -- Create the switch datatable if multiple versions 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') end return self end --[[ If multiple versions exist, creates a set of buttons for switching -- self.max_buttons : if the number of versions exceeds this value, a dropdown will be created instead --]] function Infobox:buttons() if self.versions < 2 then return end -- Button caption local buttons = self.rtable:tag('caption') :tag('div') :addClass('infobox-buttons') :attr('data-default-index', self.default_version) -- Dropdown list instead of buttons if too many versions if self.versions > self.max_buttons then buttons:addClass('infobox-buttons-select') end -- Create all the buttons for version=1, self.versions do local button = buttons:tag('span') :attr('data-switch-index', version) :attr('data-switch-anchor', '#'..self.version_names[version]) :addClass('button') :wikitext(self.version_names[version]) -- In case of dropdown list, hide the buttons as the switch gadget will convert them to a dropdown list - we can't directly create the dropdown list here as the select/option tags are rejected by wikitext if self.versions > self.max_buttons then button:addClass('hidden') end end end --[[ For each version, stores a subobject for all params that have smw_property defined --]] function Infobox:store_smw() for version=1, self.versions do -- Generate a subobject name -- Reminder - subobject name cannot have a . in the first 5 characters local subobject_name = self.version_names[version] -- Store each param that has smw_property defined and is not nil local subobject = {Infobox = self.infobox_name} -- Also store the current Infobox name for _, param_name in ipairs(self.param_names) do local property = self.params[param_name].smw_property if property then local value = self:get_param(self.smw_param(param_name), version) if value ~= nil then subobject[property] = value end end end -- Keep a copy for debugging self.__smw_debug[subobject_name] = subobject -- Save subobjects if not in mainspace if mw.title.getCurrentTitle():inNamespace(0) then local result = true if self.versions == 1 then result = mw.smw.set(subobject) else result = mw.smw.subobject(subobject, subobject_name) end if result ~= true then table.insert(self.errors, 'SMW error: '..result.error) end end end end --[[ Automatically add categories for each param as defined in define_params() --]] function Infobox:parse_categories() for _, param_name in ipairs(self.param_names) do local param = self.params[param_name] local defined = self:is_param_defined(Infobox.param(param_name)) if defined == 0 and param.category_never then self.categories[param.category_never] = 1 end if defined == 1 and param.category_partial then self.categories[param.category_partial] = 1 end if defined < 2 and param.category_incomplete then self.categories[param.category_incomplete] = 1 end if defined == 2 and param.category_complete then self.categories[param.category_complete] = 1 end end end --[[ When a parameter is added into the table, add the alternative versions' data into the switch datatable -- content : a non-table value (string, number, etc), or Infobox.param(name), Infobox.raw_param(name), Infobox.smw_param(name) Returns the name of the parameter in the tag 'data-attr-param' --]] function Infobox:add_switch_data(content) if self.versions < 2 then return false end -- Only needed for non-constant params if type(content) ~= 'table' then return false end -- Only needed if the param changes value between different versions local first_value = self:get_param(content, 1) local all_same = true for version=2, self.versions do if first_value ~= self:get_param(content, version) then all_same = false break end end if all_same then return false end -- Let's build the datatable -- datum name: 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 local data_param = self.switch_datatable:tag('span'):attr('data-attr-param', name) -- Add each version to the datatable for version=1, self.versions do local text = self:get_param(content, version) if text == nil then text = self.params[content.param_name].empty end data_param:tag('span'):attr('data-attr-index', version):wikitext(text) end -- return the 'data-attr-param' name return name end --[[ Override tostring --]] function Infobox:__tostring() -- Create error messages local error_text = '' for _, v in ipairs(self.errors) do error_text = error_text..'<span class="mw-message-box-error">'..v..'</span>' end -- Create categories local category_text = '' if mw.title.getCurrentTitle():inNamespace(0) then for key, _ in pairs(self.categories) do category_text = category_text..'[[Category:'..key..']]' end end local dump = '' if self.args_raw.__dump then setmetatable(self, nil) dump = '<nowiki>'..mw.dumpObject(self)..'</nowiki>' setmetatable(self, Infobox) end return tostring(self.rtable) .. tostring(self.switch_datatable) .. error_text .. category_text .. dump end --[[ Debug function --]] function Infobox:dump() -- Temporarily detach the metatable so we don't override tostring anymore, allowing us to use dumpObject setmetatable(self, nil) mw.log(mw.dumpObject(self)) setmetatable(self, Infobox) mw.log(tostring(self)) end return Infobox
Summary:
Please note that all contributions to Brighter Shores Wiki are considered to be released under the CC BY-NC-SA 3.0 (see
Brighter Shores:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Preview page with this template
Templates used on this page:
Template:DependencyList
(
edit
)
Template:DependencyList/doc
(
edit
)
Template:Documentation
(
edit
)
Template:Extension DPL
(
edit
)
Template:Main
(
edit
)
Template:ToC
(
edit
)
Module:Array
(
edit
)
Module:DPLlua
(
edit
)
Module:DependencyList
(
edit
)
Module:Documentation
(
edit
)
Module:Edit button
(
edit
)
Module:Hatnote
(
edit
)
Module:Infobox
(
edit
)
Module:Infobox/doc
(
edit
)
Module:Infobox Class
(
edit
)
Module:Infobox Emote
(
edit
)
Module:Infobox Episode
(
edit
)
Module:Infobox Item
(
edit
)
Module:Infobox Monster
(
edit
)
Module:Infobox NPC
(
edit
)
Module:Infobox Profession
(
edit
)
Module:Infobox Quest
(
edit
)
Module:Infobox Room
(
edit
)
Module:Infobox Scenery
(
edit
)
Module:Infobox Shop
(
edit
)
Module:Infobox Skill Node
(
edit
)
Module:Infobox Spell
(
edit
)
Module:Infobox Venture
(
edit
)
Module:Main article
(
edit
)
Module:Param Parse
(
edit
)
Module:Paramtest
(
edit
)
Module:SMW Utils
(
edit
)
Module:Tooltip
(
edit
)
Module:Yesno
(
view source
) (semi-protected)
This page is a member of a hidden category:
Category:Pages using DynamicPageList3 parser function