Editing Module:Infobox 0 You do not have permission to edit this page, for the following reasons: The action you have requested is limited to users in one of the groups: Autoconfirmed users, FANDOM Staff, FANDOM Helpers, Wiki Managers, Content Team Members. This page has been semi-protected and may only be edited by registered users. To request a change, create a new topic here or ask an administrator to reduce the protection level here. Additional information on this page's status may be found in the protection log. {|class="messagebox info" |width="50px"| |Please log in to edit the wiki. Joining is free and it only takes a minute.We hope that you sign up and become a member of our community! |} You must confirm your e-mail address before editing pages. Please set and validate your e-mail address through your user preferences. more + You can view and copy the source of this page: --[=[ -- For documentation, see [[Template:Module:Infobox/doc]] --]=] -- <pre> local Infobox = {} Infobox.__index = Infobox Infobox.__tostring = Infobox.tostring -- Edit button for unknown params local editbutton = require('Module:Edit button') local edit = editbutton("'''?''' (edit)") -- Page title local pagename = mw.title.getCurrentTitle().fullText -- map of flags to html tags used by Infobox.addRow() -- let's only define it once, since :addRow() is used multiple times per module local tagmap = { tr = 'tr', th = 'th', td = 'td', argh = 'th', argd = 'td' } --[=[ -- Standardized functions -- called as string with defineParams --]=] -- Standardized "has content" function function hasContent(arg, default) -- Return arg if any non-whitespace character is found return string.match(arg or '','%S') and arg or default end -- Standardized "name" function function subjectName(arg) return string.match(arg or '','%S') and arg or nil end -- Create a standardized release function, since so many pages use it -- Turns release and update into a single parameter function releaseUpdate(release,update) -- "release ([[update|Update]])" or -- "release (update unknown)" or -- unknown if release and release:find('%S') then if update and update:find('%S') then return string.format('%s ([[Update:%s|Update]])',release,update) else return string.format('%s (Update unknown)',release) end else return nil end end -- Standardized image function function image(img) if img and img:find('%S') then return img else return nil end end -- Standardized numbers function numbers(num) num = string.gsub(num or '',',','') return tonumber(num) end -- map of names to pre-defined functions, used by Infobox:defineParams local func_map = { name = subjectName, release = { name = releaseUpdate, params = { 'release', 'update' }, flag = 'p' }, removal = { name = releaseUpdate, params = { 'removal', 'removalupdate' }, flag = 'p' }, has_content = hasContent, hasContent = hasContent, image = image, numbers = numbers, } -- used to fill nil params in switching sections -- this message isn't kidding -- If you see this message anywhere outside of this code -- (including inside switchfo box data) -- report it local nil_param = 'UH OH YOU SHOULDN\'T SEE THIS!' -- In case the nil_param is needed outside of this module -- give it an easy way to be accessed function Infobox.nilParam() return nil_param end -- quick test to see if a value is considered nil function Infobox.isDefined(arg) if arg == nil then return false end if type(arg) == 'string' then if arg == nil_param then return false elseif arg:find('%S') then if arg:find('action=edit') then return false else return true end else return false end end return true end --[[ Infobox class -- args : parameters from frame to pass through -- Sets a meta table and creates a <div> tag wrapper -- other fields are initialized in other functions --]] function Infobox.new(args) local rdiv = mw.html.create('div') :addClass('infobox-wrapper') local obj = setmetatable({ args = args, -- parameters (uncleaned) rargs = {}, -- parameters (cleaned) params = {}, -- parameters mapped to functions paramnames = {}, -- parameter names dupeable = {}, -- parameters that are allowed to have duplicated switch data switchfo = false, -- switch infobox? or not? switchfoattr = {}, -- switch data class changes maxbuttons = 5, -- maximum number of buttons before switching becomes a menu rdiv = rdiv, -- returned div wrapper rtable = nil, -- returned infobox table labels = nil, -- returned labels _smw = { -- semantic mediawiki data members = 'Is members only', release = 'Release date' }, versions = -1, -- number of switch versions (-1 is uncalculated) infoboxname = nil, -- template name bottomlinks = { -- template bottom links { 'Template talk:%s', 'talk' }, { 'Template:%s', 'view' }, }, catdata = {}, -- meta category data catlist = {}, -- defined table of category names (strings) __finished = false, -- infobox status }, Infobox) return obj end --[[ Creates an infobox -- If Infobox:maxVersions() has not been run, it will be run here -- If the infobox should be a switch infobox, all labels will be added -- Creates a wikitable that will be the infobox THIS SHOULD BE DONE AFTER ADDING AND CLEANING PARAMETERS --]] function Infobox:create() -- Run to find if this is a switch infobox and if so, how many boxes if self.versions == -1 then self:maxVersion() end -- Run if switch infobox if self.switchfo then -- Buttons wrapper -- Hidden by default, unhidden by javascript local btns = self.rdiv:tag('div') :addClass('infobox-buttons') :addClass('hidden') -- default version to immediately switch to via js local defv = tonumber(self.args.defver) if defv and defv <= self.versions then -- you troll, don't try to show something that isn't there btns:attr('data-default-version',defv) end -- Used by JavaScript to turn the buttons into a menu list if too many variants if self.versions > self.maxbuttons then btns:addClass('infobox-buttons-select') end -- Add individual buttons to the wrapper local halfv = self.versions/2 for i=1,self.versions do btns:tag('span') :attr('data-switch-index',tostring(i)) -- space to underscore :attr('data-switch-anchor','#'..string.gsub(self.labels[i] or i,' ','_')) :addClass('button') :wikitext(self.labels[i] or i) :done() if self.versions >= 5 and (i==halfv or i==(halfv+.5)) then btns:tag('br',{selfClosing=true}) end end btns:done() end -- Create infobox table self.rtable = self.rdiv:tag('table') :addClass('wikitable') :addClass('infobox') :addClass('plainlinks') -- Add necessary class if switch infobox if self.switchfo then self.rtable:addClass('infobox-switch') end end -- Defines an infobox name ({{Template:arg}}) -- Used to create a link at the bottom of pages function Infobox:defineName(arg) self.infoboxname = arg end -- Defines the bottom links of the infobox -- pass a table whose elements are tables that define a link and a label -- { -- { 'link', 'label }, -- ... -- } -- The template name can be substituted into the tables using '%s' -- If we wanted Template:InFooBar to link to it's /doc page with a "doc" label: -- { ... -- { 'Template:%s/doc', 'doc' }, -- ... } -- The template's name can only be called 5 times function Infobox:defineLinks(arg) if type(arg) == 'table' then self.bottomlinks = arg end end -- Change max number of buttons before switching to menu -- defaults to 5 -- MUST BE RUN BEFORE :create() function Infobox:setMaxButtons(arg) -- if not a number, just go back to default self.maxbuttons = tonumber(arg) or 5 end --[[ Add parameters functions All parameters should be tables The first parameter defines the type of cell to create -- th : <th> -- td : <td> -- argh : <th> -- argd : <td> The second parameter defines what is inside the tag -- th | th : text passed -- argh | argd : parameter with the name passed 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 at "meta" -- meta.addClass : mw.html:addClass('arg') -- this function currently only supports a single string --]] function Infobox.addRow(box, ...) -- New row to add local args = ... local _row = box.rtable:tag('tr') -- For each member of tags for i, v in ipairs(args) do -- map tag name to appropriate tag, default to <td> local _cell = _row:tag(tagmap[v.tag] or 'td') -- 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 -- if the cell is a normal th or td, add the exact argument passed if v.tag == 'th' or v.tag == 'td' then _cell:wikitext(v.content) -- if defined with "arg", add the argument with name passed elseif v.tag == 'argh' or v.tag == 'argd' then local content = box.rargs[v.content] -- if the requested parameter doesn't exist whatsoever, just return a blank string if not content then content = '' -- If switches exist, first attempt to use the version1 values elseif content.switches then if content.switches[1] ~= nil_param then content = content.switches[1] or '' else content = content.d or '' end -- fallback to default value else content = content.d or '' end _cell:wikitext(content) -- add necessary attribute for switch infoboxes if box.switchfo then _cell:attr('data-attr-param',v.content) end end end -- not that meta -- allow classes to be defined on the whole row -- okay, sort of meta if args.meta then if args.meta.addClass then _row:addClass(args.meta.addClass) end end return box end --[[ -- functions the same as mw.html:wikitext() on the wrapper -- Should only be used for categories really --]] function Infobox.wikitext(box, arg) box.rdiv:wikitext(arg) return box end --[[ -- Adds a caption to the infobox -- defaults to the pagename -- or the default argument if defined --]] function Infobox.caption(box) -- default to the article's name local name = pagename -- first see if the name parameter exists if box.rargs.name then -- then try the default if box.rargs.name.d then name = box.rargs.name.d -- then look for swithes elseif box.rargs.name.switches then -- then look at version 1 if box.rargs.name.switches[1] ~= nil_param then name = box.rargs.name.switches[1] end end end local caption = box.rtable:tag('caption') :wikitext(name) -- add necessary attribute for switch infoboxes if box.switchfo then caption:attr('data-attr-param','name') end return box end --[[ -- Functions for styling the infobox -- works the same as the respective mw.html functions --]] -- attr function Infobox.attr(box, arg) box.rtable:attr(arg) return box end -- css function Infobox.float(box,float) box.rdiv:css('float',float) return box end function Infobox.css(box, ...) box.rtable:css(...) return box end -- addClass function Infobox.addClass(box, arg) box.rtable:addClass(arg) return box end -- Much like Infobox.addClass, but adds multiple classes function Infobox.addClasses(box, ...) for _, v in ipairs(...) do box.rtable:addClass(box) end return box end --[[ Add tags directly to the infobox table Use sparingly Returns the tag created rather than the entire box Which is an mw.html object Further uses of :tag() will be mw.html.tag, rather than Infobox.tag As such, Infobox:addRow() cannot be used afterwards without restating the infobox as the object --]] function Infobox.tag(box, arg) return box.rtable:tag(arg) end --[[ Allows the infobox to use Semantic Media Wiki and give parameters properties Pass a table to this function to map parameter names to properties Calling syntax: -- {{#show:page|?property}}: -- "<property>" - unqualified and without a number will display the default value -- "<property#>" - with a number will show the switch data from that index -- "all <property>" - adding all will display every unique value in a comma separated list Properties initiated in Infobox:finish() --]] function Infobox:useSMW(arg) if type(arg) == 'table' or true then for w, v in pairs(arg) do self._smw[w] = v end end end --[[ Finishing function -- Finishes the return, adding necessary final tags --]] function Infobox:finish() local onmain = mw.title.getCurrentTitle().namespace == 0 -- Don't finish twice if self.__finished then return end -- Add switch infobox resources if self.switchfo then -- Wrapper tag, hidden local res_tag = self.rdiv:tag('div') :addClass('infobox-switch-resources') :addClass('hidden') for _, v in ipairs(self.paramnames) do local param = self.rargs[v] -- Parameters may not have any switches data, those are ignored if param.switches then local switchattr = self.switchfoattr[v] -- Parameter data wrapper local res_span = res_tag:tag('span') :attr('data-attr-param',v) -- Child for default value local def = res_span:tag('span') :attr('data-attr-index',0) :wikitext(tostring(param.d or edit)) -- Switch classes if switchattr then def:attr('data-addclass',switchattr.d) end def:done() -- Add all switches, ignore those defined as nil for i, w in ipairs(param.switches) do if w ~= nil_param and w ~= nil then local _w = res_span:tag('span') :attr('data-attr-index',i) :wikitext(tostring(w)) -- Switch classes if switchattr then _w:attr('data-addclass',switchattr.switches[i]) end _w:done() end end res_span:done() end end -- Add a tracking category for mainspace pages that have more than 1 version if onmain then -- version count data res_tag:tag('span') :wikitext(string.format('Versions: [[Version count::%s]]',self.versions)) :done() res_tag:wikitext('[[Category:Pages that contain switch infobox data]]') end res_tag:done() end -- smw data if onmain then -- members smw display, yes --> true; no --> false; other --> unknown local function smwMembers(smw_arg) local smw_argv = string.lower(smw_arg or '') if smw_argv == 'yes' then return 'true' elseif smw_argv == 'no' then return 'false' else return 'unknown' end end -- release date smw display local function smwRelease(smw_arg) local _d,_m,_y = string.match(smw_arg or '', '%[%[(%d%d?) (%a+)%]%] %[%[(%d%d%d%d)%]%]') return table.concat({_d,_m,_y},' ') end -- default, just return the text local function smwDefault(smw_arg) if smw_arg ~= nil_param and smw_arg ~= edit then return smw_arg else return 'unknown' end end local smw_to_func = { members = smwMembers, release = smwRelease, default = smwDefault } local res_tag = self.rdiv:tag('div') :addClass('infobox-semantics-data') :addClass('hidden') :css('display','none') local smw_data = res_tag:tag('div') :css({ ['white-space'] = 'pre-wrap', ['background-color'] = '#f7f7f7', border = '1px solid #ddd', ['border-radius'] = '2px', ['line-height'] = '14px', overflow = 'auto', padding = '12px', ['word-wrap'] = 'normal', display = 'block', ['font-family'] = 'monospace', }) :wikitext('Defined properties:\n') -- custom properties for w, v in pairs(self._smw) do -- only needed to give special formatting to release -- and to make members true/false local smwfunc = smw_to_func[w] or smw_to_func.default local curarg = self.rargs[w] if curarg then local _arg = curarg.d local argdefault = _arg if _arg == edit then argdefault = 'Unknown' else local temp_smw_data = smwfunc(_arg) smw_data:wikitext(string.format('All %s: [[All %s::%s]]\n%s: [[%s::%s]]\n',v,v,temp_smw_data,v,v,temp_smw_data)) end if curarg.switches then local _args = {} for _, x in ipairs(curarg.switches) do if x ~= nil_param then table.insert(_args,x) else table.insert(_args,argdefault or nil_param) end end for i, x in ipairs(_args) do local temp_smw_data = smwfunc(x) smw_data:wikitext(string.format('All %s: [[All %s::%s]]\n%s%s: [[%s%s::%s]]\n',v,v,temp_smw_data,v,i,v,i,temp_smw_data)) end end end end smw_data:done() res_tag:done() end -- Add view and talk links to infobox -- Only done if a name is defined if self.infoboxname then local bottom_links = {} for _, v in ipairs(self.bottomlinks) do table.insert(bottom_links, string.format( table.concat({'[[[', v[1], '|', v[2], ']]]'}), self.infoboxname, self.infoboxname, self.infoboxname, self.infoboxname, self.infoboxname) ) end bottom_links = table.concat(bottom_links,' • ') self.rdiv:tag('span') :addClass('infobox-bottom-links') :wikitext(bottom_links) :done() end -- Define as finished self.__finished = true 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:defineParams(...) for _, v in ipairs(...) do -- For every parameter, store its corresponding function to self.params if v.name then -- If the value is a function or a table (which should define a function) if type(v.func) == 'function' or type(v.func) == 'table' then self.params[v.name] = v.func -- If the value is a string, use the predefined Infobox function of that name elseif type(v.func) == 'string' then self.params[v.name] = func_map[v.func] or hasContent -- Everything else just looks for blanks else self.params[v.name] = hasContent() end -- Create a list of all param names table.insert(self.paramnames,v.name) -- function to allow duplicated values if v.dupes then self.dupeable[v.name] = true end end end end --[[ -- Forces an infobox to only use 1 variant -- Mainly used by lite infoboxes -- This should be run before creation --]] function Infobox:noSwitch() self.versions = 1 self.switchfo = false end --[[ -- Calculates the max version -- Adds labels -- Sees if this needs to be a switch infobox -- Returns extra version count (even if already run) --]] function Infobox.maxVersion(box) -- Only allowed to run once if box.versions ~= -1 then return box.versions end box.labels = {} box.versions = 0 -- Look for up to 125 variants, defined in order for i=1, 125 do -- If variant# exists if box.args['version'..i] then -- Increase version count box.versions = box.versions + 1 -- Add its label table.insert(box.labels,box.args['version'..i] or ('Version '..i)) -- Stop if it doesn't exist else break end end -- Define self as a switch infobox if at least 1 other version is found if box.versions > 0 then box.switchfo = true end -- versions calculated return box.versions end --[[ -- Cleans parameters as defined by the above function -- SHOULD NOT BE RUN UNTIL ALL THINGS ARE DEFINED -- Handles switches as well -- adds table _add to rargs, a cleaned up version of arguments -- d : default value -- switches : table of switches (in numerical order) -- Functions can be defined with tables ---- name : name of function ---- params : table of args to pass to functions ---- flag : flags for input d | #default : use the cleaned parameter first, otherwise passed p : use the passed value of parameters r | l : use raw (literal) text, rather than values -- Defining a single flag will use that flag on all parameters -- Defining a table of flags will use the respective flag by position --]] function Infobox:cleanParams() -- map of flags to functionality local flagmap = { r = 'r', l = 'r', d = 'd', p = 'p' } -- For all parameters named for _, v in ipairs(self.paramnames) do -- Parameter to add local _add = {} local catdata = { all_defined = true, one_defined = false } -- If the value of params is a function if type(self.params[v]) == 'function' then -- Perform that function with the parameter _add.d = self.params[v](self.args[v]) -- If it's a table, parse it into a function elseif type(self.params[v]) == 'table' then -- Find the functions name local func = self.params[v].name if type(func) == 'string' then func = func_map[func] end -- catch all if type(func) ~= 'function' then func = has_content end -- Recreate table of args and flags local func_args = {} local flag = {} -- If the flags are NOT a table, turn them into a table -- Same size as the parameter table -- Every flag will be the same if type(self.params[v].flag) ~= 'table' then -- Map flags, if unmapped, use default local _flag = flagmap[self.params[v].flag] or 'd' -- recreate table for x=1,#self.params[v].params do table.insert(flag,_flag) end -- If flags are already a table, recreate them in new table elseif type(self.params[v].flag) == 'table' then local _flag = self.params[v].flag -- recreate table for x=1,#self.params[v].params do -- Map flags, if unmapped, use default table.insert(flag,flagmap[_flag[x]] or 'd') end end -- Recreate param table, parsing flags as instructions for x, w in ipairs(self.params[v].params) do local xarg -- By default or defined as 'd' -- looks for the cleaned value of the named parameter first -- if it doesn't exist, look at the passed value next -- if that doesn't exist, use blank if flag[x] == 'd' then xarg = (self.rargs[w] and self.rargs[w].d) or self.args[w] or '' -- Look only at the passed value of the named parameter -- if that doesn't exist, use blank elseif flag[x] == 'p' then xarg = self.args[w] or '' -- Don't interpret value as a parameter name, and paste the as is elseif flag[x] == 'r' then xarg = w end -- Add parsed argument to table table.insert(func_args,xarg) end -- Run function _add.d = func(unpack(func_args)) end if _add.d == nil or _add.d == nil_param then -- have to do pagename defaults here to prevent weird behaviour with switch values if v == 'name' then _add.d = pagename else _add.d = edit end catdata.all_defined = false else -- _add.d is not nil catdata.one_defined = true end if self.switchfo then -- Table of switches values and count of them local _add_switch = {} local switches = 0 -- Look for up to the maximum number for i=1, self.versions do local _addarg -- see if this param is allowed to have switch if v ~= 'image' and v ~= 'examine' and string.find(self.args[v..i] or '','%$%d') then local refi = string.match(self.args[v..i],'%$(%d+)') _addarg = _add_switch[tonumber(refi)] or nil_param else -- If the value of params is a function if type(self.params[v]) == 'function' then -- Perform that function with the parameter at that index _addarg = self.params[v](self.args[v..i]) -- If it's a table, parse it into a function elseif type(self.params[v]) == 'table' then -- Find the functions name local func = self.params[v].name if type(func) == 'string' then func = func_map[func] end -- catch all if type(func) ~= 'function' then func = has_content end -- Recreate table of args and flags local func_args = {} local flag = {} -- If the flags are NOT a table, turn them into a table -- Same size as the parameter table -- Every flag will be the same if type(self.params[v].flag) ~= 'table' then -- Map flags, if unmapped, use default local _flag = flagmap[self.params[v].flag] or 'd' -- recreate table for x=1,#self.params[v].params do table.insert(flag,_flag) end -- If flags are already a table, recreate them in new table elseif type(self.params[v].flag) == 'table' then local _flag = self.params[v].flag -- recreate table for x=1,#self.params[v].params do -- Map flags, if unmapped, use default table.insert(flag,flagmap[_flag[x]] or 'd') end end -- Recreate param table, parsing flags as instructions for x, w in ipairs(self.params[v].params) do local xarg -- By default or defined as 'd' -- looks for the cleaned value of the named parameter first -- if it doesn't exist, look at the passed value next -- if that doesn't exist, look at the default -- if that doesn't exist, use blank if flag[x] == 'd' then if self.rargs[w] then if self.rargs[w].switches then xarg = self.rargs[w].switches[i] else xarg = self.args[w..i] end if xarg == nil or xarg == nil_param then xarg = self.rargs[w].d end end -- multiple catches in a row just to cover everything if xarg == nil or xarg == nil_param then xarg = self.args[w..i] end if xarg == nil or xarg == edit or xarg == nil_param then xarg = self.args[w] end if xarg == nil or xarg == edit or xarg == nil_param then xarg = '' end -- Look only at the passed value of the named parameter -- if that doesn't exist, use unnumbered parameter -- if that doesn't exist, use blank elseif flag[x] == 'p' then xarg = self.args[w..i] or self.args[w] or '' -- Don't interpret value as a parameter name, and paste the as is elseif flag[x] == 'r' then xarg = w end -- Add parsed argument to table table.insert(func_args,xarg) end -- Run function _addarg = func(unpack(func_args)) end end -- If not defined, add the nil_param value -- An actual nil would cause errors in placement -- So it needs to be filled with an actual value -- "nil_param" is understood as nil in other functions -- Include table in case parameter isn't defined by template if _addarg == nil or _addarg == nil_param then table.insert(_add_switch, nil_param) else switches = switches + 1 table.insert(_add_switch, _addarg) catdata.one_defined = true end end -- If there are actually other values to switch to -- Define a switches subtable, otherwise ignore it if switches > 0 then _add.switches = _add_switch end end -- Quick fix for names (which defaults to pagename) if v == 'name' then if _add.d == pagename then if _add.switches and _add.switches[1] ~= pagename and _add.switches[1] ~= nil_param then _add.d = _add.switches[1] end end end -- Parameter cleaning finished, add to table of cleaned args self.rargs[v] = _add -- Category metadata -- If every param except default is defined, all_defined = true if catdata.all_defined == false then if _add.d == edit then if _add.switches then catdata.all_defined = true for _, v in ipairs(_add.switches) do if v == nil_param then all_defined = false break end end end end end self.catdata[v] = catdata end -- mass dupe removal -- this needs to be done at the end to keep dependent parameters working -- also removes incompatible data types for _, v in ipairs(self.paramnames) do -- not removed from dupe enabled params parameters if not self.dupeable[v] and self.rargs[v] and self.rargs[v].switches then -- tells us whether or not we'll need to remove the switch data -- switched to false if a switch values does not match the default local rmvswitch = true for q, z in ipairs(self.rargs[v].switches) do -- if it matches the default, switch it to nil if z == self.rargs[v].d then self.rargs[v].switches[q] = nil_param -- remove types that don't turn into strings properly elseif type(z) == 'table' or type(z) == 'function' then self.rargs[v].switches[q] = nil_param -- if it doesn't match and also isn't nil or an edit button -- change variable to keep the switch data elseif z ~= nil_param and z ~= edit then rmvswitch = false end end -- remove switch data if everything was a dupe if rmvswitch then self.rargs[v].switches = nil end end end -- Title parentheses (has to be done here, sadly) local _name if self.rargs.name then _name = self.rargs.name.d -- replace html entities to their actual character _name = mw.text.decode(_name) -- if the page name matches the item name, don't add parentheses if _name == mw.title.getCurrentTitle().fullText then self.rtable:addClass('no-parenthesis-style') end end end --[[ Function to link internal use parameters with JS class attribution -- self:linkParams{ { arg1, arg2 }, ... { arg1a, arg2a } } -- arg1: parameter name being linked -- arg2: parameter name that holds the classes -- THIS FUNCTION SHOULD BE RUN AFTER :cleanParams() -- THIS FUNCTION SHOULD BE RUN BEFORE :finish() -- The second argument's data should always contain a value (a CSS class name) at every index -- This function is cancelled for non switch boxes --]] function Infobox:linkParams(...) if not self.switchfo then return end for _, v in ipairs(...) do self.switchfoattr[v[1]] = self.rargs[v[2]] end end --[==========================================[ -- Functions for accessing parameters easily --]==========================================] --[[ Access the param -- arg : param name -- retp : return type d | #default : self.rargs[arg].d -- Default value f | full : self.rargs[arg] -- Entire table s | switches : self.rargs[arg].switches -- Entire switch table s# : self.rargs[arg].switches[#] -- Single switch value at index # r : switches[1] or d --]] function Infobox:param(arg, retp) -- All parameters if arg == 'all' then return self.rargs end -- case-insensitive flagging retp = tostring(retp):lower() local fmap = { d = 'd', default = 'd', s0 = 'd', -- let s-naught count as default (since that's what it is) f = 'f', full = 'f', s = 's', switch = 's', switches = 's', r = 'r' } local ret_func -- quickly see if the parameter is a value greater than 0 if retp:match('s[1-9]') then ret_func = 's2' else -- Otherwise map it to the correct flag, or the default ret_func = fmap[retp] or fmap.d end -- Fetch parameter local param = self.rargs[arg] -- Return nil if no table found if not param then return nil end -- Return default if ret_func == 'd' then return param.d end -- Return full table if ret_func == 'f' then return param end -- Return switch table if ret_func == 's' then return param.switches end -- Return the first switch, otherwise the default if ret_func == 'r' then if not param.switches then return param.d elseif param.switches[1] == nil_param then return param.d else return param.switches[1] end end -- If s2, reread the param if ret_func == 's2' then -- no switches if not param.switches then return nil end -- Parse index by removing the s local index = retp:match('s(%d+)') -- nil_param if param.switches[index] == nil_param then return nil else return param.switches[index] end end end --[[ Checks if a parameter is defined and not blank -- arg : parameter to look at -- index : index of switches to look at (defaults to default param) -- defining 'all' will look at every possible value for the parameter --]] function Infobox:paramDefined(arg,index) -- Can use cleaned params for switches -- but need the passed to identify blanks in the template local param = self.rargs[arg] local _arg = self.args[arg] if string.find(_arg or '','%?action=edit') then _arg = '' end index = index or 0 local ret -- create a long strong of every value to test for things if 'all' if string.lower(index) == 'all' then return self.catdata[arg] and (self.catdata[arg].one_defined or self.catdata[arg].all_defined) -- index to number otherwise else index = tonumber(index) or 0 if index == 0 then ret = _arg else if not param.switches then return nil end if param.switches[index] == nil_param then return nil end ret = param.switches[index] end end return tostring(ret or ''):find('%S') end --[[ Function to perform a search on all parameters of a defined name -- param: param name -- val: a value or function -- functions passed must return either true or false -- with true being counted as a match --]] function Infobox:paramGrep(param,val) local arg = self.rargs[param] -- if no parameters, return nil if not arg then return nil end local ret local valtype = type(val) -- start with the default value -- if it's a function, run it if valtype == 'function' then ret = val(arg.d) -- true means it matched if ret == true then return ret end -- switches up here for functions if arg.switches then for _, v in ipairs(arg.switches) do ret = val(v) if ret == true then return true end end end -- if it's just a value, compare the two -- only run if types match to avoid errors -- compare switches later elseif valtype == type(arg.d) then -- if a string, make case insensitive if valtype == 'string' then if string.lower(val) == string.lower(arg.d) then return true end -- everything else just test directly elseif val == arg.d then return true end end -- switch cases -- more organized putting them here if arg.switches then for _, v in ipairs(arg.switches) do if valtype == type(v) then if valtype == 'string' then if val:lower() == v:lower() then return true end elseif val == v then return true end end end end -- return false in every other case return false end ------ function Infobox.paramRead(arg,val) -- if no parameters, return nil if not arg then return nil end local ret local valtype = type(val) -- start with the default value -- if it's a function, run it if valtype == 'function' then ret = val(arg.d) -- true means it matched if ret == true then return ret end -- switches up here for functions if arg.switches then for _, v in ipairs(arg.switches) do ret = val(v) if ret == true then return true end end end -- if it's just a value, compare the two -- only run if types match to avoid errors -- compare switches later elseif valtype == type(arg.d) then -- if a string, make case insensitive if valtype == 'string' then if string.lower(val) == string.lower(arg.d) then return true end -- everything else just test directly elseif val == arg.d then return true end end -- switch cases -- more organized putting them here if arg.switches then for _, v in ipairs(arg.switches) do if valtype == type(v) then if valtype == 'string' then if val:lower() == v:lower() then return true end elseif val == v then return true end end end end -- return false in every other case return false end ---- -- Return collected category data function Infobox:categoryData() return self.catdata end -- Override tostring function Infobox.tostring(box) -- If not finished, finish if not box.__finished then box:finish() end -- Make entire html wrapper a string and return it return tostring(box.rdiv) end return Infobox Return to Module:Infobox. Edit summary Show changes