MediaWiki:Wikiminiatlas.js: Difference between revisions

From SPCodex, The Smashing Pumpkins wiki
(Per request: https://meta.wikimedia.org/w/index.php?title=MediaWiki_talk:Wikiminiatlas.js&diff=4078170&oldid=4004208)
m (242 revisions imported)
 
(65 intermediate revisions by 7 users not shown)
Line 1: Line 1:
// [[File:Erioll_world.svg|18px]] '''WikiMiniAtlas''' <br>
// '''WikiMiniAtlas'''
// Script to embed interactive maps into pages that have coordinate templates <br>
// Script to embed interactive maps into pages that have coordinate templates
// also check my user page [[User:Dschwen]] for more toolsz
// also check my user page [[User:Dschwen]] for more tools
// <nowiki>
//
//
// Revision 16.5
// Revision 16.11
 
// Source: https://github.com/dschwen/wikiminiatlas/blob/master/wikiminiatlas.js
/* jshint laxcomma:true, smarttabs:true, quotmark:single, curly:false, es3:true, browser:true */
/* global mw,jQuery */
jQuery(function ($) {
jQuery(function ($) {
  var config = {
// WMA config
  var wc = {
   width  : 600,
   width  : 600,
   height : 400,
   height : 400,
   timeout : 5000,
   timeout : 5000,
   zoom : -1,
   zoom : -1,
  quicklink : false,
  quicklinkurl : '//maps.google.com/maps?ll={latdegdec},{londegdec}&spn={span},{span}&q={latdegdec},{londegdec}',
   enabled : true,
   enabled : true,
   onlytitle : false,
   onlytitle : false,
   flowTextTooltips: (location.host === "en.wikipedia.org"),
   flowTextTooltips: (location.host==='en.wikipedia.org'),
   alwaysTooltips: false,
   alwaysTooltips: false,
   iframeurl : '//toolserver.org/~dschwen/wma/iframe2.html',
   iframeurl : '//wma.wmflabs.org/iframe.html',
   imgbase  : '//toolserver.org/~dschwen/wma/tiles/',
   imgbase  : '//wma.wmflabs.org/tiles/',
   buttonImage: '//upload.wikimedia.org/wikipedia/commons/thumb/5/55/WMA_button2b.png/17px-WMA_button2b.png'
   buttonImage: '//upload.wikimedia.org/wikipedia/commons/thumb/5/55/WMA_button2b.png/17px-WMA_button2b.png',
  buttonImage2x: '//upload.wikimedia.org/wikipedia/commons/thumb/5/55/WMA_button2b.png/34px-WMA_button2b.png'
  },
  },
  strings = {
  strings = {
Line 27: Line 28:
   als:'Ort uf dr interaktivä Chartä zeigä',
   als:'Ort uf dr interaktivä Chartä zeigä',
   ar:'شاهد الموقع على الخريطة التفاعلية',
   ar:'شاهد الموقع على الخريطة التفاعلية',
  ast:'Ver el llugar nun mapa interactivu',
  az: 'Yeri interaktiv bir xəritədə göstər',
  bar:'Ort af da interaktivn Kartn zoagn',
   'be-tarask':'паказаць месцазнаходжаньне на інтэрактыўнай мапе',
   'be-tarask':'паказаць месцазнаходжаньне на інтэрактыўнай мапе',
   'be-x-old':'паказаць месцазнаходжаньне на інтэрактыўнай мапе',
   'be-x-old':'паказаць месцазнаходжаньне на інтэрактыўнай мапе',
   bar:'Ort af da interaktivn Kartn zoagn',
   bg:'Покажи местоположението на интерактивната карта',
   bg:'покажи местоположението на интерактивната карта',
   bh:'इंटरैक्टिव नक्सा पर लोकेशन देखल जाय',
   bpy:'জীবন্ত মানচিত্রগর মা মাপাহান দেখাদিতই',
   bpy:'জীবন্ত মানচিত্রগর মা মাপাহান দেখাদিতই',
   br:'diskouez al lec\'hiadur war ur gartenn etrewezhiat',
   br:'diskouez al lec\'hiadur war ur gartenn etrewezhiat',
   ca:'mostra la localització en un mapa interactiu',
   ca:'Mostra la localització en un mapa interactiu',
   cs:'zobraz místo na interaktivní mapě',
   cs:'zobraz místo na interaktivní mapě',
   da:'vis beliggenhed på interaktivt kort',
   da:'vis beliggenhed på interaktivt kort',
Line 39: Line 43:
   dsb:'Městno na interaktiwnej kórśe zwobrazniś',
   dsb:'Městno na interaktiwnej kórśe zwobrazniś',
   fa:'نمایش مکان در نقشه‌ای پویا',
   fa:'نمایش مکان در نقشه‌ای پویا',
   el:'εμφάνιση τοποθεσίας σε διαδραστικό χάρτη',
   el:'Εμφάνιση τοποθεσίας σε διαδραστικό χάρτη',
   en:'Show location on an interactive map',
   en:'Show location on an interactive map',
   bn:'সক্রিয় মানচিত্রে অবস্থান চিহ্নিত করুন',
   bn:'সক্রিয় মানচিত্রে অবস্থান চিহ্নিত করুন',
   eo:'Montru lokigon sur interaktiva karto',
   eo:'Montru lokigon sur interaktiva karto',
   eu:'erakutsi kokalekua mapa interaktibo batean',
   eu:'erakutsi kokalekua mapa interaktibo batean',
   es:'mostrar el lugar en un mapa interactivo',
   es:'Mostrar el lugar en un mapa interactivo',
   fr:'Montrer la localisation sur une carte interactive',
   fr:'Montrer la localisation sur une carte interactive',
   fur:'mostre la localizazion suntune mape interative',
   fur:'mostre la localizazion suntune mape interative',
Line 50: Line 54:
   gl:'Amosar o lugar nun mapa interactivo',
   gl:'Amosar o lugar nun mapa interactivo',
   he:'הראה מיקום במפה האינטראקטיבית',
   he:'הראה מיקום במפה האינטראקטיבית',
   hi:'सक्रिय नक्शे पर लोकेशन या स्थान दिखायें',  
   hi:'सक्रिय नक्शे पर लोकेशन या स्थान दिखायें',
   hr:'prikaži lokaciju na interaktivnom zemljovidu',
   hr:'prikaži lokaciju na interaktivnom zemljovidu',
   hsb:'Městno na interaktiwnej karće zwobraznić',
   hsb:'Městno na interaktiwnej karće zwobraznić',
Line 56: Line 60:
   hy:'ցուցադրել դիրքը ինտերակտիվ քարտեզի վրա',
   hy:'ցուցադրել դիրքը ինտերակտիվ քարտեզի վրա',
   id:'Tunjukkan lokasi di peta interaktif',
   id:'Tunjukkan lokasi di peta interaktif',
   ilo:'Ipakita ti lokasion idiay interaktibo a mapa',
   ilo:'Ipakita ti lokasion iti interaktibo a mapa',
   is:'sýna staðsetningu á gagnvirku korti',
   is:'sýna staðsetningu á gagnvirku korti',
   it:'mostra la località su una carta interattiva',
   it:'mostra la località su una carta interattiva',
   ja:'インタラクティブ地図上に位置を表示',
   ja:'インタラクティブ地図上に位置を表示',
  kk:'интерактивті картадан орналасуын көрсету',
   km:'បង្ហាញទីតាំងនៅលើផែនទីអន្តរកម្ម',
   km:'បង្ហាញទីតាំងនៅលើផែនទីអន្តរកម្ម',
  kn:'ನಕ್ಷೆಯಲ್ಲಿ ಸ್ಥಳವನ್ನು ತೋರಿಸು',
   ko:'인터랙티브 지도에 위치를 표시',
   ko:'인터랙티브 지도에 위치를 표시',
   lt:'Rodyti vietą interaktyviame žemėlapyje',
   lt:'Rodyti vietą interaktyviame žemėlapyje',
   lv:'Rādīt atrašanās vietu interaktīvajā kartē',
   lv:'Rādīt atrašanās vietu interaktīvajā kartē',
  min:'Tunjuakan lokasi pado peta',
   mk:'прикажи положба на интерактивна карта',
   mk:'прикажи положба на интерактивна карта',
  ms:'Tunjukkan lokasi pada peta interaktif',
  my:'မြေပုံပေါ်တွင် တည်နေရာပြရန်',
   nl:'de locatie op een interactieve kaart tonen',
   nl:'de locatie op een interactieve kaart tonen',
   no:'vis beliggenhet på interaktivt kart',
   no:'vis beliggenhet på interaktivt kart',
Line 72: Line 81:
   ro:'Arată locaţia pe o hartă interactivă',
   ro:'Arată locaţia pe o hartă interactivă',
   ru:'показать положение на интерактивной карте',
   ru:'показать положение на интерактивной карте',
  sco:'Shaw location on an interactive cairt',
   sk:'zobraz miesto na interaktívnej mape',
   sk:'zobraz miesto na interaktívnej mape',
   sl:'Prikaži lego na interaktivnem zemljevidu',
   sl:'Prikaži lego na interaktivnem zemljevidu',
  sr:'Прикажи локацију на интерактивној мапи',
   sq:'trego vendndodhjen në hartë',
   sq:'trego vendndodhjen në hartë',
   fi:'näytä paikka interaktiivisella kartalla',
   fi:'näytä paikka interaktiivisella kartalla',
   sv:'visa platsen på en interaktiv karta',
   sv:'visa platsen på en interaktiv karta',
   tr:'Yeri interaktif bir haritada göster',
   tr:'Yeri interaktif bir haritada göster',
   uk:'показати положення на інтерактивній карті',
   uk:'показати положення на інтерактивній мапі',
   vi:'xem vị trí này trên bản đồ tương tác',
   vi:'xem vị trí này trên bản đồ tương tác',
   vo:'Jonön topi su kaed itjäfidik',
   vo:'Jonön topi su kaed itjäfidik',
Line 86: Line 97:
   'zh-tw':'顯示該地在地圖上的位置',
   'zh-tw':'顯示該地在地圖上的位置',
   'zh-hk':'顯示該地在地圖上的位置'
   'zh-hk':'顯示該地在地圖上的位置'
  },
  map: {
  ast:'Mapa',
  az:'Xəritə',
  bg:'Карта',
  bh:'नक्सा',
  bn:'মানচিত্র',
  bs:'Karta',
  ca:'Mapa',
  de:'Karte',
  el:'Χάρτης',
  en:'Map',
  es:'Mapa',
  fa:'نقشه',
  fi:'Kartalla',
  fr:'Carte',
  gl:'Mapa',
  hu:'Térkép',
  id:'peta',
  ilo:'Mapa',
  ja:'地図',
  kn:'ನಕ್ಷೆ',
  min:'peta',
  mk:'Карта',
  ms:'Peta',
  my:'မြေပုံညွှန်း',
  nl:'Kaart',
  pt:'Mapa',
  ru:'карте',
  sco:'Cairt',
  sv:'Karta',
  uk:'мапі',
  zh:'地圖',
  'zh-cn':'地图',
  'zh-sg':'地图',
  'zh-tw':'地圖',
  'zh-hk':'地圖'
   },
   },
   close : {
   close : {
Line 91: Line 139:
   als:'Zuä machä',
   als:'Zuä machä',
   ar:'غلق',
   ar:'غلق',
  ast:'zarrar',
  az:'bağla',
   'be-tarask':'закрыць',
   'be-tarask':'закрыць',
   'be-x-old':'закрыць',
   'be-x-old':'закрыць',
   bar:'zuamachn',
   bar:'zuamachn',
   bg:'затвори',
   bg:'Затвори',
  bh:'बंद करीं',
   bpy:'জিপা',
   bpy:'জিপা',
   br:'serriñ',
   br:'serriñ',
   ca:'tanca',
  bs:'zatvori',
   ca:'Tanca',
   cs:'zavřít',
   cs:'zavřít',
   da:'luk',
   da:'luk',
Line 106: Line 158:
   en:'close',
   en:'close',
   bn:'বন্ধ করুন',
   bn:'বন্ধ করুন',
   eo:'fermu',  
   eo:'fermu',
   eu:'itxi',
   eu:'itxi',
   es:'cerrar',
   es:'cerrar',
Line 118: Line 170:
   hr:'zatvori',
   hr:'zatvori',
   hsb:'začinić',
   hsb:'začinić',
   hu:'bezárás',  
   hu:'bezárás',
   hy:'փակել',
   hy:'փակել',
   id:'tutup',
   id:'tutup',
Line 125: Line 177:
   it:'chiudi',
   it:'chiudi',
   ja:'閉じる',
   ja:'閉じる',
  kk:'жабу',
   km:'បិទ',
   km:'បិទ',
  kn:'ಮುಚ್ಚಿರಿ',
   ko:'닫기',
   ko:'닫기',
   lt:'uždaryti',
   lt:'uždaryti',
   lv:'aizvērt',
   lv:'aizvērt',
  min:'tutuik',
   mk:'затвори',
   mk:'затвори',
  ms:'tutup',
  my:'ပိတ်ရန်',
   nl:'sluiten',
   nl:'sluiten',
   no:'lukk',
   no:'lukk',
Line 138: Line 195:
   sk:'zatvoriť',
   sk:'zatvoriť',
   sl:'zapri',
   sl:'zapri',
  sr:'затвори',
   sq:'mbylle',
   sq:'mbylle',
   fi:'sulje',
   fi:'sulje',
Line 152: Line 210:
   },
   },
   resize : {
   resize : {
   ar: 'تغيير حجم',
   ar:'تغيير حجم',
   ca: 'redimensionar',
  ast:'redimensionar',
   de: 'Größe ändern',
  az:'ölçüləri dəyiş',
   dk: 'ændre størrelse',
  bg:'Промени големина',
   en: 'resize',
  bh: 'साइज बदलीं',
   es: 'cambiar el tamaño',
  bn:'মাপ পরিবর্তন করুন',
   fi: 'muuta kokoa',
   ca:'Redimensiona',
   fr: 'redimensionner',
   de:'Größe ändern',
   ja: 'サイズを変更する',
   dk:'ændre størrelse',
   nl: 'vergroten of verkleinen',
  el:'αλλαγή μεγέθους',
   no: 'endre størrelse',
   en:'resize',
   sv: 'ändra storlek'
   es:'cambiar el tamaño',
  fa:'تغییر اندازه',
   fi:'muuta kokoa',
   fr:'redimensionner',
  gl:'cambiar o tamaño',
  hu:'átméretezés',
  ilo:'baliwan ti kadakkel',
   ja:'サイズを変更する',
  kk:'өлшемін өзгерту',
  kn:'ಗಾತ್ರ ಬದಲಿಸು',
  min:'gadangan',
  mk:'промени големина',
  ms:'ubah saiz',
  my:'အရွယ်အစားညှိရန်',
   nl:'vergroten of verkleinen',
   no:'endre størrelse',
  pt:'alterar tamanho',
  ro:'redimensionare',
  uk:'змінити розмір',
  sl:'spremeni velikost',
  sr:'промени величину',
   sv:'ändra storlek',
  zh:'调整大小',
  'zh-cn':'调整大小',
  'zh-sg':'调整大小',
  'zh-tw':'調整大小',
  'zh-hk':'調整大小'
   }
   }
  },
  },
// domain of the WMA
wma_domain = '//wma.wmflabs.org',
language = '', site = '', awt='0', rtl = /(^|\s)rtl(\s|$)/.test(document.body.className),
// Get a specific, localized string
_msg = function(k) {
  return strings[k][language] || strings[k].en;
},
dbName = mw.config.get( 'wgDBname' ),


language = '', site = '', awt="0",
  iframe = { div: null, iframe: null, closebutton: null, resizebutton: null, resizehelper: null, indom: false },
  iframe = { div: null, iframe: null, closebutton: null, resizebutton: null, resizehelper: null, indom: false },
 
  page_title = (mw.config.get( 'wgNamespaceNumber' )==0) ? encodeURIComponent(mw.config.get( 'wgTitle' )) : '',
  page_title = ( mw.config.get('wgNamespaceNumber')===0 ) ? encodeURIComponent(mw.config.get('wgTitle')) : '',


  bodyc,
  bodyc,
Line 176: Line 269:
  coord_list = [],
  coord_list = [],
  coord_highlight = -1,
  coord_highlight = -1,
//region_index = 0,
//coordinate_region = '',


  kml = null,
  kml = null,
  mes = null,
  mes = null,
 
  initPromises = [];
  quicklinkbox = null,
quicklinkdest = null;
 
// check if we are in a right-to-left-script project
function isRTL() {
  return /(^|\s)rtl(\s|$)/.test(document.body.className);
}


  // get position on page
  // get position on page
Line 198: Line 282:
  function showIFrame(e) {
  function showIFrame(e) {
   var wi = iframe, my = yPos(this),
   var wi = iframe, my = yPos(this),
       newurl = config.iframeurl + '?wma=' + e.data.param + '&lang=' + site + '&page=' + page_title + '&awt=' + awt;
       newurl = wc.iframeurl + '?wma=' + e.data.param + '&lang=' + site + '&page=' + page_title + '&awt=' + awt;


   // insert iframe into DOM on demand (to preserve page caching)
   // insert iframe into DOM on demand (to preserve page caching)
   if( !wi.indom ) {
   if (!wi.indom) {
   $('#content,#mw_content').prepend(wi.div);
   $('#content,#mw_content').prepend(wi.div);
   wi.indom = true;
   wi.indom = true;
   }
   }


   if( wi.iframe.attr('src') !== newurl ) {
   if (wi.iframe.attr('src')!==newurl) {
   wi.iframe.attr( 'src', newurl );
   wi.iframe.attr( 'src', newurl );
   } else if( wi.div.css('display') !== 'none' ) {
   } else if( wi.div.css('display') !== 'none' ) {
Line 214: Line 298:
   wi.div.css( 'top', my+'px' ).show();
   wi.div.css( 'top', my+'px' ).show();
   return false;
   return false;
}
// fill in the map-service templates
function qlURL( lat, lon, zoom ) {
  var url  = config.quicklinkurl,
      span = Math.pow( 2.0, zoom) / 150.0;
  url = url.replace( /\{latdegdec\}/g, lat );
  url = url.replace( /\{londegdec\}/g, lon );
  url = url.replace( /\{span\}/g, span.toFixed(4) );
  return url;
  }
  }


  function highlight(i) {
  function highlight(i) {
   if( coord_highlight >= 0 ) {
   if (coord_highlight>=0) {
   $(coord_list[coord_highlight].obj).css('background-color','').find('span:visible').css('background-color','');
   $(coord_list[coord_highlight].obj).css('background-color','').find('span:visible').css('background-color','');
   }
   }
   coord_highlight = i;
   coord_highlight = i;
   if( coord_highlight >= 0 ) {
   if (coord_highlight>=0) {
   $(coord_list[coord_highlight].obj).css('background-color','yellow').find('span:visible').css('background-color','yellow');
   $(coord_list[coord_highlight].obj).css('background-color','yellow').find('span:visible').css('background-color','yellow');
   }
   }
Line 245: Line 317:
   d = e.data.split(',');
   d = e.data.split(',');
   mes = e.source;
   mes = e.source;
   switch(d[0]) {  
   switch(d[0]) {
   case 'request' :
   case 'request' :
     // make a JSON encodable copy of coord_list (no HTML objects!)
     // make a JSON encodable copy of coord_list (no HTML objects!)
     // find center and extent
     // find center and extent
     for( i = 0; i < coord_list.length; ++i ) {
     for (i=0; i<coord_list.length; ++i) {
     clist.coords[i] = {
     clist.coords[i] = {
       lat: coord_list[i].lat,
       lat: coord_list[i].lat,
Line 255: Line 327:
       title: coord_list[i].title.replace(/[\+_]/g,' ')
       title: coord_list[i].title.replace(/[\+_]/g,' ')
     };
     };
     if( coord_list[i].lat < minlat ) { minlat = coord_list[i].lat; }
     if (coord_list[i].lat<minlat) { minlat = coord_list[i].lat; }
     if( coord_list[i].lat > maxlat ) { maxlat = coord_list[i].lat; }
     if (coord_list[i].lat>maxlat) { maxlat = coord_list[i].lat; }
     geoext[i] = {
     geoext[i] = {
       x: Math.cos(coord_list[i].lon/180.0*Math.PI),
       x: Math.cos(coord_list[i].lon/180.0*Math.PI),
       y: Math.sin(coord_list[i].lon/180.0*Math.PI)
       y: Math.sin(coord_list[i].lon/180.0*Math.PI)
     }
     };
     sx += geoext[i].x;
     sx += geoext[i].x;
     sy += geoext[i].y;
     sy += geoext[i].y;
Line 268: Line 340:
     clist.latmin = minlat;
     clist.latmin = minlat;
     // extent in longitude
     // extent in longitude
     for( i = 0; i < geoext.length; ++i ) {
     for (i=0; i<geoext.length; ++i) {
     s = (geoext[i].x*sy-geoext[i].y*sx);
     s = (geoext[i].x*sy-geoext[i].y*sx);
     geoext[i].z = (geoext[i].x*sx+geoext[i].y*sy);
     geoext[i].z = (geoext[i].x*sx+geoext[i].y*sy);
     if( s<0 && ( ineg<0 || geoext[i].z<geoext[ineg].z ) ) { ineg=i; }
     if (s<0 && (ineg<0 || geoext[i].z<geoext[ineg].z)) { ineg=i; }
     if( s>0 && ( ipos<0 || geoext[i].z<geoext[ipos].z ) ) { ipos=i; }
     if (s>0 && (ipos<0 || geoext[i].z<geoext[ipos].z)) { ipos=i; }
     }
     }
     if( ipos>=0 && ineg>=0 ) {
     if (ipos>=0 && ineg>=0) {
     clist.lonleft  = coord_list[ipos].lon;
     clist.lonleft  = coord_list[ipos].lon;
     clist.lonright = coord_list[ineg].lon;
     clist.lonright = coord_list[ineg].lon;
     }
     }
     if( typeof JSON !== "undefined" ) {
     if ('JSON' in window) {
     mes.postMessage( JSON.stringify(clist), document.location.protocol + '//toolserver.org' );
     mes.postMessage(JSON.stringify(clist), document.location.protocol + wma_domain);
     if( kml !== null ) {
     if (kml!==null) {
       mes.postMessage( JSON.stringify(kml), document.location.protocol + '//toolserver.org' );
       mes.postMessage(JSON.stringify(kml), document.location.protocol + wma_domain);
     }
     }
     }
     }
    break;
   case 'unhighlight' :
   case 'unhighlight' :
     highlight(-1);  
     highlight(-1);
     break;
     break;
   case 'toggle' :  
   case 'toggle' :
     coord_list[parseInt(d[1])].mb.click();
     coord_list[parseInt(d[1],10)].mb.click();
     break;
     break;
   case 'scroll' :
   case 'scroll' :
     $("html:not(:animated),body:not(:animated)").animate({ scrollTop: $(coord_list[parseInt(d[1])].obj).offset().top - 20 + parseInt(d[2]||0) }, 500 );
     $('html:not(:animated),body:not(:animated)').animate({ scrollTop: $(coord_list[parseInt(d[1],10)].obj).offset().top - 20 + parseInt(d[2]||'0',10) }, 500 );
     iframe.div.css( { top: yPos( coord_list[parseInt(d[1])].obj ) + 'px'} );
     iframe.div.css( { top: yPos( coord_list[parseInt(d[1],10)].obj ) + 'px'} );
     // make sure scroll target gets highlighted
     // make sure scroll target gets highlighted
     setTimeout( function () { highlight(parseInt(d[1])); }, 200 );
     setTimeout(function () { highlight(parseInt(d[1],10)); }, 200);
     break;
     break;
   case 'highlight' :
   case 'highlight' :
     highlight(parseInt(d[1]));
     highlight(parseInt(d[1],10));
     break;
     break;
   }
   }
  }
  }


Line 305: Line 378:
  function parseParams(url) {
  function parseParams(url) {
   var map = {}, h, i, pair = url.substr(url.indexOf('?')+1).split('&');
   var map = {}, h, i, pair = url.substr(url.indexOf('?')+1).split('&');
   for( i=0; i<pair.length; ++i ) {
   for (i=0; i<pair.length; ++i) {
   h = pair[i].split('=');
   h = pair[i].split('=');
   map[h[0]] = h[1];
   map[h[0]] = h[1];
Line 315: Line 388:


  var wi = iframe,
  var wi = iframe,
    wc = config,
     marker = { lat:0, lon:0 }, coordinates = null,
     marker = { lat:0, lon:0 }, coordinates = null,
     link, links, key, len, coord_title, icons, startTime, content, mapbutton;
     links, key, startTime, mapbutton;


  // apply settings
  // apply settings
  if( typeof(wma_settings) === 'object' ) {
  if (typeof wma_settings==='object') {
   for( key in wma_settings ) {
   for (key in wma_settings) {
   if( typeof(wma_settings[key]) === typeof(wc[key]) ) {
   if (typeof wma_settings[key]===typeof wc[key]) { wc[key] = wma_settings[key]; }
    wc[key] = wma_settings[key];
  }
   }
   }
  }
  }


  if( wc.enabled === false ) { return; }
  if (wc.enabled===false) { return; }


  site = ( wgNoticeProject == "commons" ) ? "commons" : wgPageContentLanguage;
  site = (dbName==='commonswiki') ? 'commons' : (mw.config.get('wgUserVariant') || mw.config.get('wgPageContentLanguage'));
  language = mw.config.get( 'wgUserLanguage' );
  language = mw.config.get( 'wgUserLanguage' );
// bhwiki reports bho as language. I do not understand that yet, so let's add an exception
if (site === 'bho') site = 'bh';


  // remove icons from title coordinates
  // remove icons from title coordinates
  $('#coordinates,#coordinates-title,#tpl_Coordinaten').find('a.image').detach();
  $('#coordinates,#coordinates-title,#tpl_Coordinaten').find('a.image').detach();
 
  bodyc = $( wc.onlytitle ? '#coordinates,#coordinates-title' : 'html' );
  bodyc = $( wc.onlytitle ? '#coordinates,#coordinates-title' : 'html' );
  startTime = (new Date()).getTime();
  startTime = (new Date()).getTime();


  bodyc.find('a.external.text').each( function( key, link ) {
  bodyc.find('a.external.text').each( function( key, link ) {
   var ws, coord_params, params, zoomlevel, globe="Earth";
   var ws, coord_params, params, zoomlevel, globe='Earth';


   // check for timeout (every 10 links only)
   // check for timeout (every 10 links only)
   if( key % 10 === 9 && (new Date()).getTime() > startTime + wc.timeout ) {  
   if (key%10===9 && (new Date()).getTime() > startTime+wc.timeout) {
   return false; // break out of each
   return false; // break out of each
   }
   }


   if( !link.href || !coord_filter.exec(link.href) ){ // invalid links do not contain href attribute in IE!
   if (!('href' in link) || !coord_filter.exec(link.href)) { // invalid links do not contain href attribute in IE!
   return true;
   return true;
   }
   }
   marker.lat=(1.0*RegExp.$1) + ((RegExp.$2||0)/60.0) + ((RegExp.$3||0)/3600.0);
   marker.lat=(1.0*RegExp.$1) + ((RegExp.$2||0)/60.0) + ((RegExp.$3||0)/3600.0);
   if( RegExp.$4 !== 'N' ) { marker.lat*=-1; }
   if (RegExp.$4!=='N') { marker.lat*=-1; }
   marker.lon=(1.0*RegExp.$5) + ((RegExp.$6||0)/60.0) + ((RegExp.$7||0)/3600.0);
   marker.lon=(1.0*RegExp.$5) + ((RegExp.$6||0)/60.0) + ((RegExp.$7||0)/3600.0);
   if( RegExp.$8 === 'W' ) { marker.lon*=-1; }
   if (RegExp.$8==='W') { marker.lon*=-1; }
   coord_params = RegExp.$9;
   coord_params = RegExp.$9;


   // Zoom based on coordinate N/S precision  
   // Zoom based on coordinate N/S precision
   var coord_digits = RegExp.$3 ? 4 : RegExp.$2 ? 2 : RegExp.$1.length - (RegExp.$1+".").indexOf('.') - 1;
   var coord_digits = RegExp.$3 ? 4 : RegExp.$2 ? 2 : RegExp.$1.length - (RegExp.$1+'.').indexOf('.') - 1;
   zoomlevel = coord_digits * Math.log(10)/Math.log(2);
   zoomlevel = coord_digits * Math.log(10)/Math.log(2);


Line 363: Line 436:
   if( /_type:(airport|edu|pass|landmark|railwaystation)/.test(coord_params) ) {
   if( /_type:(airport|edu|pass|landmark|railwaystation)/.test(coord_params) ) {
   zoomlevel = 8;
   zoomlevel = 8;
   } else if( /_type:(event|forest|glacier)/.test(coord_params) ) {
   } else if (/_type:(event|forest|glacier)/.test(coord_params)) {
   zoomlevel = 6;
   zoomlevel = 6;
   } else if( /_type:(adm3rd|city|mountain|isle|river|waterbody)/.test(coord_params) ) {
   } else if (/_type:(adm3rd|city|mountain|isle|river|waterbody)/.test(coord_params)) {
   zoomlevel = 4;
   zoomlevel = 4;
   }
   }


   // wma shows dim approx 4e7m at zoom 0 or 1.5e8 is the scale of zoomlevel 0
   // wma shows dim approx 4e7m at zoom 0 or 1.5e8 is the scale of zoomlevel 0
   if( /_dim:([\d.+-]+)(km|m|_|$)/.exec(coord_params) ) {
   if (/_dim:([\d.+-]+)(km|m|_|$)/.exec(coord_params)) {
   zoomlevel = Math.log( ( RegExp.$2 === "km" ? 4e4 : 4e7 ) / RegExp.$1 ) / Math.log(2);
   zoomlevel = Math.log((RegExp.$2==='km' ? 4e4 : 4e7) / RegExp.$1)/Math.log(2);
   }
   }
   if( /_scale:(\d+)(_|$)/.exec(coord_params) ) {
   if (/_scale:(\d+)(_|$)/.exec(coord_params)) {
   zoomlevel = Math.log( 1.5e8/RegExp.$1 ) / Math.log(2);
   zoomlevel = Math.log(1.5e8/RegExp.$1) / Math.log(2);
   }
   }


   if( wc.zoom !== -1 ) { zoomlevel = wc.zoom; }
   if (wc.zoom!==-1) { zoomlevel = wc.zoom; }
   //if( zoomlevel > 12 ) { zoomlevel = 12; }
   //if( zoomlevel > 12 ) { zoomlevel = 12; }
   if( zoomlevel < 0 ) { zoomlevel = 0; }
   if (zoomlevel<0) { zoomlevel = 0; }


   function capitalize(s) { return s.substr(0,1).toUpperCase()+s.substr(1).toLowerCase(); }
   function capitalize(s) { return s.substr(0,1).toUpperCase()+s.substr(1).toLowerCase(); }
   if( /_globe:([^_&]+)/.test(coord_params) ) { globe = capitalize(RegExp.$1); }
   if (/_globe:([^_&]+)/.test(coord_params)) { globe = capitalize(RegExp.$1); }
   if( globe!="Earth" && globe!="Moon" && globe!="Mars" && globe!="Venus" && globe!="Mercury" && globe!="Io"  && globe!="Titan" ) { return; }
   if ($.inArray(globe,['Earth','Moon','Mars','Venus','Mercury','Io','Titan']) < 0 ) { return; }


   // Test the unicode Symbol
   // Test the unicode Symbol
   if( site === 'de' && link.parentNode.id !== 'coordinates' ) {
   if (site==='de' && link.parentNode.id!=='coordinates') {
   mapbutton = $('<span>♁</span>').css('color','blue');
   mapbutton = $('<span>♁</span>').css('color','blue');
   } else {
   } else {
   mapbutton = $('<img>').attr('src', wc.buttonImage);
   mapbutton = $('<img>').attr('src', wc.buttonImage).attr('srcset', wc.buttonImage + ' 1x, ' + wc.buttonImage2x + ' 2x');
   }
   }
   mapbutton.attr( {
   mapbutton.addClass('wmamapbutton noprint').attr( {
   title: strings.buttonTooltip[language] || strings.buttonTooltip.en,
   title: _msg('buttonTooltip'),
   alt: ''  
   alt: ''
   } )
   } )
//  .css('opacity', 0.75)
  .on('mouseenter', function (){ $(this).css('opacity', 0.75); })
//  .hover(function (){ $(this).fadeTo(50, 1.0); }, function () { $(this).fadeTo(250, 0.75); })
   .on('mouseleave', function () { $(this).css('opacity', ''); })
   .hover(function (){ $(this).css('opacity', 0.75); }, function () { $(this).css('opacity', ''); })
   .css('padding', rtl ? '0px 0px 0px 3px' : '0px 3px 0px 0px' ).css('cursor', 'pointer');
  .addClass('noprint')
   .css('padding', isRTL() ? '0px 0px 0px 3px' : '0px 3px 0px 0px' ).css('cursor', 'pointer');


   if( wc.alwaysTooltips || ( wc.flowTextTooltips && $(link).parents('li, table, #coordinates').length == 0 ) ) {
   if (wc.alwaysTooltips || ( wc.flowTextTooltips && $(link).parents('li, table, #coordinates').length===0)) {
   // insert tooltip rather than icon to improve text readability
   // insert tooltip rather than icon to improve text readability
   mapbutton = $('<span>').append(mapbutton).append("&nbsp;WikiMiniAtlas").css('cursor','pointer');
   mapbutton = $('<span>').append(mapbutton).append('&nbsp;WikiMiniAtlas').css('cursor','pointer');
   var tooltip = $('<div>').css( {
   var tooltip = $('<div>').css( {
     backgroundColor: 'white', padding: '0.2em', border: '1px solid black',
     backgroundColor: 'white', padding: '0.2em', border: '1px solid black',
     position: 'absolute', top: '1em', left: '0em',  
     position: 'absolute', top: '1em', left: '0em',
     display: 'none', zIndex : 15
     display: 'none', zIndex : 15
   }).append(mapbutton);
   }).append(mapbutton);
   $(link).wrap(  
   $(link).wrap(
     $('<span/>')
     $('<span>')
     .css( { position: 'relative', whiteSpace: 'nowrap' } )
     .css( { position: 'relative', whiteSpace: 'nowrap' } )
     .mouseleave( function () { tooltip.fadeOut() } )  
     .on('mouseleave', function () { tooltip.fadeOut(); })
     )
     )
     .before( tooltip )
     .before(tooltip)
     .mouseenter( function () { tooltip.fadeIn() } );
     .on('mouseenter', function () { tooltip.fadeIn(); });
   } else {
   } else {
   // insert icon directly
   // insert icon directly
   ws = $(link).css('whiteSpace');
   ws = $(link).css('whiteSpace');
   $(link).wrap( $('<span/>').css('whiteSpace', 'nowrap') ).css('whiteSpace', ws).before(mapbutton);
   if (site!=='de' || link.parentNode.id!=='coordinates') {
    $(link).wrap( $('<span>').css('whiteSpace', 'nowrap') ).css('whiteSpace', ws).before(mapbutton);
  } else {
    $('#coordinates').append('<span class="noprint coordinates-separator"> | </span>').append(mapbutton);
  }
   }
   }


   mapbutton.bind( 'click', { param:
   mapbutton.on( 'click', { param:
   marker.lat + '_' + marker.lon + '_' +
   marker.lat + '_' + marker.lon + '_' +
   wc.width + '_' + wc.height + '_' +
   wc.width + '_' + wc.height + '_' +
Line 431: Line 506:
   params = parseParams(link.href);
   params = parseParams(link.href);
   coord_list.push( { lat: marker.lat, lon: marker.lon, obj: link, mb: mapbutton, title: params.title || params.pagename || '' } );
   coord_list.push( { lat: marker.lat, lon: marker.lon, obj: link, mb: mapbutton, title: params.title || params.pagename || '' } );
} ); //end each


   if ( wc.quicklink ) {
var titlebutton = false;
   link.href = qlURL( marker.lat, marker.lon, zoomlevel );
 
  }
function addTitleButton( alat, alon, zoomlevel ) {
} ); //end each
   mapbutton = $('<img>')
  .on('mouseenter', function (){ $(this).css('opacity', 0.75); })
   .on('mouseleave', function () { $(this).css('opacity', ''); })
  .css('padding', rtl ? '0px 3px 0px 0px' : '0px 0px 0px 3px' ).css('cursor', 'pointer')
  .attr('src', wc.buttonImage).attr('srcset', wc.buttonImage + ' 1x, ' + wc.buttonImage2x + ' 2x')
  .addClass('wmamapbutton noprint')
  .on( 'click', { param:
    alat + '_' + alon + '_' +
    wc.width + '_' + wc.height + '_' +
    site + '_' + zoomlevel + '_' + language
  }, showIFrame ); // zoomlevel!


// awareness tooltip
  if (!titlebutton) {
// (experiment, only shown to anonymous users on en.wp if the browser supports localStorage)
  if ($('#coordinates').length) {
if( wgUserName === null && wgDBname === 'enwiki' &&
    $('#coordinates').find('img').detach();
    window.localStorage &&
    $('#coordinates').append(mapbutton);
    window.localStorage.getItem('wmatooltipdismissed') === null ) {
   } else {
  (function() {
     $('<span id="coordinates"></span>').text(_msg('map')).append(mapbutton).appendTo('#bodyContent');
  var wrap, span=$('#coordinates>span>span>img')
    , bubble = $('<div><div>').css( { width: '150px', border: '1px solid #bbb', borderRadius: '8px', position: 'absolute', bottom: '22px', right: '-4px', whiteSpace: 'normal', textAlign: 'left', padding: '0.25em 0.75em 0.25em 0.75em', fontSize: '90%', backgroundColor: '#f9f9f9', boxShadow: '4px 4px 10px rgba(0,0,0,0.2)' } ).text('Click the blue globe to open an interactive map.').append( $('<div></div>').css({position: 'absolute', width: 0, height: 0, bottom: '-10px', right: '10px', borderBottom:0, borderLeft: '5px solid transparent', borderRight:  '5px solid transparent', borderTop:  '10px solid #bbb'})  ).append( $('<div></div>').css({position: 'absolute', width: 0, height: 0, bottom: '-7px', right: '10px', borderBottom:0, borderLeft: '5px solid transparent', borderRight:  '5px solid transparent', borderTop:  '10px solid #f9f9f9'})  ).hide();
   if( span.length>0 ) {
     wrap = $('<span></span>').css( { width: '20px', height: '17px', position: 'relative' } );
    span.wrap(wrap).parent().append(bubble.fadeIn().click(function(){ bubble.fadeOut(); window.localStorage.setItem('wmatooltipdismissed','yes') }));
    setTimeout( function() { bubble.fadeOut() }, 10*1000 );
    awt="1";
   }
   }
   })();
  titlebutton = true;
   }
  }
  }


Line 457: Line 537:
  // also insert globe even if no title coords are given
  // also insert globe even if no title coords are given
  (function () {
  (function () {
   var i, l = $('table.metadata').find('a')
   var i, l = $('div.kmldata')
     ,alat = 0, alon = 0, np = 0
     ,alat = 0, alon = 0
     ,la1 = Infinity, la2 =- Infinity
     ,la1 = Infinity, la2 =- Infinity
     ,lo1 = Infinity, lo2 =- Infinity
     ,lo1 = Infinity, lo2 =- Infinity
     ,ex,ey;
     ,ex,ey, req;
  for( i = 0; i < l.length; ++i ) {// TODO: replace with .each
  if( $(l[i]).attr('href') === '//en.wikipedia.org/w/index.php?title=Template:Attached_KML/'+mw.config.get( 'wgPageName' )+'&action=raw' ) {
    coordinates = 1;
    $.ajax({
    url: l[i].href,
    dataType: 'xml',
    success: function (xml) {
      function processCoords(t) {
      var way = [], c, p = t.split(' '), i, lat, lon;
      for( i=0; i<p.length; ++i ) {
        c=p[i].split(',');
        if( c.length >= 2 ) {
        lat = parseFloat(c[1]);
        lon = parseFloat(c[0]);
        way.push( { lat: lat, lon: lon } );


        // determine extent of way
  for (i=0; i<l.length; ++i) {// TODO: replace with .each
        if( lat<la1 ) { la1=lat; }
  coordinates = true;
        if( lon<lo1 ) { lo1=lon; }
  req = $.ajax({
        if( lat>la2 ) { la2=lat; }
    url: '/wiki/' + encodeURI(l.eq(i).attr('title')) + '?action=raw',
        if( lon>lo2 ) { lo2=lon; }
    dataType: 'xml',
        }
    success: function (xml) {
    var zoomlevel;
 
    function processCoords(t) {
      var way = [], c, p = t.split(' '), i, lat, lon;
      for( i=0; i<p.length; ++i ) {
      c=p[i].split(',');
      if( c.length >= 2 ) {
        lat = parseFloat(c[1]);
        lon = parseFloat(c[0]);
        way.push( { lat: lat, lon: lon } );
 
        // determine extent of way
        if (lat<la1) { la1=lat; }
        if (lon<lo1) { lo1=lon; }
        if (lat>la2) { la2=lat; }
        if (lon>lo2) { lo2=lon; }
       }
       }
      return way;
       }
       }
      return way;
    }


      // initialize transfer datastructure
    // initialize transfer datastructure
      kml = { ways: [], areas: [] };
    kml = { ways: [], areas: [] };
window.kmldata = xml; // DEBUG!


      // ways
    // ways
      $(xml).find('LineString > coordinates').each(function () {
    $(xml).find('LineString > coordinates').each(function () {
      var way = processCoords( $(this).text() );
      var way = processCoords( $(this).text() );
      if( way.length > 0 ) { kml.ways.push(way); }
      if (way.length>0) { kml.ways.push(way); }
      });
    });


      // areas
    // areas
      $(xml).find('Polygon').each(function () {
    $(xml).find('Polygon').each(function () {
      var i, j, c,
      var area = { inner: [], outer: [] };
        area = { inner: [], outer: [] };


      // outer boundary
      // outer boundary
      $(this).find('outerBoundaryIs > LinearRing > coordinates').each(function () {
      $(this).find('outerBoundaryIs > LinearRing > coordinates').each(function () {
        var way = processCoords( $(this).text() );
      var way = processCoords($(this).text());
        if( way.length > 0 ) {
      if (way.length>0) { area.outer.push(way); }
        area.outer.push(way);
      });
        }
      });


      // inner boundary (holes in the polygon)
      // inner boundary (holes in the polygon)
      $(this).find('innerBoundaryIs > LinearRing > coordinates').each(function () {
      $(this).find('innerBoundaryIs > LinearRing > coordinates').each(function () {
        var way = processCoords( $(this).text() );
      var way = processCoords($(this).text());
        if( way.length > 0 ) { area.inner.push(way); }
      if (way.length>0) { area.inner.push(way); }
      });
 
      // only add if we have an outer boundary
      if( area.outer.length>0 ) { kml.areas.push(area); }
       });
       });


       // inset min/max extent
       // only add if we have an outer boundary
       kml.minlon = lo1;
       if (area.outer.length>0) { kml.areas.push(area); }
      kml.maxlon = lo2;
    });
      kml.minlat = la1;
      kml.maxlat = la2;
window.kml = kml; // DEBUG!


      // already got a request message
    // inset min/max extent
      if( mes !== null && kml.ways.length > 0 && typeof JSON !== "undefined" ) {
    kml.minlon = lo1;
      mes.postMessage( JSON.stringify(kml), document.location.protocol + '//toolserver.org' );
    kml.maxlon = lo2;
      }
    kml.minlat = la1;
    kml.maxlat = la2;


      // insert blue globe
    // already got a request message
      if( coord_list.length == 0 ) {
    if (mes!==null && kml.ways.length>0 && 'JSON' in window) {
      // determine center
      mes.postMessage(JSON.stringify(kml), document.location.protocol + wma_domain);
      alat = (la1+la2)/2;
    }
      alon = (lo1+lo2)/2;


      //determine zoomfactor
    // insert blue globe
      ex = (lo2-lo1)/180.0 * 3.0*128;
    if (coord_list.length===0 || (!$('#coordinates').find('.wmamapbutton').length)) {
      ey = (la2-la1)/180.0 * 3.0*128; // max extent in degrees, zoom0 has 3*128/180 px/degree
      // determine center
      for( zoomlevel = 0; zoomlevel < 12; ++zoomlevel ) {
      alat = (la1+la2)/2;
        if( ex>config.width/2 || ey>config.height/2 ) break;
      alon = (lo1+lo2)/2;
        ex *= 2; ey *= 2;
      }


      // add mapbutton
      //determine zoomfactor
      mapbutton = $('<img>')
      ex = (lo2-lo1)/180.0 * 3.0*128;
        .attr('src', wc.buttonImage)
      ey = (la2-la1)/180.0 * 3.0*128; // max extent in degrees, zoom0 has 3*128/180 px/degree
        .bind( 'click', { param:
      for (zoomlevel=0; zoomlevel<12; ++zoomlevel) {
          alat + '_' + alon + '_' +
      if( ex>wc.width/2 || ey>wc.height/2 ) break;
          wc.width + '_' + wc.height + '_' +
      ex *= 2; ey *= 2;
          site + '_' + zoomlevel + '_' + language
      }
        }, showIFrame ); // zoomlevel!


      if( $('#coordinates').length ) {
      // add mapbutton
        $('#coordinates').append(mapbutton);
      addTitleButton( alat, alon, zoomlevel );
      } else {
        $('<span id="coordinates">Map </span>').append(mapbutton).appendTo('#bodyContent');
      }
      }
     }
     }
     });
     }
    break;
  });
   }
  // Add request promise to init array, and cast any errors to success so that
   }
  // we don't abort init early when one of the requests failed. These are expected
  // to fail for titles we can't find.
   initPromises.push(req.then(null, function () { return $.Deferred().resolve(); } ));
   } // end for
  })();
  })();


  // prepare quicklink menu box
  // detect "All Coordinates"
  if ( coordinates !== null && wc.quicklink ) {
links = $('#coordinates>span>a');
  quicklinkbox = document.createElement('div');
  if (links.length && links[0].href.indexOf('http://www.lenz-online.de/cgi-bin/wiki/wiki-osm.pl') === 0) {
  // more to come :-)
  addTitleButton( 0, 0, 1 );
  coordinates = true;
  }
  }


  // prepare iframe to house the map
  // prepare iframe to house the map
  if ( coordinates !== null ) {
  if (coordinates!==null) {
   wi.div = $('<div/>').css( {
   wi.div = $('<div>').css( {
   width: (wc.width+2)+'px', height: (wc.height+2)+'px',
   width: (wc.width+2)+'px', height: (wc.height+2)+'px',
   margin: '0px', padding: '0px',  
   margin: '0px', padding: '0px',
   backgroundColor : 'white', border: '1px solid gray',
   backgroundColor : 'white', border: '1px solid gray',
   position: 'absolute', top: '1em', zIndex: 13, boxShadow: '3px 3px 25px rgba(0,0,0,0.3)'
   position: 'absolute', top: '1em', zIndex: 13, boxShadow: '3px 3px 25px rgba(0,0,0,0.3)'
   } ).css( isRTL() ? 'left' : 'right', '2em' ).hide();
   } ).css( rtl ? 'left' : 'right', '2em' ).hide();


   var rbrtl = [ '//upload.wikimedia.org/wikipedia/commons/b/b5/Button_resize.png',
   var rbrtl = [ '//upload.wikimedia.org/wikipedia/commons/b/b5/Button_resize.png',
                 '//upload.wikimedia.org/wikipedia/commons/3/30/Button_resize_rtl.png' ]
                 '//upload.wikimedia.org/wikipedia/commons/3/30/Button_resize_rtl.png' ];
   wi.resizebutton = $('<img>').attr( {  
   wi.resizebutton = $('<img>').attr( {
   title : strings.resize[language] || strings.resize.en,
   title : _msg('resize'),
   src : rbrtl[isRTL()?1:0]
   src : rbrtl[rtl?1:0]
   } ).hide().attr('ondragstart','return false');
   } ).hide().attr('ondragstart','return false');
 
 
   // cover the iframe to prevent loosing the mouse to the iframe during resizing
   // cover the iframe to prevent loosing the mouse to the iframe during resizing
   wi.resizehelper = $('<div/>').css( { position: 'absolute', top:0, left:0, zIndex: 20 } ).hide();
   wi.resizehelper = $('<div>').css( { position: 'absolute', top:0, left:0, zIndex: 20 } ).hide();


   wi.closebutton = $('<img>').attr( {  
   wi.closebutton = $('<img>').attr( {
   title : strings.close[language] || strings.close.en,
   title : _msg('close'),
   src : '//upload.wikimedia.org/wikipedia/commons/d/d4/Button_hide.png'
   src : '//upload.wikimedia.org/wikipedia/commons/d/d4/Button_hide.png'
   } ).css( {
   } ).css( {
   zIndex : 15, position : 'absolute', right : '11px', top : '9px', width : '18px', cursor : 'pointer'
   zIndex : 15, position : 'absolute', right : '11px', top : '9px', width : '18px', cursor : 'pointer'
   } ).click( function(e) { wi.div.hide() } );
   } ).click( function(e) { wi.div.hide(); } );


   wi.iframe = $('<iframe/>').attr( {
   wi.iframe = $('<iframe>')
  scrolling: 'no',
  .attr( { scrolling: 'no', frameBorder : 0 } )
  frameBorder : 0
  .css( {
  } ).css( {
    zIndex: 14, position: 'absolute', right: '1px', top: '1px',
  zIndex: 14, position: 'absolute', right: '1px', top: '1px',
    width: (wc.width)+'px', height: (wc.height)+'px',
  width: (wc.width)+'px', height: (wc.height)+'px',
    margin: '0px', padding: '0px'
  margin: '0px', padding: '0px'
  } );
  } );


   wi.div.append(wi.iframe);
   wi.div.append(wi.iframe);
Line 614: Line 681:
   wi.div.append(wi.closebutton);
   wi.div.append(wi.closebutton);
   (function () {
   (function () {
   var startx, starty, idle = true, dir = isRTL()?-1:1;
   var idle = true, dir = rtl?-1:1;
   function adjusthelper() {
   function adjusthelper() {
     wi.resizehelper.css( { width: (wc.width+2)+'px', height: (wc.height+2)+'px' } );
     wi.resizehelper.css( { width: (wc.width+2)+'px', height: (wc.height+2)+'px' } );
   }
   }
   wi.div.append(
   wi.div.append(
     $('<div/>')
     $('<div>')
     .css( {
     .css( {
       zIndex : 15, position : 'absolute', bottom : '3px',  
       zIndex : 15, position : 'absolute', bottom : '3px',
       width : '18px', height: '18px', cursor : (isRTL()?'se-resize':'sw-resize'),
       width : '18px', height: '18px', cursor : (rtl?'se-resize':'sw-resize'),
       'user-select': 'none', '-moz-user-select': 'none', '-ms-user-select': 'none'
       'user-select': 'none', '-moz-user-select': 'none', '-ms-user-select': 'none'
       } ).css( (isRTL()?'right':'left'), '3px' )
       } ).css( (rtl?'right':'left'), '3px' )
     .mouseenter( function(e) { wi.resizebutton.fadeIn() } )
     .on('mouseenter', function(e) { wi.resizebutton.fadeIn(); } )
     .mouseleave( function(e) { if( idle ) { wi.resizebutton.fadeOut(); } } )
     .on('mouseleave', function(e) { if( idle ) { wi.resizebutton.fadeOut(); } } )
     .mousedown( function(e) {
     .on('mousedown', function(e) {
       if( idle ) {  
       if (idle) {
        var lastx = e.pageX, lasty = e.pageY;
         wi.resizehelper.show();
         wi.resizehelper.show();
         adjusthelper();
         adjusthelper();
        lastx = e.pageX;
 
        lasty = e.pageY;
         $('body')
         $('body').bind('mouseup.wmaresize', function(e) {  
        .on('mouseup.wmaresize', function(e) {
        $('body').unbind('mousemove.wmaresize');
          $('body').off('mousemove.wmaresize');
        $('body').unbind('mouseup.wmaresize');  
          $('body').off('mouseup.wmaresize');
        idle = true;
          idle = true;
        wi.resizehelper.hide();
          wi.resizehelper.hide();
        } );
        } )
        $('body').bind('mousemove.wmaresize', function(e) {  
        .on('mousemove.wmaresize', function(e) {
        wc.width -= dir*(e.pageX-lastx);
          wc.width -= dir*(e.pageX-lastx);
        wc.height += (e.pageY-lasty);
          wc.height += (e.pageY-lasty);
        lastx = e.pageX; lasty = e.pageY;
          lastx = e.pageX; lasty = e.pageY;
        wi.div.css( { width: (wc.width+2)+'px', height: (wc.height+2)+'px' } );
          wi.div.css( { width: (wc.width+2)+'px', height: (wc.height+2)+'px' } );
        wi.iframe.css( { width: wc.width+'px', height: wc.height+'px' } );
          wi.iframe.css( { width: wc.width+'px', height: wc.height+'px' } );
        adjusthelper();
          adjusthelper();
        } );
        } );
 
         idle = false;
         idle = false;
       }
       }
       } )
       } )
     .append(wi.resizebutton)  
     .append(wi.resizebutton)
   );
   );
   })();
   })();


   $(window).bind('message', messageHub);
   $(window).on('message', messageHub);
 
  // Fire event for other code to extend or integrate with WMA
  if (initPromises.length) {
    $.when.apply( null, initPromises ).then(function () {
      mw.hook('WikiMiniAtlas.load').fire();
    } );
  } else {
    mw.hook('WikiMiniAtlas.load').fire();
  }
  }
  }
});
});


// </nowiki>
// </nowiki>

Latest revision as of 06:28, 1 August 2020

// '''WikiMiniAtlas'''
// Script to embed interactive maps into pages that have coordinate templates
// also check my user page [[User:Dschwen]] for more tools
//
// Revision 16.11
// Source: https://github.com/dschwen/wikiminiatlas/blob/master/wikiminiatlas.js
/* jshint laxcomma:true, smarttabs:true, quotmark:single, curly:false, es3:true, browser:true */
/* global mw,jQuery */
jQuery(function ($) {
 // WMA config
 var wc = {
  width  : 600,
  height : 400,
  timeout : 5000,
  zoom : -1,
  enabled : true,
  onlytitle : false,
  flowTextTooltips: (location.host==='en.wikipedia.org'),
  alwaysTooltips: false,
  iframeurl : '//wma.wmflabs.org/iframe.html',
  imgbase   : '//wma.wmflabs.org/tiles/',
  buttonImage: '//upload.wikimedia.org/wikipedia/commons/thumb/5/55/WMA_button2b.png/17px-WMA_button2b.png',
  buttonImage2x: '//upload.wikimedia.org/wikipedia/commons/thumb/5/55/WMA_button2b.png/34px-WMA_button2b.png'
 },
 strings = {
  buttonTooltip : {
   af:'Vertoon ligging op \'n interaktiwe kaart.',
   als:'Ort uf dr interaktivä Chartä zeigä',
   ar:'شاهد الموقع على الخريطة التفاعلية',
   ast:'Ver el llugar nun mapa interactivu',
   az: 'Yeri interaktiv bir xəritədə göstər',
   bar:'Ort af da interaktivn Kartn zoagn',
   'be-tarask':'паказаць месцазнаходжаньне на інтэрактыўнай мапе',
   'be-x-old':'паказаць месцазнаходжаньне на інтэрактыўнай мапе',
   bg:'Покажи местоположението на интерактивната карта',
   bh:'इंटरैक्टिव नक्सा पर लोकेशन देखल जाय',
   bpy:'জীবন্ত মানচিত্রগর মা মাপাহান দেখাদিতই',
   br:'diskouez al lec\'hiadur war ur gartenn etrewezhiat',
   ca:'Mostra la localització en un mapa interactiu',
   cs:'zobraz místo na interaktivní mapě',
   da:'vis beliggenhed på interaktivt kort',
   de:'Ort auf interaktiver Karte anzeigen',
   dsb:'Městno na interaktiwnej kórśe zwobrazniś',
   fa:'نمایش مکان در نقشه‌ای پویا',
   el:'Εμφάνιση τοποθεσίας σε διαδραστικό χάρτη',
   en:'Show location on an interactive map',
   bn:'সক্রিয় মানচিত্রে অবস্থান চিহ্নিত করুন',
   eo:'Montru lokigon sur interaktiva karto',
   eu:'erakutsi kokalekua mapa interaktibo batean',
   es:'Mostrar el lugar en un mapa interactivo',
   fr:'Montrer la localisation sur une carte interactive',
   fur:'mostre la localizazion suntune mape interative',
   fy:'it plak op in oanpasbere kaart oanjaan',
   gl:'Amosar o lugar nun mapa interactivo',
   he:'הראה מיקום במפה האינטראקטיבית',
   hi:'सक्रिय नक्शे पर लोकेशन या स्थान दिखायें',
   hr:'prikaži lokaciju na interaktivnom zemljovidu',
   hsb:'Městno na interaktiwnej karće zwobraznić',
   hu:'Mutasd a helyet egy interaktív térképen!',
   hy:'ցուցադրել դիրքը ինտերակտիվ քարտեզի վրա',
   id:'Tunjukkan lokasi di peta interaktif',
   ilo:'Ipakita ti lokasion iti interaktibo a mapa',
   is:'sýna staðsetningu á gagnvirku korti',
   it:'mostra la località su una carta interattiva',
   ja:'インタラクティブ地図上に位置を表示',
   kk:'интерактивті картадан орналасуын көрсету',
   km:'បង្ហាញទីតាំងនៅលើផែនទីអន្តរកម្ម',
   kn:'ನಕ್ಷೆಯಲ್ಲಿ ಸ್ಥಳವನ್ನು ತೋರಿಸು',
   ko:'인터랙티브 지도에 위치를 표시',
   lt:'Rodyti vietą interaktyviame žemėlapyje',
   lv:'Rādīt atrašanās vietu interaktīvajā kartē',
   min:'Tunjuakan lokasi pado peta',
   mk:'прикажи положба на интерактивна карта',
   ms:'Tunjukkan lokasi pada peta interaktif',
   my:'မြေပုံပေါ်တွင် တည်နေရာပြရန်',
   nl:'de locatie op een interactieve kaart tonen',
   no:'vis beliggenhet på interaktivt kart',
   nv:'kéyah tʼáá dah siʼą́ą́ ńtʼę́ę́ʼ beʼelyaaígíí',
   pl:'Pokaż lokalizację na mapie interaktywnej',
   pt:'mostrar a localidade num mapa interactivo',
   ro:'Arată locaţia pe o hartă interactivă',
   ru:'показать положение на интерактивной карте',
   sco:'Shaw location on an interactive cairt',
   sk:'zobraz miesto na interaktívnej mape',
   sl:'Prikaži lego na interaktivnem zemljevidu',
   sr:'Прикажи локацију на интерактивној мапи',
   sq:'trego vendndodhjen në hartë',
   fi:'näytä paikka interaktiivisella kartalla',
   sv:'visa platsen på en interaktiv karta',
   tr:'Yeri interaktif bir haritada göster',
   uk:'показати положення на інтерактивній мапі',
   vi:'xem vị trí này trên bản đồ tương tác',
   vo:'Jonön topi su kaed itjäfidik',
   zh:'显示该地在地图上的位置',
   'zh-cn':'显示该地在地图上的位置',
   'zh-sg':'显示该地在地图上的位置',
   'zh-tw':'顯示該地在地圖上的位置',
   'zh-hk':'顯示該地在地圖上的位置'
  },
  map: {
   ast:'Mapa',
   az:'Xəritə',
   bg:'Карта',
   bh:'नक्सा',
   bn:'মানচিত্র',
   bs:'Karta',
   ca:'Mapa',
   de:'Karte',
   el:'Χάρτης',
   en:'Map',
   es:'Mapa',
   fa:'نقشه',
   fi:'Kartalla',
   fr:'Carte',
   gl:'Mapa',
   hu:'Térkép',
   id:'peta',
   ilo:'Mapa',
   ja:'地図',
   kn:'ನಕ್ಷೆ',
   min:'peta',
   mk:'Карта',
   ms:'Peta',
   my:'မြေပုံညွှန်း',
   nl:'Kaart',
   pt:'Mapa',
   ru:'карте',
   sco:'Cairt',
   sv:'Karta',
   uk:'мапі',
   zh:'地圖',
   'zh-cn':'地图',
   'zh-sg':'地图',
   'zh-tw':'地圖',
   'zh-hk':'地圖'
  },
  close : {
   af:'Sluit',
   als:'Zuä machä',
   ar:'غلق',
   ast:'zarrar',
   az:'bağla',
   'be-tarask':'закрыць',
   'be-x-old':'закрыць',
   bar:'zuamachn',
   bg:'Затвори',
   bh:'बंद करीं',
   bpy:'জিপা',
   br:'serriñ',
   bs:'zatvori',
   ca:'Tanca',
   cs:'zavřít',
   da:'luk',
   de:'schließen',
   dsb:'zacyniś',
   nv:'doo yishʼį́ nisin da',
   el:'έξοδος',
   en:'close',
   bn:'বন্ধ করুন',
   eo:'fermu',
   eu:'itxi',
   es:'cerrar',
   fa:'بستن',
   fr:'Quitter',
   fur:'siere',
   fy:'ticht',
   gl:'pechar',
   he:'לסגור',
   hi:'बंद करें',
   hr:'zatvori',
   hsb:'začinić',
   hu:'bezárás',
   hy:'փակել',
   id:'tutup',
   ilo:'irikep',
   is:'loka',
   it:'chiudi',
   ja:'閉じる',
   kk:'жабу',
   km:'បិទ',
   kn:'ಮುಚ್ಚಿರಿ',
   ko:'닫기',
   lt:'uždaryti',
   lv:'aizvērt',
   min:'tutuik',
   mk:'затвори',
   ms:'tutup',
   my:'ပိတ်ရန်',
   nl:'sluiten',
   no:'lukk',
   pl:'zamknij',
   pt:'fechar',
   ro:'închide',
   ru:'закрыть',
   sk:'zatvoriť',
   sl:'zapri',
   sr:'затвори',
   sq:'mbylle',
   fi:'sulje',
   sv:'stäng',
   tr:'kapat',
   uk:'закрити',
   vi:'đóng',
   vo:'färmükön',
   zh:'关闭',
   'zh-cn':'关闭',
   'zh-sg':'关闭',
   'zh-tw':'關閉',
   'zh-hk':'關閉'
  },
  resize : {
   ar:'تغيير حجم',
   ast:'redimensionar',
   az:'ölçüləri dəyiş',
   bg:'Промени големина',
   bh: 'साइज बदलीं',
   bn:'মাপ পরিবর্তন করুন',
   ca:'Redimensiona',
   de:'Größe ändern',
   dk:'ændre størrelse',
   el:'αλλαγή μεγέθους',
   en:'resize',
   es:'cambiar el tamaño',
   fa:'تغییر اندازه',
   fi:'muuta kokoa',
   fr:'redimensionner',
   gl:'cambiar o tamaño',
   hu:'átméretezés',
   ilo:'baliwan ti kadakkel',
   ja:'サイズを変更する',
   kk:'өлшемін өзгерту',
   kn:'ಗಾತ್ರ ಬದಲಿಸು',
   min:'gadangan',
   mk:'промени големина',
   ms:'ubah saiz',
   my:'အရွယ်အစားညှိရန်',
   nl:'vergroten of verkleinen',
   no:'endre størrelse',
   pt:'alterar tamanho',
   ro:'redimensionare',
   uk:'змінити розмір',
   sl:'spremeni velikost',
   sr:'промени величину',
   sv:'ändra storlek',
   zh:'调整大小',
   'zh-cn':'调整大小',
   'zh-sg':'调整大小',
   'zh-tw':'調整大小',
   'zh-hk':'調整大小'
  }
 },
 // domain of the WMA
 wma_domain = '//wma.wmflabs.org',

 language = '', site = '', awt='0', rtl = /(^|\s)rtl(\s|$)/.test(document.body.className),

 // Get a specific, localized string
 _msg = function(k) {
  return strings[k][language] || strings[k].en;
 },
 dbName = mw.config.get( 'wgDBname' ),

 iframe = { div: null, iframe: null, closebutton: null, resizebutton: null, resizehelper: null, indom: false },

 page_title = ( mw.config.get('wgNamespaceNumber')===0 ) ? encodeURIComponent(mw.config.get('wgTitle')) : '',

 bodyc,
 coord_filter = /&params=([\d.+-]+)_([\d.+-]*)_?([\d.+-]*)_?([NSZ])_([\d.+-]+)_([\d.+-]*)_?([\d.+-]*)_?([EOW])([^&=<>|]{0,250})/,
 coord_list = [],
 coord_highlight = -1,

 kml = null,
 mes = null,
 initPromises = [];

 // get position on page
 function yPos(el) {
  return $(el).offset().top + $(el).outerHeight();
 }

 // show, move, and update iframe
 function showIFrame(e) {
  var wi = iframe, my = yPos(this),
      newurl = wc.iframeurl + '?wma=' + e.data.param + '&lang=' + site + '&page=' + page_title + '&awt=' + awt;

  // insert iframe into DOM on demand (to preserve page caching)
  if (!wi.indom) {
   $('#content,#mw_content').prepend(wi.div);
   wi.indom = true;
  }

  if (wi.iframe.attr('src')!==newurl) {
   wi.iframe.attr( 'src', newurl );
  } else if( wi.div.css('display') !== 'none' ) {
   wi.div.hide();
   return false;
  }
  wi.div.css( 'top', my+'px' ).show();
  return false;
 }

 function highlight(i) {
  if (coord_highlight>=0) {
   $(coord_list[coord_highlight].obj).css('background-color','').find('span:visible').css('background-color','');
  }
  coord_highlight = i;
  if (coord_highlight>=0) {
   $(coord_list[coord_highlight].obj).css('background-color','yellow').find('span:visible').css('background-color','yellow');
  }
 }

 function messageHub(e) {
  var i, d, clist = { coords: [] }
    , geoext = [], sx=0, sy=0, s
    , minlat = Infinity, maxlat = -Infinity, ineg = -1, ipos = -1;
  e = e.originalEvent;
  d = e.data.split(',');
  mes = e.source;
  switch(d[0]) {
   case 'request' :
    // make a JSON encodable copy of coord_list (no HTML objects!)
    // find center and extent
    for (i=0; i<coord_list.length; ++i) {
     clist.coords[i] = {
      lat: coord_list[i].lat,
      lon: coord_list[i].lon,
      title: coord_list[i].title.replace(/[\+_]/g,' ')
     };
     if (coord_list[i].lat<minlat) { minlat = coord_list[i].lat; }
     if (coord_list[i].lat>maxlat) { maxlat = coord_list[i].lat; }
     geoext[i] = {
      x: Math.cos(coord_list[i].lon/180.0*Math.PI),
      y: Math.sin(coord_list[i].lon/180.0*Math.PI)
     };
     sx += geoext[i].x;
     sy += geoext[i].y;
    }
    clist.loncenter = Math.atan2(sy,sx)*180.0/Math.PI;
    clist.latmax = maxlat;
    clist.latmin = minlat;
    // extent in longitude
    for (i=0; i<geoext.length; ++i) {
     s = (geoext[i].x*sy-geoext[i].y*sx);
     geoext[i].z = (geoext[i].x*sx+geoext[i].y*sy);
     if (s<0 && (ineg<0 || geoext[i].z<geoext[ineg].z)) { ineg=i; }
     if (s>0 && (ipos<0 || geoext[i].z<geoext[ipos].z)) { ipos=i; }
    }
    if (ipos>=0 && ineg>=0) {
     clist.lonleft  = coord_list[ipos].lon;
     clist.lonright = coord_list[ineg].lon;
    }
    if ('JSON' in window) {
     mes.postMessage(JSON.stringify(clist), document.location.protocol + wma_domain);
     if (kml!==null) {
      mes.postMessage(JSON.stringify(kml), document.location.protocol + wma_domain);
     }
    }
    break;
   case 'unhighlight' :
    highlight(-1);
    break;
   case 'toggle' :
    coord_list[parseInt(d[1],10)].mb.click();
    break;
   case 'scroll' :
    $('html:not(:animated),body:not(:animated)').animate({ scrollTop: $(coord_list[parseInt(d[1],10)].obj).offset().top - 20 + parseInt(d[2]||'0',10) }, 500 );
    iframe.div.css( { top: yPos( coord_list[parseInt(d[1],10)].obj ) + 'px'} );
    // make sure scroll target gets highlighted
    setTimeout(function () { highlight(parseInt(d[1],10)); }, 200);
    break;
   case 'highlight' :
    highlight(parseInt(d[1],10));
    break;
  }
 }

 // parse url parameters into a hash
 function parseParams(url) {
  var map = {}, h, i, pair = url.substr(url.indexOf('?')+1).split('&');
  for (i=0; i<pair.length; ++i) {
   h = pair[i].split('=');
   map[h[0]] = h[1];
  }
  return map;
 }

 // Insert the IFrame into the page.

 var wi = iframe,
     marker = { lat:0, lon:0 }, coordinates = null,
     links, key, startTime, mapbutton;

 // apply settings
 if (typeof wma_settings==='object') {
  for (key in wma_settings) {
   if (typeof wma_settings[key]===typeof wc[key]) { wc[key] = wma_settings[key]; }
  }
 }

 if (wc.enabled===false) { return; }

 site = (dbName==='commonswiki') ? 'commons' : (mw.config.get('wgUserVariant') || mw.config.get('wgPageContentLanguage'));
 language = mw.config.get( 'wgUserLanguage' );

 // bhwiki reports bho as language. I do not understand that yet, so let's add an exception
 if (site === 'bho') site = 'bh';

 // remove icons from title coordinates
 $('#coordinates,#coordinates-title,#tpl_Coordinaten').find('a.image').detach();

 bodyc = $( wc.onlytitle ? '#coordinates,#coordinates-title' : 'html' );
 startTime = (new Date()).getTime();

 bodyc.find('a.external.text').each( function( key, link ) {
  var ws, coord_params, params, zoomlevel, globe='Earth';

  // check for timeout (every 10 links only)
  if (key%10===9 && (new Date()).getTime() > startTime+wc.timeout) {
   return false; // break out of each
  }

  if (!('href' in link) || !coord_filter.exec(link.href)) { // invalid links do not contain href attribute in IE!
   return true;
  }
  marker.lat=(1.0*RegExp.$1) + ((RegExp.$2||0)/60.0) + ((RegExp.$3||0)/3600.0);
  if (RegExp.$4!=='N') { marker.lat*=-1; }
  marker.lon=(1.0*RegExp.$5) + ((RegExp.$6||0)/60.0) + ((RegExp.$7||0)/3600.0);
  if (RegExp.$8==='W') { marker.lon*=-1; }
  coord_params = RegExp.$9;

  // Zoom based on coordinate N/S precision
  var coord_digits = RegExp.$3 ? 4 : RegExp.$2 ? 2 : RegExp.$1.length - (RegExp.$1+'.').indexOf('.') - 1;
  zoomlevel = coord_digits * Math.log(10)/Math.log(2);

  // Find a sensible Zoom-level based on type
  if( /_type:(airport|edu|pass|landmark|railwaystation)/.test(coord_params) ) {
   zoomlevel = 8;
  } else if (/_type:(event|forest|glacier)/.test(coord_params)) {
   zoomlevel = 6;
  } else if (/_type:(adm3rd|city|mountain|isle|river|waterbody)/.test(coord_params)) {
   zoomlevel = 4;
  }

  // wma shows dim approx 4e7m at zoom 0 or 1.5e8 is the scale of zoomlevel 0
  if (/_dim:([\d.+-]+)(km|m|_|$)/.exec(coord_params)) {
   zoomlevel = Math.log((RegExp.$2==='km' ? 4e4 : 4e7) / RegExp.$1)/Math.log(2);
  }
  if (/_scale:(\d+)(_|$)/.exec(coord_params)) {
   zoomlevel = Math.log(1.5e8/RegExp.$1) / Math.log(2);
  }

  if (wc.zoom!==-1) { zoomlevel = wc.zoom; }
  //if( zoomlevel > 12 ) { zoomlevel = 12; }
  if (zoomlevel<0) { zoomlevel = 0; }

  function capitalize(s) { return s.substr(0,1).toUpperCase()+s.substr(1).toLowerCase(); }
  if (/_globe:([^_&]+)/.test(coord_params)) { globe = capitalize(RegExp.$1); }
  if ($.inArray(globe,['Earth','Moon','Mars','Venus','Mercury','Io','Titan']) < 0 ) { return; }

  // Test the unicode Symbol
  if (site==='de' && link.parentNode.id!=='coordinates') {
   mapbutton = $('<span>♁</span>').css('color','blue');
  } else {
   mapbutton = $('<img>').attr('src', wc.buttonImage).attr('srcset', wc.buttonImage + ' 1x, ' + wc.buttonImage2x + ' 2x');
  }
  mapbutton.addClass('wmamapbutton noprint').attr( {
   title: _msg('buttonTooltip'),
   alt: ''
  } )
  .on('mouseenter', function (){ $(this).css('opacity', 0.75); })
  .on('mouseleave', function () { $(this).css('opacity', ''); })
  .css('padding', rtl ? '0px 0px 0px 3px' : '0px 3px 0px 0px' ).css('cursor', 'pointer');

  if (wc.alwaysTooltips || ( wc.flowTextTooltips && $(link).parents('li, table, #coordinates').length===0)) {
   // insert tooltip rather than icon to improve text readability
   mapbutton = $('<span>').append(mapbutton).append('&nbsp;WikiMiniAtlas').css('cursor','pointer');
   var tooltip = $('<div>').css( {
    backgroundColor: 'white', padding: '0.2em', border: '1px solid black',
    position: 'absolute', top: '1em', left: '0em',
    display: 'none', zIndex : 15
   }).append(mapbutton);
   $(link).wrap(
    $('<span>')
     .css( { position: 'relative', whiteSpace: 'nowrap' } )
     .on('mouseleave', function () { tooltip.fadeOut(); })
    )
    .before(tooltip)
    .on('mouseenter', function () { tooltip.fadeIn(); });
  } else {
   // insert icon directly
   ws = $(link).css('whiteSpace');
   if (site!=='de' || link.parentNode.id!=='coordinates') {
    $(link).wrap( $('<span>').css('whiteSpace', 'nowrap') ).css('whiteSpace', ws).before(mapbutton);
   } else {
    $('#coordinates').append('<span class="noprint coordinates-separator"> | </span>').append(mapbutton);
   }
  }

  mapbutton.on( 'click', { param:
   marker.lat + '_' + marker.lon + '_' +
   wc.width + '_' + wc.height + '_' +
   site + '_' + zoomlevel + '_' + language + '&globe=' + globe }, showIFrame );

  // store coordinates
  coordinates = link.href;
  params = parseParams(link.href);
  coord_list.push( { lat: marker.lat, lon: marker.lon, obj: link, mb: mapbutton, title: params.title || params.pagename || '' } );
 } ); //end each

 var titlebutton = false;

 function addTitleButton( alat, alon, zoomlevel ) {
  mapbutton = $('<img>')
   .on('mouseenter', function (){ $(this).css('opacity', 0.75); })
   .on('mouseleave', function () { $(this).css('opacity', ''); })
   .css('padding', rtl ? '0px 3px 0px 0px' : '0px 0px 0px 3px' ).css('cursor', 'pointer')
   .attr('src', wc.buttonImage).attr('srcset', wc.buttonImage + ' 1x, ' + wc.buttonImage2x + ' 2x')
   .addClass('wmamapbutton noprint')
   .on( 'click', { param:
    alat + '_' + alon + '_' +
    wc.width + '_' + wc.height + '_' +
    site + '_' + zoomlevel + '_' + language
   }, showIFrame ); // zoomlevel!

  if (!titlebutton) {
   if ($('#coordinates').length) {
    $('#coordinates').find('img').detach();
    $('#coordinates').append(mapbutton);
   } else {
    $('<span id="coordinates"></span>').text(_msg('map')).append(mapbutton).appendTo('#bodyContent');
   }
   titlebutton = true;
  }
 }

 // detect and load KML
 // also insert globe even if no title coords are given
 (function () {
  var i, l = $('div.kmldata')
     ,alat = 0, alon = 0
     ,la1 = Infinity, la2 =- Infinity
     ,lo1 = Infinity, lo2 =- Infinity
     ,ex,ey, req;

  for (i=0; i<l.length; ++i) {// TODO: replace with .each
   coordinates = true;
   req = $.ajax({
    url: '/wiki/' + encodeURI(l.eq(i).attr('title')) + '?action=raw',
    dataType: 'xml',
    success: function (xml) {
     var zoomlevel;

     function processCoords(t) {
      var way = [], c, p = t.split(' '), i, lat, lon;
      for( i=0; i<p.length; ++i ) {
       c=p[i].split(',');
       if( c.length >= 2 ) {
        lat = parseFloat(c[1]);
        lon = parseFloat(c[0]);
        way.push( { lat: lat, lon: lon } );

        // determine extent of way
        if (lat<la1) { la1=lat; }
        if (lon<lo1) { lo1=lon; }
        if (lat>la2) { la2=lat; }
        if (lon>lo2) { lo2=lon; }
       }
      }
      return way;
     }

     // initialize transfer datastructure
     kml = { ways: [], areas: [] };

     // ways
     $(xml).find('LineString > coordinates').each(function () {
      var way = processCoords( $(this).text() );
      if (way.length>0) { kml.ways.push(way); }
     });

     // areas
     $(xml).find('Polygon').each(function () {
      var area = { inner: [], outer: [] };

      // outer boundary
      $(this).find('outerBoundaryIs > LinearRing > coordinates').each(function () {
       var way = processCoords($(this).text());
       if (way.length>0) { area.outer.push(way); }
      });

      // inner boundary (holes in the polygon)
      $(this).find('innerBoundaryIs > LinearRing > coordinates').each(function () {
       var way = processCoords($(this).text());
       if (way.length>0) { area.inner.push(way); }
      });

      // only add if we have an outer boundary
      if (area.outer.length>0) { kml.areas.push(area); }
     });

     // inset min/max extent
     kml.minlon = lo1;
     kml.maxlon = lo2;
     kml.minlat = la1;
     kml.maxlat = la2;

     // already got a request message
     if (mes!==null && kml.ways.length>0 && 'JSON' in window) {
      mes.postMessage(JSON.stringify(kml), document.location.protocol + wma_domain);
     }

     // insert blue globe
     if (coord_list.length===0 || (!$('#coordinates').find('.wmamapbutton').length)) {
      // determine center
      alat = (la1+la2)/2;
      alon = (lo1+lo2)/2;

      //determine zoomfactor
      ex = (lo2-lo1)/180.0 * 3.0*128;
      ey = (la2-la1)/180.0 * 3.0*128; // max extent in degrees, zoom0 has 3*128/180 px/degree
      for (zoomlevel=0; zoomlevel<12; ++zoomlevel) {
       if( ex>wc.width/2 || ey>wc.height/2 ) break;
       ex *= 2; ey *= 2;
      }

      // add mapbutton
      addTitleButton( alat, alon, zoomlevel );
     }
    }
   });
   // Add request promise to init array, and cast any errors to success so that
   // we don't abort init early when one of the requests failed. These are expected
   // to fail for titles we can't find.
   initPromises.push(req.then(null, function () { return $.Deferred().resolve(); } ));
  } // end for
 })();

 // detect "All Coordinates"
 links = $('#coordinates>span>a');
 if (links.length && links[0].href.indexOf('http://www.lenz-online.de/cgi-bin/wiki/wiki-osm.pl') === 0) {
   addTitleButton( 0, 0, 1 );
   coordinates = true;
 }

 // prepare iframe to house the map
 if (coordinates!==null) {
  wi.div = $('<div>').css( {
   width: (wc.width+2)+'px', height: (wc.height+2)+'px',
   margin: '0px', padding: '0px',
   backgroundColor : 'white', border: '1px solid gray',
   position: 'absolute', top: '1em', zIndex: 13, boxShadow: '3px 3px 25px rgba(0,0,0,0.3)'
  } ).css( rtl ? 'left' : 'right', '2em' ).hide();

  var rbrtl = [ '//upload.wikimedia.org/wikipedia/commons/b/b5/Button_resize.png',
                '//upload.wikimedia.org/wikipedia/commons/3/30/Button_resize_rtl.png' ];
  wi.resizebutton = $('<img>').attr( {
   title : _msg('resize'),
   src : rbrtl[rtl?1:0]
  } ).hide().attr('ondragstart','return false');

  // cover the iframe to prevent loosing the mouse to the iframe during resizing
  wi.resizehelper = $('<div>').css( { position: 'absolute', top:0, left:0, zIndex: 20 } ).hide();

  wi.closebutton = $('<img>').attr( {
   title : _msg('close'),
   src : '//upload.wikimedia.org/wikipedia/commons/d/d4/Button_hide.png'
  } ).css( {
   zIndex : 15, position : 'absolute', right : '11px', top : '9px', width : '18px', cursor : 'pointer'
  } ).click( function(e) { wi.div.hide(); } );

  wi.iframe = $('<iframe>')
   .attr( { scrolling: 'no', frameBorder : 0 } )
   .css( {
    zIndex: 14, position: 'absolute', right: '1px', top: '1px',
    width: (wc.width)+'px', height: (wc.height)+'px',
    margin: '0px', padding: '0px'
   } );

  wi.div.append(wi.iframe);
  wi.div.append(wi.resizehelper);
  wi.div.append(wi.closebutton);
  (function () {
   var idle = true, dir = rtl?-1:1;
   function adjusthelper() {
    wi.resizehelper.css( { width: (wc.width+2)+'px', height: (wc.height+2)+'px' } );
   }
   wi.div.append(
    $('<div>')
     .css( {
       zIndex : 15, position : 'absolute', bottom : '3px',
       width : '18px', height: '18px', cursor : (rtl?'se-resize':'sw-resize'),
       'user-select': 'none', '-moz-user-select': 'none', '-ms-user-select': 'none'
      } ).css( (rtl?'right':'left'), '3px' )
     .on('mouseenter', function(e) { wi.resizebutton.fadeIn(); } )
     .on('mouseleave', function(e) { if( idle ) { wi.resizebutton.fadeOut(); } } )
     .on('mousedown', function(e) {
       if (idle) {
        var lastx = e.pageX, lasty = e.pageY;
        wi.resizehelper.show();
        adjusthelper();

        $('body')
         .on('mouseup.wmaresize', function(e) {
          $('body').off('mousemove.wmaresize');
          $('body').off('mouseup.wmaresize');
          idle = true;
          wi.resizehelper.hide();
         } )
         .on('mousemove.wmaresize', function(e) {
          wc.width -= dir*(e.pageX-lastx);
          wc.height += (e.pageY-lasty);
          lastx = e.pageX; lasty = e.pageY;
          wi.div.css( { width: (wc.width+2)+'px', height: (wc.height+2)+'px' } );
          wi.iframe.css( { width: wc.width+'px', height: wc.height+'px' } );
          adjusthelper();
         } );

        idle = false;
       }
      } )
     .append(wi.resizebutton)
   );
  })();

  $(window).on('message', messageHub);

  // Fire event for other code to extend or integrate with WMA
  if (initPromises.length) {
    $.when.apply( null, initPromises ).then(function () {
      mw.hook('WikiMiniAtlas.load').fire();
    } );
  } else {
    mw.hook('WikiMiniAtlas.load').fire();
  }
 }
});

// </nowiki>