User:Jayprakash12345/wikidata-coord.js

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/*
    Wikidata Item Coordinate Adder
	
    @Author [[User:Jayprakash12345]]
    @OwnBy [[meta:Indic-TechCom]]
*/

( function ( $ ) {
	'use strict';

	$( function () {
		
		// Check whether we are in the main namespace pages or not
        if( mw.config.get("wgCanonicalNamespace") !== '' || mw.config.get('wgIsMainPage') === true ){
            return;
        }

        function wikidataCoord( item ){
            var param = {
                "action": "wbgetclaims",
                "format": "json",
                "entity": item,
                "property": "P625",
                "origin": "*"
            };
            
            $.ajax( { url: 'https://www.wikidata.org/w/api.php', data: param } ).done( function ( data ) {
                var coords = [ '0.000', '0.000' ],
                    newCoords = null,
                    precision = null,
                    guid = null;

                try {
                    coords = data.claims.P625[0].mainsnak.datavalue.value;
                    coords = [ coords.latitude, coords.longitude ];
                    guid = data.claims.P625[0].id;
                    precision = data.claims.P625[0].mainsnak.datavalue.value.precision;
                } catch(err) { }

                // Create and Append Element
                var dialog = $( '<div/>' ).attr('title', 'Wikidata Coordinate' ).attr('id', 'wd-coords-dialog' );
                var mapDiv = $( '<div/>' ).attr( 'id', 'mapDiv' ).attr( 'style', 'height: 350px;' );
                var inputHtml = '<label for="latitude">  Latitude: </label><input type="text" id="wd-coord-latitude" value="' + coords[0] + '">' +
                                '<label for="longitude">  Longitude: </label><input type="text" id="wd-coord-longitude" value="' + coords[1] + '"><br>' +
                                '<input type="button" id="wd-coord-go" value="Go" />' +
                                '<input type="button" id="wd-coord-reset" value="Reset to Default" />';

                $( dialog ).append( mapDiv );
                $( dialog ).append( inputHtml );
                $( '#bodyContent' ).append( dialog );

                // Create the map
                var map = L.map('mapDiv').setView( coords, 13 );
                L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                }).addTo(map);

                // Add Search Control in the map
                map.addControl( new L.Control.Search({
                    url: 'https://nominatim.openstreetmap.org/search?format=json&q={s}',
                    jsonpParam: 'json_callback',
                    propertyName: 'display_name',
                    propertyLoc: ['lat','lon'],
                    autoType: false,
                    minLength: 2
                }) );

                // Add marker in the map
                var marker = L.marker( coords ).addTo(map);
                    marker.dragging.enable();
                    $('.leaflet-marker-shadow').hide();

                // Update position of the marker on the map click
                map.on('click', function(res) {
                    updatePosition( res.latlng.lat, res.latlng.lng );
                });

                // Update position of the marker on the marker drag
                marker.on('dragend', function(res) {
                    updatePosition( marker.getLatLng().lat, marker.getLatLng().lng ); 
                });

                // Callback to update the position
                function updatePosition( lat, lng ) {

                    // Slice coords upto 3 decimal float point
                    lat = lat.toFixed(3);
                    lng = lng.toFixed(3);

                    // Set marker coords
                    marker.setLatLng( L.latLng( lat, lng) );

                    // Change input box value
                    $('#wd-coord-latitude').val( lat );
                    $('#wd-coord-longitude').val( lng );
                    map.panTo(new L.LatLng(lat, lng));

                    // Set new coords
                    newCoords = [ lat, lng ];
                }

                // Rest button callback
                $('#wd-coord-reset').on( 'click', function(){
                    updatePosition( Number( coords[0] ), Number( coords[1] ) );
                });

                // Go button callback
                $('#wd-coord-go').on( 'click', function(){
                    updatePosition( Number( $('#wd-coord-latitude').val() ), Number( $('#wd-coord-longitude').val() ) );
                });

                // Create the dialog
                $( dialog ).dialog({
                	modal: true,
                    height: 500,
                    width: 850,
                    buttons: {
                        Submit: {
                            text: 'Do Edit',
                            click: function(){
                                if( newCoords !== null){
                                	editCoords( newCoords[0], newCoords[1], precision, guid, item );
                                } else {
                                    mw.notify( 'New Coordinates and old Coordinates are same.', { type: 'error' } );
                                }
                            }
                        },
                        Cancel: {
                            text: 'Cancel',
                            click: function(){
                                $( this ).dialog( "close" );
                                location.reload(); 
                            }
                        }
                    }
                });
                $('.ui-icon-closethick').hide();

            } ).fail( function ( data ) {
            	mw.notify( 'Something went wrong :(', { type: 'error' } );
                return;
            });
        }
        
        function editCoords(lat, lng, pre, guid, item){
        	
        	// Check and set precision
        	pre = pre ? pre : 0.016666666666667;
        	
        	// Create snakData for API request
        	var snakData = '{ "latitude":' + lat + ',"longitude":' + lng + ',"precision":' + pre + ',"globe":"http://www.wikidata.org/entity/Q2"}',
        		api = null,
        		param = null;

			// Check where we are and create api constructor acccording to it
            if( mw.config.get( 'wgDBname' ) === 'wikidatawiki' ){
                api = new mw.Api( 'https://www.wikidata.org/w/api.php' );
            } else {
                api = new mw.ForeignApi( 'https://www.wikidata.org/w/api.php' );
            }

			if( guid !== null) { 
				param = {
	                "action": "wbsetclaimvalue",
	                "claim": guid,
	                "snaktype": "value",
	                "summary": "Add/Modify Geo Coordinate",
	                "value": snakData,
	                "format": "json"
            	};
			} else {
				param = {
	                "action": "wbcreateclaim",
	                "entity": item,
	                "snaktype": "value",
	                "property": "P625",
	                "summary": "Add/Modify Geo Coordinate",
	                "value": snakData,
	                "format": "json"
            	};
			}
			
			// Make a API request to edit the page
            api.postWithToken( 'csrf', param ).done( function ( data ) {
                mw.notify( 'Coordinate added sucessfully :)' );
                $( '#wd-coords-dialog' ).dialog( "close" ); 
                location.reload();
            } ).fail( function ( data ) {
                mw.notify( 'Something went wrong. Page couldn\'t edit :(', { type: 'error' } );
            } );
                                
        }

        /**
        * Load both RL modules and external scripts with a unified interface
        *
        * @source https://www.mediawiki.org/wiki/Snippets/Load_modules_and_external_scripts
        * @version 4
        */
        function loadScripts(scripts) {
            var deferreds = [];
            $.each(scripts, function (i, script) {
                // External script, use $.getScript
                if (script.match(/^(https?:|\/\/)/)) {
                    deferreds.push($.getScript(script));
                // Use mw.using, convert callbacks to Deferreds
                } else {
                    var d = $.Deferred();
                    // TODO: make only one mw.loader.using call, passing an array of module names
                    mw.loader.using(script, d.resolve, d.reject);
                    deferreds.push(d);
                }
            });
            return $.when.apply($, deferreds);
        }

        var requires = [
            'mediawiki.util',
            'mediawiki.ForeignApi',
            'jquery.ui',
            'https://unpkg.com/leaflet@1.5.1/dist/leaflet.js'
        ];

        loadScripts( requires ).done(function () {
        	
            // Get the Wikidata item
            var item = '';
            if( mw.config.get( 'wgDBname' ) === 'wikidatawiki' ){
                item = mw.config.get( 'wgPageName' );
            } else {

                // Check whether the Wiki Page is connected to Wikidata or not
                if( $('#t-wikibase').length ) {
                    item = $('li#t-wikibase a:first').attr('href').split('/')["5"];
                } else {
                    return;
                }

            }
            
        	mw.loader.load( 'https://meta.wikimedia.org/w/index.php?title=User:Jayprakash12345/leaflet.css&action=raw&ctype=text/css', 'text/css');
            mw.loader.load( 'https://meta.wikimedia.org/w/index.php?title=User:Jayprakash12345/leaflet-search.css&action=raw&ctype=text/css', 'text/css');
            mw.loader.load( 'https://meta.wikimedia.org/w/index.php?title=User:Jayprakash12345/leaflet-search.js&action=raw&ctype=text/javascript');
        	
            // Add a portlet link. 
			var link = mw.util.addPortletLink(
				'p-tb',
				'#',
				'Add/Modify Wikidata Item Coordinate'
			);
			
			// Trigger for portlet link
			$( link ).click( function( e ) {
				e.preventDefault();
				wikidataCoord( item );
			});
        });

	} );

}( $ ) );