If you find this page useful and would like to be notified of changes made to this page, start by inputting your email below.
powered by ChangeDetection
| 40x40px | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This module implements the {{Location map}}, {{Location map+}}, {{Location map~}}, and {{Location map many}} templates. Please see the template pages for usage instructions.
local p = {}
local getArgs = require('Module:Arguments').getArgs
local function round(n, digits)
local mult = math.pow(10, digits)
return math.floor(n * mult + 0.5) / mult
end
local function getMapParams(map, frame)
if mw.title.new('Module:Location map/data/' .. map).exists then
local mapData = mw.loadData('Module:Location map/data/' .. map)
return function(name, params)
if mapData[name] == nil then
return ''
elseif params then
return mw.message.newRawMessage(mapData[name], unpack(params)):plain()
else
return mapData[name]
end
end
else
local cache = {}
return function(name, params)
if params then
return frame:expandTemplate{title = 'Location map ' .. map, args = { name, unpack(params) }}
else
if cache[name] == nil then
cache[name] = frame:expandTemplate{title = 'Location map ' .. map, args = { name }}
end
return cache[name]
end
end
end
end
local function decdeg(degrees, minutes, seconds, hemisphere, digits, decimal)
if degrees == nil then
return tonumber(decimal)
end
decimal = (degrees or 0) + (minutes or 0)/60 + (seconds or 0)/3600
if hemisphere == 'W' or hemisphere == 'w' or hemisphere == 'S' or hemisphere == 's' then
decimal = -decimal
end
if digits == nil then
digits = 7
end
return round(decimal, digits)
end
function p.top(frame, args, map)
if not args then
args = getArgs(frame)
end
if not map then
map = getMapParams(args[1], frame)
end
local width
if args.width then
width = mw.ustring.gsub(args.width, 'px', '')
else
width = round((args.default_width or 240) * (tonumber(map('defaultscale')) or 1), 0)
end
local retval = ''
if args.float == 'center' then
retval = retval .. '<div class="center">'
end
if args.caption then
retval = retval .. '<div class="thumb '
if args.float == '"left"' or args.float == 'left' then
retval = retval .. 'tleft'
elseif args.float == '"center"' or args.float == 'center' or args.float == '"none"' or args.float == 'none' then
retval = retval .. 'tnone'
else
retval = retval .. 'tright'
end
retval = retval .. '"><div class="thumbinner" style="width:' .. (width + 2) .. 'px; '
if args.border == 'none' then
retval = retval .. 'border: none;'
elseif args.border then
retval = retval .. 'border-color:' .. args.border .. ';'
end
retval = retval .. '"><div style="position: relative; '
if args.border ~= 'none' then
retval = retval .. 'border: 1px solid lightgray'
end
retval = retval .. '">'
else
retval = retval .. '<div style="width:' .. width .. 'px; '
if args.float == '"left"' or args.float == 'left' then
retval = retval .. 'float: left; clear: left'
elseif args.float == '"center"' or args.float == 'center' then
retval = retval .. 'float: none; clear: both; margin-left: auto; margin-right: auto'
elseif args.float == '"none"' or args.float == 'none' then
retval = retval .. 'float: none; clear: none'
else
retval = retval .. 'float: right; clear: right'
end
retval = retval .. '"><div style="width:' .. width .. 'px; padding:0"><div style="position: relative; ">'
end
local image
if args.AlternativeMap then
image = args.AlternativeMap
elseif args.relief and map('image1') ~= '' then
image = map('image1')
else
image = map('image')
end
retval = retval .. '[[File:' .. image .. '|' .. width .. 'px|' .. (args.alt or ((args.label or mw.title.getCurrentTitle().text) .. ' is located in ' .. map('name'))) .. ']]'
if args.overlay_image then
retval = retval .. '<div style="position:absolute; top: 0; left: 0">[[File:' .. args.overlay_image .. '|' .. width .. 'px|link=File:' .. image .. ']]</div>'
end
return retval
end
function p.bottom(frame, args, map)
if not args then
args = getArgs(frame)
end
if not map then
map = getMapParams(args[1], frame)
end
local retval = ''
retval = retval .. '</div><div ' .. (args.caption and 'class="thumbcaption"' or 'style="font-size: 90%; padding-top:3px"') .. '>'
local caption = frame.args.caption or frame:getParent().args.caption
if caption and not args.caption_undefined then
retval = retval .. mw.text.trim(caption)
else
retval = retval .. (args.label or mw.title.getCurrentTitle().text) .. ' (' .. map('name') .. ')'
end
retval = retval .. '</div></div></div>'
if args.float == 'center' then
retval = retval .. '</div>'
end
return retval
end
function p.container(frame, args, map)
if not args then
args = getArgs(frame)
end
if not map then
map = getMapParams(args[1], frame)
end
return p.top(frame, args, map) .. (args.places or '') .. p.bottom(frame, args, map)
end
local function markOuterDiv(x, y, content)
return '<div style="position:absolute;top:' .. y .. '%;left:' .. x .. '%;height:0;width:0;margin:0;padding:0">' .. content .. '</div>'
end
local function markImageDiv(mark, marksize, label, link, alt, title)
local retval = '<div style="position:relative;text-align:center;left:-' .. round(marksize / 2, 0) .. 'px;top:-' .. round(marksize / 2, 0) .. 'px;width:' .. marksize .. 'px;font-size:' .. marksize .. 'px;line-height:0"'
if title then
retval = retval .. ' title="' .. title .. '"'
end
retval = retval .. '>'
if marksize ~= 0 then
retval = retval .. '[[File:' .. mark .. '|' .. marksize .. 'x' .. marksize .. 'px|' .. label .. '|link=' .. link
if alt then
retval = retval .. '|alt=' .. alt
end
retval = retval .. ']]'
end
return retval .. '</div>'
end
local function markLabelDiv(label, label_size, label_width, position, background, x)
local retval = '<div style="font-size:' .. label_size .. '%;line-height:110%;position:relative;top:-1.5em;width:' .. label_width .. 'em;'
if position == 'top' then -- specified top
retval = retval .. 'top:-2.65em;left:-3em;text-align:center'
elseif position == 'bottom' then -- specified bottom
retval = retval .. 'top:-0.15em;left:-3em;text-align:center'
elseif position == 'left' or (tonumber(x) > 70 and position ~= 'right') then -- specified left or autodetected to left
retval = retval .. 'left:-6.5em;text-align:right'
else -- specified right or autodetected to right
retval = retval .. 'left:0.5em;text-align:left'
end
retval = retval .. '"><span style="padding:1px'
if background then
retval = retval .. ';background-color:' .. background
end
return retval .. '">' .. label .. '</span></div>'
end
local function getX(longitude, latitude, lon_dir, left, right, top, bottom, crosses180, skew, lon_shift)
local crosses180_correction = crosses180 and lon_dir == 'W' and (-36000/(left - right)) or 0
if skew then
local lat_ratio = (top - latitude)/(top - bottom)
local skew_factor = (1 - skew) * lat_ratio + skew
longitude = (longitude - 0.5 * (right + left) + lon_shift) * skew_factor + 0.5 * (right + left) - lon_shift
end
return round(crosses180_correction + 100 * (longitude - left) / (right - left), 1)
end
local function getY(latitude, top, bottom)
return round(100 * (top - latitude) / (top - bottom), 1)
end
function p.mark(frame, args, map)
if not args then
args = getArgs(frame)
end
if not map then
map = getMapParams(args[1], frame)
end
local x, y, longitude, latitide
longitude = decdeg(args.lon_deg, args.lon_min, args.lon_sec, args.lon_dir, nil, args.long)
latitude = decdeg(args.lat_deg, args.lat_min, args.lat_sec, args.lat_dir, nil, args.lat)
if map('x') ~= '' then
x = frame:callParserFunction('#expr', map('x', { latitude, longitude }))
else
x = getX(longitude, latitude, args.lon_dir, map('left'), map('right'), map('top'), map('bottom'), map('crosses180') ~= '', tonumber(args.skew or map('skew')), args.lon_shift or 0)
end
if map('y') ~= '' then
y = frame:callParserFunction('#expr', map('y', { latitude, longitude }))
else
y = getY(latitude, map('top'), map('bottom'))
end
local mark = args.mark or map('mark')
if mark == '' then
mark = 'Red pog.svg'
end
local divContent = markImageDiv(mark, tonumber(args.marksize) or tonumber(map('marksize')) or 8, args.label or mw.title.getCurrentTitle().text, args.link or '', args.alt, args[2])
if args.label and args.position ~= 'none' then
divContent = divContent .. markLabelDiv(args.label, args.label_size or 90, args.label_width or 6, args.position, args.background, x)
end
return markOuterDiv(x, y, divContent)
end
function p.main(frame, args, map)
if not args then
args = getArgs(frame)
end
if not args[1] then
args[1] = 'World'
end
if not map then
map = getMapParams(args[1], frame)
end
return p.top(frame, args, map) .. p.mark(frame, args, map) .. p.bottom(frame, args, map)
end
return p