Module:Navbox

-- Navbox Module -- -- * Fully CSS styled (inline styles possible but not default) -- * Supports unlimited rows -- * Supports collapsible groups (just set parameter withcollapsiblegroups) -- -- By User:Effan_R from disneymagickingdomswiki.fandom.com -- Adapted from Navbox Module by User:Tjcool007 from layton.wikia.com

local p = {}

local args = {} -- Arguments passed to template local navbox -- Actual navbox

local rownums = {} local hasrows, alt, altg, isChild = false, false, false, false local cimage, cimageleft local colspan, rowspan local spacer = false

-- Title

--- Processes the VDE links in the title -- -- @param titlecell The table cell of the title local function processVde( titlecell ) if not args.name then return end

local vdeCell = titlecell:tag('div') :addClass('noprint plainlinks navbar') :css({['background'] = 'none',							['padding'] = '0',							['font-weight'] = 'normal',							['border'] = 'none',							['font-size'] = 'xx-small'						})

vdeCell:wikitext('')	local spanV = vdeCell:tag('span')						:attr('title', "View this template")						:css('border', 'none')						:wikitext('v')	vdeCell:wikitext(' ') vdeCell:tag('span'):css('font-size', '80%'):wikitext('•') vdeCell:wikitext(' ')

vdeCell:wikitext('[', tostring(mw.uri.fullUrl('Template talk:' .. args.name))) local spanD = vdeCell:tag('span') :attr('title', "Discuss this template") :css('border', 'none') :wikitext('d') vdeCell:wikitext('] ') vdeCell:tag('span'):css('font-size', '80%'):wikitext('•') vdeCell:wikitext(' ')

vdeCell:wikitext('[', tostring(mw.uri.fullUrl('Template:' .. args.name, 'action=edit'))) local spanE = vdeCell:tag('span') :attr('title', "Edit this template") :css('border', 'none') :wikitext('e') vdeCell:wikitext(']')

if args.basestyle then vdeCell:cssText(args.basestyle) spanV:cssText(args.basestyle) spanD:cssText(args.basestyle) spanE:cssText(args.basestyle) end if args.titlestyle then vdeCell:cssText(args.titlestyle) spanV:cssText(args.titlestyle) spanD:cssText(args.titlestyle) spanE:cssText(args.titlestyle) end end

--- Processes the main title row local function processTitle -- Nothing to do if no title -- if not args.title then return end

local titleRow = navbox:tag('tr')

if args.titlegroup then titleRow:tag('td') :addClass('navbox-group') :wikitext(args.titlegroup) if args.titlegroupstyle then titlerow:cssText(args.titlegroupstyle) end end

local titleCell = titleRow:tag('th')

if args.titlegroup then titleCell:css('border-left', '2px solid #fdfdfd') :css('width', '100%') end

titleCell:addClass('navbox-title') :attr('colspan', colspan)

if args.basestyle then titleCell:cssText(args.basestyle) end if args.titlestyle then titleCell:cssText(args.titlestyle) end

local titlebar = titleCell:tag('div') titlebar:css('width', '6.0em')

if not args.name and isChild or args.navbar == 'plain' or args.navbar == 'off' then if args.navbar == 'off' then if args.state == 'plain' then titlebar:css('float', 'right') :wikitext(' ') end else if args.state ~= 'plain' then titlebar:css('float', 'left') :css('text-align', 'left') :wikitext(' ') end end else titlebar:css('float', 'left') :css('text-align', 'left') processVde(titlebar) end

titleCell :tag('span') :addClass(args.titleclass) :css('font-size', (isChild and '100%' or '110%')) :wikitext(args.title)

spacer = true end

--- Processes the group title row local function processGroupTitle(parent, num) -- Nothing to do if no group #	-- if not args['group' .. num] then return end

local titleRow = parent:tag('tr')

local titleCell = titleRow:tag('th')

titleCell:addClass('navbox-title') :attr('colspan', colspan)

if args.basestyle then titleCell:cssText(args.basestyle) end if args.groupstyle then titleCell:cssText(args.groupstyle) end if args['group' .. num .. 'style'] then titleCell:cssText(args['group' .. num .. 'style']) end

local titlebar = titleCell:tag('div') titlebar:css('width', '6.0em') :css('float', 'left') :css('text-align', 'left') :wikitext(' ')

titleCell :tag('span') :css('font-size', '100%') :wikitext(args['group' .. num])

spacer = true end

-- Gutter

--- Add gutter between rows -- -- @param parent node, inRowspan to increment image rowspan local function _addGutter( parent, incRowspan ) if spacer then local gutterCell = parent:tag('tr'):css('height', '2px') gutterCell:tag('td') end

if incRowspan then rowspan = rowspan + 1 end spacer = false end

-- Above/Below

--- Processes the above and below rows -- -- @param rowtype Either 'above' or 'below' local function processAboveBelow( rowtype ) if not args[rowtype] then return end

local abrow = mw.html.create('tr') local abcell = mw.html.create('td')

abcell:addClass('navbox-abovebelow') :attr('colspan', colspan)

if args[rowtype .. 'class'] then abcell:addClass(args[rowtype .. 'class']) end if args.basestyle then abcell:cssText(args.basestyle) end if args[rowtype .. 'style'] then abcell:cssText(args[rowtype .. 'style']) end

abcell:tag('div') :wikitext(args[rowtype])

abrow:node(abcell) _addGutter( navbox ) navbox:node( abrow )

spacer = true end

-- Main Rows

--- Processes the images local function _processImage(row, imgtype) if not args[imgtype] then return end

local imagecell = row:tag('td') :addClass('navbox-image')

imagecell:css('width', '0%') :css('padding', '0px 0px 0px 2px')

if args.imageclass then imagecell:addClass(args.imageclass) end if args.imagestyle then imagecell:cssText(args.imagestyle) end

local imagediv = imagecell:tag('div') :wikitext(args[imgtype])

if imgtype == 'image' then cimage = imagecell else cimageleft = imagecell end end

--- Handles Odd Even Groups -- -- @return Alternatingly returns true (odd) or false (even). Returns fixed value of --	      true (odd) or false (even) if specified by args.evenodd local function _evenoddGroup if args.evenodd == 'even' then return false end if args.evenodd == 'odd' then return true end

altg = not altg

return altg end

--- Handles Odd Even rows -- -- @return Alternatingly returns true (odd) or false (even). Returns fixed value of --	      true (odd) or false (even) if specified by args.evenodd local function _evenoddRow if args.evenodd == 'even' then return false end if args.evenodd == 'odd' then return true end

alt = not alt

return alt end

--- Processes a single list row -- -- @param num Number of the row to be processed local function processList(num) if not args['list'..num] then return end

local row = mw.html.create('tr') local listrow = row

if not hasrows then _processImage(row, 'imageleft') end

local listpadding = args['list' .. num .. 'padding'] or args.listpadding or '0em 0.25em'

if args['group'..num] then if args.withcollapsiblegroups then -- convert Group to collapsible title row -- _addGutter(navbox)

local altGroup = _evenoddGroup

local headercell = row:tag('td') :addClass('navbox-list') :attr('colspan', 2) :css('padding', '0px')

if altGroup then headercell:addClass('navbox-odd') if args.oddstyle then headercell:cssText(args.oddstyle) end else headercell:addClass('navbox-even') if args.evenstyle then headercell:cssText(args.evenstyle) end end

if args.listclass then headercell:addClass(args.listclass) end if args.liststyle then headercell:cssText(args.liststyle) end if args['list' .. num .. 'style'] then headercell:cssText(args['list' .. num .. 'style']) end if not args.groupwidth then headercell:css('width', '100%') end

headercell:tag('div') :css('padding', listpadding)

local headertable = headercell:tag('table') headertable:addClass('navbox-subgroup') if args.bodystyle then headertable:cssText(args.bodystyle) end if args.style then headertable:cssText(args.style) end

headertable:addClass('nowraplinks') :addClass('mw-collapsible') :attr('cellspacing', '0') :attr('data-expandtext', 'show') :attr('data-collapsetext', 'hide') :css('border-spacing', 0)

if args.bodyclass then headertable:addClass(args.bodyclass) end if args.innerstyle then headertable:cssText(args.innerstyle) end

if args.selected ~= args['abbr' .. num] then if args['state' .. num] then headertable:addClass(args['state' .. num]) else headertable:addClass('mw-collapsed') end end

processGroupTitle(headertable, num) _addGutter(headertable)

alt = (args.evenodd == 'swap')

listrow = headertable:tag('tr') else local groupcell = row:tag('th') :addClass('navbox-group') :attr('scope','row') :wikitext( args['group'..num] )

if args.groupclass then groupcell:addClass( args.groupclass ) end if args.groupstyle then groupcell:cssText( args.groupstyle ) end if args.basestyle then groupcell:cssText( args.basestyle ) end if args['group' .. num .. 'style'] then groupcell:cssText(args['group' .. num .. 'style'])	end if args.groupwidth then groupcell:css('width', args.groupwidth) end end end

local altRow = _evenoddRow

local listcell = listrow:tag('td') :addClass('navbox-list') :css('padding', '0px')

if altRow then listcell:addClass('navbox-odd') if args.oddstyle then listcell:cssText(args.oddstyle) end else listcell:addClass('navbox-even') if args.evenstyle then listcell:cssText(args.evenstyle) end end

