跳转到内容

模組:NavboxV2

本页使用了标题或全文手工转换
被永久保护的模块
维基百科,自由的百科全书

这是本页的一个历史版本,由Cwek留言 | 贡献2017年3月7日 (二) 06:29 (init)编辑。这可能和当前版本存在着巨大的差异。

(差异) ←上一修订 | 最后版本 (差异) | 下一修订→ (差异)

--
-- This module will implement {{Navbox}}
--

local p = {}

local navbar = require('Module:Navbar')._navbar
local NavboxContext = require('模块:沙盒/Cwek/NavboxV2/Context')
local getArgs -- lazily initialized

local args

--Constant Define
local Limit={
      vertical=35
     ,horizontal={
         col=20
        ,list=6
      }
     ,vertical_collapsible=11
     ,child=10
}

local NavType={
     V="vertical" --垂直,list
    ,H="horizontal" --水平,col
    ,VC="vertical_collapsible" --折叠垂直
}

--Util Function
local function trim(s)
    return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
end

local function addNewline(s)
    if s:match('^[*:;#]') or s:match('^{|') then
        return '\n' .. s ..'\n'
    else
        return s
    end
end

---Functional Function
local getArg=function( _a , _b)
    local prefix= ( _b==nil and _a~=nil ) and _a or ""
    local key= _b==nil and _a or _b
    return args[ prefix .. (prefix=="" and "" or "-") ..key ]
end

local checkHaveChild=function(prefix,valuekey)
    if getArg(prefix..valuekey..'type') and getArg(prefix..valuekey..'border') then 
        return true
    end
    return false
end

---Element Render
function createNavTableHeader(context)
    local rootTable=
        mw.html.create('table')
            :attr('cellspacing', 0)
            :addClass('nowraplinks')
            :addClass(getArg(prefix,"bodyclass"))
            :css('border-spacing', 0)
            :cssText(getArg(prefix,"innerstyle"))

    local state=getArg(prefix,"state")
    if getArg(prefix,"title") and (state ~= 'plain' and state ~= 'off') then
        rootTable
            :addClass('collapsible')
            :addClass(state or 'autocollapse')
    end

    local border=getArg(prefix,"border")
    if border == 'subgroup' or border == 'child' or border == 'none' then
        rootTable
            :addClass('navbox-subgroup')
            :cssText(getArg(prefix,"bodystyle"))
            :cssText(getArg(prefix,"style"))
    else -- regular navobx - bodystyle and style will be applied to the wrapper table
        rootTable
            :addClass('navbox-inner')
            :css('background', 'transparent')
            :css('color', 'inherit')
    end
    
    return rootTable
end

