Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Period fossil range

Permanently protected module
From Wikipedia, the free encyclopedia
local p = {} --p stands for package

local getArgs = require('Module:Arguments').getArgs

function p.zoomController ( frame )
	period, _ = string.gsub(mw.ustring.lower(frame.args[1]), '%s', '')
	breakpoint = string.find( period, "%W" )
	if breakpoint then
		return p.multiZoom( frame, period, {string.sub(period, 1, breakpoint-1), string.sub(period, breakpoint+1)} )
	elseif period == 'cenozoic' then
		return p.multiZoom( frame, 'cenozoic', {'paleogene', 'neogene', 'quaternary'} )
	elseif period == 'proterozoic' then
		return p.multiZoom( frame, 'proterozoic', {'paleoproterozoic', 'mesoproterozoic', 'neoproterozoic'} )
	else
		return p.zoom(frame)
	end
end

function p.zoom( frame )
	period = mw.ustring.lower(frame.args[1])
	periodStart = tonumber(frame:expandTemplate{ title = 'period start', args = { period } })
	periodEnd = tonumber(frame:expandTemplate{ title = 'period end', args = { period } })
	
	if periodStart > 650 then
		frameStart = frame:expandTemplate{ title = 'period start', args = { 'hadean' } }
		frameEnd = 0
	else
		frameStart = 650 -- Main timescale goes mid Cryogenian – Recent
		frameEnd = 0
	end
	
	left = tostring(250 * (frameStart - periodStart) / (frameStart - frameEnd))
	right = tostring(250 * (frameStart - periodEnd) / (frameStart - frameEnd))
	
	if period == 'silurian' or period == 'neogene' or period == 'quaternary' then
		opacity = '85'
	else
		opacity = '50'
	end
	color = frame:expandTemplate{ title = 'period color', args = { period } }
	
	style = 'height:12px; width: 250px; margin: 0 auto; clear:both; opacity:' .. opacity .. '%; color:inherit; background-color: ' .. color .. '; clip-path: polygon('
	if period == 'quaternary' then
		style = style .. left .. 'px 1px, ' .. left .. 'px 0, ' .. right .. 'px 0, 250px 12px, 0 12px);'
	else
		style = style .. left .. 'px 0, ' .. right .. 'px 0, 250px 12px, 0 12px);'
	end
	
	return '<div style="' .. style .. '"></div>'
end

function p.multiZoom( frame, period, subdivisions )
	content = '<div style="width:250px; height:12px; margin: 0 auto; clear:both; position:relative">'
	periodStart = tonumber(frame:expandTemplate{ title = 'period start', args = { subdivisions[1] } })
	periodEnd = tonumber(frame:expandTemplate{ title = 'period end', args = { subdivisions[#subdivisions] } })
	
	for i, s in ipairs(subdivisions) do
		content = content .. p.multizoomCore( frame, s, periodStart, periodEnd )
	end
	
	content = content .. '</div>'
	return content
end

function p.multizoomCore( frame, subperiod, periodStart, periodEnd )
	subperiodStart = tonumber(frame:expandTemplate{ title = 'period start', args = { subperiod } })
	subperiodEnd = tonumber(frame:expandTemplate{ title = 'period end', args = { subperiod } })
	
	if periodStart > 650 then
		frameStart = frame:expandTemplate{ title = 'period start', args = { 'hadean' } }
		frameEnd = 0
	else
		frameStart = 650 -- Main timescale goes mid Cryogenian – Recent
		frameEnd = 0
	end
	
	leftTop = 250 * (frameStart - subperiodStart) / (frameStart - frameEnd)
	leftBottom = 250 * (periodStart - subperiodStart) / (periodStart - periodEnd)
	rightTop = 250 * (frameStart - subperiodEnd) / (frameStart - frameEnd)
	rightBottom = 250 * (periodStart - subperiodEnd) / (periodStart - periodEnd)
	
	if subperiod == 'silurian' or subperiod == 'neogene' or subperiod == 'quaternary' then
		opacity = '85'
	elseif subperiod == 'neoproterozoic' then
		opacity = '60'
	else
		opacity = '50'
	end
	color = frame:expandTemplate{ title = 'period color', args = { subperiod } }
	
	style = 'position: absolute; height:12px; width: 250px; margin: 0 auto; clear:both; opacity:' .. opacity .. '%; color:inherit; background-color: ' .. color .. '; clip-path: polygon('
	style = style .. leftTop .. 'px 0, ' .. rightTop .. 'px 0, ' .. rightBottom .. 'px 12px, ' .. leftBottom .. 'px 12px);'
	
	return '<div style="' .. style .. '"></div>'
end

function p.periodToStart( frame, period )
	if tonumber(period) ~= nil then
		return tonumber(period)
	else
		return tonumber(frame:expandTemplate{ title = 'period start', args = { mw.ustring.lower(period) } })
	end
end

function p.periodToEnd( frame, period )
	if tonumber(period) ~= nil then
		return tonumber(period)
	else
		return tonumber(frame:expandTemplate{ title = 'period end', args = { mw.ustring.lower(period) } })
	end
end

function p.markerController ( frame )
	period, _ = string.gsub(mw.ustring.lower(frame.args[1]), '%s', '')
	breakpoint = string.find( period, "%W" )
	if breakpoint then
		periodStart = tonumber(frame:expandTemplate{ title = 'period start', args = { string.sub(period, 1, breakpoint-1) } })
		periodEnd = tonumber(frame:expandTemplate{ title = 'period end', args = { string.sub(period, breakpoint+1) } })
	else
		periodStart = tonumber(frame:expandTemplate{ title = 'period start', args = { period } })
		periodEnd = tonumber(frame:expandTemplate{ title = 'period end', args = { period } })
	end
	
	rangeStart = p.periodToStart(frame, frame.args[2])
	
	if frame.args[3] ~= 'nil' then
		rangeEnd = p.periodToEnd(frame, frame.args[3])
	else
		rangeEnd = p.periodToEnd(frame, frame.args[2])
	end
	
	if frame.args['earliest'] ~= 'nil' then
		rangeEarliest = p.periodToStart(frame, frame.args['earliest'])
	else
		rangeEarliest = p.periodToStart(frame, frame.args[2])
	end
	
	if frame.args['latest'] ~= 'nil' then
		rangeLatest = p.periodToEnd(frame, frame.args['latest'])
	elseif frame.args[3] ~= 'nil' then
		rangeLatest = p.periodToEnd(frame, frame.args[3])
	else
		rangeLatest = p.periodToEnd(frame, frame.args[2])
	end
	
	firstMarker = p.markerWide( frame, periodStart, periodEnd, rangeEarliest, rangeLatest )
	secondMarker = p.marker( frame, periodStart, periodEnd, rangeStart, rangeEnd )
	
	divStyle = 'margin:0 auto; line-height:0; clear:both; width:250px; padding:0px; height:8px; overflow:visible; color:inherit; background-color:transparent; position:relative; top:14px; z-index:100;'
	return '<div name=Range style="' .. divStyle .. '">' .. firstMarker .. secondMarker .. '</div>'
end

function p.marker( frame, periodStart, periodEnd, rangeStart, rangeEnd )
	left = math.max( -1, (periodStart - rangeStart) / (periodStart - periodEnd) * 250 )
	right = math.min( 251, (periodStart - rangeEnd) / (periodStart - periodEnd) * 250 )
	outerWidth = math.min(250, right) - math.max(0, left)
	innerWidth = right - left - 2
	if rangeStart - rangeEnd > (periodStart - periodEnd) * 2/250 then
		outerDiv = '<div style="position:absolute; height:8px; left:' .. math.max(0, left) .. 'px; width:' .. outerWidth .. 'px; color:inherit; background-color:#360; "><!--range-border--></div>'
		innerDiv = '<div style="position:absolute; height:6px; top: 1px; left:' .. (left + 1) .. 'px; width:' .. innerWidth .. 'px; color:inherit; background-color:#6c3; "><!--range-marker--></div>'
		return outerDiv .. innerDiv
	else
		return '<div style="position:absolute; left:' .. (left - 4) .. 'px; top:4px; width:0px; border-bottom:8px solid #360; border-left:4px solid transparent; border-right:4px solid transparent;";><div style="position:absolute; top:1px; left:-3px; width:0px; border-bottom: 6px solid #6c3; border-left: 3px solid transparent; border-right: 3px solid transparent;";></div></div>'
	end
end

function p.markerWide( frame, periodStart, periodEnd, rangeEarliest, rangeLatest )
	left = math.max( 0, (periodStart - rangeEarliest) / (periodStart - periodEnd) * 250 )
	right = math.min( 250, (periodStart - rangeLatest) / (periodStart - periodEnd) * 250 )
	width = right - left
	if rangeEarliest - rangeLatest > (periodStart - periodEnd) * 2/250 then
		return '<div style="position:absolute; height:8px; left:' .. left .. 'px; width:' .. width .. 'px; color:inherit; background-color:#360; opacity: 0.42; "><!--range-border--></div>'
	else
		return ''
	end
end

return p