Module:Multiple image

From ChaldeanWiki
Revision as of 12:00, 13 February 2015 by Edokter (Talk) (Add classes to enable interaction with gadgets and other scripts)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Documentation for this module may be created at Module:Multiple image/doc

-- implements [[template:multiple image]]
local p = {}

local function isnotempty(s)
	return s and s:match( '^%s*(.-)%s*$' ) ~= ''
end

local function renderImageCell(image, width, height, link, alt, caption, textalign) 
	local root = mw.html.create('')
	
	local altstr = '|alt=' .. (alt or '')
	local linkstr = link and ('|link=' .. link) or ''
	local widthstr = '|' .. tostring(width) .. 'px'
	
	local imagediv = root:tag('div')
	imagediv:addClass('thumbimage')
	if( height ) then
		imagediv:css('height', tostring(height) .. 'px')
		imagediv:css('overflow', 'hidden')
	end
	imagediv:wikitext('[[file:' .. image .. widthstr .. linkstr .. altstr .. ']]')
	if isnotempty(caption) then
		local captiondiv = root:tag('div')
		captiondiv:addClass('thumbcaption')
		captiondiv:css('clear', 'left')
		if isnotempty(textalign) then
			captiondiv:css('text-align', textalign)
		end
		captiondiv:wikitext(caption)
	end
	return tostring(root)
end

local function getWidth(w1, w2)
	local w
	if isnotempty(w1) then
		w = tonumber(w1)
	elseif isnotempty(w2) then
		w = tonumber(w2)
	end
	return w or 200
end

local function renderMultipleImages(frame)
	local pargs = frame:getParent().args
	local args = frame.args
	local width = pargs['width'] or ''
	local dir = pargs['direction'] or ''
	local align = pargs['align'] or args['align'] or ''
	local captionalign = pargs['caption_align'] or args['caption_align'] or ''
	local totalwidth = pargs['total_width'] or args['total_width'] or ''
	local height = nil
	local header = pargs['header'] or pargs['title'] or ''
	local footer = pargs['footer'] or ''
	local thumbclass = {
		["left"] = 'tleft',
		["none"] = 'tnone',
		["center"] = 'tnone',
		["centre"] = 'tnone',
		["right"] = 'tright'
		}

	-- find all the nonempty images and corresponding widths
	-- also compute the sum of widths and maximum width
	local imagenumbers = {}
	local widths = {}
	local imagecount = 0
	local widthmax = 0
	local widthsum = 0
	for k, v in pairs( pargs ) do
		local i = tonumber(tostring(k):match( '^%s*image([%d]+)%s*$' ) or '0')
		if( i > 0 and isnotempty(v) ) then
			table.insert( imagenumbers, i)
			imagecount = imagecount + 1
			local w = getWidth(width, pargs['width' .. i])
			-- compute maximum width and width sum
			widthmax = math.max(widthmax, w)
			widthsum = widthsum + w
			-- store the modified width
			widths[i] = w
		end
	end

	-- sort the imagenumbers
	table.sort(imagenumbers)
	
	-- if total_width has been specified, rescale the image widths
	if( isnotempty(totalwidth) ) then
		totalwidth = tonumber(totalwidth)
		if( dir == 'vertical' ) then
			width = totalwidth - 12
		else
			local tw = totalwidth - 4 * (imagecount - 1) - 12
			local ar = {}
			local arsum = 0
			for k=1,imagecount do
				local i = imagenumbers[k]
				local h = tonumber( pargs['height' .. i] or '' ) or 0
				if (h > 0) then
					ar[i] = widths[i]/h
					height = h
				else
					ar[i] = widths[i]/100
				end
				arsum = arsum + ar[i]
			end
			local ht = tw/arsum
			local ws = 0
			for k=1,imagecount do
				local i = imagenumbers[k]
				widths[i] = math.floor(ar[i]*ht + 0.5)
				ws = ws + widths[i]
			end
			widthsum = ws
			if height then
				height = math.floor(ht)
			end
		end
	end	

	-- start building the array of images, if there are images
	if( imagecount > 0 ) then
		local bodywidth = 0
		local bg = pargs['background color'] or ''
		-- create the array of images
		local root = mw.html.create('div')
		root:addClass('thumb')
		root:addClass('tmulti')
		root:addClass(thumbclass[align] or 'tright')
		if( dir == 'vertical') then
			bodywidth = widthmax + 12
		else
			bodywidth = widthsum + 4 * (imagecount - 1) + 12
		end
		if( align == 'center' or align == 'centre' ) then
			root:addClass('center')
		end
		if( pargs['margin_top'] or args['margin_top']) then
			root:css('margin-top', pargs['margin_top'] or args['margin_top'])
		end
		if( pargs['margin_bottom'] or args['margin_bottom']) then
			root:css('margin-bottom', pargs['margin_bottom'] or args['margin_bottom'])
		end
		if( bg ~= '' ) then
			root:css('background-color', bg)
		end
		-- The body has a min-width of 100, which needs to be taken into account on specific widths
		bodywidth = math.max( 100, bodywidth - 8);
		local div = root:tag('div')
		div:addClass('thumbinner')
		div:css('width', tostring(bodywidth) .. 'px')
			:css('max-width', tostring(bodywidth) .. 'px')
		if( bg ~= '' ) then
			div:css('background-color', bg)
		end
		-- add the header
		if( isnotempty(header) ) then
			div:tag('div')
				:css('clear', 'both')
				:css('font-weight', 'bold')
				:css('text-align', pargs['header_align'] or 'center')
				:css('background-color', pargs['header_background'] or 'transparent')
				:wikitext(header)
		end
		-- loop through the images
		for k=1,imagecount do
			local imagediv = div:tag('div')
			imagediv:addClass('tsingle')
			if dir ~= 'vertical' then
				imagediv:css('float', 'left')
			end
			if bg ~= '' then
				imagediv:css('background-color', bg);
			end
			imagediv:css('margin', '1px')
			local i = imagenumbers[k]
			local img = pargs['image' .. i]
			local w = widths[i]
			imagediv:css('width', tostring(2 + w) .. 'px')
				:css('max-width', tostring(2 + w) .. 'px')
			imagediv:wikitext(renderImageCell(img, w, height, 
				pargs['link' .. i], pargs['alt' .. i], pargs['caption' .. i], captionalign))
		end
		-- only float content gives a parent height:0, so add a clearing div
		div:tag('div')
			:css('clear', 'left')
		-- add the footer
		if( isnotempty(footer) ) then
			div:tag('div')
				:addClass('thumbcaption')
				:css('clear', 'left')
				:css('text-align', pargs['footer_align'] or args['footer_align'] or 'left')
				:css('background-color', pargs['footer_background'] or 'transparent')
				:wikitext(footer)
		end
		return tostring(root)
	end
	return ''
end

function p.render( frame )
    return renderMultipleImages( frame )
end
 
return p