Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

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

local p = {}

local function is_rtl(lang)
	lang = lang or mw.getCurrentFrame():preprocess('{{int:lang}}')
	return require('Module:Is rtl')[lang] == true
end

function get_portalicon(portalicon)
	if portalicon == nil then
		return ''
	else
		return '<span class="portal-navigation-portalicon">' .. portalicon .. '</span>'
	end
end

function converttolinearrgb(c)
	c = tonumber(c, 16)
	c = c / 255.0
	if c <= 0.03928 then
		c = c/12.92
	else
		c = ((c+0.055)/1.055) ^ 2.4
	end
	
	return c
end

function p.render(frame)
	-- Default values
	portalname = 'Portal'
	tabs = {}
	subtabs = {}
	wrc = 0

	-- Default values (customizations)
	themecolor = '#54595d'
	headerstyle = ''
	tabsicons = {}
	ff = nil
	lang = nil
	wrcadditional = nil
	
	-- Populating variables
	for key, value in pairs(frame:getParent().args) do
		if key == 'portalname' then
			portalname = value
		elseif key == 'portalicon' then
			portalicon = value
		elseif key == 'active' then
			active = tonumber(value)
		elseif key == 'wrc' then
			wrc = value
		elseif key == 'themecolor' then
			themecolor = value
		elseif key == 'headerstyle' then
			headerstyle = value
		elseif key == 'forceflip' then
			ff = value
		elseif key == 'lang' then
			lang = value
		elseif key == 'hidenav' then
			hidenav = value
		elseif key == 'hidesubnav' then
			hidesubnav = value
		elseif key == 'wrcadditional' then
			wrcadditional = value
		elseif string.find(key, 'tab') ~= nil
		and string.find(key, 'subtab') == nil then  -- matches tab1, tab2, ...
    		id = string.gsub(key, 'tab', '')
    		id = tonumber(id)
    		tabs[id] = value
    	elseif string.find(key, 'icon') ~= nil then -- matches icon1, icon2, etc.
    		id = string.gsub(key, 'icon', '')
    		id = tonumber(id)
    		tabsicons[id] = value
    	elseif string.find(key, 'subtab') ~= nil then -- matches subtab1-1, etc.
    		id = string.gsub(key, 'subtab', '')
    		-- Subtab params take the form [prime tab]-[sub tab]
    		id = mw.text.split(id, '-')
    		primetab = tonumber(id[1])
    		subtab = tonumber(id[2])
    		if subtabs[primetab] == nil then
    			subtabs[primetab] = {}
    		end
    		subtabs[primetab][subtab] = value
    	end
	end
	
	if ff == 'yes' or ff == 'true' or ff == '1' then
		ff = true
	end
	
	if hidenav == 'yes' or hidenav == 'true' or hidenav == '1' then
		hidenav = true
	end
	
	if hidesubnav == 'yes' or hidesubnav == 'true' or hidesubnav == '1' then
		hidesubnav = true
	end

	-- Constructing header
	-- Relevant variables: portalname, wrc, themecolor, headerstyle
	
	-- The text color in the header is automatically chosen based on the best contrast
	-- https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
	headertextcolor = '#fff'
	
	rgb = string.gsub(themecolor, '#', '')
	rgb = mw.text.split(rgb, '')
	if #rgb == 6 then
		r = rgb[1] .. rgb[2]
		g = rgb[3] .. rgb[4]
		b = rgb[5] .. rgb[6]
	elseif #rgb == 3 then
		r = rgb[1] .. rgb[1]
		g = rgb[2] .. rgb[2]
		b = rgb[3] .. rgb[3]
	end
	r = converttolinearrgb(r)
	g = converttolinearrgb(g)
	b = converttolinearrgb(b)
	
	luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
	
	if luminance > 0.179 then
		headertextcolor = '#000'
	end

	-- Applying customizations to headerstyle
	headerstyle = 'background:' .. themecolor .. '; color:' .. headertextcolor .. ';'
		.. headerstyle
	
	header = '<div class="portal-navigation-header" style="' .. headerstyle .. '">'

	if ff ~= true or (ff == true and not is_rtl()) then
		header = header .. get_portalicon(portalicon) .. portalname .. '</div>'
	else
		header = header .. portalname .. get_portalicon(portalicon) .. '</div>'
	end

	if wrc == '1' or wrc == 1 or wrc == 'true' or wrc == true or wrc == 'yes' then
		badgeargs = {}
		if ff == true then
			badgeargs['forceflip'] = ff
		end
		if wrcadditional ~= nil then
			badgeargs['additional'] = wrcadditional
		end

		header = frame:expandTemplate{
			title = 'Wikimedia Resource Center badge',
			args = badgeargs }
			.. '\n\n' .. header
	end
	
	-- Constructing the rest
	-- Relevant variables: themecolor tabs tabsicons active subtabs

	body = ''

	if hidenav ~= true then
		body = body .. '<ul class="portal-navigation-body">'

		for index, pagelink in ipairs(tabs) do
			-- Open TOC entry container
			body = body .. '<li>'
			
			-- Create the tab itself
			local entryclass = 'portal-navigation-entry'
			local entrystyle = ''
			if index == active then
				if subtabs[index] == nil or hidesubnav == true then
					entrystyle = ' style="border-bottom-color:' .. themecolor .. ';"'
				else
					entryclass = entryclass .. ' portal-navigation-entry-has-subtabs'
				end
			end
			
			icon = ''
			if tabsicons[index] ~= nil then
				icon = '<span class="portal-navigation-tabicon">' .. tabsicons[index] .. '</span>'
			end
			
			body = body
				.. '<span class="' .. entryclass .. '"' .. entrystyle .. '>'
				.. icon .. pagelink
				.. '</span>'
			
			-- If the tab is active, show the subnav if there is any
			
			if index == active and subtabs[index] ~= nil and hidesubnav ~= true then
				body = body .. '<ul class="portal-navigation-subtabs" style="border-color:' .. activecolor or themecolor .. ';">'
				
				for _, subpagelink in ipairs(subtabs[index]) do
					body = body .. '<li>' .. subpagelink .. '</li>'
				end
				
				body = body .. '</ul>'
			end
			
			-- Close TOC entry container
			body = body .. '</li>'
		end
	
		body = body .. '</ul>'
	end

	local templatestyles = frame:extensionTag('templatestyles', '', {src = 'Module:Portal navigation/styles.css'})

	local classes = 'portal-navigation'
	local attributes = ''
	if lang then
		attributes = ' lang="' .. lang .. '" dir="' .. (is_rtl(lang) and 'rtl' or 'ltr') .. '"'
	end
	if ff == true then
		classes = classes .. ' portal-navigation-force-' .. (is_rtl() and 'rtl' or 'ltr')
	end

	return '<div class="' .. classes .. '"' .. attributes .. '>' .. templatestyles .. header .. body .. '</div>'
end

return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.