Modul:Location map

require('Module:No globals')localp={}localgetArgs=require('Module:Arguments').getArgsfunctionp.getMapParams(map,frame)ifnotmapthenerror('The name of the location map definition to use must be specified',2)endlocalmoduletitle=mw.title.new('Module:Location map/data/'..map)ifnotmoduletitlethenerror('"'..map..'" is not a valid name for a location map definition',2)elseifmoduletitle.existsthenlocalmapData=mw.loadData('Module:Location map/data/'..map)returnfunction(name,params)ifmapData[name]==nilthenreturn''elseifparamsthenreturnmw.message.newRawMessage(tostring(mapData[name]),unpack(params)):plain()elsereturnmapData[name]endendelseifmw.title.new('Template:Location map '..map).existsthenlocalcache={}returnfunction(name,params)ifparamsthenreturnframe:expandTemplate{title='Location map '..map,args={name,unpack(params)}}elseifcache[name]==nilthencache[name]=frame:expandTemplate{title='Location map '..map,args={name}}endreturncache[name]endendelseerror('Unable to find the specified location map definition. Neither "Module:Location map/data/'..map..'" nor "Template:Location map '..map..'" exists',2)endendfunctionp.data(frame,args,map)ifnotargsthenargs=getArgs(frame)endifnotmapthenmap=p.getMapParams(args[1],frame)endlocalparams={}fork,vinipairs(args)doifk>2thenparams[k-2]=vendendreturnmap(args[2],#paramsandparams)endlocalhemisphereMultipliers={longitude={W=-1,w=-1,E=1,e=1},latitude={S=-1,s=-1,N=1,n=1}}localfunctiondecdeg(degrees,minutes,seconds,hemisphere,decimal,direction)ifnotdegreesthenifnotdecimalthenerror('No value was provided for '..direction,2)endlocalretval=tonumber(decimal)ifretvalthenreturnretvalenderror('The value "'..decimal..'" provided for '..direction..' is not valid',2)enddecimal=tonumber(degrees)ifnotdecimalthenerror('The degree value "'..degrees..'" provided for '..direction..' is not valid',2)endifminutesandnottonumber(minutes)thenerror('The minute value "'..minutes..'" provided for '..direction..' is not valid',2)endifsecondsandnottonumber(seconds)thenerror('The second value "'..seconds..'" provided for '..direction..' is not valid',2)enddecimal=decimal+(minutesor0)/60+(secondsor0)/3600ifhemispherethenlocalmultiplier=hemisphereMultipliers[direction][hemisphere]ifnotmultiplierthenerror('The hemisphere "'..hemisphere..'" provided for '..direction..' is not valid',2)enddecimal=decimal*multiplierendreturndecimalendfunctionp.top(frame,args,map)ifnotargsthenargs=getArgs(frame)endifnotmapthenmap=p.getMapParams(args[1],frame)endlocalwidthifnotargs.widththenwidth=math.floor((args.default_widthor240)*(tonumber(map('defaultscale'))or1)+0.5)elseifmw.ustring.sub(args.width,-2)=='px'thenwidth=mw.ustring.sub(args.width,1,-3)elsewidth=args.widthendlocalretval=args.float=='center'and'<div class="center">'or''ifargs.captionthenretval=retval..'<div class="thumb 'ifargs.float=='"left"'orargs.float=='left'thenretval=retval..'tleft'elseifargs.float=='"center"'orargs.float=='center'orargs.float=='"none"'orargs.float=='none'thenretval=retval..'tnone'elseretval=retval..'tright'endretval=retval..'"><div class="thumbinner" style="width:'..(width+2)..'px'ifargs.border=='none'thenretval=retval..';border:none'elseifargs.borderthenretval=retval..';border-color:'..args.borderendretval=retval..'"><div style="position:relative;width:'..width..'px'..(args.border~='none'and';border:1px solid lightgray">'or'">')elseretval=retval..'<div style="width:'..width..'px;'ifargs.float=='"left"'orargs.float=='left'thenretval=retval..'float:left;clear:left'elseifargs.float=='"center"'orargs.float=='center'thenretval=retval..'float:none;clear:both;margin-left:auto;margin-right:auto'elseifargs.float=='"none"'orargs.float=='none'thenretval=retval..'float:none;clear:none'elseretval=retval..'float:right;clear:right'endretval=retval..'"><div style="width:'..width..'px;padding:0"><div style="position:relative;width:'..width..'px">'endlocalimageifargs.AlternativeMapthenimage=args.AlternativeMapelseifargs.reliefandmap('image1')~=''thenimage=map('image1')elseimage=map('image')endretval=retval..'[[File:'..image..'|'..width..'px|'..(args.altor((args.labelormw.title.getCurrentTitle().text)..' is located in '..map('name')))..']]'ifargs.overlay_imagethenreturnretval..'<div style="position:absolute;top:0;left:0">[[File:'..args.overlay_image..'|'..width..'px|link=File:'..image..']]</div>'elsereturnretvalendendfunctionp.bottom(frame,args,map)ifnotargsthenargs=getArgs(frame)endifnotmapthenmap=p.getMapParams(args[1],frame)endlocalretval='</div><div '..(args.captionand'class="thumbcaption">'or'style="font-size:90%;padding-top:3px">')localcaption=frame.args.captionorframe:getParent().args.captionifcaptionandnotargs.caption_undefinedthenretval=retval..mw.text.trim(caption)elseretval=retval..(args.labelormw.title.getCurrentTitle().text)..' ('..map('name')..')'endretval=retval..'</div></div></div>'ifargs.float=='center'thenretval=retval..'</div>'endifargs.caption_undefinedthenretval=retval..'[[Category:Location maps using skew|!]]'endreturnretvalendfunctionp.container(frame,args,map)ifnotargsthenargs=getArgs(frame)endifnotmapthenmap=p.getMapParams(args[1],frame)endreturnp.top(frame,args,map)..(args.placesor'')..p.bottom(frame,args,map)endlocalfunctionmarkOuterDiv(x,y,content)return'<div style="position:absolute;top:'..y..'%;left:'..x..'%;height:0;width:0;margin:0;padding:0">'..content..'</div>'endlocalfunctionmarkImageDiv(mark,marksize,label,link,alt,title)localretval='<div style="position:relative;text-align:center;left:-'..math.floor(marksize/2+0.5)..'px;top:-'..math.floor(marksize/2+0.5)..'px;width:'..marksize..'px;font-size:'..marksize..'px;line-height:0"'..(titleand(' title="'..title..'">')or'>')ifmarksize~=0thenretval=retval..'[[File:'..mark..'|'..marksize..'x'..marksize..'px|'..label..'|link='..linkifaltthenretval=retval..'|alt='..altendretval=retval..']]'endreturnretval..'</div>'endlocalfunctionmarkLabelDiv(label,label_size,label_width,position,background,x)localretval='<div style="font-size:'..label_size..'%;line-height:110%;position:relative;top:-1.5em;width:'..label_width..'em;'ifposition=='top'then-- specified topretval=retval..'top:-2.65em;left:-3em;text-align:center'elseifposition=='bottom'then-- specified bottomretval=retval..'top:-0.15em;left:-3em;text-align:center'elseifposition=='left'or(tonumber(x)>70andposition~='right')then-- specified left or autodetected to leftretval=retval..'left:-6.5em;text-align:right'else-- specified right or autodetected to rightretval=retval..'left:0.5em;text-align:left'endretval=retval..'"><span style="padding:1px'ifbackgroundthenretval=retval..';background-color:'..backgroundendreturnretval..'">'..label..'</span></div>'endlocalfunctiongetX(longitude,left,right)localwidth=(right-left)%360ifwidth==0thenwidth=360endlocaldistanceFromLeft=(longitude-left)%360-- the distance needed past the map to the right equals distanceFromLeft - width. the distance needed past the map to the left equals 360 - distanceFromLeft. to minimize page stretching, go whichever way is shorterifdistanceFromLeft-width/2>=180thendistanceFromLeft=distanceFromLeft-360endreturn100*distanceFromLeft/widthendlocalfunctiongetY(latitude,top,bottom)return100*(top-latitude)/(top-bottom)endfunctionp.mark(frame,args,map)ifnotargsthenargs=getArgs(frame)endifnotmapthenmap=p.getMapParams(args[1],frame)endlocalx,y,longitude,latitudelongitude=decdeg(args.lon_deg,args.lon_min,args.lon_sec,args.lon_dir,args.long,'longitude')latitude=decdeg(args.lat_deg,args.lat_min,args.lat_sec,args.lat_dir,args.lat,'latitude')localretval=''ifargs.skeworargs.lon_shiftor(map('skew')~='')or(map('lat_skew')~='')or(map('crosses180')~='')thenretval=retval..'[[Category:Location maps using skew|'..args[1]..']]'endifmap('x')~=''thenx=frame:callParserFunction('#expr',map('x',{latitude,longitude}))elsex=getX(longitude,map('left'),map('right'))endifmap('y')~=''theny=frame:callParserFunction('#expr',map('y',{latitude,longitude}))elsey=getY(latitude,map('top'),map('bottom'))endlocalmark=args.markormap('mark')ifmark==''thenmark='Red pog.svg'endlocaldivContent=markImageDiv(mark,tonumber(args.marksize)ortonumber(map('marksize'))or8,args.labelormw.title.getCurrentTitle().text,args.linkor'',args.alt,args[2])ifargs.labelandargs.position~='none'thendivContent=divContent..markLabelDiv(args.label,args.label_sizeor90,args.label_widthor6,args.position,args.background,x)endreturnretval..markOuterDiv(x,y,divContent)endfunctionp.main(frame,args,map)ifnotargsthenargs=getArgs(frame)endifnotargs[1]thenargs[1]='World'endifnotmapthenmap=p.getMapParams(args[1],frame)endreturnp.top(frame,args,map)..p.mark(frame,args,map)..p.bottom(frame,args,map)endlocalfunctionmanyMakeArgs(fullArgs,n)ifn==1thenreturn{fullArgs[1],lat=fullArgs.lat1orfullArgs.lat,long=fullArgs.long1orfullArgs.long,lat_deg=fullArgs.lat1_degorfullArgs.lat_deg,lat_min=fullArgs.lat1_minorfullArgs.lat_min,lat_sec=fullArgs.lat1_secorfullArgs.lat_sec,lat_dir=fullArgs.lat1_dirorfullArgs.lat_dir,lon_deg=fullArgs.lon1_degorfullArgs.lon_deg,lon_min=fullArgs.lon1_minorfullArgs.lon_min,lon_sec=fullArgs.lon1_secorfullArgs.lon_sec,lon_dir=fullArgs.lon1_dirorfullArgs.lon_dir,mark=fullArgs.mark1orfullArgs.mark,marksize=fullArgs.mark1sizeorfullArgs.marksize,link=fullArgs.link1orfullArgs.link,label=fullArgs.label1orfullArgs.label,label_size=fullArgs.label1_sizeorfullArgs.label_size,position=fullArgs.position1orfullArgs.pos1orfullArgs.positionorfullArgs.pos,background=fullArgs.background1orfullArgs.bg1orfullArgs.backgroundorfullArgs.bg}elsereturn{fullArgs[1],lat=fullArgs['lat'..n],long=fullArgs['long'..n],lat_deg=fullArgs['lat'..n..'_deg'],lat_min=fullArgs['lat'..n..'_min'],lat_sec=fullArgs['lat'..n..'_sec'],lat_dir=fullArgs['lat'..n..'_dir'],lon_deg=fullArgs['lon'..n..'_deg'],lon_min=fullArgs['lon'..n..'_min'],lon_sec=fullArgs['lon'..n..'_sec'],lon_dir=fullArgs['lon'..n..'_dir'],mark=fullArgs['mark'..n],marksize=fullArgs['mark'..n..'size'],link=fullArgs['link'..n],label=fullArgs['label'..n],label_size=fullArgs['label'..n..'_size'],position=fullArgs['position'..n]orfullArgs['pos'..n],background=fullArgs['background'..n]orfullArgs['bg'..n]}endendfunctionp.many(frame,args,map)ifnotargsthenargs=getArgs(frame)endifnotargs[1]thenargs[1]='World'endifnotmapthenmap=p.getMapParams(args[1],frame)endlocalmarks={}localmarkhigh=args.markhighfork,vinpairs(args)do-- @todo change to uargs once we have thatifvthenifstring.sub(k,-4)=='_deg'thenk=string.sub(k,1,-5)endifstring.sub(k,1,3)=='lat'thenk=tonumber(string.sub(k,4))ifkthentable.insert(marks,k)endendendendtable.sort(marks)ifmarks[1]~=1and(args.latorargs.lat_deg)thentable.insert(marks,1,1)endlocalbody=''for_,vinipairs(marks)do-- don't try to consolidate this into the above loop. ordering of elements from pairs() is unspecifiedbody=body..p.mark(frame,manyMakeArgs(args,v),map)ifargs['mark'..v..'high']thenmarkhigh=trueendendargs.label=nil-- there is no global labelreturnp.top(frame,args,map)..body..p.bottom(frame,args,map)..(markhighand'[[Category:Location map many using markhigh parameter]]'or'')endreturnp