function renderNavBar(titleCell,context)
    local prefix = context.prefix
    local  navbar = getArg(prefix,"navbar")
    local state  = getArg(prefix,"state")
   	local border = getArg(prefix,"border")
    local name   = getArg(prefix,"name")
    -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
    -- or right to keep the title centered.
    local spacerSide = nil

    if navbar == 'off' then
        -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
        -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
        if state == 'plain' then spacerSide = 'right' end
    elseif navbar == 'plain' or
        (   not name and
            mw.getCurrentFrame():getParent():getTitle() == 'Template:Navbox' 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 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 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(' ')
    end
end

---
function renderSplitRow(rootTable,context)
    if context.needAddSplitRow then
        rootTable
            :tag('tr')
                :css('height', '2px')
                :tag('td')
                    :attr('colspan',2)
    end
    context.needAddSplitRow=true
end

function renderTitleRow(rootTable,context)
    local prefix=context.prefix
    local title=getArg(prefix,"title")
    if not title then return end
    renderSplitRow(rootTable)

    local titleColspan=context.TotalColspan
    local titlegroup=getArg(prefix,"titlegroup")
    local titleRow=mw.html.create('tr')
    if titlegroup then
        titleRow
            :tag('th')
                :attr('scope', 'row')
                :addClass('navbox-group')
                :addClass(getArg(prefix,"titlegroupclass"))
                :cssText(getArg(prefix,"basestyle"))
                :cssText(getArg(prefix,"groupstyle"))
                :cssText(getArg(prefix,"titlegroupstyle"))
                :wikitext(getArg(prefix,"titlegroup"))
    end

    local titleCell = titleRow:tag('th'):attr('scope', 'col')
    if titlegroup then
        titleCell
            :css('border-left', '2px solid #fdfdfd')
            :css('width', '100%')

       titleColspan = titleColspan - 1
    end
    titleCell
        :cssText(getArg(prefix,"basestyle"))
        :cssText(getArg(prefix,"titlestyle"))
        :addClass('navbox-title')
        :attr('colspan', titleColspan)

    renderNavBar(titleCell)

    titleCell
         :tag('div')
             :addClass(getArg(prefix,"titleclass"))
             :css('font-size', '110%')
             :wikitext(addNewline(title))

    rootTable:node(titleRow)
end

function renderAboveRow(rootTable,context)
    local prefix=context.prefix
    local above=getArg(prefix,"above")
    if not above then return end
    renderSplitRow(rootTable)

    local Colspan=context.TotalColspan
    local AboveRow=mw.html.create('tr')
    AboveRow
        :tag('td')
            :addClass('navbox-abovebelow')
            :addClass(getArg(prefix,"aboveclass"))
            :cssText(getArg(prefix,"basestyle"))
            :cssText(getArg(prefix,"abovestyle"))
            :attr('colspan', Colspan)
            :tag('div')
                :wikitext(addNewline(above))

    rootTable:node(AboveRow)
end

function renderBelowRow(rootTable,context)
    local prefix=context.prefix
    local below=getArg(prefix,"below")
    if not below then return end
    renderSplitRow(rootTable)

    local Colspan=context.TotalColspan
    local BelowRow=mw.html.create('tr')
    BelowRowmw
        :tag('td')
            :addClass('navbox-abovebelow')
            :addClass(getArg(prefix,"belowclass"))
            :cssText(getArg(prefix,"basestyle"))
            :cssText(getArg(prefix,"belowstyle"))
            :attr('colspan', Colspan)
            :tag('div')
                :wikitext(addNewline(below))

    rootTable:node(BelowRowmw)
end

function _renderListRow(rootTable,context)
    renderSplitRow(rootTable)
    local prefix,level=context.prefix,context.level
    local listnum=listnum or context.listnum
    local isFirst = (listnum==1)
    local isOdd = (listnum % 2) == 1
    local ImageRowspan = 2 * context.Totalrowspan - 1 
    
    local listRow=rootTable:tag('tr')
    local  imageLeftCell
          ,imageCell
          ,groupCell
          ,listCell
          
    --image
    if isFirst and (not context.notNeedImage) then
        local  imageLeft=context.imageLeft or getArg(prefix,"imageleft")
        local  image=context.image or getArg(prefix,"image")
        if imageLeft then
            imageLeftCell=mw.html.create('td')
                :addClass('navbox-image')
                :addClass(getArg(prefix,"imageclass"))
                :css('width', '0%')
                :css('padding', '0px 2px 0px 0px')
                :cssText(getArg(prefix,"imageleftstyle"))
                :attr('rowspan', ImageRowspan)
                :tag('div')
                        :wikitext(addNewline(imageLeft))
            listRow:node(imageLeftCell)
            --imageLeftCell=nil
        end
        if image then
            imageCell=mw.html.create('td')
                :addClass('navbox-image')
                :addClass(getArg(prefix,"imageclass"))
                :css('width', '0%')
                :css('padding', '0px 2px 0px 0px')
                :cssText(getArg(prefix,"imagestyle"))
                :attr('rowspan', ImageRowspan)
                :tag('div')
                    :wikitext(addNewline(image))
        end
    end
    
    --group
    local  group=getArg(prefix,"group"..listnum)
    local groupwidth= ( group and getArg(prefix,"groupwidth") ) or nil
    if group --[[and (not haveColList)]] 
        then
        groupCell=listRow:tag('th') --=mw.html.create('th')
               :attr('scope', 'row')
               :addClass('navbox-group')
               :addClass(getArg(prefix,"groupclass"))
               :cssText(getArg(prefix,"basestyle"))
               :cssText(getArg(prefix,"groupstyle"))
               :cssText(getArg(prefix,'group' .. listnum .. 'style'))
               :wikitext(group)
        if groupwidth then
            groupCell:css('width', groupwidth )
        end
        --listRow:node(groupCell)
        --groupCell=nil
    end
    
    --list
    do
        listCell=listRow:tag('td') --mw.html.create('td')
        if group --[[and (not haveColList) ]]
            then
            listCell
                :css('text-align', 'left')
                :css('border-left-width', '2px')
                :css('border-left-style', 'solid')
        else
            listCell:attr('colspan', 2)
        end
        
        local evenOdd = getArg(prefix,"evenodd")
        evenOdd = (
            evenOdd == 'swap' and
            (isOdd and 'even' or 'odd') or
            (isOdd and (evenOdd or 'odd') or (evenOdd or 'even'))
        )

        local list1padding = haveColList and "0px;" or getArg(prefix,"list1padding")
        local listNstyle= ( haveColList and listnum==1 ) and
                         "background:transparent;color:inherit;" or
                         getArg(prefix,'list' .. listnum .. 'style')
        listCell
            :css('padding', '0px')
            :cssText(getArg(prefix,"liststyle"))
            :cssText(isOdd and getArg(prefix,"evenstyle") or getArg(prefix,"oddstyle"))
            :cssText(listNstyle)
            :addClass('navbox-list')
            :addClass('navbox-' .. evenOdd)
            :addClass(getArg(prefix,"listclass"))
            :tag('div')
                :css('padding', (isFirst and list1padding) or getArg(prefix,"listpadding") or '0em 0.25em')
        --[[if haveColList then
            listCell:node(renderColRow(prefix,context))
        else]]if ( getArg(prefix,'list'..listnum..'border') and getArg(prefix,'list'..listnum..'type') ) and level<= Limit.child then
            listCell:node(p.renderNavTable('list'..listnum,level+1))
        else
            listCell:wikitext(addNewline(getArg(prefix,'list' .. listnum)))
        end
    end
    --end
    --listRow:node(listCell)
    if imageCell then listRow:node(imageCell) end    
end

function renderListRow(rootTable,context)
    _renderListRow(rootTable,context)
end

function renderColRow(rootTable,context)
    --TODO
end

function _renderSmallNavboxInCollapsibleListRow(rootTable,context,listnum)
    --TODO
end

function renderCollapsibleListRow(rootTable,context,listnum)
   --TODO
end

---SubType Implement
function renderHorizontalTable(context)
    local prefix , level = context.prefix, context.level
    local rootTable = createNavTableHeader(context)
    
    local listnums={}--,colnums={}
    for k, v in pairs(args) do
        local listnum = ('' .. k):match('^'..prefix..(prefix=="" and "" or "-")..'list(%d+)$')
        --local colhead_num = ('' .. k):match('^'..prefix..(prefix=="" and "" or "-")..'colheader(%d+)$')
        --local colbody_num = ('' .. k):match('^'..prefix..(prefix=="" and "" or "-")..'col(%d+)$')
        --local colnum = colhead_num or colbody_num
        if listnum and tonumber(listnum)<=Limit.horizontal.list then
            table.insert(listnums, tonumber(listnum))
        end
        --[[
        if colnum and tonumber(colnum)<=Limit.horizontal.col then
            table.insert(colnums, tonumber(colnum))
        end
        ]]
    end
    table.sort(listnums)
    
    local Totalcolspan=2 --title,above,below
    local Totalrowspan=#listnums --image,imageleft
    if getArg(prefix,"imageleft") then Totalcolspan =Totalcolspan + 1 end
    if getArg(prefix,"image") then Totalcolspan =Totalcolspan + 1 end    
    context.TotalColspan = Totalcolspan
    context.Totalrowspan = Totalrowspan
    
    renderTitleRow(rootTable,context)
    renderAboveRow(rootTable,context)       
    renderColRow(rootTable,context)
    for i,listnum in ipairs(listnums) do
        context.listnum=listnum
        renderListRow(rootTable,context)
    end
    renderBelowRow(rootTable,context)

    return rootTable
end

function renderVerticalTable(context)
    local prefix , level  = context.prefix , context.level
        
    local rootTable = createNavTableHeader(context)
    
    local listnums={}
    for k, v in pairs(args) do
        local listnum = ('' .. k):match('^'..prefix..(prefix=="" and "" or "-")..'list(%d+)$')
        if listnum and listnum<=Limit.vertical then
            table.insert(listnums, tonumber(listnum))
        end
    end
    table.sort(listnums)
    
    local Totalcolspan=2 --title,above,below
    local Totalrowspan=#listnums --image,imageleft
    if getArg(prefix,"imageleft") then Totalcolspan =Totalcolspan + 1 end
    if getArg(prefix,"image") then Totalcolspan =Totalcolspan + 1 end    
    context.TotalColspan = Totalcolspan
    context.Totalrowspan = Totalrowspan
    
    renderTitleRow(rootTable,context)
    renderAboveRow(rootTable,context)   
    for i,listnum in ipairs(listnums) do
        context.listnum=listnum
        renderListRow(rootTable,context)
    end
    renderBelowRow(rootTable,context)

    return rootTable
end

function renderVerticalCollapsibleTable(context)
    local prefix , level  = context.prefix , context.level
    
    local rootTable = createNavTableHeader(context)
    
    local listnums={}
    for k, v in pairs(args) do
        local listnum = ('' .. k):match('^'..prefix..(prefix=="" and "" or "-")..'list(%d+)$')
        if listnum and listnum<=Limit.vertical then
            table.insert(listnums, tonumber(listnum))
        end
    end
    table.sort(listnums)
    
    local Totalcolspan=2 --title,above,below
    local Totalrowspan=#listnums --image,imageleft
    if getArg(prefix,"imageleft") then Totalcolspan =Totalcolspan + 1 end
    if getArg(prefix,"image") then Totalcolspan =Totalcolspan + 1 end    
    context.TotalColspan = Totalcolspan
    context.Totalrowspan = Totalrowspan
    
    renderTitleRow(rootTable,context)
    renderAboveRow(rootTable,context)   
    for i,listnum in ipairs(listnums) do
        context.listnum=listnum
        renderCollapsibleListRow(rootTable,context)
    end
    renderBelowRow(rootTable,context)

    return rootTable
end

---Type Selector
function _renderNavTable(context)
    local NavType  = context.type

    if NavType==NavType.H then
        return renderHorizontalTable(context)
    elseif NavType==NavType.V then
        return renderVerticalTable(context)
    elseif NavType==NavType.VC then
        return renderVerticalCollapsibleTable(context)
    end
    return mw.html.create("div")
end

--Main Funtion
function p._navbox(conctext)
    local prefix , level  = context.prefix , context.level
    local rootTable = mw.html.create('table')
    rootTable
        :attr('cellspacing', 0)
        :addClass('navbox')
        :css('border-spacing', 0)
        :cssText(getArg(prefix,'bodystyle'))
        :cssText(getArg(prefix,'style'))
        :tag('tr')
            :tag('td')
                :css('padding', '2px')
                :node(_renderNavTable(conctext))

    return rootTable
end

function p.navbox(frame)
    if not getArgs then
    	getArgs = require('Module:Arguments').getArgs
    end
    args = getArgs(frame, {wrappers = 'Template:Navbox'})
    local prefix, level = "", 1
    local NavType =  getArg() or NavType.V
    -- Read the arguments in the order they'll be output in, to make references number in the right order.
    p.shakeArgs(prefix,level,NavType)
    
    local L0Context=NavboxContext.new(prefix,level,NavType)
    local rootNode=p._navbox(L0Context)
    return tostring(rootNode)
end