FANDOM


-- by User:The Mol Man
-- used in [[Template:TimelineTable]]
-- <pre>
 
local p = {}
 
-- bar colors, used up in this order
local legend_colors = { '#F86C67', '#F5EB4E', '#98E553', '#8FD7fA', '#F3BFF3' }
 
-- need this for getting epoch times
local lang = mw.language.new('en')
 
-- date format
-- d <month> YYYY
local dfm = 'j F Y'
 
-- main func
function p.main(frame)
	local args = frame:getParent().args
	-- pull graph definition/style args
	local start_year = args.start
	local end_year = args['end']
	local title = args.title
	local width = args.width or '450px'
	local labelheight = args.labelheight or '12px'
	local labelsize = args.labelnamesize or '12px'
	local labellineheight = args.lineheight or labelnamesize
 
	-- index based table for {names} to keep them in order seen
	-- color and links are associative
	-- {colors} links a color to a key name
	-- {links} defines if the key is made into a wikilink in the legend
	local keys = { names = {}, colors = {}, links = {} }
 
	-- keep track of keys found for indexing color
	local key_count = 1;
 
	-- welcome to the circus of values
	local lbls = {}
 
	-- read through unnamed params for table labels
	for _, v in ipairs(args) do
		-- format:
		-- <label>::<start: yyyy-mm-dd> to <end: yyyy-mm-dd> ## <key>::...
		-- example:
		-- Butts::2002-02-25 to 2004-05-16 ## Jagex::2006-03-15 to 2009-01-30 ## MicroSoft
 
		local bar_defs = mw.text.split(v,'::')
		local bars = {}
 
		-- pull and remove label
		local l = table.remove(bar_defs,1)
 
		-- for each "yyyy-mm-dd to yyyy-mm-dd ## affil"
		for _, w in ipairs(bar_defs) do
			-- define: start, end, key
			-- this retarded pattern is roughly: dddd-dd-dd to dddd-dd-dd ## .+
			-- month and day don't need 2 digits
			-- unnecessary whitespace is trimmed
			local s,e,k = mw.ustring.match(w,'%s*(%d%d%d%d%-%d?%d%-%d?%d)%s*[Tt][Oo]%s*(%d%d%d%d%-%d?%d%-%d?%d)%s*##%s*(.-)%s*$')
 
			-- separate value for manipulation
			local _k = mw.ustring.gsub(k or 'undef','[%]%[]','')
 
			-- add new legend keys
			-- base existence on color definition
			if not keys.colors[_k] then
				table.insert(keys.names,_k)
				keys.colors[_k] = legend_colors[key_count]
				-- increment key count
				-- fetus will either need to add more colors
				-- or we can use modulation
				-- preferably the former
				key_count = key_count + 1
 			end
 
			-- If we find brackets, assume it's a link
			if k:find('%[%[') then
				keys.links[_k] = true
			end
 
			table.insert(bars,{
				startdate = s,
				enddate = e,
				lkey = _k
			})
		end
 
		table.insert(lbls,{ name = l, bars = bars })
	end
 
	return p._main(lbls,title,start_year,end_year,keys,width,labelheight,labelsize,labellineheight)
end
 
