Editing Module:Navbox

From PSP2i Wiki
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
-- <nowiki>
--
--
-- Implements {{navbox}}
-- This module implements {{Navbox}}
--
--


local p = {}
local p = {}
local tnavbar = require( 'Module:Tnavbar' )
 
local yesno = require( 'Module:Yesno' )
local navbar = require('Module:Navbar')._navbar
local page_title = mw.title.getCurrentTitle().fullText
local getArgs -- lazily initialized
--
 
-- Helper for inserting a new row into the navbox
local args
--
local border
-- @param tbl {mw.html table}
local listnums
-- @return tbl {mw.html table}
local ODD_EVEN_MARKER = '\127_ODDEVEN_\127'
--
local RESTART_MARKER = '\127_ODDEVEN0_\127'
local function insertRow( tbl )
local REGEX_MARKER = '\127_ODDEVEN(%d?)_\127'
return tbl:tag( 'tr' )
 
local function striped(wikitext)
-- Return wikitext with markers replaced for odd/even striping.
-- Child (subgroup) navboxes are flagged with a category that is removed
-- by parent navboxes. The result is that the category shows all pages
-- where a child navbox is not contained in a parent navbox.
local orphanCat = '[[Category:Navbox orphans]]'
if border == 'subgroup' and args.orphan ~= 'yes' then
-- No change; striping occurs in outermost navbox.
return wikitext .. orphanCat
end
local first, second = 'odd', 'even'
if args.evenodd then
if args.evenodd == 'swap' then
first, second = second, first
else
first = args.evenodd
second = first
end
end
local changer
if first == second then
changer = first
else
local index = 0
changer = function (code)
if code == '0' then
-- Current occurrence is for a group before a nested table.
-- Set it to first as a valid although pointless class.
-- The next occurrence will be the first row after a title
-- in a subgroup and will also be first.
index = 0
return first
end
index = index + 1
return index % 2 == 1 and first or second
end
end
local regex = orphanCat:gsub('([%[%]])', '%%%1')
return (wikitext:gsub(regex, ''):gsub(REGEX_MARKER, changer))  -- () omits gsub count
end
 
local function processItem(item, nowrapitems)
if item:sub(1, 2) == '{|' then
-- Applying nowrap to lines in a table does not make sense.
-- Add newlines to compensate for trim of x in |parm=x in a template.
return '\n' .. item ..'\n'
end
if nowrapitems == 'yes' then
local lines = {}
for line in (item .. '\n'):gmatch('([^\n]*)\n') do
local prefix, content = line:match('^([*:;#]+)%s*(.*)')
if prefix and not content:match('^<span class="nowrap">') then
line = prefix .. '<span class="nowrap">' .. content .. '</span>'
end
table.insert(lines, line)
end
item = table.concat(lines, '\n')
end
if item:match('^[*:;#]') then
return '\n' .. item ..'\n'
end
return item
end
 
local function renderNavBar(titleCell)
 
if args.navbar ~= 'off' and args.navbar ~= 'plain' and not (not args.name and mw.getCurrentFrame():getParent():getTitle():gsub('/sandbox$', '') == 'Template:Navbox') then
titleCell:wikitext(navbar{
args.name,
mini = 1,
fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;box-shadow:none;padding:0;'
})
end
 
end
end


--
--
-- Creates the navbox table
--   Title row
--
--
-- @param args {table}
local function renderTitleRow(tbl)
-- @return tbl {mw.html table}
if not args.title then return end
--
local function createTbl( args )


local tbl = mw.html.create( 'table' )
local titleRow = tbl:tag('tr')


tbl
if args.titlegroup then
:addClass( yesno(args.subgroup, false) and 'navbox-subgroup' or 'navbox' )
titleRow
:addClass( 'nowraplinks' )
:tag('th')
:attr('scope', 'row')
:addClass('navbox-group')
:addClass(args.titlegroupclass)
:cssText(args.basestyle)
:cssText(args.groupstyle)
:cssText(args.titlegroupstyle)
:wikitext(args.titlegroup)
end


if not yesno(args.subgroup, false) and
local titleCell = titleRow:tag('th'):attr('scope', 'col')
( args.state == 'collapsed' or
  args.state == 'uncollapsed' or
  args.state == 'autocollapse' or
  -- defaults to autocollapse
  args.state == nil )
then
tbl:addClass( 'mw-collapsible' )


if args.state == 'collapsed' then
if args.titlegroup then
tbl:addClass( 'mw-collapsed' )
titleCell
elseif args.state == 'uncollapsed' then
:css('border-left', '2px solid #fdfdfd')
tbl:addClass('navbox-uncollapsed')
:css('width', '100%')
end
end
end


