FANDOM


--------------------------------------------------------------------
-- Navbox Module
--
-- * Fully CSS styled (inline styles possible but not default)
-- * Supports unlimited rows
--
-- By User:Tjcool007 from layton.wikia.com
--
-- Next changes are applied:
-- * Parameter names are translated into Korean
-- * Vde links no more requires Template:Vdelinks
-- * Plain text as seperator in lists, instead CSS pseudo trick.
-- * Parameters `altgroup-`, `altlist-` and
--   option have been removed. Instead, parameters for individual cells
--   such as `제목클래스n`, `제목모양n`, `내용클래스n`, `내용모양n` are introduced.
-- * Make nested navbox have same syntax as their parent navbox
-- * Remove a few unwanted parameters: `name`, `border`
-- * CSS class nameing now reflects BEM rules
-- * CSS selector modifications to ease styling
--------------------------------------------------------------------
 
local p = {}
 
-- Default config. Values will be replaced with
-- proprecessed arguments passed to template
local args = {}
local navbox -- Actual navbox
 
local rownums, skiprows = {}, {}
local alt, hasrows, hasData = false, false, false
local activeSection, sections, cimage, cimageleft
local colspan, rowspan
 
local showText, hideText = '보이기', '숨기기'
 
------------------------------------------------
-- Title
------------------------------------------------
 
--- Processes the VDE links in the title
--
-- @param titlecell The table cell of the title
local function processVde( titlecell )
    if not args['안내참조'] then return end
 
    local vde = { '보기', '토론', '편집' }
    local str, ns, fullurl
    local vdeLinks = {}
 
    for k, v in pairs(vde) do
        if v ~= '편집' then
            ns = v == '토론' and '틀토론' or '틀'
            str = '[[' .. ns .. ':'.. args['안내참조'] .. '|<span style="color:' .. args['안내참조색'] .. ';">' .. v .. '</span>]]'
        else
            fullurl = mw.uri.fullUrl(args['안내참조'], 'action=edit')
            str = '[' .. tostring(fullurl) .. '|<span style="color:' .. args['안내참조색'] .. ';">' .. v .. '</span>]'
        end
        table.insert(vdeLinks, str)
    end
 
    titlecell
        :tag('span')
            :addClass('navbox__vde')
            :wikitext( table.concat(vdeLinks, '&#x30FB;') )
end
 