-- table of labels, start of graph, end of graph, table of keys, graph width, height of bars
function p._main(lbls,title,ystart,yend,keys,width,labelheight,labelsize,labellineheight)
	-- extract length in pixels as a number
	-- may need to change to allow percentage/other values?
	local graph_width = tonumber(string.match(width,'(%d+)'),10)
 
	-- return table
	-- small width because we need to manipulate it to work properly
	local ret = mw.html.create('table'):css({ ['border-collapse'] = 'collapse', width = '1%' })
 
	if title then
		ret:tag('caption'):wikitext(title):css('font-weight','bold'):done()
	end
 
	-- get seconds after epoch for date math
	-- first day of start year
	local ustart = lang:formatDate('U',ystart..'-01-01')
 
	-- first day of year after end
	-- increment end year for this
	yend = yend + 1
	local uend = lang:formatDate('U',yend..'-01-01')
 
	-- epoch difference for span of chart
	local uspan = uend - ustart
 
	-- number of years
	local yspan = yend - ystart
	-- number of columns, based on number of years
	-- colspan only defines the number of columns used to create the graph
	-- the entire table will be this number plus 1
	-- goddamn this is such an inappropriate use of <table> elements
	local colspan = yspan
 
	-- width of each interval, as a percentage of the total graph
	local sparepx = graph_width % yspan
	graph_width = graph_width - sparepx
	local ywidth = (graph_width / yspan / graph_width) * 100
	local ywidthpx = graph_width / yspan
 
	-- number of years
	yspan = yspan + 1
 
	-- ghost element css
	local ghost_cell = { height = '1px', width = ywidthpx..'px', visibility = 'hidden', ['font-size'] = '0pt', ['margin-right'] = '0px !important' }
 
	yend = yend - 1
	--create a ghost row that expands the graph to proper size
	ret	:tag('tr')
			:tag('td'):done()
			:tag('td'):attr('colspan',colspan):css({ padding = '0', width = '1%'})
				 -- ghost element, hidden and small to not make a huge difference
				:tag('div'):css({ height = '1px', width = graph_width, visibility = 'hidden' }):done()
			:done()
	for i, v in ipairs(lbls) do
		-- create new row
		local row = ret:tag('tr'):css('background',(i % 2 == 0) and '#f4f4f4' or '#fafafa')
 
		-- first cell in row, label name
		-- creates y-axis lines with right border
		row	:tag('td'):css({ ['text-align'] = 'right', ['border-right'] = '1px solid #000', ['white-space'] = 'nowrap', ['font-size'] = labelsize, ['line-height'] = labellineheight, ['padding-left'] = '7px', ['padding-right'] = '7px' })
				:tag('div'):css('vertical-align','middle'):wikitext(v.name):done()
			:done()
		-- second cell; holds the bars
		local rcell = row:tag('td'):attr('colspan',colspan):css({ width = graph_width, ['font-size'] = '1px', position = 'relative', padding = '0' })
 
		-- go through label's bars
		for _, w in ipairs(v.bars) do
				-- more epoch math
				local wstart = lang:formatDate('U',w.startdate)
				local wend = lang:formatDate('U',w.enddate)
				local wspan = ((wend - wstart) / uspan) * 100
				local woffset = ((wstart - ustart) / uspan) * 100
 
				local wstartwords = lang:formatDate(dfm,w.startdate)
				local wendwords = lang:formatDate(dfm,w.enddate)
 
				local tooltip = string.format('%s–%s | %s',wstartwords,wendwords,w.lkey)
				-- inline blocks that are positioned to within the parent element (the table cell)
				-- positioned with "woffset", as a percent
				-- length determined with "wspan", as a percent
				rcell:tag('div'):attr('title',tooltip):css({ display = 'inline-block', width = wspan..'%', position = 'absolute', top = '20%', left = woffset..'%', background = keys.colors[w.lkey], height = labelheight }):wikitext('&nbsp;'):done()
		end
 
		rcell:done()
		row:done()
	end
 
	-- this gets a bit involved
	-- make bar lines on the x axis
	-- first row to make; blank, with lines on the interior of the graph
	local yrow = ret	:tag('tr')
							-- first cell, empty
							:tag('td'):css('padding','0'):done()
 
	-- add a line for every year
	for i=ystart,yend do
		yrow:tag('td'):css({ width = '1%', height = '3px', ['border-left'] = '1px solid #000', ['border-right'] = '1px solid #000', padding = '0' })
				-- more ghost elements
				:tag('div'):css(ghost_cell):wikitext('&nbsp;'):done()
			:done()
	end
 
	yrow:done()
 
	-- another row, this time just to give lines on the underside
	yrow = ret	:tag('tr')
					-- first cell, empty
					:tag('td'):done()
 
	-- add a line for every year
	-- also makes line for x-axis
	for i=ystart,yend do
		yrow:tag('td'):css({ width = '1%', height = '2px', ['border-top'] = '1px solid #000', ['border-left'] = '1px solid #000', ['border-right'] = '1px solid #000', padding = '0' })
				-- more ghost elements
				:tag('div'):css(ghost_cell):wikitext('&nbsp;'):done()
			:done()
	end
 
	yrow:done()
 
	-- another row, this time to give the years with labels a longer bar
	yrow = ret	:tag('tr'):css('height','3px')
					-- first cell, blank
					:tag('td'):done()
 
	-- add a line for every year
	for i=ystart,yend,2 do
		yrow:tag('td'):css({ ['border-left'] = '1px solid #000', padding = '0', width = '1%'})
				-- more ghost elements
				:tag('div'):css(ghost_cell):wikitext('&nbsp;'):done()
			:done()
		if i < (yspan - 1 + ystart) then
			-- blank cell, no need for styling
			yrow:tag('td'):css({ padding = '0', width = '1%'})
				-- more ghost elements
				:tag('div'):css(ghost_cell):wikitext('&nbsp;'):done()
			:done()
		end
	end
 
	yrow:done()
 
	-- yet another row, this time holding the year labels
	-- also make font slightly smaller
	yrow = ret	:tag('tr'):css({ ['text-align'] = 'center', ['font-size'] = '75%' })
						-- first cell, blank
						:tag('td'):css('padding','0'):done()
 
	-- only label every other year
	for i=ystart,yend,2 do
		-- years with labels
		yrow:tag('td'):css({ position = 'relative', padding = '0', width = '1%'})
				:tag('span'):css({ position = 'absolute', top = '-10%', left = '-35%' }):wikitext(i):done()
			:done()
 
		-- years without labels
		if i < (yspan - 1 + ystart) then
			yrow:tag('td'):css({ padding = '0', width = '1%'})
				-- hidden label to keep the heights in check
				:tag('span'):css('visibility','hidden'):wikitext('|'):done()
			:done()
		end
	end
 
	yrow:done()
 
	-- need to be tricky with legend variable to avoid using mw.html.create() again
	-- add new row
	local legend = ret:tag('tr')
	-- add new cell
	-- colspan so it spans under both the labels and the graph
	legend:tag('td'):done()
 
	legend = legend:tag('td'):attr('colspan',colspan)
	-- add list, no bullets
	legend = legend:tag('ul'):css({ ['list-style'] = 'none', ['margin-left'] = '0', ['font-size'] = labelsize, ['line-height'] = labellineheight })
 
	for _, v in ipairs(keys.names) do
		local kname = v
		-- if it had a link in its first definition, give it a link here
		if keys.links[v] then
			kname = string.format('[[%s]]',kname)
		end
 
		legend	:tag('li')
					-- builds a square based on the bar color
					:tag('div'):css({ width = '12px', height = '12px', background = keys.colors[v], display = 'inline-block', ['vertical-align'] = 'middle', ['margin-right'] = '5px', ['margin-top'] = '-3px' }):wikitext('&nbsp;'):done()
					:wikitext(kname)
				:done()
	end
 
	legend:done()
 
	return ret
end
 
return p

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.