Module:Period fossil range
Documentation for this module may be created at Module:Period fossil range/doc
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