Module:Infobox

From Freeside Atlanta
Revision as of 16:24, 8 June 2013 by Thrillgore (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

--

-- This module implements
Template:Main other

--

local p = {}

local HtmlBuilder = require('Module:HtmlBuilder')

local args local root

function union(t1, t2)

   -- Returns the union of the values of two tables, as a sequence.
   local vals = {}
   for k, v in pairs(t1) do
       vals[v] = true
   end
   for k, v in pairs(t2) do
       vals[v] = true
   end
   local ret = {}
   for k, v in pairs(vals) do
       table.insert(ret, k)
   end
   return ret

end

local function getArgNums(prefix)

   -- Returns a table containing the numbers of the arguments that exist
   -- for the specified prefix. For example, if the prefix was 'data', and
   -- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.
   local nums = {}
   for k, v in pairs(args) do
       local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
       if num then table.insert(nums, tonumber(num)) end
   end
   table.sort(nums)
   return nums

end

local function addRow(rowArgs)

   -- Adds a row to the infobox, with either a header cell
   -- or a label/data cell combination.
   if rowArgs.header then
       root
           .tag('tr')
               .tag('th')
                   .attr('colspan', 2)
                   .addClass(rowArgs.class)
                   .css('text-align', 'center')
                   .cssText(args.headerstyle)
                   .wikitext(rowArgs.header)
   elseif rowArgs.data then
       local row = root.tag('tr')
       row.addClass(rowArgs.rowclass)
       if rowArgs.label then
           row
               .tag('th')
                   .attr('scope', 'row')
                   .css('text-align', 'left')
                   .cssText(args.labelstyle)
                   .wikitext(rowArgs.label)
                   .done()
       end
       
       local dataCell = row.tag('td')
       if not rowArgs.label then 
           dataCell
               .attr('colspan', 2)
               .css('text-align', 'center') 
       end
       dataCell
           .addClass(rowArgs.class)
           .cssText(rowArgs.datastyle)
           .newline()
           .wikitext(rowArgs.data)
   end

end

local function renderTitle()

   if not args.title then return end
   root
       .tag('caption')
           .addClass(args.titleclass)
           .cssText(args.titlestyle)
           .wikitext(args.title)

end

local function renderAboveRow()

   if not args.above then return end
   
   root
       .tag('tr')
           .tag('th')
               .attr('colspan', 2)
               .addClass(args.aboveclass)
               .css('text-align', 'center')
               .css('font-size', '125%')
               .css('font-weight', 'bold')
               .cssText(args.abovestyle)
               .wikitext(args.above)

end

local function renderBelowRow()

   if not args.below then return end
   
   root
       .tag('tr')
           .tag('td')
               .attr('colspan', '2')
               .addClass(args.belowclass)
               .css('text-align', 'center')
               .cssText(args.belowstyle)
               .newline()
               .wikitext(args.below)
               .newline()

end

local function renderSubheaders()

   if args.subheader then
       args.subheader1 = args.subheader
   end
   if args.subheaderrowclass then
       args.subheaderrowclass1 = args.subheaderrowclass
   end
   local subheadernums = getArgNums('subheader')
   for k, num in ipairs(subheadernums) do
       addRow({
           data = args['subheader' .. num],
           datastyle = args.subheaderstyle or args['subheaderstyle' .. num],
           class = args.subheaderclass,
           rowclass = args['subheaderrowclass' .. num]
       })
   end

end

local function renderImages()

   if args.image then
       args.image1 = args.image
   end
   if args.caption then
       args.caption1 = args.caption
   end
   local imagenums = getArgNums('image')
   for k, num in ipairs(imagenums) do
       local caption = args['caption' .. num]
       local data = HtmlBuilder.create().wikitext(args['image' .. num])
       if caption then
           data
               .tag('br', {selfClosing = true})
                   .done()
               .tag('span')
                   .cssText(args.captionstyle)
                   .wikitext(caption)
       end
       addRow({
           data = tostring(data),
           datastyle = args.imagestyle,
           class = args.imageclass,
           rowclass = args['imagerowclass' .. num]
       })
   end

end

local function renderRows()

   -- Gets the union of the header and data argument numbers,
   -- and renders them all in order using addRow.
   local rownums = union(getArgNums('header'), getArgNums('data'))
   table.sort(rownums)
   for k, num in ipairs(rownums) do
       addRow({
           header = args['header' .. num],
           label = args['label' .. num],
           data = args['data' .. num],
           datastyle = args.datastyle,
           class = args['class' .. num],
           rowclass = args['rowclass' .. num]
       })
   end

end

local function renderNavBar()

   if not args.name then return end
   
   root
       .tag('tr')
           .tag('td')
               .attr('colspan', '2')
               .css('text-align', 'right')
               .wikitext(mw.getCurrentFrame():expandTemplate({ 
                   title = 'navbar', 
                   args = { args.name, mini = 1 }
               }))

end

local function renderItalicTitle()

   local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
   if italicTitle ==  or italicTitle == 'force' or italicTitle == 'yes' then
       root.wikitext(mw.getCurrentFrame():expandTemplate({title = 'italic title'}))
   end

end

local function renderTrackingCategories()

   if args.decat ~= 'yes' then
       if #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
           root.wikitext()
       end
       if args.child == 'yes' and args.title then
           root.wikitext()
       end
   end

end

local function _infobox()

   -- Specify the overall layout of the infobox, with special settings
   -- if the infobox is used as a 'child' inside another infobox.
   if args.child ~= 'yes' then
       root = HtmlBuilder.create('table')
       
       root
           .addClass('infobox')
           .addClass(args.bodyclass)
           .attr('cellspacing', 3)
           .css('border-spacing', '3px')
           
           if args.subbox == 'yes' then
               root
                   .css('padding', '0')
                   .css('border', 'none')
                   .css('margin', '-3px')
                   .css('width', 'auto')
                   .css('min-width', '100%')
                   .css('font-size', '100%')
                   .css('clear', 'none')
                   .css('float', 'none')
                   .css('background-color', 'transparent')
           else
               root
                   .css('width', '22em')
           end
       root
           .cssText(args.bodystyle)
   
       renderTitle()
       renderAboveRow()
   else
       root = HtmlBuilder.create()
       
       root
           .wikitext(args.title)
   end
   renderSubheaders()
   renderImages() 
   renderRows() 
   renderBelowRow()  
   renderNavBar()
   renderItalicTitle()
   renderTrackingCategories()
   
   return tostring(root)

end

local function touchParameters(prefixTable, origArgs, step)

   -- Parse the parameters with the given prefixes, in order, in batches 
   -- of the step size specified. This is to prevent references etc. from
   -- appearing in the wrong order.
   if type(prefixTable) ~= 'table' or type(origArgs) ~= 'table' then
       error("Invalid input to the touchParameters function detected. Both parameters must be tables.", 2)
   end
   if step and type(step) ~= 'number' then
       error("Non-numerical step value detected.", 2)
   end
   
   step = step or 20 -- If the step size is not given, the default is 20.
   local temp
   local a = 1 -- Counter variable.
   local moreArgumentsExist = true
   for j,v in ipairs(prefixTable) do
       if not type(v) == "string" then
           error("Non-string value detected in the prefix table in the touchParameters function.", 2)
       end
       temp = origArgs[v]
   end
   while moreArgumentsExist == true do
       moreArgumentsExist = false
       for i = a, a + step - 1 do
           for j,v in ipairs(prefixTable) do
               temp = origArgs[v .. tostring(i)]
               if temp then
                   moreArgumentsExist = true
               end
           end
       end
       a = a + step
   end

end

function p.infobox(frame)

   local origArgs
   -- If called via #invoke, use the args passed into the invoking template.
   -- Otherwise, for testing purposes, assume args are being passed directly in.
   if frame == mw.getCurrentFrame() then
       origArgs = frame:getParent().args
   else
       origArgs = frame
   end
   
-- Parse the data parameters in the same order that the old
Template:Main other did, so that
   -- references etc. will display in the expected places.
   local temp
   temp = origArgs.title
   temp = origArgs.above
   touchParameters({'subheader'}, origArgs, 5)
   touchParameters({'image', 'caption'}, origArgs, 5)
   touchParameters({'header', 'label', 'data'}, origArgs, 20)
   temp = origArgs.below

   -- ParserFunctions considers whitespace to be false, so to preserve the previous 
-- behavior of
Template:Main other, change any whitespace arguments to nil, so Lua will consider
   -- them false too. (Except the 'italic title' param, which specifies different behavior
   -- depending on whether it's absent or empty)
   args = {}
   for k, v in pairs(origArgs) do
       if mw.ustring.match(v, '%S') or k == 'italic title' then
           args[k] = v
       end
   end

   return _infobox()

end

return p

Personal tools
Namespaces

Variants
Actions
About Us
Support Us
Activities and Culture
Membership
Outreach
Leadership
Teams
Organization
Toolbox