--- Processes the main title row
local function processTitle()
    local titlerow = mw.html.create('tr')
    local titlecell = mw.html.create('th'):addClass('navbox__title'):attr('colspan',colspan):attr('scope','col')
 
    processVde( titlecell )
 
    titlecell:wikitext( args['큰제목'] )
 
    if args['큰제목클래스'] then titlerow:addClass( args['큰제목클래스'] ) end
    if args['큰제목모양'] then titlecell:cssText( args['큰제목모양'] ) 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, prefix )
    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 .. '클래스'] then abrow:addClass( args[rowtype .. '클래스'] ) end
    if args[rowtype .. '모양'] then abcell:cssText( args[rowtype .. '모양'] ) 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 == '그림' 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 .. '너비'] or '100px'
        imagecell:css('width',width):wikitext('[[' .. image  .. '|' .. width .. '|link=' .. (args[imgtype .. '링크'] or '') .. ']]')
    else
        imagecell:css('width','0%'):wikitext(image)
    end
 
    if args[imgtype .. '클래스'] then imagecell:addClass( args[imgtype .. '클래스'] ) end
    if args[imgtype .. '모양'] then imagecell:cssText( args[imgtype .. '모양'] ) end
 
    row:node( imagecell )
    if imgtype == '그림' 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,'왼쪽그림')  
    end
 
    cell:node(sections[activeSection])
    row:node(cell)
 
    local firstRow = false
    if not hasrows then
        firstRow = true
        hasrows = true
        _processImage(row,'그림')  
    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['색교차'] == '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['작은제목'..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['작은제목'..num] )
 
    local collapseme = args['작은제목상태'..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['작은제목기본상태'] or false
        if collapseall then
            state = collapseall == 'expanded' and 'expanded' or 'collapsed' 
        end
    end
 
    if state then
        subtable:addClass('mw-collapsible'):attr('data-expandtext',showText):attr('data-collapsetext',hideText)
        if state == 'collapsed' then
            subtable:addClass('mw-collapsed')   
        end
    end
 
    if args['작은제목클래스'] then headerrow:addClass( args['작은제목클래스'] ) end
    if args['작은제목모양'] then header:cssText( args['작은제목모양'] ) 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['내용'..num] then return end
 
    local row = mw.html.create('tr'):addClass('navbox__row')
 
    if not hasrows and not activeSection then
        _processImage(row, '왼쪽그림') 
    end
 
    local listcell = mw.html.create('td'):addClass('navbox__list')
    local data = args['내용'..num]
    local dataset = {}
 
    for line in data:gmatch('[^\r\n]+') do -- get line by line
        line = line:gsub('%*%s?', '') -- trim leading * and an optional space
        table.insert(dataset, line)
    end
 
    listcell:wikitext( table.concat(dataset, '&#x30FB;') )
 
    if args['모든줄클래스'] then row:addClass( args['모든줄클래스'] ) end
    if args['모든줄모양'] then row:cssText( args['모든줄모양'] ) end
 
    local altRow = _alternateRow()
    if altRow then row:addClass( 'alt' ) end -- 홀수 행
 
    local listclass = args['내용클래스'..num] or false
    if listclass then listcell:addClass( listclass ) end
 
    local liststyle = args['내용모양'..num] or false
    if liststyle then listcell:cssText( liststyle ) end
 
    if args['제목'..num] then
        local groupcell = mw.html.create('th'):addClass('navbox__group'):attr('scope','row'):wikitext( args['제목'..num] )
 
        local groupclass = args['제목클래스'..num] or false
        if groupclass then groupcell:addClass( groupclass ) end
 
        local groupstyle = args['제목모양'..num] or false
        if groupstyle then groupcell:cssText( groupstyle ) 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, '그림')
    end
 
    if activeSection then
        local parent = sections[activeSection]
        if not firstRow then
            _addGutter(parent)
        end
        parent:node(row)
        hasData = true
    else
        if 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('^(.+)([1-9]%d*)$')
 
            if cat == '제목' or cat == '내용' then
                nums[num] = true
            end
 
            args[k] = v -- Simple copy
        end
    end
 
    colspan = args['그림'] and 3 or 2
    if args['왼쪽그림'] then colspan = colspan + 1 end
    rowspan = 0
 
    if args['색교차'] == '반전' then alt = true end
 
    for k, v in pairs(nums) do
        table.insert(rownums, tonumber(k))
    end
 
    table.sort(rownums)
 
    -- Calculate skip rows
    local cSection, cSkip
    local showall = args['상태']
    for i = 1, #rownums do
        local num = rownums[i]
        if args['작은제목'..num] then
            cSection = true
            cSkip = false
            local showme = args['작은제목상태'..num]
            if showme == hideText then
                cSkip = true
            elseif showme == '자동' or (showme ~= showText and showall ~= showText) then
                if not args['내용'..num] then
                    local nextNum = rownums[i+1]
                    cSkip = not nextNum or args['작은제목'..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
 
    navbox = mw.html.create('table'):addClass('navbox')
 
    if args['상태'] ~= 'plain' then
        navbox:addClass('mw-collapsible'):attr('data-expandtext',showText):attr('data-collapsetext',hideText)
        if args['상태'] == 'collapsed' then
            navbox:addClass('mw-collapsed')
        end
    end
 
    if args['클래스'] then navbox:addClass(args['클래스']) end
    if args['모양'] then navbox:cssText(args['모양']) end
 
    -- Process...
    processTitle()
    processAboveBelow('above', '윗')
    processRows()
    processAboveBelow('below', '아랫')
 
    return tostring(navbox)
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