Module:Vector map

From OpenStreetMap Wiki
Jump to navigation Jump to search
[Edit] [Purge] Documentation

This module powers {{Vector map}}.

See also

local p = {}

function p.main(frame)
	-- Merge the current frame’s arguments with its parent frame’s arguments
	local args = {}
	for key, value in pairs(frame.args) do
		args[key] = value
	end
	local parent = frame:getParent() or {args={}}
	for key, value in pairs(parent.args) do
		args[key] = value
	end
	
	-- [[MediaWiki:Gadget-maps.js]] already defines default values for these
	-- parameters, but the HTML needs to specify an inline width and height
	-- upfront to keep the content from jumping around when the gadget loads.
	local width = args.width or 400
	local height = args.height or 400
	local zoom = args.zoom or 11
	
	-- Copy frame arguments verbatim to the container’s data attributes.
	local simpleAttrs = {
		"lat", "lon", "bearing", "pitch", "layer", "date",
		"navigation-position", "full-screen-position", "attribution-position",
	}
	local hasMarker = args.marker ~= "no"
	local dataAttrs = {
		["data-width"] = width,
		["data-height"] = height,
		["data-zoom"] = zoom,
	}
	for i, attr in ipairs(simpleAttrs) do
		dataAttrs["data-" .. attr] = args[attr]
	end
	
	local container = mw.html.create("div")
		:addClass("maplibre-map")
		:attr(dataAttrs)
		-- [[MediaWiki:Gadget-maps.js]] already sets these dimensions in an
		-- inline style, but the transcluded HTML needs to specify these same
		-- dimensions upfront to keep the content from jumping around when the
		-- gadget loads.
		:css("width", width .. "px")
		:css("height", height .. "px")
	
	-- Numbered series of arguments can start with an unnumbered argument.
	-- Also backfill legacy unnumbered arguments.
	args.commons1 = args.commons1 or args.commons
	args["marker1-lat"] = args["marker1-lat"] or args["marker-lat"] or args.mlat or args.lat
	args["marker1-lon"] = args["marker1-lon"] or args["marker-lon"] or args.mlon or args.lon

	-- Gather numbered series arguments by index.
	local commonsAttrIndices = {}
	local markerAttrIndices = {}
	for key, value in pairs(args) do
		local index = mw.ustring.match(key, "^commons(%d+)$")
		if index then
			table.insert(commonsAttrIndices, tonumber(index))
		end
		index = mw.ustring.match(key, "^marker(%d+)-lat$") or
			mw.ustring.match(key, "^marker(%d+)-lon")
		if index then
			table.insert(markerAttrIndices, tonumber(index))
		end
	end
	-- Numerically sort the indices in these arguments.
	table.sort(commonsAttrIndices)
	table.sort(markerAttrIndices)
	
	-- Insert a placeholder child element for each GeoJSON overlay hosted on
	-- Wikimedia Commons.
	if #commonsAttrIndices > 0 then
		for _, i in ipairs(commonsAttrIndices) do
			container:tag("span")
				:addClass("maplibre-map-geojson")
				:attr("data-commons", args["commons" .. i])
		end
	end
	
	-- Insert a placeholder child element for each marker overlay.
	if args.marker ~= "no" and #markerAttrIndices > 0 then
		-- Deduplicate indices since marker#-lat and marker#-lon typically come
		-- in pairs.
		local insertedIndices = {}
		for _, i in ipairs(markerAttrIndices) do
			if not insertedIndices[i] then
				container:tag("span")
					:addClass("maplibre-map-marker")
					:attr("data-lat", args["marker" .. i .. "-lat"])
					:attr("data-lon", args["marker" .. i .. "-lon"])
				insertedIndices[i] = true
			end
		end
	end
	
	return container
end

return p