Toggle menu
209
926
189
6.3K
Dovedale Railway Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.
Module documentation[view][edit][history][purge]
This documentation is transcluded from Module:Dimensions/doc. Changes can be proposed in the talk page.
Function list
L 14 — getTextHTML
L 46 — getReferenceObjectHTML
L 84 — getObjectHTML
L 156 — getDimensionsValue
L 182 — getDimensionsData
L 226 — p._main
L 241 — p.main

--- Module:Dimensions
--- Used to display an isometric cube showing the dimensions of an object

require( 'strict' )

local p = {}

local lang = mw.getContentLanguage()

--- Get the text HTML object
---
--- @param data table
--- @return mw.html
local function getTextHTML( data )
	if not data.label and not data.value then return end
	local html = mw.html.create( 'div' )
		:addClass( 'template-dimensions-box-text' )

	if data.variant then
		html:addClass( 'template-dimensions-box-text-' .. data.variant )
	end

	if data.label then
		html:tag( 'div' )
			:addClass( 'template-dimensions-label' )
			:wikitext( data.label )
			:done()
	end

	if data.value then
		html:tag( 'div' )
			:addClass( 'template-dimensions-data' )
			:wikitext( data.value )
			:done()
	end

	return html
end


--- Create a human-sized object for reference
--- FIXME: Figure out how to do a box properly, haven't done trigonometry in ages...
---
--- @param type string|nil
--- @return mw.html|nil
local function getReferenceObjectHTML( type )
	if not type then return end

	local refData = {}
	if type == 'human' then
		refData.length = 0.2;
		refData.width = 0.4;
		refData.height = 1.8;
	end
	if refData == {} then return end

	local html = mw.html.create( 'div' )
		:addClass( 'template-dimensions-reference template-dimensions-box-faces' )
		:attr( 'title', string.format( '%s for reference', type ) )
		:css( 'transform-style', 'preserve-3d' )
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-top' )
		:done()
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-front' )
		:done()
		--:tag( 'div' )
		--:addClass( 'template-dimensions-box-face template-dimensions-box-face-right' )
		--:done()

	for k, v in pairs( refData ) do
		local cssVar = string.format( '--reference-%s', k )
		html:css( cssVar, tostring( v ) )
	end

	return html
end


--- Get the object HTML object
---
--- @param data table
--- @return mw.html
local function getObjectHTML( data )
	local html = mw.html.create( 'div' )
		:addClass( 'template-dimensions' )
		:css( {
			[ '--object-length' ] = data.length.number,
			[ '--object-width' ] = data.width.number,
			[ '--object-height' ] = data.height.number,
		} )

	local isometric = html:tag( 'div' )
		:addClass( 'template-dimensions-isometric' )
		:css( {
			[ 'transform-style' ] = 'preserve-3d',
			[ 'grid-template-areas' ] = "'layer'"
		} )

	-- Top layer
	isometric:tag( 'div' )
		:addClass( 'template-dimensions-layer template-dimensions-layer-top' )
		:css( 'transform-style', 'preserve-3d' )
		:tag( 'div' )
		:addClass( 'template-dimensions-box-faces' )
		:css( 'transform-style', 'preserve-3d' )
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-top' )
		:done()
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-front' )
		:done()
		:tag( 'div' )
		:addClass( 'template-dimensions-box-face template-dimensions-box-face-right' )
		:done()
		:done()
		:node( getTextHTML( {
			label = data.height.label,
			value = data.height.value,
			variant = 'y'
		} ) )
		:node( getTextHTML( {
			label = data.mass.label,
			value = data.mass.value,
			variant = 'z'
		} ) )
		:done()

	-- Bottom layer
	isometric:tag( 'div' )
		:addClass( 'template-dimensions-layer template-dimensions-layer-bottom' )
		:css( 'transform-style', 'preserve-3d' )
		:node( getReferenceObjectHTML( data.referenceType ) )
		:node( getTextHTML( {
			label = data.length.label,
			value = data.length.value,
			variant = 'z'
		} ) )
		:node( getTextHTML( {
			label = data.width.label,
			value = data.width.value,
			variant = 'x'
		} ) )
		:done()

	return html
end


--- Return string containing the number with separator and unit
---
--- @param arg string|number|nil
--- @param unit string
--- @param altArg string|number|nil
--- @return string|nil
local function getDimensionsValue( arg, unit, altArg )
	if not arg or not unit then return end
	local num = tonumber( arg )
	if not num then return end

	local value = string.format( '%s %s', lang:formatNum( num ), unit )
	if not altArg or arg == altArg then
		return value
	end

	local altValue = getDimensionsValue( altArg, unit )
	if not altValue then
		return value
	end
	return string.format(
		'%s <span class="template-dimensions-data-subtle">(%s)</span>',
		value,
		altValue
	)
end


--- Format arguments into data used by HTML functions
---
--- @param args table
--- @return table|nil
local function getDimensionsData( args )
	local lengthNum = tonumber( args.length )
	local widthNum = tonumber( args.width )
	local heightNum = tonumber( args.height )

	if not lengthNum or not widthNum or not heightNum then return end
	-- TODO: Make this cleaner by using another table to map the units?
	local lengthValue = getDimensionsValue( args.length, 'm', args.lengthAlt )
	local widthValue = getDimensionsValue( args.width, 'm', args.widthAlt )
	local heightValue = getDimensionsValue( args.height, 'm', args.heightAlt )

	-- TODO: Perhaps this can be done in a loop
	local data = {
		length = {
			number = lengthNum,
			label = 'Length',
			value = lengthValue
		},
		width = {
			number = widthNum,
			label = 'Width',
			value = widthValue
		},
		height = {
			number = heightNum,
			label = 'Height',
			value = heightValue
		},
		mass = {
			label = 'Mass' ,
			value = getDimensionsValue( args.mass, 'kg' ) or '-'
		},
		referenceType = args.referenceType
	}

	return data
end


--- Lua entry point
---
--- @param args table
--- @param frame table
--- @return string|nil
function p._main( args, frame )
	if not args.length or not args.width or not args.height then return end
	-- Frame object can be missing if function is invoked from Lua
	frame = frame or mw.getCurrentFrame()

	local data = getDimensionsData( args )
	if not data then return end
	return tostring( getObjectHTML( data ) ) .. frame:extensionTag {
		name = 'templatestyles', args = { src = 'Module:Dimensions/styles.css' }
	}
end

--- Wikitext entry point
---
--- @return string|nil
function p.main( frame )
	local args = require( 'Module:Arguments' ).getArgs( frame )
	return p._main( args, frame )
end

return p
🍪 Yum Yum Yum! Cookies help us better deliver our services. By using our site, you agree to our use of cookies.