Difference between revisions of "Module:Infobox mapframe"

From blackwiki
Jump to navigation Jump to search
test>Evad37
(remove config["coordinates"], config["coord"]; leave note referencing talk page)
test>Evad37
(update from sandbox: allow locally-specified coords to override Wikidata (per Template talk:Maplink#Template:Infobox power station/sandbox))
Line 1: Line 1:
 
local mf = require('Module:Mapframe')
 
local mf = require('Module:Mapframe')
  
function setCleanArgs(argsTable)
+
-- Trim whitespace from args, and remove empty args
 +
function trimArgs(argsTable)
 
local cleanArgs = {}
 
local cleanArgs = {}
 
for key, val in pairs(argsTable) do
 
for key, val in pairs(argsTable) do
Line 49: Line 50:
  
 
p._main = function(_config)
 
p._main = function(_config)
local config = setCleanArgs(_config)
+
-- `config` is the args passed to this module
 +
local config = trimArgs(_config)
 +
 +
-- Use wikidata by default
 +
local useWikidata = true
 +
-- Do not use wikidata when coords are specified, unless explicitly set
 +
if config.coord then
 +
useWikidata = config.wikidata and true or false
 +
end
 +
 +
-- Require wikidata item, or specified coords
 
local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
 
local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
if not wikidataId then
+
if not(wikidataId) and not(config.coord) then
 
return ''
 
return ''
 
end
 
end
  
-- Require wikidata item with coords, so something will be centred somewhere
+
-- Require coords (specified or from wikidata), so that map will be centred somewhere
local hasCoordinates = hasWikidataProperty(wikidataId, 'P625') -- P625 = coordinate location
+
-- (P625 = coordinate location)
 +
local hasCoordinates = hasWikidataProperty(wikidataId, 'P625') or config.coordinates or config.coord
 
if not hasCoordinates then   
 
if not hasCoordinates then   
 
return ''
 
return ''
 
end
 
end
  
-- arguments for mapframe module
+
-- `args` is the arguments which will be passed to the mapframe module
 
local args = {}
 
local args = {}
  
Line 94: Line 106:
  
 
-- Shape
 
-- Shape
args.type = "shape"
+
if useWikidata then
if config.id then args.id = config.id end
+
args.type = "shape"
args["stroke-width"] = config["shape-stroke-width"] or config["stroke-width"] or "3"
+
if config.id then args.id = config.id end
args["stroke-color"] = config["shape-stroke-color"] or config["shape-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or "#FF0000"
+
args["stroke-width"] = config["shape-stroke-width"] or config["stroke-width"] or "3"
 
+
args["stroke-color"] = config["shape-stroke-color"] or config["shape-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or "#FF0000"
 +
end
 +
 
-- Line
 
-- Line
args.type2 = "line"
+
if useWikidata then
if config.id then args.id2 = config.id end
+
args.type2 = "line"
args["stroke-width2"] = config["line-stroke-width"] or config["stroke-width"] or "5"
+
if config.id then args.id2 = config.id end
args["stroke-color2"] = config["line-stroke-color"] or config["line-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or "#FF0000"
+
args["stroke-width2"] = config["line-stroke-width"] or config["stroke-width"] or "5"
 +
args["stroke-color2"] = config["line-stroke-color"] or config["line-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or "#FF0000"
 +
end
  
 
-- Point
 
-- Point
 
local hasOsmRelationId = hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
 
local hasOsmRelationId = hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
local shouldShowPointMarker = not(hasOsmRelationId) or (config.marker and config.marker ~= 'none')
+
local shouldShowPointMarker = not(hasOsmRelationId) or (config.marker and config.marker ~= 'none') or (config.coordinates or config.coord)
 
if shouldShowPointMarker then
 
if shouldShowPointMarker then
args.type3 = "point"
+
local argNumber = useWikidata and "3" or ""
if config.id then args.id3 = config.id end
+
args["type"..argNumber] = "point"
if config.marker then args.marker3 = config.marker end
+
if config.id then args["id"..argNumber] = config.id end
args["marker-color3"] = config["marker-color"] or config["marker-colour"] or "#5E74F3"
+
if config.coord then args["coord"..argNumber] = config.coord end
 +
if config.marker then args["marker"..argNumber] = config.marker end
 +
args["marker-color"..argNumber] = config["marker-color"] or config["marker-colour"] or "#5E74F3"
 
end
 
end
 
local mapframe = mf._main(args)
 
local mapframe = mf._main(args)

Revision as of 01:58, 10 March 2019

Usage

Module that automatically makes a mapframe suitable for an infobox automatically, with minimal user input.

Generic usage

Just use the template {{Infobox mapframe}}, following the documentation there. This module may also be imported to another Lua module.

Automatic maps in infoboxes

Example edits: Template:Infobox prison, Template:Infobox prison/doc

Edit the infobox template (or its sandbox). Add lines like the following examples to the infobox. Replace numbers (4, or 97 to 99), with the appropriate number based on how many other image or data parameters are already present.

If placing near the top of infobox If placing at/near the bottom of the infobox
| image4     = {{#invoke:Infobox mapframe|auto}}
| caption4   = {{#invoke:Infobox mapframe|autocaption}}
| header97   = {{#if:{{{mapframe|}}}|Location}}
| data98     = {{#invoke:Infobox mapframe|auto}}
| data99     = {{#invoke:Infobox mapframe|autocaption}}

If the template has a {{#invoke:Check for unknown parameters}}, add the following parameters:

| mapframe | mapframe-caption | mapframe-custom | mapframe-id | mapframe-coord | mapframe-wikidata | mapframe-point | mapframe-shape | mapframe-frame-width | mapframe-frame-height | mapframe-shape-fill | mapframe-shape-fill-opacity | mapframe-stroke-color | mapframe-stroke-colour | mapframe-stroke-width | mapframe-marker | mapframe-marker-color | mapframe-marker-colour | mapframe-geomask | mapframe-geomask-stroke-color | mapframe-geomask-stroke-colour | mapframe-geomask-stroke-width | mapframe-geomask-fill | mapframe-geomask-fill-opacity | mapframe-zoom | mapframe-length_km | mapframe-length_mi | mapframe-area_km2 | mapframe-area_mi2 | mapframe-frame-coordinates | mapframe-frame-coord | mapframe-switcher

Once this is done, the above parameters will be available to users of the template.

  • Defaults values for these parameters can also be specified in the #invoke calls above, e.g. {{#invoke:Infobox mapframe|auto|mapframe-marker=library}} means that the library marker will be used, unless a different value is passed in to the template.
  • The maps are off by default, which means maps will not be displayed unless |mapframe=yes is present in the template call. To turn maps on by default, in the #invoke calls above add |onByDefault=yes – which means maps will be displayed unless |mapframe=no is present in the template call. onByDefault can also be set to a conditional, such as if another parameters is present, e.g. |onByDefault={{#if:{{{pushpin_map|}}}|no|yes}}
  • Add the new parameters to the document. You can use {{Infobox mapframe/doc/parameters}}. Specify default values (if any are used in the #invoke calls) using by adding parameters in the form Template:Ttparameter-nameTemplate:Ttvalue. The default output is shown here collapsed:
Extended content
  • Basic parameters:
    • mapframe – Specify yes or no to show or hide the map, overriding the default. Default: no
    • mapframe-caption – Caption for the map. Default: blank (or if |mapframe-geomask= is set, "Location in geomask's label")
    • mapframe-custom – Use a custom map instead of the automatic mapframe. Specify either a {{maplink}} template, or another template that generates a mapframe map, or an image name. If used, the subsequent mapframe parameters will be ignored. Default: not specified
    • mapframe-id or id or qid – Id (Q-number) of Wikidata item to use. Default: item for current page
    • mapframe-coordinates or mapframe-coord or coordinates or coord – Coordinates to use, instead of any on Wikidata. Use the {{Coord}} template, e.g. |coord={{Coord|12.34|N|56.78|E}}. Default: coordinates from Wikidata
    • mapframe-wikidata – Set to yes to show shape/line features from the wikidata item, if any, when |coord= is set. Default: not specified
  • Customise which features are displayed:
  • Other optional parameters:
    • mapframe-frame-width or mapframe-width – Frame width. Default: 270
    • mapframe-frame-height or mapframe-height – Frame height. Default: 200
    • mapframe-shape-fill – Color used to fill shape features. Default: #606060
    • mapframe-shape-fill-opacity – Opacity level of shape fill, a number between 0 and 1. Default: 0.5
    • mapframe-stroke-color or mapframe-stroke-colour – Color of line features, and outlines of shape features. Default: #ff0000
    • mapframe-stroke-width – Width of line features, and outlines of shape features; default is "5". Default: 5
    • mapframe-marker – Marker symbol to use for coordinates; see mw:Help:Extension:Kartographer/Icons for options. Default: not specified (i.e. blank)
      • Can also be set to blank to override any default marker symbol
    • mapframe-marker-color or mapframe-marker-colour – Background color for the marker. Default: #5E74F3
    • mapframe-geomask-stroke-color or mapframe-geomask-stroke-colour – Color of outline of geomask shape. Default: #555555
    • mapframe-geomask-stroke-width – Width of outline of geomask shape. Default: 2
    • mapframe-geomask-fill – Color used to fill outside geomask features. Default: #606060
    • mapframe-geomask-fill-opacity – Opacity level of fill outside geomask features, a number between 0 and 1. Default: 0.5
    • mapframe-zoom – Set the zoom level, from "1" to "18", to used if the zoom level cannot be determined automatically from object length or area. Default: 10
    • mapframe-length_km or mapframe-length_mi or mapframe-area_km2 or mapframe-area_mi2 – Determine zoom level by passing in object's length (in kilometres or miles) or area (in square kilometres or square miles). Default: not specified
    • mapframe-frame-coordinates or mapframe-frame-coord – Alternate latitude and longitude coordinates for initial placement of map, using {{coord}}. Default: derived from item coordinates

See also


local mf = require('Module:Mapframe')

-- Trim whitespace from args, and remove empty args
function trimArgs(argsTable)
	local cleanArgs = {}
	for key, val in pairs(argsTable) do
		if type(val) == 'string' then
			val = val:match('^%s*(.-)%s*$')
			if val ~= '' then
				cleanArgs[key] = val
			end
		else
			cleanArgs[key] = val
		end
	end
	return cleanArgs
end

function hasWikidataProperty(item_id, property_id)
	if not(item_id) or not(mw.wikibase.isValidEntityId(item_id)) or not(mw.wikibase.entityExists(item_id)) then
		return false
	end
	local statements = mw.wikibase.getBestStatements(item_id, property_id)
	if not statements or #statements == 0 then
		return false
	end
	local hasNoValue = ( statements[1].mainsnak and statements[1].mainsnak.snaktype == 'novalue' )
	if hasNoValue then
		return false
	end
	return true
end


function getZoom(length_km)
	-- max for zoom 2 is 6400km, for zoom 3 is 3200km, for zoom 4 is 1600km, etc
	local zoom = math.floor(8 - (math.log10(length_km) - 2)/(math.log10(2)))
	-- limit to values between 1 and 17
	return math.max(1, math.min(17, zoom))
end

local p = {}

p.main = function(frame)
	local parent = frame.getParent(frame)
	local parentArgs = parent.args
	local mapframe = p._main(parentArgs)
	return frame:preprocess(mapframe)
end

p._main = function(_config)
	-- `config` is the args passed to this module
	local config = trimArgs(_config)
	
	-- Use wikidata by default
	local useWikidata = true
	-- Do not use wikidata when coords are specified, unless explicitly set
	if config.coord then
		useWikidata = config.wikidata and true or false
	end
	
	-- Require wikidata item, or specified coords
	local wikidataId = config.id or mw.wikibase.getEntityIdForCurrentPage()
	if not(wikidataId) and not(config.coord) then
		return ''
	end

	-- Require coords (specified or from wikidata), so that map will be centred somewhere
	-- (P625 = coordinate location)
	local hasCoordinates = hasWikidataProperty(wikidataId, 'P625') or config.coordinates or config.coord
	if not hasCoordinates then  
		return ''
	end

	-- `args` is the arguments which will be passed to the mapframe module
	local args = {}

	-- Some defaults/overrides for infobox presentation
	args.display = "inline"
	args.frame = "yes"
	args.plain = "yes"
	args["frame-width"]  = config["frame-width"] or "270"
	args["frame-height"] = config["frame-height"] or "200"
	args["frame-align"]  = "center"

	args["frame-coord"] = config["frame-coordinates"] or config["frame-coord"] or ""
	-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;
	-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )

	-- deprecated lat and long parameters
	args["frame-lat"]    = config["frame-lat"] or config["frame-latitude"] or ""
	args["frame-long"]   = config["frame-long"] or config["frame-longitude"] or ""

	-- Calculate zoom from length or area (converted to km or km2)
	if config.length_km then
		args.zoom = getZoom(tonumber(config.length_km))
	elseif config.length_mi then
		args.zoom = getZoom(tonumber(config.length_mi)*1.609344)
	elseif config.area_km2 then
		args.zoom = getZoom(math.sqrt(tonumber(config.area_km2)))
	elseif config.area_mi2 then
		args.zoom = getZoom(math.sqrt(tonumber(config.area_mi2))*1.609344)
	else
		args.zoom = config.zoom or 10
	end

	-- Shape
	if useWikidata then
		args.type = "shape"
		if config.id then args.id = config.id end
		args["stroke-width"] = config["shape-stroke-width"] or config["stroke-width"] or "3"
		args["stroke-color"] = config["shape-stroke-color"] or config["shape-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or "#FF0000"
	end
	
	-- Line
	if useWikidata then
		args.type2 = "line"
		if config.id then args.id2 = config.id end
		args["stroke-width2"] = config["line-stroke-width"] or config["stroke-width"] or "5"
		args["stroke-color2"] = config["line-stroke-color"] or config["line-stroke-colour"] or config["stroke-color"] or config["stroke-colour"] or "#FF0000"
	end

	-- Point
	local hasOsmRelationId = hasWikidataProperty(wikidataId, 'P402') -- P402 is OSM relation ID
	local shouldShowPointMarker = not(hasOsmRelationId) or (config.marker and config.marker ~= 'none') or (config.coordinates or config.coord)
	if shouldShowPointMarker then
		local argNumber = useWikidata and "3" or ""
		args["type"..argNumber] = "point"
		if config.id then args["id"..argNumber] = config.id end
		if config.coord then args["coord"..argNumber] = config.coord end
		if config.marker then args["marker"..argNumber] = config.marker end
		args["marker-color"..argNumber] = config["marker-color"] or config["marker-colour"] or "#5E74F3"
	end
	local mapframe = mf._main(args)
	local tracking = hasOsmRelationId and '' or '[[Category:Infobox mapframe without OSM relation ID on Wikidata]]'
	return mapframe .. tracking
end

return p