Higashi Wiki
Advertisement

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

local p = {}
-- The navbox we will create and return
local navbox = mw.html.create("div")
-- Prevent from being printed by ebook maker
navbox
	:addClass("print-no")
	:addClass("entry-unrelated")

--- Searching for the prefix corresponding the project
-- @param #string pageName the name to search
-- @param #table prefixData all prefixes stocked
function searchPrefix(pageName, prefixData)
	-- Finding and returning the longest matching key
	local keyFounded = ''
    for key, var in pairs(prefixData) do
        if mw.ustring.find(mw.ustring.lower(pageName),mw.ustring.lower(key),1,true) ~= nil then
            if mw.ustring.len(key) > mw.ustring.len(keyFounded) then
				keyFounded = key
			end
        end
    end
    return keyFounded
end

--- Personalizing the Navbox according to parameters
-- @param #table args all parameters transmitted
function customSkin(args)
    -- Loading the default skin for Navbox
    local defaultSkin = mw.loadData("Module:Default Nav Skin") or {}
    local skin = {}
    for key, var in pairs(defaultSkin) do
        skin[key] = (mw.text.trim(tostring(var)))
    end
    for key, var in pairs(args) do
        skin[key] = (mw.text.trim(tostring(var)))
    end
    return skin
end

--- Make wikia interne link from page name
-- @param #table data containing full name, short name, etc. associating this page from pagesList
-- @param #boolean shortened shorten the name of page or not
-- @param #string style styling this link
function wikiaLink(data, shortened, style)
	local appear_text = mw.html.create("span")
	appear_text:cssText(style)
	
    if shortened then
        appear_text:wikitext(data.shortname or data.fullname)
    else
        appear_text:wikitext(data.longname or data.fullname)
    end
	return "[[" .. data.fullname .. "|" .. tostring(appear_text) .."]]"
end

--- Create the local navigator (forwarding/backwarding)
-- @param #string pageName name of this page
-- @param #table pagesList all the pages of this project
-- @param #table customizedSkin personalizing parameters
function makeLocalNav(pageName,pagesList,customizedSkin)
    --Looking for mainpage
    local mainPageData, mainPagePos = {}, 0
    for k, v in ipairs(pagesList) do
        if v.mainpage then
            mainPageData = v
            mainPagePos = k
            break
        end
    end
    --Determining the position of this page, couting the number of pages as well (n)
    local actualPos, n = 0, 0
    for k, v in ipairs(pagesList) do
        n = n + 1
        if v.fullname == pageName then
            actualPos = k
        end
    end
    if actualPos == 0 then
        actualPos = mainPagePos
    end
    --Determining the preceding page
    local previousPageData = {}
    if actualPos > 1 then
        if not pagesList[actualPos - 1].mainpage then
            previousPageData = pagesList[actualPos - 1]
        end
    end
    --Determining the successing page
    local nextPageData = {}
    if actualPos < n then
        if not pagesList[actualPos + 1].mainpage then
            nextPageData = pagesList[actualPos + 1]
        end
    end
    --Constructing html
    local localNav, localNav_row, previousPage, mainPage, nextPage
        = mw.html.create("table"), mw.html.create("tr"), mw.html.create("td"), mw.html.create("td"), mw.html.create("td")

    previousPage
        :cssText(customizedSkin.previousPage)
    if previousPageData.longname ~= nil then
        previousPage:wikitext("► Xem lại " .. wikiaLink(previousPageData,false,customizedSkin.previousPage_link) ..  " ◄")
    else
        previousPage:wikitext("&nbsp;")
    end

    mainPage
        :cssText(customizedSkin.mainPage)
    if mainPageData.fullname ~= nil then
        mainPage:wikitext(customizedSkin.mainPage_left .. wikiaLink(mainPageData,true,customizedSkin.mainPage_link) .. customizedSkin.mainPage_right)
    else
        mainPage:wikitext("&nbsp;")
    end


    nextPage
        :cssText(customizedSkin.nextPage)
    if nextPageData.longname ~= nil then
        nextPage:wikitext("► Xem tiếp " .. wikiaLink(nextPageData,false,customizedSkin.nextPage_link) ..  " ◄")
    else
        nextPage:wikitext("&nbsp;")
    end

    localNav_row
        :cssText(customizedSkin.localNav_row)
        :node(previousPage)
        :node(mainPage)
        :node(nextPage)
        :addClass("localNav")

    localNav
        :cssText(customizedSkin.localNav)
        :node(localNav_row)

    return localNav
end