if yesno(args.collapsible, false) then
local titleColspan = 2
tbl:addClass( 'navbox-collapsible' )
if args.imageleft then titleColspan = titleColspan + 1 end
end
if args.image then titleColspan = titleColspan + 1 end
if args.titlegroup then titleColspan = titleColspan - 1 end


if args.style then
titleCell
tbl:cssText( args.style )
:cssText(args.basestyle)
end
:cssText(args.titlestyle)
:addClass('navbox-title')
:attr('colspan', titleColspan)


-- manually set collapse/expand messages
renderNavBar(titleCell)
-- bug causing the default database messages to be used
tbl
:attr( {
['data-expandtext'] = 'show',
['data-collapsetext'] = 'hide',
['data-navbox-name'] = args.name
} )


return tbl
titleCell
:tag('div')
-- id for aria-labelledby attribute
:attr('id', mw.uri.anchorEncode(args.title))
:addClass(args.titleclass)
:css('font-size', '114%')
:css('margin', '0 4em')
:wikitext(processItem(args.title))
end
end


--
--
-- Wrapper for [[Module:Tnavbar]]
--   Above/Below rows
--
--
-- @param args {table}
 
-- @return {string}
local function getAboveBelowColspan()
--
local ret = 2
local function navbar( args )
if args.imageleft then ret = ret + 1 end
return tnavbar._collapsible( { [1] = args.title, [2] = args.name } )
if args.image then ret = ret + 1 end
return ret
end
 
local function renderAboveRow(tbl)
if not args.above then return end
 
tbl:tag('tr')
:tag('td')
:addClass('navbox-abovebelow')
:addClass(args.aboveclass)
:cssText(args.basestyle)
:cssText(args.abovestyle)
:attr('colspan', getAboveBelowColspan())
:tag('div')
-- id for aria-labelledby attribute, if no title
:attr('id', args.title and nil or mw.uri.anchorEncode(args.above))
:wikitext(processItem(args.above, args.nowrapitems))
end
end


--
local function renderBelowRow(tbl)
-- Creates the header (what you see when the navbox is collapsed)
if not args.below then return end
--
-- @param tbl {mw.html table}
-- @param args {table}
-- @return {mw.html table}
--
local function header( tbl, args )
    local paddingClass
    if args.name then
        if args.state == 'plain' then
            paddingClass = 'navbox-title-name-plain'
        else
            paddingClass = 'navbox-title-name-notplain'
        end
    else
        if args.state == 'plain' then
            paddingClass = 'navbox-title-noname-plain'
        else
            paddingClass = 'navbox-title-noname-notplain'
        end
    end
   
    local div = insertRow( tbl )
        :tag( 'th' )
            :attr( 'colspan', '2' )
            :addClass( 'navbox-title' )
            :attr( 'id' , 'navbox-title' )
                :tag( 'div' )
                    :addClass ( paddingClass  )
                    :wikitext( args.name and navbar( args ) or args.title )


    return div:allDone()
tbl:tag('tr')
:tag('td')
:addClass('navbox-abovebelow')
:addClass(args.belowclass)
:cssText(args.basestyle)
:cssText(args.belowstyle)
:attr('colspan', getAboveBelowColspan())
:tag('div')
:wikitext(processItem(args.below, args.nowrapitems))
end
end


--
--
-- Inserts a row into the navbox
--   List rows
--
-- @param tbl {mw.html table}
-- @param gtitle {string}
-- @param group {string}
-- @param gtype {string}
-- @param style {string}
-- @return {mw.html table}
--
--
local function row( tbl, gtitle, group, gtype, style, _name, subgroup )
local function renderListRow(tbl, index, listnum)
local tr = insertRow( tbl )
local row = tbl:tag('tr')
local td


