Mô đun:Horizontal timeline

local horizontal_timeline = {};
local getArgs = require('Module:Arguments').getArgs
local builder = mw.html.create()
local function defaultInvokeFunc(funcName)
	return function (frame)
		args = getArgs(frame, {
trim = true,
removeBlanks = true,
parentFirst = true
})
local from = getNotNilValue(tonumber(args'from'))
local to =  getNotNilValue(tonumber(args'to'))
if not from or not to or from == to then
return ("from and to cannot be nil or equal.")
else
	return horizontal_timelinefuncName(args)
end
	end
end
horizontal_timeline.showTimeLine = defaultInvokeFunc('_showTimeLine')
function horizontal_timeline._showTimeLine(args)
local wdth = getNotNilValue(args'width', '100%' )
local bordr = getNotNilValue(args'border', '1px solid rgb(170, 170, 170)' )
local bgCol = getNotNilValue(args'plot-color', args'plot-colour', 'transparent')
local mrgn = getNotNilValue(args'margin', '1em')
local div_root = builder
:tag('div')
:cssText('float:left;border:'..bordr .. ';width:'..wdth)
local cntnt = div_root
:tag('div')
:cssText('text-align:left; padding:1em; font-size:95%; margin:' ..mrgn.. '; background:'..bgCol)

local rowNums = affixNums(args, 'row') -- Gets numbers for row1, row2, etc. with nil arguments removed.
for _, num in ipairs(rowNums) do
local rowType = args'row' .. num -- Gets args.rowtype1, args.rowtype2, etc. with nil arguments removed.
if rowType == 'scale' then
cntnt:wikitext(horizontal_timeline.scaleRow(args))
elseif rowType == 'note' then
cntnt:wikitext(horizontal_timeline.noteRow(num, args))
elseif rowType == 'timeline' then
cntnt:wikitext(horizontal_timeline.timelineRow(num, args))
else
cntnt:wikitext(rowType)
end
end
if args.caption then
cntnt:tag('div')
:cssText('clear:both; text-align:center')
:wikitext(args.caption)
:done()
end
return tostring(div_root) .. ""
end
horizontal_timeline.showOneRow = defaultInvokeFunc('_showOneRow')
function horizontal_timeline._showOneRow(args)
local rowNums = affixNums(args, 'row') -- Gets numbers for row1, row2, etc. with nil arguments removed.
for _, num in ipairs(rowNums) do
local rowType = args'row' .. num -- Gets args.rowtype1, args.rowtype2, etc. with nil arguments removed.
if rowType == 'scale' then
return horizontal_timeline.scaleRow(args)
elseif rowType == 'note' then
return horizontal_timeline.noteRow(num, args)
elseif rowType == 'timeline' then
return horizontal_timeline.timelineRow(num, args)
else
return wikitext(rowType)
end
end
return "?"
end
function horizontal_timeline.timelineRow(num, args)
local root = mw.html.create()

local from = getNotNilValue(tonumber(args'from'))
local to =  getNotNilValue(tonumber(args'to'))

local style    = getNotNilValue(args'row' .. num .. '-style', )
local hght     = getNotNilValue (args'row' .. num .. '-height',
									 argsstyle .. '-height',
									 '2.5em')
local bordrTop = getNotNilValue (args'row' .. num .. '-bordertop',
									 argsstyle .. '-bordertop',
									 'none')
local bordrBtm = getNotNilValue (args'row' .. num .. '-borderbottom',
									 argsstyle .. '-borderbottom',
									 'none')
local txtTop   = getNotNilValue (args'row' .. num .. '-texttop',
									 argsstyle .. '-texttop',
									 '0em')
local colr     = getNotNilValue (args'row' .. num .. '-colour',
	                             args'row' .. num .. '-color',
	                             argsstyle .. '-colour',
	                             argsstyle .. '-color',
	                             'transparent')
	local barborder = getNotNilValue (args'bar-border', '1px solid #000')
	                             
if bordrTop ~= 'none' then
	bordrTop = 'border-top:' .. bordrTop .. ';'
else
	bordrTop = 
	end
	
	if bordrBtm ~= 'none' then
	bordrBtm = 'border-bottom:' .. bordrBtm .. ';'
else
	bordrBtm = 
	end
local p = root
:tag('div')
:cssText("clear:both;width:100%; padding:0px; height:".. hght)
:cssText(bordrTop.. bordrBtm .. "background-color:"..colr)
local rowDat = affixNums(args, 'row'..num..'%-', '%-a-zA-Z*')
local lastTo = from
local firstNode = true
for _, vals in ipairs(rowDat) do
	local styleL    = getNotNilValue(args'row' .. num .. '-'.. vals ..  '-style', style)
