香港巴士大典

了解更多

香港巴士大典
(temp test)
標籤原始碼編輯
無編輯摘要
 
(未顯示由 2 位使用者於中間所作的 3 次修訂)
第1行: 第1行:
  +
--------------------------------------------------------------------
  +
--<pre> Navbox Module
 
--
 
--
  +
-- * Fully CSS styled (inline styles possible but not default)
-- This module will implement {{Navbox}}
 
  +
-- * Supports unlimited rows
 
--
 
--
  +
-- By User:Tjcool007 from layton.fandom.com
  +
--------------------------------------------------------------------
 
 
 
local p = {}
 
local p = {}
 
 
  +
local args = {} -- Arguments passed to template
local navbar = require('Module:Navbar')._navbar
 
local getArgs -- lazily initialized
+
local navbox -- Actual navbox
  +
local args
 
local tableRowAdded = false
+
--local working = {}
  +
local rownums, skiprows = {}, {}
local border
 
  +
local hasrows, alt, hasData, isChild = false, false, false, false
local listnums = {}
 
  +
local activeSection, sections, cimage, cimageleft
local function trim(s)
 
  +
local colspan, rowspan
return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
 
  +
  +
local showText, hideText = '展開', '摺疊'
  +
  +
local langCode = mw.getContentLanguage():getCode()
  +
local localization = {} --localized strings table
  +
localization['en'] = {show = 'Show', hide = 'Hide'}
  +
localization['ru'] = {show = 'показать', hide = 'скрыть'}
  +
localization['zh'] = {show = '展開', hide = '摺疊'}
  +
if localization[langCode] then
  +
showText = localization[langCode]['show']
  +
hideText = localization[langCode]['hide']
 
end
 
end
  +
local function addNewline(s)
 
  +
------------------------------------------------
if s:match('^[*:;#]') or s:match('^{|') then
 
  +
-- Title
return '\n' .. s ..'\n'
 
  +
------------------------------------------------
else
 
  +
return s
 
  +
--- Processes the VDE links in the title
end
 
  +
--
  +
-- @param titlecell The table cell of the title
  +
local function processVde( titlecell )
  +
if not args.template then return end
  +
  +
titlecell:wikitext('<span class="navbox-vde">'
  +
.. mw.getCurrentFrame():expandTemplate({
  +
title = 'vdelinks',
  +
args = { args.template, ['type'] = 'navbox' }
  +
}) .. '</span>')
 
end
 
end
  +
local function addTableRow(tbl)
 
  +
--- Processes the main title row
-- If any other rows have already been added, then we add a 2px gutter row.
 
  +
local function processTitle()
if tableRowAdded then
 
  +
local titlerow = mw.html.create('tr'):addClass('navbox-title')
tbl
 
  +
local titlecell = mw.html.create('th'):attr('colspan',colspan):attr('scope','col')
:tag('tr')
 
  +
:css('height', '2px')
 
  +
if not pcall( processVde, titlecell ) then
:tag('td')
 
  +
titlecell:wikitext( '<b class="navbox-vde error" title="Missing Template:Vdelinks">!!!</b>' )
:attr('colspan', 3)
 
end
+
end
  +
 
  +
titlecell:wikitext( args.title or '{{{title}}}' )
tableRowAdded = true
 
  +
 
  +
-- Padding
return tbl:tag('tr')
 
  +
local hasTemplate = args.template ~= nil
  +
local hasState = not args.state or args.state ~= 'plain'
  +
  +
if hasTemplate ~= hasState then
  +
if hasTemplate then
  +
titlecell:addClass('navbox-title-padright')
  +
else
  +
titlecell:addClass('navbox-title-padleft')
  +
end
  +
end
  +
  +
if args.titleclass then titlerow:addClass( args.titleclass ) end
  +
if args.titlestyle then titlecell:cssText( args.titlestyle ) end
  +
  +
titlerow:node(titlecell)
  +
navbox:node(titlerow)
 
end
 
end
  +
local function renderNavBar(titleCell)
 
  +
local function _addGutter( parent, incRowspan )
-- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
 
  +
