Module:Navbox

    From Nonbinary Wiki
    Revision as of 04:36, 1 March 2013 by m>Toohool (rewrite with htmlbuilder)

    Documentation for this module may be created at Module:Navbox/doc

    --
    -- This module will implement {{Navbox}}
    --
     
    local p = {}
     
    local HtmlBuilder = require('Module:Sandbox/Toohool/HtmlBuilder')
    
    local args
    local tableRowAdded = false
    local border
    local listnums = {}
     
    function trim(s)
        return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
    end
     
    function addTableRow(tbl)
        -- If any other rows have already been added, then we add a 2px gutter row.
        if tableRowAdded then
    		tbl
    			.tag('tr')
    				.css('height', '2px')
    				.tag('td')
    	end
    	
    	tableRowAdded = true
    	
    	return tbl.tag('tr')
    end
    
    
    --
    --   Title row
    --
    function renderTitleRow(tbl)
        if not args.title then return end
     
     	local titleRow = addTableRow(tbl)
     	
        if args.titlegroup then
        	titleRow
        		.tag('th')
        			.attr('scope', 'row')
        			.addClass('navbox-group')
        			.addClass(args.titlegroupclass)
        			.cssText(args.basestyle)
        			.cssText(args.groupstyle)
        			.cssText(args.titlegroupstyle)
        			.wikitext(args.titlegroup)
        end
        
        local titleCell = titleRow.tag('th').attr('scope', 'col')
        		
        if args.titlegroup then
        	titleCell
        		.css('border-left', '2px solid #fdfdfd')
        		.css('width', '100%')
        end
        
        local titleColspan = 2
        if args.imageleft then titleColspan = titleColspan + 1 end
        if args.image then titleColspan = titleColspan + 1 end
        if args.titlegroup then titleColspan = titleColspan - 1 end
        
        titleCell
        	.cssText(args.basestyle)
        	.cssText(args.titlestyle)
        	.addClass('navbox-title')
        	.attr('colspan', titleColspan)
     
     	renderNavBar(titleCell)
     
     	titleCell
     		.tag('div')
     			.addClass(args.titleclass)
     			.css('font-size', '110%')
     			.newline()
     			.wikitext(args.title)
    end
     
    function renderNavBar(titleCell)
     	local addStateLinkPlaceholder = false
        if args.navbar == 'plain' or args.navbar == 'off' or (not args.name and (border == 'subgroup' or border == 'child' or border == 'none')) then
            if args.navbar == 'off' then
            	addStateLinkPlaceholder = (args.state == 'plain')
            else
            	addStateLinkPlaceholder = (args.state ~= 'plain')
            end
        else
            if args.name then
                titleCell.wikitext(mw.getCurrentFrame():expandTemplate{ title = 'navbar', args = { 
                    args.name, 
                    mini = 1, 
                    fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') ..  ';background:none transparent;border:none;'
                }})
            else
            	titleCell
            		.tag('span')
            			.addClass('error')
            			.css('float', 'left')
            			.css('white-space', 'nowrap')
            			.wikitext('Error: No name provided')
                addStateLinkPlaceholder = (args.state == 'plain')
            end
        end
        
        if addStateLinkPlaceholder then
        	titleCell
        		.tag('span')
        			.css('float', 'right')
        			.css('width', '6em')
        			.wikitext(' ')
        end
    end
    
    
    --
    --   Above/Below rows
    --
    function renderAboveRow(tbl)
        if not args.above then return end
     
     	addTableRow(tbl)
    		.tag('td')
    			.addClass('navbox-abovebelow')
    			.addClass(args.aboveclass)
    			.cssText(args.basestyle)
    			.cssText(args.abovestyle)
     			.attr('colspan', getAboveBelowColspan())
     			.tag('div')
     				.newline()
     				.wikitext(args.above)
    end
    
    function renderBelowRow(tbl)
    	if not args.below then return end
    	
    	addTableRow(tbl)
    		.tag('td')
    			.addClass('navbox-abovebelow')
    			.addClass(args.belowclass)
    			.cssText(args.basestyle)
    			.cssText(args.belowstyle)
    			.attr('colspan', getAboveBelowColspan())
    			.tag('div')
    				.newline()
    				.wikitext(args.below)
    end
    
    function getAboveBelowColspan()
        local ret = 2
        if args.imageleft then ret = ret + 1 end
        if args.image then ret = ret + 1 end
        return ret
    end
     
     
    --
    --   List rows
    --
    function renderFirstListRow(tbl)
        if not args.list1 then return end
     
     	local row = addTableRow(tbl)
     	
        if args.imageleft then
        	row
        		.tag('td')
        			.addClass('navbox-image')
        			.addClass(args.imageclass)
        			.css('width', '0%')
        			.css('padding', '0px 2px 0px 0px')
        			.cssText(args.imageleftstyle)
        			.attr('rowspan', 2 * #listnums - 1)
        			.tag('div')
        				.newline()
        				.wikitext(args.imageleft)
        end
     
        if args.group1 then
        	local groupCell = row.tag('th')
        	
        	groupCell
       			.attr('scope', 'row')
       			.addClass('navbox-group')
       			.addClass(args.groupclass)
       			.cssText(args.basestyle)
       			
       		if args.groupwidth then
       			groupCell.css('width', args.groupwidth)
       		end
    
    		groupCell
    			.cssText(args.groupstyle)
    			.cssText(args.group1style)
    			.wikitext(args.group1)
        end
        
        local listCell = row.tag('td')
        
        if args.group1 then
        	listCell
        		.css('text-align', 'left')
        		.css('border-left-width', '2px')
        		.css('border-left-style', 'solid')
        else
        	listCell.attr('colspan', 2)
        end
        
        if not args.groupwidth then 
        	listCell.css('width', '100%')
        end
    
        local evenOdd = args.evenodd or 'odd'
        if args.evenodd == 'swap' then evenOdd = 'even' end
        
        listCell
        	.css('padding', '0px')
        	.cssText(args.liststyle)
        	.cssText(args.oddstyle)
        	.cssText(args.list1style)
        	.addClass('navbox-list')
        	.addClass('navbox-' .. evenOdd)
        	.addClass(args.listclass)
        	.tag('div')
        		.css('padding', args.list1padding or args.listpadding or '0em 0.25em')
        		.newline()
        		.wikitext(args.list1)
    
        if args.image then
        	row
        		.tag('td')
        			.addClass('navbox-image')
        			.addClass(args.imageclass)
        			.css('width', '0%')
        			.css('padding', '0px 0px 0px 2px')
        			.cssText(args.imagestyle)
        			.attr('rowspan', 2 * #listnums - 1)
        			.tag('div')
        				.newline()
        				.wikitext(args.image)
        end
    end
     
    function renderNthListRow(tbl, listnum)
    	local row = addTableRow(tbl)
    	
        if args['group' .. listnum] then
        	local groupCell = row.tag('th')
        	
        	groupCell
       			.attr('scope', 'row')
       			.addClass('navbox-group')
       			.addClass(args.groupclass)
       			.cssText(args.basestyle)
       			
       		if args.groupwidth then
       			groupCell.css('width', args.groupwidth)
       		end
       		
       		groupCell
       			.cssText(args.groupstyle)
       			.cssText(args['group' .. listnum .. 'style'])
       			.wikitext(args['group' .. listnum])
        end
        
        local listCell = row.tag('td')
    
        if args['group' .. listnum] then
        	listCell
        		.css('text-align', 'left')
        		.css('border-left-width', '2px')
        		.css('border-left-style', 'solid')
        else
        	listCell.attr('colspan', 2)
        end
        
        if not args.groupwidth then 
        	listCell.css('width', '100%')
        end
        
        local isOdd = (listnum % 2) == 1
        local rowstyle = args.evenstyle
        if isOdd then rowstyle = args.oddstyle end
     
     	local evenOdd
     	if args.evenodd == 'swap' then
     		if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
     	else
    		if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
    	end
    	
        listCell
        	.css('padding', '0px')
        	.cssText(args.liststyle)
        	.cssText(rowstyle)
        	.cssText(args['list' .. listnum .. 'style'])
        	.addClass('navbox-list')
        	.addClass('navbox-' .. evenOdd)
        	.addClass(args.listclass)
        	.tag('div')
        		.css('padding', args.listpadding or '0em 0.25em')
        		.newline()
        		.wikitext(args['list' .. listnum])
    end
    
    
    --
    --   Main navbox tables
    --
    function renderMainTable()
     	local tbl = HtmlBuilder.create('table')
     		.attr('cellspacing', 0)
     		.addClass('nowraplinks')
     		.addClass(args.bodyclass)
     			
        if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
        	tbl
        		.addClass('collapsible')
        		.addClass(args.state or 'autocollapse')
        end
     
     	tbl.css('border-spacing', 0)
        if border == 'subgroup' or border == 'child' or border == 'none' then
        	tbl
        		.addClass('navbox-subgroup')
        		.cssText(args.bodyStyle)
        		.cssText(args.style)
        else -- regular navobx - bodyStyle and style will be applied to the wrapper table
        	tbl
        		.addClass('navbox-inner')
        		.css('background', 'transparent')
        		.css('color', 'inherit')
        end
        tbl.cssText(args.innerstyle)
     
        renderTitleRow(tbl)
        renderAboveRow(tbl)
        renderFirstListRow(tbl)
     
        -- render lists 2 through N
        for i, listnum in ipairs(listnums) do
            if listnum > 1 then
                renderNthListRow(tbl, listnum) 
            end
        end
     
        renderBelowRow(tbl)
        
        return tbl
    end
    
    function p._navbox(navboxArgs)
    	args = navboxArgs
    	
        for k, v in pairs(args) do
            local listnum = ('' .. k):match('^list(%d+)$')
            if listnum then table.insert(listnums, tonumber(listnum)) end
        end
        table.sort(listnums)
     
        border = trim(args.border or args[1] or '')
    
    	-- render the main body of the navbox
     	local tbl = renderMainTable()
    
    	-- render the appropriate wrapper around the navbox, depending on the border param
    	local res = HtmlBuilder.create()
        if border == 'subgroup' or border == 'child' then
            res
           		.tag('/div', {unclosed = true})
           		.done()
           		.node(tbl)
           		.tag('div', {unclosed = true})
        elseif border ~= 'none' then
        	res
        		.tag('table')
       				.attr('cellspacing', 0)
        			.addClass('navbox')
        			.css('border-spacing', 0)
        			.cssText(args.bodystyle)
        			.cssText(args.style)
        			.tag('tr')
        				.tag('td')
        					.css('padding', '2px')
        					.node(tbl)
        end
     
        -- TODO: add tracking categories
     
        return tostring(res)
    end
     
    function p.navbox(frame)
        return p._navbox(frame:getParent().args)
    end
     
    return p