Module:Infobox

-- Extended Infobox Module -- -- * Fully CSS styled (inline styles possible but not default) -- * Supports Multiple images (either under eachother or in a tabber) -- * Automatically hidden sections -- * Collapsible sections (requires JS) -- * Alternating row styles -- -- By User:Tjcool007

local p = {} local args = {} -- Arguments passed to template local infobox -- Actual infobox local sections, activeSection local imagenums, rownums, skiprows = {}, {}, {} local hasData, alt = false, false local showText, hideText = 'Show', 'Hide'

-- TITLE

--- Processes the VDE links local function _processVde(header) if not args.template then return end header :tag('span') :addClass('infobox-vde') :wikitext(mw.getCurrentFrame:expandTemplate({ title = 'vdelinks', args = { args.template, ['type'] = 'infobox' } })) end --- Processes the main title row local function processTitle if not args.title then args.title = mw.title.getCurrentTitle.text end local h = infobox :tag('tr'):addClass('infobox-title') :tag('th'):attr('colspan', 2) :tag('div') _processVde(h) h:wikitext(args.title) end --- Adds a Gutter row local function _addGutter(parent) parent:tag('tr'):addClass('infobox-gutter'):tag('td'):attr('colspan',2) end

-- IMAGES

--- Gets a single image from the arguments -- -- @param num The number of the image. Note that this number is 1 higher than the argument --           passed to the infobox. Eg. for "image5", num would be 6. This is because the --           number 1 is reserved for "image" without a number. local function _getImage(num) local t = tostring(num-1) if t == '0' then t = '' end local i = args['image'..t]	if not i:find('%[') then if not i:find(':') then i = 'File:' .. i		end local imagewidth = args['imagewidth'..t] or '250px' if tonumber(imagewidth) then imagewidth = imagewidth .. 'px' end i = ..imagewidth.. end local image = mw.html.create('div'):wikitext(i) if args['caption' .. t] then local caption = mw.html.create('span') :addClass('infobox-imagecaption') :wikitext(args['caption' .. t]) image:tag('br'):done:node(caption) end return image end --- Processeses the images in default mode -- Adds images underneath eachother. local function _processImagesDefault local iclass = args.imageclass for i=1, #imagenums do		local num = imagenums[i] local image = _getImage(num) _addGutter(infobox) infobox:tag('tr'):addClass('infobox-image') :tag('td'):attr('colspan', 2):wikitext(tostring(image)) end end --- Processes images in tabber mode -- Adds images in a tabber with one image per tab. -- Tabs without a title will be automatically numbered. local function _processImagesTabber local isloaded, Tabber = pcall(require,'Module:Tabber') if not isloaded then _processImagesDefault return end local tb = Tabber.new for i=1, #imagenums do		local num = imagenums[i] local image = _getImage(num) -- Get title local t = tostring(num-1) if t == '0' then t = '' end local title = args['tab'..t] or k		tb:addTab( title, tostring(image) ) end _addGutter(infobox) infobox:tag('tr'):addClass('infobox-image') :tag('td'):attr('colspan', 2):wikitext(tostring(tb)) end --- Dispatcher for image processing local function processImages if #imagenums == 0 then return end if args.imagemode == 'tabber' and #imagenums > 1 then return _processImagesTabber else return _processImagesDefault end end

-- ABOVE/BELOW

--- Processeses the Above and Below rows -- -- @param rowtype Either "above" or "below" local function processAboveBelow(rowtype) if not args[rowtype] then return end _addGutter(infobox) infobox:tag('tr'):addClass('infobox-abovebelow'):addClass('infobox-' .. rowtype) :tag('td'):attr('colspan',2):wikitext(args[rowtype]) end

-- MAIN ROWS

--- Closes the currently active section, if any -- Will add the section to the infobox if there is data or the showX parameters are used. local function _closeCurrentSection if not activeSection then return end _addGutter(infobox) infobox :tag('tr'):addClass('infobox-sectionrow') :tag('td'):attr('colspan',2):node(sections[activeSection]) activeSection = false hasData = false end --- Handles alternating rows -- -- @return Alternatingly returns true or false. Always returns false if alternating rows --        are disabled with "alternaterows = no" local function _alternateRow if args.alternaterows == 'no' then return false end if alt then	alt = false; return true else alt = true; return false end end --- Processes a Header row -- -- @param num The number of the Header row (eg. "headerX") local function _processHeader(num) if not args['header'..num] then return end -- Begin a new section _closeCurrentSection activeSection = num local header = mw.html.create('th'):attr('colspan', 2):wikitext( args['header'..num] ) local t = mw.html.create('table'):addClass('infobox-section') :tag('tr'):addClass('infobox-headerrow'):node(header):done -- Header collapse local collapseme = args['state'..num] or false if collapseme ~= 'plain' then local collapseall = args.defaultstate or false if collapseall == 'plain' then collapseall = false end if collapseall or collapseme then t:addClass('mw-collapsible'):attr('data-expandtext',showText):attr('data-collapsetext',hideText) header:css('padding-left','50px') end if collapseme == 'collapsed' or (not collapseme and collapseall == 'collapsed') then t:addClass('mw-collapsed') end end sections[num] = t	_alternateRow -- Comment this line to stop alternating on headers end --- Processes a data row -- -- @param num The number of the data row (eg. "dataX"), as well as the label with the --           same number (eg. "labelX") local function _processData(num) local data = args['data'..num] if not data then return end local t = infobox local s = activeSection or false if s then t = sections[s] -- Open the section hasData = true -- This section has data! end local altRow = _alternateRow local datarow = mw.html.create('tr') :addClass('infobox-datarow') :addClass((s and 'ib-section'..s) or '') :addClass('ib-row'..num) local datacell = mw.html.create('td') :addClass('infobox-rowdata')

if tostring(data):sub(1,1) == '*' then -- Add newlines to support lists datacell :newline :wikitext(data) :newline else datacell:wikitext(data) end if altRow then datarow:addClass('alt') end local lbl = args['label'..num] if lbl then local label = mw.html.create('th') :addClass('infobox-rowlabel') :wikitext(lbl) datarow:node(label) else datacell:addClass('no-label'):attr('colspan',2) end datarow:node(datacell) _addGutter(t) t:node(datarow) end --- Processeses ONE normal row. A normal row contains a header and/or a label/data pair -- -- @param num Number of the row to be processed. local function processRow(num) _processHeader(num) _processData(num) end --- Processes ALL normal rows; making use of the above functions local function processRows sections = {} -- Init sections storage local rnum = rownums for i=1, #rnum do		local num = rnum[i] if not skiprows[num] then processRow(num) end end _closeCurrentSection -- Close last section if any end

-- ARGUMENTS PREPROCESSOR -- * Extracts arguments from frame and stores them in args table -- * At the same time, checks for valid row and image numbers

--- Process Language Rows (Layton Wiki addition) local function _preProcessLanguages(a) rownums[#rownums+1] = 10000 args.header10000 = 'In other languages' args.state10000 = 'collapsed' local i = 10000 local langrows = { {'jpname',' 日本語 '}, {'dename',' Deutsch '}, {'esname',' Español '}, {'frname',' Français '}, {'itname',' Italiano '}, {'nlname',' Nederlands '}, {'korname',' 한국의 '} }	for l=1,#langrows do		local lang = langrows[l][1] if a[lang] and a[lang] ~= '' then if i > 10000 then rownums[#rownums+1] = i end args['label'..i] = langrows[l][2] args['data'..i] = a[lang] args[lang] = nil end i = i + 1 end end --- Preprocessor for the arguments. -- Will fill up the args table with the parameters from the frame grouped by their type. -- -- @param frame The frame passed to the Module. local function preProcessArgs(frame) local tmp = {} if frame == mw.getCurrentFrame then tmp = frame:getParent.args else tmp = frame end -- Storage tables local nums = {} -- Loop over all the args for k,v in pairs(tmp) do		-- Skip empty args, which are useless if v ~= '' then local s = tostring(k) if s == 'image' then imagenums[#imagenums+1] = 1 else local cat,num = s:match('^(%a+)([1-9]%d*)$') if cat == 'header' or cat == 'data' then nums[num] = true elseif cat == 'image' then imagenums[#imagenums+1] = tonumber(num+1) end end args[k] = v -- Simple copy end end for k, v in pairs(nums) do		rownums[#rownums+1] = tonumber(k) end if args.enablelanguages ~= 'no' then _preProcessLanguages(tmp) end -- Sort table.sort(rownums) table.sort(imagenums) -- Calculate skip rows local cSection, cSkip local showall = args.showall for i=1,#rownums do		local num = rownums[i] if args['header'..num] then cSection = true cSkip = false local showme = args['show'..num] if showme == 'no' then cSkip = true elseif showme == 'auto' or (showme ~= 'yes' and showall ~= 'yes') then if not args['data'..num] then local nextNum = rownums[i+1] cSkip = not nextNum or args['header'..nextNum] -- If next has a header -> skip end end end if cSection and cSkip then skiprows[num] = true end end end

-- MAIN FUNCTIONS

--- Processes the arguments to create the infobox. -- -- @return A string with HTML that is the infobox. local function _infobox -- Create the root HTML element infobox = mw.html.create('table'):addClass('infobox') -- Process... processTitle processAboveBelow('above') processImages processRows processAboveBelow('below') return tostring(infobox) end --- Main module entry point. -- To be called with or directly from another module. -- -- @param frame The frame passed to the module via the #invoke. If called from another --             module directly, this should be a table with the parameter definition. function p.main(frame) -- Save the arguments in a local variable so other functions can use them. preProcessArgs(frame) return _infobox end return p --