parent:tag('tr'):addClass('navbox-gutter'):tag('td'):attr('colspan',2)
-- or right to keep the title centered.
 
  +
local spacerSide = nil
 
if args.navbar == 'off' then
+
if incRowspan then
  +
rowspan = rowspan + 1
-- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
 
  +
end
-- also no show/hide link, then we need a spacer on the right to achieve the left shift.
 
if args.state == 'plain' then spacerSide = 'right' end
 
elseif args.navbar == 'plain' or (not args.name and mw.getCurrentFrame():getParent():getTitle() == 'Template:Navbox/temp' and (border == 'subgroup' or border == 'child' or border == 'none')) then
 
-- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
 
if args.state ~= 'plain' then spacerSide = 'left' end
 
else
 
-- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
 
-- to balance out the width of the navbar.
 
if args.state == 'plain' then spacerSide = 'right' end
 
titleCell:wikitext(navbar{
 
args.name,
 
mini = 1,
 
fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;'
 
})
 
end
 
 
-- Render the spacer div.
 
if spacerSide then
 
titleCell
 
:tag('span')
 
:css('float', spacerSide)
 
:css('width', '8em')
 
:css('font-size', '80%')
 
:css('margin-' .. (spacerSide == 'left' and 'right' or 'left'), '0.5em')
 
:wikitext('&nbsp;')
 
end
 
 
end
 
end
  +
  +
------------------------------------------------
  +
-- Above/Below
  +
------------------------------------------------
  +
  +
--- Processes the above and below rows
 
--
 
--
  +
-- @param rowtype Either 'above' or 'below'
-- Title row
 
  +
local function processAboveBelow( rowtype )
--
 
  +
if not args[rowtype] then return end
local function renderTitleRow(tbl)
 
  +
if not args.title then return end
 
  +
local abrow = mw.html.create('tr'):addClass('navbox-'..rowtype)
  +
local abcell = mw.html.create('td'):attr('colspan',colspan):wikitext( args[rowtype] )
 
 
  +
if args[rowtype .. 'class'] then abrow:addClass( args[rowtype .. 'class'] ) end
local titleRow = addTableRow(tbl)
 
  +
if args[rowtype .. 'style'] then abcell:cssText( args[rowtype .. 'style'] ) end
 
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')
 
:addClass(args.titleclass)
 
:attr('colspan', titleColspan)
 
 
 
  +
abrow:node( abcell )
renderNavBar(titleCell)
 
  +
_addGutter( navbox )
titleCell
 
  +
navbox:node( abrow )
:tag('div')
 
:css('font-size', '110%')
 
:wikitext(addNewline(args.title))
 
 
end
 
end
  +
--
 
  +
------------------------------------------------
-- Above/Below rows
 
  +
-- Main Rows
--
 
  +
------------------------------------------------
local function getAboveBelowColspan()
 
  +
local ret = 2
 
  +
--- Processes the images
if args.imageleft then ret = ret + 1 end
 
  +
local function _processImage(row, imgtype)
if args.image then ret = ret + 1 end
 
return ret
+
if not args[imgtype] then return end
  +
  +
local iclass = imgtype == 'image' and 'navbox-image-right' or 'navbox-image-left'
  +
  +
local imagecell = mw.html.create('td'):addClass('navbox-image'):addClass(iclass)
  +
  +
local image = args[imgtype]
  +
if image:sub(1,1) ~= '[' then
  +
local width = args[imgtype .. 'width'] or '100px'
  +
imagecell:css('width',width):wikitext('['..'[' .. image .. '|' .. width .. '|link=' .. (args[imgtype .. 'link'] or '') .. ']]')
  +
else
  +
imagecell:css('width','0%'):wikitext(image)
  +
end
  +
  +
if args[imgtype .. 'class'] then imagecell:addClass( args[imgtype .. 'class'] ) end
  +
if args[imgtype .. 'style'] then imagecell:cssText( args[imgtype .. 'style'] ) end
  +
  +
row:node( imagecell )
  +
if imgtype == 'image' then
  +
cimage = imagecell
  +
else
  +
cimageleft = imagecell
  +
end
 
end
 
end
  +