if gtitle then
if index == 1 and args.imageleft then
td = tr
row
:addClass( 'navbox-group' )
:tag('td')
:tag( 'td' )
:addClass('noviewer')
:addClass( 'navbox-group-title' )
:addClass('navbox-image')
:wikitext( gtitle )
:addClass(args.imageclass)
:done()
:css('width', '1px')               -- Minimize width
:tag( 'td' )
:css('padding', '0px 2px 0px 0px')
else
:cssText(args.imageleftstyle)
td = tr
:attr('rowspan', #listnums)
:addClass( 'navbox-group' )
:tag('div')
:addClass( 'navbox-group-split' )
:wikitext(processItem(args.imageleft))
:tag( 'td' )
:addClass( 'navbox-group-title-hidden' )
:attr( 'colspan', '0' )
:css( 'display', 'none' )
:done()
:tag( 'td' )
:attr( 'colspan', '2' )
end
end


--[[
if args['group' .. listnum] then
  List styling
local groupCell = row:tag('th')
  This is unlikely to be implemented in the near future due to it requiring extra css to work
  and mobile currently not supporting that css.
  As an example, it lets you do the following instead if using {{*}} all the time
  | group3 =
  * {{plink|foo}}
  * {{plink|bar}}
  * {{plink|baz}}
]]
if mw.ustring.match( group, '^%s*%*' ) then
td:newline()


-- trim whitespace on bullets
-- id for aria-labelledby attribute, if lone group with no title or above
local spl = mw.text.split( group, '\n' )
if listnum == 1 and not (args.title or args.above or args.group2) then
groupCell
:attr('id', mw.uri.anchorEncode(args.group1))
end


for i = 1, #spl do
groupCell
spl[i] = mw.text.trim( spl[i] )
:attr('scope', 'row')
end
:addClass('navbox-group')
:addClass(args.groupclass)
:cssText(args.basestyle)
:css('width', args.groupwidth or '1%') -- If groupwidth not specified, minimize width


group = '\n' .. table.concat( spl, '\n' )
groupCell
:cssText(args.groupstyle)
:cssText(args['group' .. listnum .. 'style'])
:wikitext(args['group' .. listnum])
end
end


--local group2 = group
local listCell = row:tag('td')
--local group3 = group2
-- analytics


--if _name then
if args['group' .. listnum] then
-- local name = mw.ustring.gsub(_name,' ','_')
listCell
-- for v in mw.ustring.gmatch(group,'%[%[[^%]]+%]%]') do
:css('text-align', 'left')
-- if mw.ustring.match(v,'%[%[File:.+|link=') then
:css('border-left-width', '2px')
-- local link = mw.ustring.match(v,'|link=([^%]|]+)')
:css('border-left-style', 'solid')
-- if link then
else
-- local linkrep = mw.ustring.gsub(link,'([%%%]%[%-^$*()+?])','%%%1')
listCell:attr('colspan', 2)
-- local _link = mw.ustring.gsub(link,' ','_')
end
-- local newfile = mw.ustring.gsub(v,'|link='..linkrep,string.format('|link=https://oldschool.runescape.wiki/w/%s?f=%s',_link,name))
-- local w = mw.ustring.gsub(v,'([%%%]%[%-^$*()+?])','%%%1')
-- group2 = mw.ustring.gsub(group2,w,newfile)
-- end
-- elseif mw.ustring.match(v,'%[%[Category:') then
-- nothing
-- else
-- local link = mw.ustring.match(v,'%[%[([^%]|]+)')
-- local txt = mw.ustring.match(v,'%|([^%]|]+)') or link


-- local newlink = ''
if not args.groupwidth then
listCell:css('width', '100%')
end


-- black links if current page
local rowstyle  -- usually nil so cssText(rowstyle) usually adds nothing
-- if link == page_title then
if index % 2 == 1 then
-- newlink = string.format('<b>%s</b>',txt)
rowstyle = args.oddstyle
-- else
else
-- local _link = mw.ustring.gsub(link or '',' ','_')
rowstyle = args.evenstyle
-- newlink = string.format('[https://oldschool.runescape.wiki.com/w/%s?n=%s %s]',_link,name,txt)
end
-- end
-- local w = mw.ustring.gsub(v,'([%%%]%[%-^$*()+?])','%%%1')
-- group2 = mw.ustring.gsub(group2,w,newlink)
-- end
-- end
 
--[==[
fix [[these kind]]s of [[link]]s post analytics parse
]==]
-- group3 = group2
 
-- for v in mw.ustring.gmatch(group2,'%[https://oldschool.runescape.wiki.com/w[^%]]-%]%a') do
-- local rep = mw.ustring.gsub(v,'%]','')
-- rep = rep..']'
-- local w = mw.ustring.gsub(v,'([%%%]%[%-^$*()+?])','%%%1')
 
-- group3 = mw.ustring.gsub(group2,w,rep)
-- end
--end


td
local listText = args['list' .. listnum]
:addClass( 'navbox-list' )
local oddEven = ODD_EVEN_MARKER
:wikitext( group ) --group3
if listText:sub(1, 12) == '</div><table' then
 
-- Assume list text is for a subgroup navbox so no automatic striping for this row.
if gtype and mw.ustring.lower( gtype ) == 'subgroup' then
oddEven = listText:find('<th[^>]*"navbox%-title"') and RESTART_MARKER or 'odd'
td
:addClass( 'navbox-parent' )
:css( {
padding = '0'
} )
end
end
listCell
:css('padding', '0px')
:cssText(args.liststyle)
:cssText(rowstyle)
:cssText(args['list' .. listnum .. 'style'])
:addClass('navbox-list')
:addClass('navbox-' .. oddEven)
:addClass(args.listclass)
:addClass(args['list' .. listnum .. 'class'])
:tag('div')
:css('padding', (index == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
:wikitext(processItem(listText, args.nowrapitems))


if style then
if index == 1 and args.image then
td:cssText( style )
row
:tag('td')
:addClass('noviewer')
:addClass('navbox-image')
:addClass(args.imageclass)
:css('width', '1px')              -- Minimize width
:css('padding', '0px 0px 0px 2px')
:cssText(args.imagestyle)
:attr('rowspan', #listnums)
:tag('div')
:wikitext(processItem(args.image))
end
end
end


return td:allDone()
end


--
--
-- Inserts a footer into the navbox
--   Tracking categories
--
--
-- @param tbl {mw.html table}
-- @param args {table}
-- @return {mw.html table}
--
local function footer( tbl, args )
local th = insertRow( tbl )
:tag( 'th' )
:attr( 'colspan', '2' )
:addClass( 'navbox-footer' )


if args.fstyle then
local function needsHorizontalLists()
th:cssText( args.fstyle )
if border == 'subgroup' or args.tracking == 'no' then
return false
end
end
local listClasses = {
['plainlist'] = true, ['hlist'] = true, ['hlist hnum'] = true,
['hlist hwrap'] = true, ['hlist vcard'] = true, ['vcard hlist'] = true,
['hlist vevent'] = true,
}
return not (listClasses[args.listclass] or listClasses[args.bodyclass])
end


if mw.ustring.match( args.footer, '^%s*%*' ) then
local function hasBackgroundColors()
th:newline()
for _, key in ipairs({'titlestyle', 'groupstyle', 'basestyle', 'abovestyle', 'belowstyle'}) do
if tostring(args[key]):find('background', 1, true) then
return true
end
end
end


-- trim whitespace on bullets
local function hasBorders()
local spl = mw.text.split( args.footer, '\n' )
for _, key in ipairs({'groupstyle', 'basestyle', 'abovestyle', 'belowstyle'}) do
 
if tostring(args[key]):find('border', 1, true) then
for i = 1, #spl do
return true
spl[i] = mw.text.trim( spl[i] )
end
end
end
end


args.footer = table.concat( spl, '\n' )
local function isIllegible()
local styleratio = require('Module:Color contrast')._styleratio


th:addClass( 'navbox-list' )
for key, style in pairs(args) do
if tostring(key):match("style$") then
if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
return true
end
end
end
end
return false
end


th:wikitext( args.footer )
local function getTrackingCategories()
 
local cats = {}
return th:allDone()
if needsHorizontalLists() then table.insert(cats, 'Navigational boxes without horizontal lists') end
if hasBackgroundColors() then table.insert(cats, 'Navboxes using background colours') end
if isIllegible() then table.insert(cats, 'Potentially illegible navboxes') end
if hasBorders() then table.insert(cats, 'Navboxes using borders') end
return cats
end
end


--
local function renderTrackingCategories(builder)
-- Adds [[Category:Navbox templates]] to navbox template pages
--
-- @return {string}
--
local function categories()
local title = mw.title.getCurrentTitle()
local title = mw.title.getCurrentTitle()
local page = title.text
if title.namespace ~= 10 then return end -- not in template space
local ns = title.nsText
local subpage = title.subpageText
if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end


if ns == 'Template' then
for _, cat in ipairs(getTrackingCategories()) do
-- sort in category by pagename
builder:wikitext('[[Category:' .. cat .. ']]')
return '[[Category:Navbox templates| ' .. page .. ']]'
else
return ''
end
end
end
end


--
--
-- Adds [[Template:Navbox/doc]] to navbox template pages
--   Main navbox tables
--
--
-- @param args {table}
local function renderMainTable()
-- @return {string}
local tbl = mw.html.create('table')
--
:addClass('nowraplinks')
local function docs( args )
:addClass(args.bodyclass)
local frame = mw.getCurrentFrame()
 
local title = mw.title.getCurrentTitle()
if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
local base = title.baseText
if args.state == 'collapsed' then args.state = 'mw-collapsed' end
local ns = title.nsText
tbl
:addClass('mw-collapsible')
:addClass(args.state or 'autocollapse')
end
 
tbl:css('border-spacing', 0)
if border == 'subgroup' or border == 'none' then
tbl
:addClass('navbox-subgroup')
:cssText(args.bodystyle)
:cssText(args.style)
else  -- regular navbox - 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)


-- not if a subpage of [[Template:Navbox]]
renderTitleRow(tbl)
if base ~= 'Navbox' and
renderAboveRow(tbl)
-- in template ns
for i, listnum in ipairs(listnums) do
ns == 'Template' and
renderListRow(tbl, i, listnum)
-- not a navbox group within a navbox
not yesno(args.subgroup, false) and
-- not a collapsible navbox within a navbox
not yesno(args.collapsible, false) and
-- not if the doc argument is not set to "yes"
yesno(args.doc, false)
then
return frame:expandTemplate{ title = 'Navbox/doc' }
else
return ''
end
end
renderBelowRow(tbl)


return tbl
end
end


--
function p._navbox(navboxArgs)
-- Navbox method to allow it to be called by other modules
args = navboxArgs
--
listnums = {}
-- @param _args {table}
 
-- @return {string}
for k, _ in pairs(args) do
--
if type(k) == 'string' then
function p._navbox( _args )
local listnum = k:match('^list(%d+)$')
local args = {}
if listnum then table.insert(listnums, tonumber(listnum)) end
local wkCss = ''
local wkDiv = ''
local j
-- preserves parser function behaviour where an empty string is considered undefined
-- or nil in lua's case
for k, v in pairs( _args ) do
if v ~= '' then
args[k] = v
end
end
end
end
table.sort(listnums)


local tbl = createTbl( args )
border = mw.text.trim(args.border or args[1] or '')
 
if border == 'child' then
if not yesno(args.subgroup, false) then
border = 'subgroup'
tbl = header( tbl, args )
end
end


-- insert up to 25 rows
-- render the main body of the navbox
for i = 1, 25 do
local tbl = renderMainTable()
j = tostring( i )


if args['group' .. j] then
-- render the appropriate wrapper around the navbox, depending on the border param
tbl = row( tbl, args['gtitle' .. j], args['group' .. j], args['gtype' .. j], args['style' .. j], args.name, args.subgroup )
local res = mw.html.create()
if border == 'none' then
local nav = res:tag('div')
:attr('role', 'navigation')
:node(tbl)
-- aria-labelledby title, otherwise above, otherwise lone group
if args.title or args.above or (args.group1 and not args.group2) then
nav:attr('aria-labelledby', mw.uri.anchorEncode(args.title or args.above or args.group1))
else
nav:attr('aria-label', 'Navbox')
end
elseif border == 'subgroup' then
-- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
-- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the
-- padding being applied, and at the end add a <div> to balance out the parent's </div>
res
:wikitext('</div>')
:node(tbl)
:wikitext('<div>')
else
local nav = res:tag('div')
:attr('role', 'navigation')
:addClass('navbox')
:addClass(args.navboxclass)
:cssText(args.bodystyle)
:cssText(args.style)
:css('padding', '3px')
:node(tbl)
-- aria-labelledby title, otherwise above, otherwise lone group
if args.title or args.above or (args.group1 and not args.group2) then
nav:attr('aria-labelledby', mw.uri.anchorEncode(args.title or args.above or args.group1))
else
else
break
nav:attr('aria-label', 'Navbox')
end
end
end
end


if args.footer then
if (args.nocat or 'false'):lower() == 'false' then
tbl = footer( tbl, args )
renderTrackingCategories(res)
end
end
return striped(tostring(res))
end


tbl = tostring( tbl )
function p.navbox(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
args = getArgs(frame, {wrappers = {'Template:Navbox'}})


local cats = ''
-- Read the arguments in the order they'll be output in, to make references number in the right order.
if not yesno(args.subgroup, false) and not yesno(args.hidecat, false) then
local _
cats = categories()
_ = args.title
_ = args.above
for i = 1, 20 do
_ = args["group" .. tostring(i)]
_ = args["list" .. tostring(i)]
end
end
local docs = docs( args )
_ = args.below


return tbl .. cats .. docs
return p._navbox(args)
end
 
--
-- Main navbox method accessed through #invoke
--
-- @param frame {table}
-- @return {string}
--
function p.navbox( frame )
local args = frame:getParent().args
return p._navbox( args )
end
end


return p
return p
-- </nowiki>
Please note that all contributions to PSP2i Wiki are considered to be released under the CC BY-NC-SA 3.0 (see PSP2i:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)

Template used on this page: