2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

Module:菜单栏

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索
Template-info.svg 模块文档  [创建] [刷新]
local menuBar = {}
local getArgs = require('Module:Arguments').getArgs

local toolStripItem={}
local toolStripContainer={
}
function toolStripContainer.base(args)
	return setmetatable(args or {},toolStripContainer)
end
toolStripContainer.__index=toolStripContainer
function toolStripContainer.create()
	return toolStripContainer.base({items={}})
end
function toolStripContainer:addItem(item_name)
	local item=toolStripItem.create(item_name)
	table.insert(self.items,item)
	return item
end
toolStripContainer._collapseToggle=require('Module:折叠标签')._toggle
function toolStripContainer._collapse(name,text_off,text_on)
	local node	=toolStripContainer._collapseToggle(name,text_off or name,text_on or text_off or name)
				:css("min-width","100%")
	return node
end
function toolStripContainer.analysisItemSp(text)
	local value=text:match("^%b[]",2)
	if not value then
		return text
	end
	local strs=mw.text.split(value:sub(2,#value-1),"|")
	local node=toolStripContainer._collapse(unpack(strs))
	return tostring(node)
end
function toolStripContainer:addItemSp(item_name)--解释折叠
	local node=mw.html.create()
	local str = item_name:gsub('%b[]',toolStripContainer.analysisItemSp)
	return self:addItem(str)
end
function toolStripContainer:_node()
	local node  =mw.html.create("div")
				:addClass("template_menu_container")
	local context=node:tag("div")
				:css("background-color",self.back_color)
				:css("border-width",self.border_width)
				:css("border-color",self.border_color)
				:css("border-style","solid")
	return node,context
end
function toolStripContainer:_hr()
	local node  =mw.html.create("hr")
				:css("margin","0")
				:css("background-color",self.border_color)
				:css("border-color",self.border_color)
				:css("color",self.border_color);
	return node
end
function toolStripContainer:_nodeItem(node,item)
	node:node(item:toNode())
end
function toolStripContainer:_nodeGroup(node)
	for index=1,#self.items-1 do
		self:_nodeItem(node,self.items[index])
		if self.split then
			node:node(self:_hr())
		end
	end
	self:_nodeItem(node,self.items[#self.items])
end
function toolStripContainer:toNode()
	if #self.items==0 then return end
	local node,context=self:_node()
	self:_nodeGroup(context)
	return node
end


local toolStripGroup=toolStripContainer.base()
toolStripGroup.__index=toolStripGroup
function toolStripGroup.create()
	return setmetatable({items={}},toolStripGroup)
end
function toolStripGroup:_node()
	local node  =mw.html.create("div")
				:addClass("template_menu_container")
	local context=node:tag("div")
	context		:css("display","flex")
				:css("flex-direction",self.flex_direction)
	context		=context:tag("div")
	context		:css("background-color",self.back_color)
				:css("border-width",self.border_width)
				:css("border-color",self.border_color)
				:css("border-style","solid")
				
	node		:css("text-align",self.text_align)
				:css("position","relative")
	context		:css("position","absolute")
				:css("min-width","100%")
	return node,context
end
function toolStripGroup:_hr()
	local node  =toolStripContainer._hr(self)
	return node
end
function toolStripGroup:_split()
	local node  =mw.html.create("hr")
				:css("padding","2px")
				:css("background-color",self.back_color)
	node		:tag("hr")
				:css("margin","2px")
				:css("border-color",self.border_color)
	return node
end
function toolStripGroup:_nodeItem(node,item)
	if item.context=="-" then
		node:node(toolStripGroup:_split())
	else
		node:node(item:toNode())
	end
end


function toolStripItem.base(args)
	local item=args or {}
	return setmetatable(item,toolStripItem)
end
function toolStripItem.create(context,group)
	local item={
		context=context,
		group=group or toolStripGroup.create(),
	}
	return setmetatable(item,toolStripItem)
end
toolStripItem.__index=toolStripItem
function toolStripItem:addItem(item_name)
	return self.group:addItem(item_name)
end
function toolStripItem:addItemSp(item_name)
	return self.group:addItemSp(item_name)
end
function toolStripItem:_title(args)
	local node  =mw.html.create("div")
	if self.select_border_width=="0" then
		node			:css("background-color",self.cover_color)
						:css("flex","auto")
						:node(self.context)
		return node
	end
	node				:css("border-color",self.cover_color)
						:css("border-width",self.select_border_width)
						:css("border-style","solid")
						:css("flex","auto")
	local main  =node   :tag("div")
						:css("background-color",self.cover_color)
						:node(self.context)
	return node,main
end
function toolStripItem:_node()
	local node  =mw.html.create("div")
				:addClass("template_menu_item")
				:css("min-width",self.min_width)
	node		:node(self:_title())
	return node
end
function toolStripItem:toNode()
	local node=self:_node()
	local childs=self.group:toNode()
	if childs then
		node:css("display","flex")
			:css("align-items",self.align_items)
			:node(childs)
	end
	return node
end


local menuItem=toolStripItem.base()
function menuItem.create(context,group)
	return setmetatable(toolStripItem.create(context,group),menuItem)
end
menuItem.__index=menuItem
function menuItem:_node()
	local node  =toolStripItem._node(self)
				:css("flex",self.flex)
				:css("display","flex")
				:css("flex-direction",self.flex_direction)
	return node
end
function menuItem:toNode()
	local node=self:_node()
	node:node(self.group:toNode())
	return node
end



local menuBar=toolStripContainer.base()
function menuBar.create()
	return setmetatable({items={}},menuBar)
end
menuBar.__index=menuBar
function menuBar:addItem(item_name)
	local result=menuItem.create(item_name)
	table.insert(self.items,result)
	return result
end
function menuBar:_hr()
	local node  =toolStripContainer._hr(self)
	if self.flex_direction=="column-reverse" or self.flex_direction=="column" then
		node	:css("width","auto")
				:css("height",self.border_width);
	else
		node	:css("height","auto")
				:css("width",self.border_width);
	end
	return node
end
function menuBar:_node()
	local node,context=toolStripContainer._node(self)
	context		:css("display","flex")
				:css("white-space","nowrap")
				:css("border-left-width",self.left_width)
				:css("width",self.width)
				:css("flex-direction",self.flex_direction)
				:css("text-align",self.text_align)
	return node,context
end
function menuBar:toNode()
	if #self.items==0 then return end
	local node,context=self:_node()
	self:_nodeGroup(context)
	if menuItem.flex~="auto" and self.width~="min-context" then--追加覆盖
		if self.split then
			context:node(self:_hr())
		end
		context	:tag("div")
				:css("flex","auto")
				:css("background-color",menuItem.cover_color)
	end
	return node
end

function menuBar.argsSet(args)
	local tab={
		left	="row-reverse",
		right	="row",
		up		="column-reverse",
		down	="column",
	}
	local tab2={
		left	="flex-end",
		right	="flex-start",
		up		="flex-end",
		down	="flex-start",
	}
	local expend_direction=args["flex-direction"] or args["菜单项排列方向"] or "rigth"
	local pop_direction=args["pop-direction"] or args["菜单弹出方向"] or "down"
	local child_pop_direction=args["chlid-pop-direction"] or args["子菜单弹出方向"] or "right"
	local child_expend_direction=args["chlid-flex-direction"] or args["子菜单展开方向"] or pop_direction
	--menuBar
	menuBar.flex_direction=tab[expend_direction]
	menuBar.width=args["width"] or args["菜单宽度"] or "auto"--min-content
	menuBar.back_color=args["back-color"] or args["菜单背景色"] or "white"
	menuBar.border_width=args["border-width"] or args["菜单框架宽度"] or "1px"
	menuBar.border_color=args["border-color"] or args["菜单框架色"] or "green"
	menuBar.left_width=args["left-width"] or args["菜单开端宽度"] or "15px"
	menuBar.text_align=args["text-align"] or args["菜单文字位置"] or "center"
	menuBar.split=((args["item-split"] or args["菜单项分割线"]~="false"))
	--menuItem
	menuItem.flex_direction=tab[pop_direction]
	menuItem.flex=args["flex"] or args["排列"] or "auto"--
	menuItem.min_width=args["item-min-width"] or args["菜单项最小宽度"] or "50px"
	menuItem.select_color=args["select-color"] or args["菜单项选择色"] or menuBar.border_color
	menuItem.select_border_width=args["select-border-width"] or args["菜单项选择框架宽度"] or "0"
	--menuItem.select_border_color=args["select-border-color"]--选择框架颜色
	--toolStripGroup
	toolStripGroup.flex_direction=tab[child_expend_direction]
	toolStripGroup.up=((args["child-direct"] or args["子菜单弹出方向"])=="up")--
	toolStripGroup.back_color=args["child-back-color"] or args["子菜单背景色"] or menuBar.back_color
	toolStripGroup.border_width=args["child-border-width"] or args["子菜单框架宽度"] or menuBar.border_width
	toolStripGroup.border_color=args["child-border-color"] or args["子菜单框架色"] or menuBar.border_color
	toolStripGroup.text_align=args["child-text-align"] or args["子菜单文字位置"] or menuBar.text_align
	toolStripGroup.split=((args["child-item-split"] or args["子菜单项分割线"]~="false"))
	--toolStripItem
	toolStripItem.flex_direction=tab[child_pop_direction]
	toolStripItem.select_color=args["child-select-color"] or args["子菜单项选择色"] or toolStripGroup.border_color
	toolStripItem.min_width=args["child-item-min-width"] or args["子菜单项最小宽度"]
	toolStripItem.select_border_width=args["child-select-back-color"] or args["子菜单项选择框架宽度"] or "3px"
	toolStripItem.align_items=tab2[child_expend_direction]
	--toolStripItem.select_border_color=args["child-select-border-color"] or toolStripGroup.back_color--子菜单项选择框架颜色

	--由于实际上选择时进行的是透明化处理,因此参数调整
	menuItem.cover_color=menuBar.back_color--未选择时用背景色遮盖
	menuBar.back_color=menuItem.select_color--选择时透出背景色遮盖
	toolStripItem.cover_color=toolStripGroup.back_color--未选择时用背景色遮盖
	toolStripGroup.back_color=toolStripItem.select_color--选择时透出背景色遮盖
end
function menuBar.analysisItem(text)
	local s,s2,v,v2
	local b,e=text:find("^%*+")
	local level,sp
	if not b then
		b,e=text:find("^#+")
		sp=true
		if not b then
			return nil 
		end
	end
	level=e+1-b
	return text:sub(e+1),level,sp
end
function menuBar._main(args)--主函数
	menuBar.argsSet(args)
	local texts=mw.text.split(args[1],"\n")
	local main=menuBar.create()
	local stack = {[0]=main}
	local currectLevel=1
	local arg,level
	for _,text in pairs(texts) do
		str,level,sp=menuBar.analysisItem(text)
		if str then
			while level-1>currectLevel do
				stack[currectLevel+1]=stack[currectLevel]:addItem("")
				currectLevel=currectLevel+1
			end
			if sp then
				stack[level]=stack[level-1]:addItemSp(str)
			else
				stack[level]=stack[level-1]:addItem(str)
			end
			currectLevel=level
		end
	end
	return main:toNode():done()
end
function menuBar.main(frame)--主函数
	local args = getArgs(frame)
	return menuBar._main(args)
end
 
 
return menuBar