local function renderAboveRow(tbl)
 
  +
--- Closes the currently active section (if any)
if not args.above then return end
 
  +
local function _closeCurrentSection()
addTableRow(tbl)
 
  +
if not activeSection then return end
:tag('td')
 
  +
:addClass('navbox-abovebelow')
 
:addClass(args.aboveclass)
+
local row = mw.html.create('tr'):addClass('navbox-section-row')
  +
local cell = mw.html.create('td'):attr('colspan',2)
:cssText(args.basestyle)
 
  +
:cssText(args.abovestyle)
 
  +
if not hasrows then
:attr('colspan', getAboveBelowColspan())
 
  +
_processImage(row,'imageleft')
:tag('div')
 
  +
end
:wikitext(addNewline(args.above))
 
  +
  +
cell:node(sections[activeSection])
  +
row:node(cell)
  +
  +
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
  +
  +
activeSection = false
  +
hasData = false
 
end
 
end
  +
local function renderBelowRow(tbl)
 
  +
--- Handles alternating rows
if not args.below then return end
 
  +
--
addTableRow(tbl)
 
  +
-- @return Alternatingly returns true or false. Always returns false if alternating rows
:tag('td')
 
:addClass('navbox-abovebelow')
+
-- are disabled with "alternaterows = no"
  +
local function _alternateRow()
:addClass(args.belowclass)
 
  +
if args.alternaterows == 'no' then return false end
:cssText(args.basestyle)
 
  +
if alt then
:cssText(args.belowstyle)
 
  +
alt = false
:attr('colspan', getAboveBelowColspan())
 
  +
return true
:tag('div')
 
  +
else
:wikitext(addNewline(args.below))
 
  +
alt = true
  +
return false
  +
end
 
end
 
end
 
 
  +
--- Process a single Header "row"
 
--
 
--
  +
-- @param num Number of the row to be processed
-- List rows
 
  +
local function processHeader(num)
--
 
  +
if not args['header'..num] then return end
local function renderListRow(tbl, listnum)
 
local row = addTableRow(tbl)
 
 
if listnum == 1 and 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')
 
:wikitext(addNewline(args.imageleft))
 
end
 
 
 
  +
_closeCurrentSection()
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 subtable = mw.html.create('table'):addClass('navbox-section')
local evenOdd
 
  +
local headerrow = mw.html.create('tr')
if args.evenodd == 'swap' then
 
  +
local header = mw.html.create('th'):addClass('navbox-header'):attr('colspan',2):attr('scope','col'):wikitext( args['header'..num] )
if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
 
  +
else
 
  +
local collapseme = args['state'..num] or false
if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
 
  +
local state = false
end
 
  +
listCell
 
  +
if collapseme then
:css('padding', '0px')
 
  +
-- Look at this one
:cssText(args.liststyle)
 
  +
if collapseme ~= 'plain' then
:cssText(rowstyle)
 
  +
state = collapseme == 'expanded' and 'expanded' or 'collapsed'
:cssText(args['list' .. listnum .. 'style'])
 
  +
end
:addClass('navbox-list')
 
  +
else
:addClass('navbox-' .. evenOdd)
 
  +
-- Look at default
:addClass(args.listclass)
 
  +
local collapseall = args.defaultstate or false
:tag('div')
 
  +
if collapseall then
:css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
 
  +
state = collapseall == 'expanded' and 'expanded' or 'collapsed'
:wikitext(addNewline(args['list' .. listnum]))
 
  +
end
if listnum == 1 and args.image then
 
  +
end
row
 
  +
:tag('td')
 
  +
if state then
:addClass('navbox-image')
 
  +
subtable:addClass('mw-collapsible'):attr('data-expandtext',args['expandtext'..num] or args['defaultexpandtext'] or showText):attr('data-collapsetext',args['collapsetext'..num] or args['defaultcollapsetext'] or hideText)
:addClass(args.imageclass)
 
  +
if state == 'collapsed' then
:css('width', '0%')
 
  +
subtable:addClass('mw-collapsed')
:css('padding', '0px 0px 0px 2px')
 
  +
end
:cssText(args.imagestyle)
 
  +