--These vars should be initialized every iteration. Do not move outside of loop
local bar_to = tonumber(getNotNilValue(args'row' .. num .. '-'.. vals .. '-to',
argsstyleL .. '-to',
argsstyle.. '-'.. vals .. '-to', to  ) )
local bar_fontsize =getNotNilValue(args'row' .. num .. '-'.. vals .. '-fontsize',
								argsstyleL .. '-fontsize',
argsstyle..'-'.. vals .. '-fontsize', '0.9em' )
local bar_bordr= getNotNilValue(args'row' .. num .. '-'.. vals .. '-border',
								argsstyleL .. '-border',
argsstyle..'-'.. vals .. '-border',
'none')
local bar_txtTop= getNotNilValue(args'row' .. num .. '-'.. vals .. '-texttop',
								argsstyleL .. '-texttop',
argsstyle..'-'.. vals .. '-texttop', txtTop )
local bar_text = getNotNilValue(args'row' .. num .. '-'.. vals .. '-text',
								argsstyleL .. '-text',
argsstyle..'-'.. vals .. '-text', )
local bar_colour = getNotNilValue(args'row' .. num .. '-'.. vals .. '-colour',
args'row' .. num .. '-'.. vals .. '-color',
argsstyleL .. '-boxcolour',
argsstyleL .. '-boxcolor',
argsstyle..'-'.. vals .. '-colour',
argsstyle..'-'.. vals .. '-color',
'transparent' )

if from  to then bar_to = to end
if lastTo  from then lastTo = from end
	end
local width =( (bar_to-lastTo)*100 / (to-from) ) --math.abs
if width > 0 and width Please specify location for note at "..'row' .. num .. '-'.. vals .. '-at'.." parameter.")
end
for _, vals in ipairs(rowDat) do
local note_at   =args'row' .. num .. '-'.. vals .. '-at' --will never be nil as it is what is used to receive rowDat
local note_text =getNotNilValue(args'row' .. num .. '-'.. vals .. '-text',  )
local note_shift=getNotNilValue(args'row' .. num .. '-'.. vals .. '-shift', '0em' )
local note_lift =getNotNilValue(args'row' .. num .. '-'.. vals .. '-lift', '0em' )
local note_arrow=getNotNilValue(args'row' .. num .. '-'.. vals .. '-arrow', '↓' )
		local note_sft = 100*(note_at - from) / (to-from)

p:tag('div')
:cssText("position:absolute; top:0px; width:100%")
:tag('div')
:cssText("margin-left:".. note_sft .."%; margin-top:0; position:relative")
:tag('span')
:cssText("position:relative; top:0.25em; left:-1.5px")
:wikitext(note_arrow)
:done()
:tag('span')
:cssText("font-size:90% ;position:relative; line-height:3px; overflow:visible")
:cssText("left:"..note_shift.."; top:"..note_lift.."; z-index:".. (1000- tonumber(num)))
:wikitext(note_text)
:done()
:done()
:done()
:done()
end
return tostring(root)
end
function horizontal_timeline.scaleRow(args)
	local from = getNotNilValue(tonumber(args'from'))
local to =  getNotNilValue(tonumber(args'to'))
local inc = getNotNilValue( tonumber(args'inc'), (math.floor( (from - to) / 5 ) * -1) )
local negativeFmt = getNotNilValue(args'axis-negativeFmt', '−%s')
local positiveFmt = getNotNilValue(args'axis-positiveFmt', '%s')
local zeroFmt     = getNotNilValue(args'axis-zeroFmt', '%s')
local nudge       = getNotNilValue(args'axis-nudge', '-1.8em')
local wdth = math.abs ( (100 * inc) / (from - to) )
local root = mw.html.create()
local p = root
:wikitext("")
:tag('div')
:attr('id', 'Scale')
:cssText('clear:both;position:relative;top:-1.4em;left:-0.2em;width:100%;padding:0;height:2.5em')

for var=from, to, inc do
if from  to then wdth = 0 end
else
if var+inc  0 then
lbl = string.format( positiveFmt, math.abs(var) )
else
lbl = string.format( zeroFmt, math.abs(var) )
end
local markr = getNotNilValue(args'axis-marker-'..lbl, '│') 
		lbl = getNotNilValue(args'axis-'..lbl, lbl)
		
p:tag('div')
:cssText('float:left;overflow:visible;width:'.. wdth .. '%')
:wikitext(markr)
:tag('div')
:cssText('font-size:86%; position:relative; left:'..nudge..'; overflow:visible; white-space:nowrap')
:wikitext(lbl)
:done()
:done()
end
p:done()
return tostring(root)
end
--Returns the first non nil value from the list of parameters.
function getNotNilValue(...)
for _,v in pairs(arg) do --Do not use ipairs. Will stop at first nil
if v then return v end
end
return nil
end
function affixNums(t, prefix, suffix)
prefix = prefix or 
suffix = suffix or 

local pattern = '^' .. prefix .. '(1-9%d*)' .. suffix .. '$'
local nums = {}
for k, v in pairs(t) do
if type(k) == 'string' then            
local num = mw.ustring.match(k, pattern)
if num then
nums#nums + 1 = tonumber(num)
end
end
end
table.sort(nums)
return nums
end
return horizontal_timeline