if not args.withcollapsiblegroups and args.listclass then listcell:addClass(args.listclass) end if args.liststyle then listcell:cssText(args.liststyle) end if args['list' .. num .. 'style'] then listcell:cssText(args['list' .. num .. 'style']) end if not args.groupwidth then listcell:css('width', '100%') end

if not args.withcollapsiblegroups and args['group'..num] then listcell:css('text-align', 'left') :css('border-left-width', '2px') :css('border-left-style', 'solid') else listcell:attr('colspan',2) end

local hlistcell = listcell:tag('div') :css('padding', listpadding)

local data = args['list'..num]

local srchpat = args['stripbegin' .. num] or args.stripbegin

if srchpat and srchpat ~= "" then srchpat = string.gsub(srchpat, "([%^%$%(%)%.%+%-%?])", "%%%1") data = string.gsub(data, "%[%[(" .. srchpat .. "%s*)([^%]|]-)%]%]", "%2") data = string.gsub(data, "%[%[([^%]]-|)(" .. srchpat .. "%s*)([^%]|]-)%]%]", "%1%3") end

srchpat = args['stripend' .. num] or args.stripend

if srchpat and srchpat ~= "" then srchpat = string.gsub(srchpat, "([%^%$%(%)%.%+%-%?])", "%%%1") data = string.gsub(data, "%[%[([^%]]-|[^%]]-)(%s*" .. srchpat .. ")%]%]", "%1")		data = string.gsub(data, "%[%[([^%]%|]-)(%s*" .. srchpat .. ")%]%]", "%1")	end

if data:match('^[*:;#]') then -- Add newlines to support lists properly hlistcell :newline :wikitext( data ) :newline else hlistcell:wikitext( data ) end

local firstRow = false if not hasrows then firstRow = true hasrows = true _processImage(row, 'image') end

_addGutter(navbox,not firstRow) navbox:node( row ) rowspan = rowspan + 1 spacer = true end

--- Processes all rows local function processRows for i=1,#rownums do		processList(rownums[i]) end

if cimageleft then cimageleft:attr('rowspan',rowspan) end if cimage then cimage:attr('rowspan',rowspan) end end

-- CLEAN SLATE -- * Resets the module state

local function cleanSlate args = {} -- Arguments passed to template navbox = nil -- Actual navbox rownums = {} hasrows = false alt = false altg = false isChild = false cimage = nil cimageleft = nil colspan = nil rowspan = nil spacer = false end

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

--- 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 cat,num = tostring(k):match('^(%a+)([1-9]%d*)$')

if cat == 'list' then nums[num] = true end

args[k] = v -- Simple copy end end

colspan = args.image and 3 or 2 if args.imageleft then colspan = colspan + 1 end if args.titlegroup then colspan = colspan - 1 end

rowspan = 0

alt = (args.evenodd == 'swap') altg = alt

for k, v in pairs(nums) do		rownums[#rownums+1] = tonumber(k) end

table.sort(rownums) end

-- MAIN FUNCTIONS

--- Processes the arguments to create the navbox. -- -- @return A string with HTML that is the navbox. local function _navbox -- Create the root HTML element local trim = function(s) return s and mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1") or '' end local border = args.border or trim(args[1]) or '' isChild = (border == 'child' or border == 'subgroup' or border == 'none')

if isChild then navbox = mw.html.create('table') navbox:addClass('navbox-subgroup') if args.bodystyle then navbox:cssText(args.bodystyle) end if args.style then navbox:cssText(args.style) end else navbox = mw.html.create('table') navbox:addClass('navbox-inner') :css('background', 'transparent') :css('color', 'inherit') end

navbox:addClass('nowraplinks') :addClass(args.bodyclass) :attr('cellspacing', '0') :attr('data-expandtext', 'show') :attr('data-collapsetext', 'hide') :css('border-spacing', 0) :cssText(args.innerstyle)

if args.title then if args.state ~= 'plain' and args.stat ~= 'off' then navbox:addClass('mw-collapsible') if args.state then	navbox:addClass(args.state) end end end

-- Process... spacer = false

processTitle processAboveBelow('above') processRows processAboveBelow('below')

-- Wrapper Table -- if not isChild then local wrapper = mw.html.create('table') wrapper:addClass('navbox') :attr('cellspacing', '0') :css('border-spacing', 0) if args.bodystyle then wrapper:cssText(args.bodystyle) end if args.style then wrapper:cssText(args.style) end local wrapperrow = wrapper:tag('tr') wrapperrow:tag('td') :css('padding', '2px') :node(navbox) return tostring(wrapper) else local wrapper = mw.html.create('') wrapper:wikitext(' ') wrapper:node(navbox) wrapper:wikitext(' ') return tostring(wrapper) end 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) -- Clear the previous state cleanSlate -- Save the arguments in a local variable so other functions can use them. preProcessArgs(frame)

return _navbox end

return p