header:addClass('navbox-header-collapsible')
:attr('rowspan', 2 * #listnums - 1)
 
  +
end
:tag('div')
 
  +
:wikitext(addNewline(args.image))
 
  +
if args.headerclass then headerrow:addClass( args.headerclass ) end
end
 
  +
if args.headerstyle then header:cssText( args.headerstyle ) end
  +
  +
headerrow:node(header)
  +
subtable:node(headerrow)
  +
  +
sections[num] = subtable
  +
activeSection = num
 
end
 
end
  +
  +
--- Processes a single list row
 
--
 
--
  +
-- @param num Number of the row to be processed
-- Tracking categories
 
  +
local function processList(num)
--
 
  +
if not args['list'..num] then return end
local function needsHorizontalLists()
 
  +
if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end
 
  +
local row = mw.html.create('tr'):addClass('navbox-row')
 
  +
local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'}
 
  +
if not hasrows and not activeSection then
for i, cls in ipairs(listClasses) do
 
  +
_processImage(row, 'imageleft')
if args.listclass == cls or args.bodyclass == cls then
 
  +
end
return false
 
  +
end
 
  +
local listcell = mw.html.create('td'):addClass('navbox-list')
end
 
  +
local hlistcell = listcell:tag('div'):addClass('hlist')
return true
 
  +
  +
local data = args['list'..num]
  +
  +
if data:sub(1,1) == '*' then
  +
-- Add newlines to support lists properly
  +
hlistcell
  +
:newline()
  +
:wikitext( data )
  +
:newline()
  +
else
  +
hlistcell:wikitext( data )
  +
end
  +
  +
local altRow = _alternateRow()
  +
if altRow then
  +
row:addClass( args.altrowclass or 'alt' )
  +
  +
local listclass = args.altlistclass or args.listclass or false
  +
if listclass then listcell:addClass( listclass ) end
  +
  +
local liststyle = args.altliststyle or args.liststyle or false
  +
if liststyle then listcell:cssText( liststyle ) end
  +
else
  +
if args.rowclass then row:addClass( args.rowclass ) end
  +
if args.listclass then listcell:addClass( args.listclass ) end
  +
if args.liststyle then listcell:cssText( args.liststyle ) end
  +
end
  +
  +
if args['group'..num] then
  +
local groupcell = mw.html.create('th'):addClass('navbox-group'):attr('scope','row'):wikitext( args['group'..num] )
  +
  +
if altRow then
  +
local groupclass = args.altgroupclass or args.groupclass or false
  +
if groupclass then groupcell:addClass( groupclass ) end
  +
  +
local groupstyle = args.altgroupstyle or args.groupstyle or false
  +
if groupstyle then groupcell:cssText( groupstyle ) end
  +
else
  +
if args.groupclass then groupcell:addClass( args.groupclass ) end
  +
if args.groupstyle then groupcell:cssText( args.groupstyle ) end
  +
end
  +
  +
row:node( groupcell )
  +
else
  +
listcell:attr('colspan',2):addClass('no-group')
  +
end
  +
  +
row:node( listcell )
  +
  +
local firstRow = false
  +
if not hasrows and not activeSection then
  +
firstRow = true
  +
hasrows = true
  +
_processImage(row, 'image')
  +
end
  +
  +
if activeSection then
  +
local parent = sections[activeSection]
  +
if not isChild or not firstRow then
  +
_addGutter(parent)
  +
end
  +
parent:node(row)
  +
hasData = true
  +
else
  +
if not isChild or not firstRow then
  +
_addGutter(navbox,not firstRow)
  +
end
  +
navbox:node( row )
  +
rowspan = rowspan + 1
  +
end
 
end
 
end
  +
local function hasBackgroundColors()
 
  +
--- Processes all rows
return mw.ustring.match(args.titlestyle or '','background') or mw.ustring.match(args.groupstyle or '','background') or mw.ustring.match(args.basestyle or '','background')
 
  +
local function processRows()
end
 
  +
sections = {}
local function argNameAndRealTitleAreDifferent()
 
  +
for i=1,#rownums do
if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end
 
  +
local num = rownums[i]
if args.name ~= mw.title.getCurrentTitle().text then
 
  +
if not skiprows[num] then
return true
 
  +
processHeader(num)
end
 
  +
processList(num)
return false
 
end
+
end
  +
end
local function getTrackingCategories()
 
  +
_closeCurrentSection()
local cats = {}
 
  +
if needsHorizontalLists() then table.insert(cats, '沒有使用水平列表的導航框') end
 
  +
if cimageleft then
if hasBackgroundColors() then table.insert(cats, '使用背景顏色的導航框') end
 
  +
cimageleft:attr('rowspan',rowspan)
if argNameAndRealTitleAreDifferent() then table.insert(cats, 'name參數和實際不同的導航框') end
 
  +
end
return cats
 
  +
if cimage then
end
 
  +
cimage:attr('rowspan',rowspan)
local function renderTrackingCategories(builder)
 
  +
end
local title = mw.title.getCurrentTitle()
 
if title.namespace ~= 10 then return end -- not in template space
 
local subpage = title.subpageText
 
if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end
 
 
for i, cat in ipairs(getTrackingCategories()) do
 
builder:wikitext('[[Category:' .. cat .. ']]')
 
end
 
 
end
 
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.
-- Main navbox tables
 
  +
local function preProcessArgs(frame)
--
 
local function renderMainTable()
+
local tmp = {}
  +
local tbl = mw.html.create('table')
 
  +
if frame == mw.getCurrentFrame() then
:attr('cellspacing', 0)
 
  +
tmp = frame:getParent().args
:addClass('nowraplinks')
 
  +
else
:addClass(args.bodyclass)
 
  +
tmp = frame
 
  +
end
if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
 
  +
tbl
 
  +
-- Storage tables
:addClass('collapsible')
 
  +
local nums = {}
:addClass(args.state or 'autocollapse')
 
  +
end
 
  +
-- 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 == 'header' or 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
  +
rowspan = 0
  +
  +
if args.alternaterows == 'swap' then
  +
alt = true
  +
end
  +
  +
for k, v in pairs(nums) do
  +
rownums[#rownums+1] = tonumber(k)
  +
end
 
 
  +
table.sort(rownums)
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)
 
 
 
  +
-- Calculate skip rows
renderTitleRow(tbl)
 
  +
local cSection, cSkip
renderAboveRow(tbl)
 
  +
local showall = args.showall
for i, listnum in ipairs(listnums) do
 
  +
for i=1,#rownums do
renderListRow(tbl, listnum)
 
  +
local num = rownums[i]
end
 
  +
if args['header'..num] then
renderBelowRow(tbl)
 
  +
cSection = true
 
  +
cSkip = false
return tbl
 
  +
local showme = args['show'..num]
  +
if showme == 'no' then
  +
cSkip = true
  +
elseif showme == 'auto' or (showme ~= 'yes' and showall ~= 'yes') then
  +
if not args['list'..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
 
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 '')
 
  +
-- MAIN FUNCTIONS
-- render the main body of the navbox
 
  +
------------------------------------------------
local tbl = renderMainTable()
 
-- render the appropriate wrapper around the navbox, depending on the border param
 
local res = mw.html.create()
 
if border == 'none' then
 
res:node(tbl)
 
elseif border == 'subgroup' or border == 'child' 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>') -- mw.html 未支持 unclosed
 
:node(tbl)
 
:wikitext('<div>') -- mw.html 未支持 unclosed
 
else
 
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
 
 
 
  +
--- Processes the arguments to create the navbox.
renderTrackingCategories(res)
 
  +
--
  +
-- @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')
 
 
  +
if isChild then
return tostring(res)
 
  +
navbox = mw.html.create('table'):addClass('navbox-subgroup')
  +
else
  +
navbox = mw.html.create('table'):addClass('navbox')
  +
  +
if args.state ~= 'plain' then
  +
navbox:addClass('mw-collapsible'):attr('data-expandtext',args['expandtext'] or args['defaultexpandtext'] or showText):attr('data-collapsetext',args['collapsetext'] or args['defaultcollapsetext'] or hideText)
  +
if args.state == 'collapsed' then
  +
navbox:addClass('mw-collapsed')
  +
end
  +
end
  +
end
  +
  +
if args.bodyclass then navbox:addClass(args.bodyclass) end
  +
if args.bodystyle then navbox:cssText(args.bodystyle) end
  +
  +
-- Process...
  +
if not isChild then
  +
processTitle()
  +
processAboveBelow('above')
  +
processRows()
  +
processAboveBelow('below')
  +
  +
return tostring(navbox)
  +
else
  +
processRows()
  +
  +
local wrapper = mw.html.create('')
  +
wrapper:wikitext('</div>')
  +
wrapper:node(navbox)
  +
wrapper:wikitext('<div class="hlist">')
  +
return tostring(wrapper)
  +
end
 
end
 
end
 
 
  +
--- Main module entry point.
function p.navbox(frame)
 
  +
-- To be called with {{#invoke:navbox|main}} or directly from another module.
if not getArgs then
 
  +
--
getArgs = require('Module:Arguments').getArgs
 
  +
-- @param frame The frame passed to the module via the #invoke. If called from another
end
 
  +
-- module directly, this should be a table with the parameter definition.
args = getArgs(frame, {wrappers = 'Template:Navbox/temp'})
 
  +
function p.main(frame)
-- Read the arguments in the order they'll be output in, to make references number in the right order.
 
  +
-- Save the arguments in a local variable so other functions can use them.
local _
 
  +
preProcessArgs(frame)
_ = args.title
 
  +
_ = args.above
 
  +
return _navbox()
for i = 1, 35 do
 
_ = args["group" .. tostring(i)]
 
_ = args["list" .. tostring(i)]
 
end
 
_ = args.below
 
return p._navbox(args)
 
 
end
 
end
 
 

於 2021年2月13日 (六) 02:55 的最新修訂

此模組的說明文件可於模組:Navbox/doc建立

--------------------------------------------------------------------
--<pre> Navbox Module
--
-- * Fully CSS styled (inline styles possible but not default)
-- * Supports unlimited rows
--
-- By User:Tjcool007 from layton.fandom.com
--------------------------------------------------------------------
 
local p = {}
 
local args = {} -- Arguments passed to template
local navbox -- Actual navbox
 
--local working = {}
local rownums, skiprows = {}, {}
local hasrows, alt, hasData, isChild = false, false, false, false
local activeSection, sections, cimage, cimageleft
local colspan, rowspan
 
local showText, hideText = '展開', '摺疊'
 
local langCode = mw.getContentLanguage():getCode()
local localization = {} --localized strings table
localization['en'] = {show = 'Show', hide = 'Hide'}
localization['ru'] = {show = 'показать', hide = 'скрыть'}
localization['zh'] = {show = '展開', hide = '摺疊'}
if localization[langCode] then
    showText = localization[langCode]['show']
    hideText = localization[langCode]['hide']
end
 
------------------------------------------------
-- Title
------------------------------------------------
 
--- Processes the VDE links in the title
--
-- @param titlecell The table cell of the title
local function processVde( titlecell )
	if not args.template then return end
 
	titlecell:wikitext('<span class="navbox-vde">'
		.. mw.getCurrentFrame():expandTemplate({
			title = 'vdelinks',
			args = { args.template, ['type'] = 'navbox' }
		}) .. '</span>')
end
 
--- Processes the main title row
local function processTitle()
	local titlerow = mw.html.create('tr'):addClass('navbox-title')
	local titlecell = mw.html.create('th'):attr('colspan',colspan):attr('scope','col')
 
	if not pcall( processVde, titlecell ) then
		titlecell:wikitext( '<b class="navbox-vde error" title="Missing Template:Vdelinks">!!!</b>' )
	end
 
	titlecell:wikitext( args.title or '{{{title}}}' )
 
	-- Padding
	local hasTemplate = args.template ~= nil
	local hasState = not args.state or args.state ~= 'plain'
 
	if hasTemplate ~= hasState then
		if hasTemplate then
			titlecell:addClass('navbox-title-padright')
		else
			titlecell:addClass('navbox-title-padleft')
		end
	end
 
	if args.titleclass then titlerow:addClass( args.titleclass ) end
	if args.titlestyle then titlecell:cssText( args.titlestyle ) end
 
	titlerow:node(titlecell)
	navbox:node(titlerow)
end
 
local function _addGutter( parent, incRowspan )
	parent:tag('tr'):addClass('navbox-gutter'):tag('td'):attr('colspan',2)
 
	if incRowspan then
		rowspan = rowspan + 1
	end
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'):addClass('navbox-'..rowtype)
	local abcell = mw.html.create('td'):attr('colspan',colspan):wikitext( args[rowtype] )
 
	if args[rowtype .. 'class'] then abrow:addClass( args[rowtype .. 'class'] ) end
	if args[rowtype .. 'style'] then abcell:cssText( args[rowtype .. 'style'] ) end
 
	abrow:node( abcell )
	_addGutter( navbox )
	navbox:node( abrow )
end
 
------------------------------------------------
-- Main Rows
------------------------------------------------
 
--- Processes the images
local function _processImage(row, imgtype)
	if not args[imgtype] then return end
 
	local iclass = imgtype == 'image' and 'navbox-image-right' or 'navbox-image-left'
 
	local imagecell = mw.html.create('td'):addClass('navbox-image'):addClass(iclass)
 
	local image = args[imgtype]
	if image:sub(1,1) ~= '[' then
		local width = args[imgtype .. 'width'] or '100px'
		imagecell:css('width',width):wikitext('['..'[' .. image  .. '|' .. width .. '|link=' .. (args[imgtype .. 'link'] or '') .. ']]')
	else
		imagecell:css('width','0%'):wikitext(image)
	end
 
	if args[imgtype .. 'class'] then imagecell:addClass( args[imgtype .. 'class'] ) end
	if args[imgtype .. 'style'] then imagecell:cssText( args[imgtype .. 'style'] ) end
 
	row:node( imagecell )
	if imgtype == 'image' then
		cimage = imagecell
	else
		cimageleft = imagecell
	end
end
 
--- Closes the currently active section (if any)
local function _closeCurrentSection()
	if not activeSection then return end
 
	local row = mw.html.create('tr'):addClass('navbox-section-row')
	local cell = mw.html.create('td'):attr('colspan',2)
 
	if not hasrows then
		_processImage(row,'imageleft')	
	end
 
	cell:node(sections[activeSection])
	row:node(cell)
 
	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
 
	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
 
--- Process a single Header "row"
--
-- @param num Number of the row to be processed
local function processHeader(num)
	if not args['header'..num] then return end
 
	_closeCurrentSection()
 
	local subtable = mw.html.create('table'):addClass('navbox-section')
	local headerrow = mw.html.create('tr')
	local header = mw.html.create('th'):addClass('navbox-header'):attr('colspan',2):attr('scope','col'):wikitext( args['header'..num] )
 
	local collapseme = args['state'..num] or false
	local state = false
 
	if collapseme then
		-- Look at this one
		if collapseme ~= 'plain' then
			state = collapseme == 'expanded' and 'expanded' or 'collapsed'
		end
	else
		-- Look at default 
		local collapseall = args.defaultstate or false
		if collapseall then
			state = collapseall == 'expanded' and 'expanded' or 'collapsed'	
		end
	end
 
	if state then
		subtable:addClass('mw-collapsible'):attr('data-expandtext',args['expandtext'..num] or args['defaultexpandtext'] or showText):attr('data-collapsetext',args['collapsetext'..num] or args['defaultcollapsetext'] or hideText)
		if state == 'collapsed' then
			subtable:addClass('mw-collapsed')	
		end
		header:addClass('navbox-header-collapsible')
	end
 
	if args.headerclass then headerrow:addClass( args.headerclass ) end
	if args.headerstyle then header:cssText( args.headerstyle ) end
 
	headerrow:node(header)	
	subtable:node(headerrow)
 
	sections[num] = subtable
	activeSection = num
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'):addClass('navbox-row')
 
	if not hasrows and not activeSection then
		_processImage(row, 'imageleft')	
	end
 
	local listcell = mw.html.create('td'):addClass('navbox-list')
	local hlistcell = listcell:tag('div'):addClass('hlist')
 
	local data = args['list'..num]
 
	if data:sub(1,1) == '*' then
		-- Add newlines to support lists properly
		hlistcell
			:newline()
			:wikitext( data )
			:newline()
	else
		hlistcell:wikitext( data )
	end
 
	local altRow = _alternateRow()
	if altRow then
		row:addClass( args.altrowclass or 'alt' )
 
		local listclass = args.altlistclass or args.listclass or false
		if listclass then listcell:addClass( listclass ) end
 
		local liststyle = args.altliststyle or args.liststyle or false
		if liststyle then listcell:cssText( liststyle ) end
	else
		if args.rowclass then row:addClass( args.rowclass ) end
		if args.listclass then listcell:addClass( args.listclass ) end
		if args.liststyle then listcell:cssText( args.liststyle ) end
	end
 
	if args['group'..num] then
		local groupcell = mw.html.create('th'):addClass('navbox-group'):attr('scope','row'):wikitext( args['group'..num] )
 
		if altRow then
			local groupclass = args.altgroupclass or args.groupclass or false
			if groupclass then groupcell:addClass( groupclass ) end
 
			local groupstyle = args.altgroupstyle or args.groupstyle or false
			if groupstyle then groupcell:cssText( groupstyle ) end
		else	
			if args.groupclass then groupcell:addClass( args.groupclass ) end
			if args.groupstyle then groupcell:cssText( args.groupstyle ) end
		end
 
		row:node( groupcell )
	else
		listcell:attr('colspan',2):addClass('no-group')
	end
 
	row:node( listcell )
 
	local firstRow = false
	if not hasrows and not activeSection then
		firstRow = true
		hasrows = true
		_processImage(row, 'image')
	end
 
	if activeSection then
		local parent = sections[activeSection]
		if not isChild or not firstRow then
			_addGutter(parent)
		end
		parent:node(row)
		hasData = true
	else
		if not isChild or not firstRow then
			_addGutter(navbox,not firstRow)
		end
		navbox:node( row )
		rowspan = rowspan + 1
	end
end
 
--- Processes all rows
local function processRows()
	sections = {}
	for i=1,#rownums do
		local num = rownums[i]
		if not skiprows[num] then
			processHeader(num)
			processList(num)
		end
	end
	_closeCurrentSection()
 
	if cimageleft then
		cimageleft:attr('rowspan',rowspan)		
	end
	if cimage then
		cimage:attr('rowspan',rowspan)
	end
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 == 'header' or 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
	rowspan = 0
 
	if args.alternaterows == 'swap' then
		alt = true
	end
 
	for k, v in pairs(nums) do
		rownums[#rownums+1] = tonumber(k)
	end
 
	table.sort(rownums)
 
	-- 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['list'..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 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')
 
	if isChild then
		navbox = mw.html.create('table'):addClass('navbox-subgroup')
	else
		navbox = mw.html.create('table'):addClass('navbox')
 
		if args.state ~= 'plain' then
			navbox:addClass('mw-collapsible'):attr('data-expandtext',args['expandtext'] or args['defaultexpandtext'] or showText):attr('data-collapsetext',args['collapsetext'] or args['defaultcollapsetext'] or hideText)
			if args.state == 'collapsed' then
				navbox:addClass('mw-collapsed')
			end
		end
	end
 
 	if args.bodyclass then navbox:addClass(args.bodyclass) end
	if args.bodystyle then navbox:cssText(args.bodystyle) end
 
	-- Process...
	if not isChild then
		processTitle()
		processAboveBelow('above')
		processRows()
		processAboveBelow('below')
 
		return tostring(navbox)
	else
		processRows()
 
		local wrapper = mw.html.create('')
		wrapper:wikitext('</div>')
		wrapper:node(navbox)
		wrapper:wikitext('<div class="hlist">')
		return tostring(wrapper)
	end
end
 
--- Main module entry point.
-- To be called with {{#invoke:navbox|main}} 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 _navbox()
end
 
return p