--- Create the list of all pages in the project
-- @param #table pagesList all the pages of this project
-- @param #table customizedSkin personalizing parameters
function makeGlobalNav(pagesList,customizedSkin)
    -- Ordering and grouping pages according to volume's numeration
    local groupedPages, orderedKeys = {}, {}
    for _, v in ipairs(pagesList) do
        if v.id then
            local thisVol = {ft = v, ch = {}}
            for _, v2 in ipairs(pagesList) do
                if v2.childOf == v.id then
                    table.insert(thisVol.ch, v2)
                end
            end
            table.insert(orderedKeys, v.id)
            groupedPages[v.id] = thisVol
        end
    end

    -- Constructing html
    local globalNav, globalNav_title, globalNav_content, unitNodes
        = mw.html.create("div"), mw.html.create("div"), mw.html.create("div"), {}

    -- title
    globalNav_title
        :cssText(customizedSkin.globalNav_title)
        :addClass("mw-customtoggle-globalNav"):addClass("mw-customtoggle-globalNavClose"):addClass("mw-customtoggle-globalNavOpen")
        :wikitext(customizedSkin.globalNav_title_text)

    -- content
    -- constructing unit nodes, which consist of volumes
    for _, id in ipairs(orderedKeys) do
        -- for each volume
        local data, vol, links = groupedPages[id], mw.html.create("table"), mw.html.create("")
        -- fulltext link
        local ft = mw.html.create("td")
        ft
            :cssText(customizedSkin.fulltext)
            :wikitext(wikiaLink(data.ft,true,customizedSkin.fulltext_link))
        links:node(ft)
        -- chapter link
        for _, chapter in ipairs(data.ch) do
            local ch = mw.html.create("td")
            ch
                :cssText(customizedSkin.chapter)
                :wikitext(wikiaLink(chapter,true,customizedSkin.chapter_link))
            links:node(ch)
        end
        -- volume case
        vol
            :cssText(customizedSkin.volume)
            :node(mw.html.create("tr"):node(links))
        -- attaching to unitNodes
        -- unitNodes and groupedPages used the same table of ordered keys
        unitNodes[id] = vol
    end
    -- constructing arcs
    local arcsStructure = pagesList.arcsStructure
    if arcsStructure then
        for _, arc in ipairs(arcsStructure) do
            if arc.including and arc.id then
                local arc_node, title, content = mw.html.create(""), mw.html.create("div"), mw.html.create("div")
                -- styling
                title
                    :addClass("mw-customtoggle-"..arc.id):addClass("mw-customtoggle-"..arc.id.."Close"):addClass("mw-customtoggle-"..arc.id.."Open")
                    :wikitext(arc.fullname)
                if not customizedSkin["arcBar_title_"..arc.id] then
                    title:cssText(customizedSkin.arcBar_title)
                else
                    title:cssText(customizedSkin["arcBar_title_"..arc.id])
                end

                content
                    :addClass("mw-collapsible"):addClass("mw-collapsed")
                    :attr("id", "mw-customcollapsible-"..arc.id)
                if not customizedSkin["arcBar_content_"..arc.id] then
                    content:cssText(customizedSkin.arcBar_content)
                else
                    content:cssText(customizedSkin["arcBar_content_"..arc.id])
                end

                -- grouping all unit nodes into @arc_node
                for _, includedId in ipairs(arc.including) do
                    content:node(unitNodes[includedId])
                end
                arc_node:node(title):node(content)
                -- deleting included nodes and inserting arc_node into unitNodes
                for index, includedId in ipairs(arc.including) do
                    unitNodes[includedId] = nil
                end
                unitNodes[arc.id] = arc_node
                -- deleting corresponding keys and inserting arc.id into orderedKeys at the first deleted key
                local index = 1
                repeat
                    -- comparing orderedKeys[index] with all includedId in arc.including
                    for i, includedId in ipairs(arc.including) do
                        if includedId == orderedKeys[index] then
                            if i==1 then
                                orderedKeys[index] = arc.id
                            else
                                table.remove(orderedKeys, index)
                                index = index - 1
                            end
                        end
                    end
                    index = index + 1
                until orderedKeys[index] == nil
            end
        end
    end

    -- appending volume cases, arc cases to globalNav_content
    for _, key in ipairs(orderedKeys) do
        globalNav_content:node(unitNodes[key])
    end

    globalNav_content
        :cssText(customizedSkin.globalNav_content)
        :attr("id", "mw-customcollapsible-globalNav")
        :addClass("mw-collapsible")
    if (customizedSkin.collapse_globalNav == "true") then
        globalNav_content
            :addClass("mw-collapsed")
            :cssText("display:none")
    end

    -- overall
    globalNav
        :cssText(customizedSkin.globalNav)
        :addClass("hidden")
        :addClass("globalNav")
        :node(globalNav_title)
        :node(globalNav_content)

    return globalNav
end

--- Searching function
--- Returns the first link, in shortened form, matching the given keyword. If research fails, it returns the mainpage
-- @param #keyword
-- @param #pagesList
function search(keyword, pagesList)
	--Looking for mainpage
    local mainPageData = {}
    for _, v in ipairs(pagesList) do
        if v.mainpage then
            mainPageData = v
            break
        end
    end
    --Determining the corresponding link of keyword
    local dataFound = nil
    for _, v in ipairs(pagesList) do
        if mw.ustring.find(mw.ustring.lower(v.fullname),mw.ustring.lower(keyword),1,true) ~= nil then
            dataFound = v
			break
        end
    end
    if dataFound == nil then
        return wikiaLink(mainPageData, true, nil)
	else
		return wikiaLink(dataFound, true, nil)
    end
end

--- The main function
-- @param #table frame what wikia transmits
function p.makeNav( frame )
    -- Getting all parameters transmis via template Auto Nav, including {{FULLPAGENAME}} and customized Navbox's styles
    local args = frame.args or {}
    -- Getting the title of page using template Auto Nav
    local pageName = args["pageName"]
    -- The prefixes
    local prefixData, pagesList = mw.loadData("Module:PrefixData")
    -- Getting the list of pages belonging to this project
    if args.src then
        pagesList = mw.loadData(args.src)
    else
        local prefixUsed = searchPrefix(pageName, prefixData)
        pagesList = mw.loadData(prefixData[prefixUsed])
    end
	if args.search == "" or args.search == nil then
		-- if user does not give value to arguement "search", then we create a navbox by default
		local customizedSkin = customSkin(args)
		local inner_navbox = mw.html.create("div")
		inner_navbox
			:addClass("dotEPUBremove")
		-- Append the local nav into our inner_navbox
		inner_navbox:node(makeLocalNav(pageName,pagesList,customizedSkin))
		-- Append the global nav into our inner_navbox
		inner_navbox:node(makeGlobalNav(pagesList,customizedSkin))
		-- Append the inner into navbox
		navbox:node(inner_navbox)
		return navbox
	else 
		return search(args.search, pagesList)
	end
end

return p
Advertisement