Jump to content

MediaWiki:Gadget-mobilemaps.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// See also: https://github.com/wikimedia/mediawiki-extensions-Kartographer/blob/master/modules/maplink/maplink.js
// Partly based on [[meta:MediaWiki:Wikiminiatlas.js]]
( function ( $, mw ) {
	var geohacklinks = [],
		routerInited = false,
		geohackUrl = '//tools.wmflabs.org/geohack/';

	if( !window.wma_settings ) {
		window.wma_settings = {};
	}
	// Try to disable wikiminiatlas
	window.wma_settings.enabled = false;

	function setupKartographer( $content ) {
		var geolinks = document.querySelectorAll('[href^="' + geohackUrl + '"]' );
		
		if( !geolinks.length) {
			return;
		}
		mw.loader.using( [
			'mediawiki.router',
			'ext.kartographer.linkbox',
			'ext.kartographer.style'
		] ).then( function( require ) {
			var router = require( 'mediawiki.router' );
			var kartolink = require( 'ext.kartographer.linkbox' );
			var uri, title, coord_params, coord_digits, lat, lon, globe, link,
				geohack, zoomlevel, marker, marker_symbol;
				
			var geohack_link_filter = /&params=([\d.+-]+)_([\d.+-]*)_?([\d.+-]*)_?([NSZ])_([\d.+-]+)_([\d.+-]*)_?([\d.+-]*)_?([EOW])([^&=<>|]{0,250})/;
			var globeRegExp = /_globe:([^_&]+)/;
			var typeRegExp = /_type:(country|satellite|state|adm1st|adm2nd|adm3rd|city|isle|river|waterbody|event|glacier|mountain|airport|edu|pass|landmark|railwaystation)/;
			var dimRegExp = /_dim:([\d.+-]+)(km|m|_|$)/;
			var scaleRegExp = /_scale:(\d+)(_|$)/;
 
			Array.prototype.forEach.call(geolinks, function (elem, index) {
				if ( !('href' in elem) || !geohack_link_filter.exec(elem.href)) {
					return;
				}
				coord_params = [];
				lat = lon = 0;
				globe = 'Earth';
				zoomlevel = 12;
				marker_symbol = 'marker';
				
				// Convert DMS to DD if needed
				lat = (1.0*RegExp.$1) + ((RegExp.$2||0)/60.0) + ((RegExp.$3||0)/3600.0);
				if (RegExp.$4!=='N') {
					lat *= -1;
				}
				lon = (1.0*RegExp.$5) + ((RegExp.$6||0)/60.0) + ((RegExp.$7||0)/3600.0);
				if (RegExp.$8==='W') {
					lon *= -1;
				}
				coord_params = RegExp.$9;
				
				// Zoom based on coordinate N/S precision
				coord_digits = RegExp.$3 ? 4 : RegExp.$2 ? 2 : RegExp.$1.length - (RegExp.$1+'.').indexOf('.') - 1;
				zoomlevel = coord_digits * Math.log(10)/Math.log(2);
				
				// Zoom level based on type, and retrieving markers symbols for those types
				if( typeRegExp.exec( coord_params ) ) {
					type = RegExp.$1;
					switch( type ) {
						case 'country':
						case 'satellite':
							zoomlevel = 5;
							break;
						case 'state':
							zoomlevel = 7;
							break;
						case 'adm1st':
							zoomlevel = 9;
							break;
						case 'adm2nd':
							zoomlevel = 11;
							break;
						case 'adm3rd':
						case 'city':
							zoomlevel = 12;
							marker_symbol = 'city';
							break;
						case 'isle':
						case 'river':
						case 'waterbody':
							zoomlevel = 12;
							break;
						case 'event':
						case 'glacier':
						case 'mountain':
							zoomlevel = 13;
							break;
						case 'airport':
							zoomlevel = 14;
							marker_symbol = 'airport';
							break;
						case 'railwaystation':
							marker_symbol = 'rail';
							break;
						case 'camera edu':
						case 'pass':
						case 'landmark':
							zoomlevel = 15;
							break;
						default:
					}
				}
				
				// wma shows dim approx 4e7m at zoom 0 or 1.5e8 is the scale of zoomlevel 0
				if (dimRegExp.exec(coord_params)) {
					zoomlevel = Math.log((RegExp.$2==='km' ? 4e4 : 4e7) / RegExp.$1)/Math.log(2);
				}
				if (scaleRegExp.exec(coord_params)) {
					zoomlevel = Math.log(1.5e8/RegExp.$1) / Math.log(2);
				}
				
				if (zoomlevel<0) { zoomlevel = 0; }
				
				// Check which globe
				if (globeRegExp.test(coord_params)) {
					globe = RegExp.$1;
					// All possible globes: ['Earth','Moon','Mars','Venus','Mercury','Io','Titan']
					// But we only handle Earth right now
					if( globe.toLowerCase() !== 'earth' ) {
						return;
					}
				}

				// Retrieve the pagename from the uri if possible
				uri = new mw.Uri( elem.href );
				title = uri.query.pagename;
				if(title) {
					title = title.replace(/_/g,' ');
				}
				marker = {
					"type": "Feature",
					"geometry": {
						"type": "Point",
						"coordinates": [lon, lat]
					},
					"properties": {
						"name": title,
						"marker-color": "#3366cc",
						"marker-symbol": marker_symbol,
						"marker-size": "medium"
					}
				};
				
				link = geohacklinks[ index ] = kartolink.link( {
					featureType: 'maplink',
					container: elem,
					center: [ lat, lon ],
					zoom: zoomlevel,
					data: [marker],
					captionText: title,
					fullScreenRoute: '/geohacklink/' + index
				} );
				$(elem).addClass('mw-kartographer-maplink').parent().removeClass('plainlinks');
			});
			
			if ( routerInited ) {
				return;
			}
			// execute this piece of code only once
			routerInited = true;
			
			// Opens a maplink in full screen. #/geohacklink(/:zoom)(/:latitude)(/:longitude)
			// Examples:
			//     #/geohacklink/0
			//     #/geohacklink/0/5
			//     #/geohacklink/0/16/-122.4006/37.7873
			router.route( /geohacklink\/([0-9]+)(?:\/([0-9]+))?(?:\/([+-]?\d+\.?\d{0,5})?\/([+-]?\d+\.?\d{0,5})?)?/, function ( maptagId, zoom, latitude, longitude ) {
				var link = geohacklinks[ maptagId ],
					position;
	
				if ( !link ) {
					router.navigate( '' );
					return;
				}
	
				if ( zoom !== undefined && latitude !== undefined && longitude !== undefined ) {
					position = {
						center: [ +latitude, +longitude ],
						zoom: +zoom
					};
				}
	
				// // We need this hack to differentiate these events from `open` events.
				// if ( !link.fullScreenMap && !link.clicked ) {
				// 	mw.track( 'mediawiki.kartographer', {
				// 		action: 'hashopen',
				// 		isFullScreen: true,
				// 		feature: link
				// 	} );
				// 	link.clicked = false;
				// }
				link.openFullScreen( position );
			} );
	
			// Check if we need to open a map in full screen.
			router.checkRoute();
		});
		
		if( $( '#coordinates' ).length && mw.config.get('skin') === 'minerva' ) {
			mw.loader.using( [
				'mediawiki.util',
				'oojs-ui.styles.icons-location'
			] ).then( function() {
				mw.util.addCSS(
					'#page-actions .mw-show-on-map, #p-views .mw-show-on-map {' +
					'	opacity: 0.6;' +
					'}'
				);
				var mapButton = $('<li>')
					.addClass('page-actions-menu__list-item')
					.removeClass( 'language-selector mw-ui-icon-language-switcher' )
					.append(
						$('<a>').addClass( 'mw-ui-icon mw-ui-icon-element mw-ui-icon-with-label-desktop mw-show-on-map mw-ui-icon-map' ) /*T240644*/
						.attr( {
							href: '', /* empty href to avoid minerva adding ... */
							title: 'Show on map',
							role: 'button'
						} )
						.text( ' Map' )
						.click( openTitleCoord )
					);
				$( '.page-actions-menu__list > li:first-child' ).after( mapButton );
			} );
		}
	}
	
	function openTitleCoord( e ) {
		e.preventDefault(); /*T247664*/
		$( '#coordinates .mw-kartographer-link' ).get( 0 ).click();
	};
	
	mw.hook( 'wikipage.content' ).add( setupKartographer );

	return geohacklinks;
}(
	jQuery,
	mediaWiki
));