/*
* KartoEditor
*
* Permet, depuis la page [[Special:Blankpage/KartoEditor]], d'éditer une carte
* interactive en y ajoutant des marqueurs, lignes ou polygones, puis d'exporter
* cette carte au format GeoJSON sur une page du namespace ''Data:'' sur commons.
*
* Auteur : [[User:0x010C]], avec des éléments de [[:fr:MediaWiki:Gadget-EditZeroth.js]]
* Création : 30 mars 2017
* Dernière révision : 20 août 2020
* {{Projet:JavaScript/Script|KartoEditor}}
*/
//<nowiki>
( function () {
function initTranslations ( ) {
var lang = mw.config.get( 'wgUserLanguage' ),
messages = {
en: {
'kartoEditor-portlet-name': 'KartoEditor',
'kartoEditor-portlet-description': 'Edit this map using KartoEditor',
'label-stroke': 'Stroke',
'label-color': 'Color',
'label-width': 'Width',
'label-opacity': 'Opacity',
'label-fill': 'Fill',
'label-size': 'Size',
'label-symbol': 'Symbol',
'label-marker': 'Marker',
'label-popup': 'Popup',
'label-title': 'Title',
'label-description': 'Description',
'label-save-button': 'Save',
'label-latitude': 'Latitude:',
'label-longitude': 'Longitude:',
'label-zoom': 'Zoom:',
'label-validate-button': 'Validate',
'label-validate-drawing-button': 'Validate the drawing',
'wrong-polygon-message': 'The sides of a polygon cannot cross!',
'label-edit-summary': 'Edit summary:',
'label-savepage-button': 'Save',
'label-savepage-title': 'Save your changes',
'tooltip-savepage-button': 'The GeoJSON code used to generate the map will be saved in the "Data:" namespace on Commons. It\'ll then be possible to display it on Wikipedia by using a template, like for images.',
'label-savepage-tab': 'Save',
'label-geojson-tab': 'GeoJSON',
'help-wikilink': 'Discussion projet:JavaScript/Notices/KartoEditor',
'help-wikilink-text': 'As a question, suggest an improvement or report a bug',
'unknown-error-message-title': 'Error',
'unknown-error-message-description': 'An error happened: [%code%] %errorinfo%'
},
fr: {
'kartoEditor-portlet-name': 'KartoEditor',
'kartoEditor-portlet-description': 'Modifier cette carte avec KartoEditor',
'label-stroke': 'Trait',
'label-color': 'Couleur',
'label-width': 'Largeur',
'label-opacity': 'Opacité',
'label-fill': 'Remplissage',
'label-size': 'Taille',
'label-symbol': 'Symbole',
'label-marker': 'Marqueur',
'label-popup': 'Pop-up',
'label-title': 'Titre',
'label-description': 'Description',
'label-save-button': 'Sauvegarder',
'label-latitude': 'Latitude :',
'label-longitude': 'Longitude :',
'label-zoom': 'Zoom :',
'label-validate-button': 'Valider',
'label-validate-drawing-button': 'Valider le dessin',
'wrong-polygon-message': 'Les côtés d\'un polygone ne peuvent se croiser !',
'label-edit-summary': 'Résumé :',
'label-savepage-button': 'Publier les modifications',
'label-savepage-title': 'Publier vos modifications',
'tooltip-savepage-button': 'Le code GeoJSON servant à générer la carte sera enregistré dans l\'espace de nom « Data: » sur Commons, et pourra par la suite être importé via un modèle sur Wikipédia, un peu à la manière des images.',
'label-savepage-tab': 'Enregistrer vos modifications',
'label-geojson-tab': 'GeoJSON',
'help-wikilink': 'Discussion projet:JavaScript/Notices/KartoEditor',
'help-wikilink-text': 'Poser une question, proposer une amélioration ou signaler un bug',
'unknown-error-message-title': 'Erreur',
'unknown-error-message-description': 'Une erreur a été rencontrée : [%code%] %errorinfo%'
}
};
if ( lang == 'en' ) {
mw.messages.set( messages.en );
}
else if (lang in messages ) {
mw.messages.set( messages[ lang ] );
}
}
var GeoLayer = function( kartoEditor, type, layer, initialStyle ) {
this.kartoEditor = kartoEditor;
this.type = type.toLowerCase();
this.layer = layer;
this.GJStyle = {};
initialStyle = initialStyle || {};
if ( this.type === 'polygon' || this.type === 'rectangle' ) {
this.updatePolygon( {
'stroke': initialStyle[ 'stroke' ] || '#555555',
'stroke-width': initialStyle[ 'stroke-width' ] || 2,
'stroke-opacity': initialStyle[ 'stroke-opacity' ] || 1,
'fill': initialStyle[ 'fill' ] || '#555555',
'fill-opacity': initialStyle[ 'fill-opacity' ] || 0.3,
'title': initialStyle[ 'title' ] || '',
'description': initialStyle[ 'description' ] || '',
} );
} else if ( this.type === 'polyline' || this.type === 'linestring' ) {
this.updateLine( {
'stroke': initialStyle[ 'stroke' ] || '#555555',
'stroke-width': initialStyle[ 'stroke-width' ] || 2,
'stroke-opacity': initialStyle[ 'stroke-opacity' ] || 1,
'title': initialStyle[ 'title' ] || '',
'description': initialStyle[ 'description' ] || '',
} );
} else {
this.updateMarker( {
'marker-size': initialStyle[ 'marker-size' ] || 'small',
'marker-color': initialStyle[ 'marker-color' ] || '#555555',
'marker-symbol': initialStyle[ 'marker-symbol' ] || '',
'title': initialStyle[ 'title' ] || '',
'description': initialStyle[ 'description' ] || '',
} );
}
this.layer.bindPopup( this.createPopup() );
};
GeoLayer.prototype.updatePolygon = function( GJStyle ) {
this.GJStyle = GJStyle || this.GJStyle;
this.layer.setStyle( {
weight: GJStyle[ 'stroke-width' ],
opacity: GJStyle[ 'stroke-opacity' ],
color: GJStyle[ 'stroke' ],
fillOpacity: GJStyle[ 'fill-opacity' ],
fillColor: GJStyle[ 'fill' ],
} );
this.kartoEditor.updateOutputs();
};
GeoLayer.prototype.updateLine = function( GJStyle ) {
this.GJStyle = GJStyle || this.GJStyle;
this.layer.setStyle( {
weight: GJStyle[ 'stroke-width' ],
opacity: GJStyle[ 'stroke-opacity' ],
color: GJStyle[ 'stroke' ],
} );
this.kartoEditor.updateOutputs();
};
GeoLayer.prototype.updateMarker = function( GJStyle ) {
this.GJStyle = GJStyle || this.GJStyle;
this.layer.setIcon( WMIcon(GJStyle[ 'marker-size' ], GJStyle[ 'marker-color' ].substring( 1 ), GJStyle[ 'marker-symbol' ] ) );
this.kartoEditor.updateOutputs();
};
GeoLayer.prototype.isPresent = function() {
if ( this.layer._map !== null ) {
return true;
}
return false;
};
GeoLayer.prototype.createPopup = function() {
var popupContent;
if ( this.type === 'polygon' || this.type === 'rectangle' ) {
popupContent = this.generatePolygonForm();
} else if ( this.type === 'polyline' ) {
popupContent = this.generateLineForm();
} else {
popupContent = this.generateMarkerForm();
}
return new L.Popup( {
minWidth: 300,
maxWidth: 500,
} ).setContent( popupContent );
};
GeoLayer.prototype.generatePolygonForm = function() {
var self = this;
var propertyInputs = {
'stroke': new OO.ui.ColorInputWidget( { value: this.GJStyle[ 'stroke' ] } ),
'stroke-width': new OO.ui.NumberInputWidget( { input: { value: this.GJStyle[ 'stroke-width' ] }, min: 0, isInteger: true, step: 1 } ),
'stroke-opacity': new OO.ui.NumberInputWidget( { input: { value: this.GJStyle[ 'stroke-opacity' ] }, min: 0, max: 1, isInteger: false, step: 0.1 } ),
'fill': new OO.ui.ColorInputWidget( { value: this.GJStyle[ 'fill' ], } ),
'fill-opacity': new OO.ui.NumberInputWidget( { input: { value: this.GJStyle[ 'fill-opacity' ]}, min: 0, max: 1, isInteger: false, step: 0.1 } ),
'title': new OO.ui.TextInputWidget( { value: JSON.stringify(this.GJStyle[ 'title' ] ) } ),
'description': new OO.ui.MultilineTextInputWidget( { value: JSON.stringify(this.GJStyle[ 'description' ] ), autoresize: true } ),
};
var strokeFieldset = new OO.ui.FieldsetLayout( { label: mw.msg( 'label-stroke' ) } );
strokeFieldset.addItems( [
new OO.ui.FieldLayout(propertyInputs[ 'stroke' ], { label: mw.msg( 'label-color' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'stroke-width' ], { label: mw.msg( 'label-width' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'stroke-opacity' ], { label: mw.msg( 'label-opacity' ), align: 'right' } ),
] );
var backgroundFieldset = new OO.ui.FieldsetLayout( { label: mw.msg( 'label-fill' ) } );
backgroundFieldset.addItems( [
new OO.ui.FieldLayout(propertyInputs[ 'fill' ], { label: mw.msg( 'label-color' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'fill-opacity' ], { label: mw.msg( 'label-opacity' ), align: 'right' } ),
] );
var popupFieldset = new OO.ui.FieldsetLayout( { label: mw.msg( 'label-popup' ) } );
popupFieldset.addItems( [
new OO.ui.FieldLayout(propertyInputs[ 'title' ], { label: mw.msg( 'label-title' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'description' ], { label: mw.msg( 'label-description' ), align: 'right' } ),
] );
var saveButton = new OO.ui.ButtonWidget( { label: mw.msg( 'label-save-button' ), iconTitle: 'Save', flags: [ 'primary', 'progressive' ] } );
var mainFieldset = new OO.ui.FieldsetLayout( {} );
mainFieldset.addItems( [
strokeFieldset,
backgroundFieldset,
popupFieldset,
saveButton,
] );
saveButton.on( 'click', function() {
self.updatePolygon( {
'stroke': propertyInputs[ 'stroke' ].getValue(),
'stroke-width': propertyInputs[ 'stroke-width' ].getValue(),
'stroke-opacity': propertyInputs[ 'stroke-opacity' ].getValue(),
'fill': propertyInputs[ 'fill' ].getValue(),
'fill-opacity': propertyInputs[ 'fill-opacity' ].getValue(),
'title': JSON.parse(propertyInputs[ 'title' ].getValue()),
'description': JSON.parse(propertyInputs[ 'description' ].getValue()),
} );
$(".leaflet-popup-close-button")[0].click();
} );
return mainFieldset.$element[ 0 ];
};
GeoLayer.prototype.generateLineForm = function() {
var self = this;
var propertyInputs = {
'stroke': new OO.ui.ColorInputWidget( { value: this.GJStyle[ 'stroke' ] } ),
'stroke-width': new OO.ui.NumberInputWidget( { input: { value: this.GJStyle[ 'stroke-width' ] }, min: 0, isInteger: true, step: 1 } ),
'stroke-opacity': new OO.ui.NumberInputWidget( { input: { value: this.GJStyle[ 'stroke-opacity' ] }, min: 0, max: 1, isInteger: false, step: 0.1 } ),
'title': new OO.ui.TextInputWidget( { value: JSON.stringify(this.GJStyle[ 'title' ] ) } ),
'description': new OO.ui.MultilineTextInputWidget( { value: JSON.stringify(this.GJStyle[ 'description' ] ), autoresize: true } ),
};
var strokeFieldset = new OO.ui.FieldsetLayout( { label: mw.msg( 'label-stroke' ) } );
strokeFieldset.addItems( [
new OO.ui.FieldLayout(propertyInputs[ 'stroke' ], { label: mw.msg( 'label-color' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'stroke-width' ], { label: mw.msg( 'label-width' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'stroke-opacity' ], { label: mw.msg( 'label-opacity' ), align: 'right' } ),
] );
var popupFieldset = new OO.ui.FieldsetLayout( { label: mw.msg( 'label-popup' ) } );
popupFieldset.addItems( [
new OO.ui.FieldLayout(propertyInputs[ 'title' ], { label: mw.msg( 'label-title' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'description' ], { label: mw.msg( 'label-description' ), align: 'right' } ),
] );
var saveButton = new OO.ui.ButtonWidget( { label: mw.msg( 'label-save-button' ), iconTitle: 'Save', flags: [ 'primary', 'progressive' ] } );
var mainFieldset = new OO.ui.FieldsetLayout( {} );
mainFieldset.addItems( [
strokeFieldset,
popupFieldset,
saveButton,
] );
saveButton.on( 'click', function() {
self.updateLine( {
'stroke': propertyInputs[ 'stroke' ].getValue(),
'stroke-width': propertyInputs[ 'stroke-width' ].getValue(),
'stroke-opacity': roundProperty( parseFloat( propertyInputs[ 'stroke-opacity' ].getValue() ) ),
'title': JSON.parse(propertyInputs[ 'title' ].getValue()),
'description': JSON.parse(propertyInputs[ 'description' ].getValue()),
} );
$(".leaflet-popup-close-button")[0].click();
} );
return mainFieldset.$element[ 0 ];
};
GeoLayer.prototype.generateMarkerForm = function() {
var self = this;
const symbols = [ {data:'', label:'(aucun symbole)'}, {data:'aerialway', label:'aerialway'}, {data:'airfield', label:'airfield'}, {data:'airport', label:'airport'}, {data:'alcohol-shop', label:'alcohol-shop'}, {data:'america-football', label:'america-football'}, {data:'art-gallery', label:'art-gallery'}, {data:'bakery', label:'bakery'}, {data:'bank', label:'bank'}, {data:'bar', label:'bar'}, {data:'baseball', label:'baseball'}, {data:'basketball', label:'basketball'}, {data:'beer', label:'beer'}, {data:'bicycle', label:'bicycle'}, {data:'building', label:'building'}, {data:'bus', label:'bus'}, {data:'cafe', label:'cafe'}, {data:'campsite', label:'campsite'}, {data:'car', label:'car'}, {data:'cemetery', label:'cemetery'}, {data:'cinema', label:'cinema'}, {data:'circle', label:'circle'}, {data:'circle-stroked', label:'circle-stroked'}, {data:'city', label:'city'}, {data:'clothing-store', label:'clothing-store'}, {data:'college', label:'college'}, {data:'commercial', label:'commercial'}, {data:'cricket', label:'cricket'}, {data:'cross', label:'cross'}, {data:'dam', label:'dam'}, {data:'danger', label:'danger'}, {data:'dog-park', label:'dog-park'}, {data:'embassy', label:'embassy'}, {data:'entrance', label:'entrance'}, {data:'farm', label:'farm'}, {data:'fast-food', label:'fast-food'}, {data:'ferry', label:'ferry'}, {data:'fire-station', label:'fire-station'}, {data:'fuel', label:'fuel'}, {data:'garden', label:'garden'}, {data:'gift', label:'gift'}, {data:'golf', label:'golf'}, {data:'grocery', label:'grocery'}, {data:'hairdresser', label:'hairdresser'}, {data:'harbor', label:'harbor'}, {data:'heart', label:'heart'}, {data:'heliport', label:'heliport'}, {data:'hospital', label:'hospital'}, {data:'ice-cream', label:'ice-cream'}, {data:'laundry', label:'laundry'}, {data:'library', label:'library'}, {data:'lighthouse', label:'lighthouse'}, {data:'lodging', label:'lodging'}, {data:'logging', label:'logging'}, {data:'marker', label:'marker'}, {data:'marker-stroked', label:'marker-stroked'}, {data:'monument', label:'monument'}, {data:'museum', label:'museum'}, {data:'music', label:'music'}, {data:'park', label:'park'}, {data:'parking', label:'parking'}, {data:'parking-garage', label:'parking-garage'}, {data:'pharmacy', label:'pharmacy'}, {data:'pitch', label:'pitch'}, {data:'place-of-worship', label:'place-of-worship'}, {data:'playground', label:'playground'}, {data:'police', label:'police'}, {data:'post', label:'post'}, {data:'prison', label:'prison'}, {data:'rail', label:'rail'}, {data:'rail-light', label:'rail-light'}, {data:'rail-metro', label:'rail-metro'}, {data:'religious-christian', label:'religious-christian'}, {data:'religious-jewish', label:'religious-jewish'}, {data:'religious-muslim', label:'religious-muslim'}, {data:'restaurant', label:'restaurant'}, {data:'roadblock', label:'roadblock'}, {data:'rocket', label:'rocket'}, {data:'school', label:'school'}, {data:'scooter', label:'scooter'}, {data:'shop', label:'shop'}, {data:'skiing', label:'skiing'}, {data:'slaughterhouse', label:'slaughterhouse'}, {data:'soccer', label:'soccer'}, {data:'square', label:'square'}, {data:'square-stroked', label:'square-stroked'}, {data:'star', label:'star'}, {data:'star-stroked', label:'star-stroked'}, {data:'suitcase', label:'suitcase'}, {data:'swimming', label:'swimming'}, {data:'telephone', label:'telephone'}, {data:'tennis', label:'tennis'}, {data:'theatre', label:'theatre'}, {data:'town', label:'town'}, {data:'town-hall', label:'town-hall'}, {data:'triangle', label:'triangle'}, {data:'triangle-stroked', label:'triangle-stroked'}, {data:'village', label:'village'}, {data:'warehouse', label:'warehouse'}, {data:'waste-basket', label:'waste-basket'}, {data:'water', label:'water'}, {data:'wetland', label:'wetland'}, {data:'zoo', label:'zoo'} ];
var propertyInputs = {
'marker-size': new OO.ui.DropdownInputWidget( {
options: [
{
data: 'small',
label: 'small'
},
{
data: 'medium',
label: 'medium'
},
{
data: 'large',
label: 'large'
},
],
value: this.GJStyle[ 'marker-size' ]
} ),
'marker-color': new OO.ui.ColorInputWidget( { value: this.GJStyle[ 'marker-color' ] } ),
'marker-symbol': new OO.ui.ComboBoxInputWidget( { options: symbols, value: this.GJStyle[ 'marker-symbol' ] } ),
'title': new OO.ui.TextInputWidget( { value: JSON.stringify(this.GJStyle[ 'title' ] ) } ),
'description': new OO.ui.MultilineTextInputWidget( { value: JSON.stringify(this.GJStyle[ 'description' ] ), autoresize: true } ),
};
var markerFieldset = new OO.ui.FieldsetLayout( { label: mw.msg( 'label-marker' ) } );
markerFieldset.addItems( [
new OO.ui.FieldLayout(propertyInputs[ 'marker-size' ], { label: mw.msg( 'label-size' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'marker-color' ], { label: mw.msg( 'label-color' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'marker-symbol' ], { label: mw.msg( 'label-symbol' ), align: 'right' } ),
] );
var popupFieldset = new OO.ui.FieldsetLayout( { label: mw.msg( 'label-popup' ) } );
popupFieldset.addItems( [
new OO.ui.FieldLayout(propertyInputs[ 'title' ], { label: mw.msg( 'label-title' ), align: 'right' } ),
new OO.ui.FieldLayout(propertyInputs[ 'description' ], { label: mw.msg( 'label-description' ), align: 'right' } ),
] );
var saveButton = new OO.ui.ButtonWidget( { label: mw.msg( 'label-save-button' ), iconTitle: 'Save', flags: [ 'primary', 'progressive' ] } );
var mainFieldset = new OO.ui.FieldsetLayout( {} );
mainFieldset.addItems( [
markerFieldset,
popupFieldset,
saveButton,
] );
saveButton.on( 'click', function() {
self.updateMarker( {
'marker-size': propertyInputs[ 'marker-size' ].getValue(),
'marker-color': propertyInputs[ 'marker-color' ].getValue(),
'marker-symbol': propertyInputs[ 'marker-symbol' ].getValue(),
'title': JSON.parse(propertyInputs[ 'title' ].getValue()),
'description': JSON.parse(propertyInputs[ 'description' ].getValue()),
} );
$(".leaflet-popup-close-button")[0].click();
} );
return mainFieldset.$element[0];
};
function WMIcon( size, color, icon ) {
const iconData = {
'small': { size: [ 20, 50 ], anchor: [ 10, 25 ], popupAnchor: [ 0, -25 ] },
'medium': { size: [ 30, 70 ], anchor: [ 15, 35 ], popupAnchor: [ 0, -35 ] },
'large': { size: [ 35, 90 ], anchor: [ 17, 45 ], popupAnchor: [ 0, -45 ] },
};
size = size || 'medium';
color = color || '555555';
icon = icon || '';
if ( icon !== '' ) {
icon = '-' + icon;
}
url = 'https://maps.wikimedia.org/v4/marker/pin-' + size.charAt(0) + icon + '+' + color + '.png';
return L.icon( {
iconUrl: url,
iconSize: iconData[size].size,
iconAnchor: iconData[size].anchor,
popupAnchor: iconData[size].popupAnchor,
} );
}
function OoUiColorInputWidget( config ) {
// Configuration initialization
config = $.extend( {
type: 'color',
}, config);
// Parent constructor
OO.ui.ColorInputWidget.parent.call( this, config );
// Properties
this.type = 'color';
this.readOnly = false;
this.required = false;
this.validate = null;
// Initialization
this.$element
.addClass( 'oo-ui-textInputWidget oo-ui-textInputWidget-type-' + this.type )
.append( this.$icon, this.$indicator );
this.$input.attr( 'type', config.type );
};
var OutputPageLayout = function( name, label, $element ) {
this.label = label;
OutputPageLayout.super.call( this, name, {} );
this.$element.append( $element );
};
function roundCoordinate( value ) {
return Math.round( value * 1000000 ) / 1000000;
}
function roundProperty( value ) {
if ( value !== undefined ) {
return value.toFixed(1);
}
}
var KartoEditor = function( container, license, description, sources, lat, lng, zoom, initialData ) {
this.container = container;
this.license = license;
this.description = description;
this.sources = sources;
this.lat = lat;
this.lng = lng;
this.zoom = zoom;
this.geoLayers = [];
this.map = undefined;
this.drawnItems = undefined;
this.baseLayer = undefined;
this.GJOutputArea = undefined;
this.templateOutputArea = undefined;
this.nbLayer = 0;
var self = this;
mw.loader.using( [ 'ext.kartographer.editor', 'oojs-ui' ], function() {
OO.ui.ColorInputWidget = OoUiColorInputWidget;
OO.inheritClass( OO.ui.ColorInputWidget, OO.ui.InputWidget );
OO.inheritClass( OutputPageLayout, OO.ui.PageLayout );
self.initializeMap();
self.initializeEditor();
self.initializeOutputArea();
if ( initialData !== undefined ) {
self.importGeoJSON( initialData );
}
self.updateOutputs();
mw.hook( 'kartoeditor.ready' ).fire( self );
} );
};
KartoEditor.prototype.initializeMap = function() {
var self = this;
this.baseLayer = L.tileLayer( 'https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '<a href="https://foundation.wikimedia.org/wiki/Maps_Terms_of_Use">Wikimedia</a> | © <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors' } );
mapContainer = $( '<div>' ).css( 'height', 600).css( 'border', '1px solid #a2a9b1' ).css( 'border-radius', '2px' ).css( 'position', 'relative' );
$( this.container ).append( mapContainer );
this.map = new L.Map( mapContainer[ 0 ], { center: new L.LatLng( this.lat, this.lng ), zoom: this.zoom } );
this.drawnItems = L.featureGroup().addTo( this.map );
this.baseLayer.addTo( this.map );
this.rightClickPopup = L.popup();
this.map.on( 'contextmenu', function( e ) {
self.rightClickPopup.setLatLng( e.latlng );
self.rightClickPopup.setContent( $( '<p>' ).css( 'text-align', 'center' )
.append( mw.msg( 'label-latitude' ) + " " )
.append( roundCoordinate( e.latlng.lat ) )
.append( '<br/>' )
.append( mw.msg( 'label-longitude' ) + " " )
.append( roundCoordinate( e.latlng.lng) )
.append( '<br/>' )
.append( mw.msg( 'label-zoom' ) + " " )
.append( this.getZoom() )
.prop( 'outerHTML' )
);
self.rightClickPopup.openOn( this );
} );
this.map.on( 'zoomend moveend', function( e ) {
self.updateOutputs();
} );
};
KartoEditor.prototype.initializeEditor = function() {
L.drawLocal.draw.toolbar.finish.text = mw.msg( 'label-validate-button' );
L.drawLocal.draw.toolbar.finish.title = mw.msg( 'label-validate-drawing-button' );
this.map.addControl( new L.Control.Draw( {
edit: {
featureGroup: this.drawnItems,
},
draw: {
polygon: {
showArea: true,
allowIntersection: false,
drawError: {
color: '#e12100',
message: mw.msg( 'wrong-polygon-message' )
},
shapeOptions: {
color: '#555555',
}
},
rectangle: {
shapeOptions: {
color: '#555555',
}
},
polyline: {
shapeOptions: {
weight: 10,
color: '#555555',
}
},
marker: {
icon: WMIcon( 'small', '555555', '' ),
},
circle: false,
}
} ) );
var self = this;
this.map.on( 'draw:created', function( event ) {
var layer = event.layer;
self.drawnItems.addLayer( layer );
var geoLayer = new GeoLayer( self, event.layerType, layer );
self.geoLayers.push( geoLayer );
self.nbLayer++;
self.updateOutputs();
} );
this.map.on( 'draw:edited', function( event ) {
self.updateOutputs();
} );
this.map.on( 'draw:deleted', function( event ) {
self.nbLayer--;
self.updateOutputs();
} );
};
KartoEditor.prototype.initializeOutputArea = function() {
var self = this;
var pages = [];
this.booklet = new OO.ui.BookletLayout( { outlined: true } );
this.GJOutputArea = new OO.ui.MultilineTextInputWidget( { label: '', value: '', rows: 12, readOnly: true } );
var summaryInput = new OO.ui.TextInputWidget( { placeholder: '' } );
var editButton = new OO.ui.ButtonWidget( { label: mw.msg( 'label-savepage-button' ), iconTitle: 'Save', flags: [ 'primary', 'progressive' ] } );
var self = this;
editButton.on( 'click', function() {
self.saveCommons( summaryInput.getValue() );
} );
var editFieldset = new OO.ui.FieldsetLayout( {
label: mw.msg( 'label-savepage-title' ),
items: [
new OO.ui.ActionFieldLayout( summaryInput, editButton, { label: mw.msg( 'label-edit-summary' ), align: 'top', help: mw.msg( 'tooltip-savepage-button' ) } ),
],
} );
pages.push( new OutputPageLayout( 'edit', mw.msg( 'label-savepage-tab' ), editFieldset.$element ) );
pages.push( new OutputPageLayout( 'geojson', mw.msg( 'label-geojson-tab' ), this.GJOutputArea.$element ) );
var self = this;
$.each( pages, function( key, page ) {
self.booklet.addPages( [ page ] );
page.outlineItem.setLabel( page.label );
} );
$( this.container ).append( $( '<div>' ).css('height', '300px').css( 'border', '1px solid #a2a9b1' ).css( 'border-radius', '2px' ).css( 'position', 'relative' ).css( 'margin-top', '0.5em' ).append( this.booklet.$element[ 0 ] ) );
$( this.container ).append( $( '<div>' ).css( 'text-align', 'right' ).append( $( '<a>' ).attr( 'href', mw.util.getUrl( mw.msg( 'help-wikilink' ) ) ).text( mw.msg( 'help-wikilink-text' ) ) ) );
};
KartoEditor.prototype.getGeoJSON = function() {
var features = [];
$.each(this.geoLayers, function( key, geoLayer ) {
if ( geoLayer.isPresent() ) {
var geoJSON = geoLayer.layer.toGeoJSON();
geoJSON.properties = geoLayer.GJStyle;
features.push( geoJSON );
}
} );
return {
'type': 'FeatureCollection',
'features': features
};
};
KartoEditor.prototype.updateOutputs = function() {
this.updateGeoJSON();
};
KartoEditor.prototype.updateGeoJSON = function() {
this.GJOutputArea.setValue( JSON.stringify( this.getGeoJSON(), null, 4 ) );
};
KartoEditor.prototype.saveCommons = function( summary ) {
mapData = {
license: this.license,
description: this.description,
sources: this.sources,
latitude: this.map.getCenter().lat,
longitude: this.map.getCenter().lng,
zoom: this.map.getZoom(),
data: this.getGeoJSON(),
};
var api = new mw.Api();
api.postWithToken( 'csrf', {
action: 'edit',
title: String( mw.config.get( 'wgPageName' ) ),
text: JSON.stringify( mapData, null, 4 ),
formatversion: '2',
summary: summary + ' (using KartoEditor)',
assert: 'user',
} ).then(function( data ) {
location.reload();
} ).fail( function( code, data ) {
OO.ui.alert( mw.msg( 'unknown-error-message-description' ).replace( '%code%', code).replace( '%errorinfo%', data.error.info), {
title: mw.msg( 'unknown-error-message-title' )
} );
} );
};
KartoEditor.prototype.importGeoJSON = function( geojson ) {
var self = this;
L.geoJson(geojson, {
onEachFeature: function (feature, layer) {
self.drawnItems.addLayer(layer);
var geoLayer = new GeoLayer( self, feature.geometry.type, layer, feature.properties );
self.geoLayers.push( geoLayer );
self.nbLayer++;
self.updateOutputs();
}
});
};
if ( mw.config.get( 'wgCanonicalNamespace' ) === 'Data' ) {
var $editPortlet = $( '#ca-edit' ),
skin = mw.config.get( 'skin' ),
portletLink,
$kartoEditorPortlet;
initTranslations();
portletLink = mw.util.addPortletLink(
( skin === 'vector' || skin === 'timeless' ) ? 'p-views' : 'p-cactions',
'#',
mw.msg( 'kartoEditor-portlet-name' ),
'ca-kartoeditor',
mw.msg( 'kartoEditor-portlet-description' ),
'k',
( $editPortlet.length > 0 && $editPortlet.next().length > 0 ) ? $editPortlet.next() : null
);
$kartoEditorPortlet = $( portletLink );
if ( skin === 'monobook' ) {
$kartoEditorPortlet.after( ' ' );
}
if ( $editPortlet.hasClass( 'selected' ) ) {
if ( mw.util.getParamValue( 'section' ) === '0' ) {
$editPortlet.removeClass( 'selected' );
$kartoEditorPortlet.addClass( 'selected' );
}
}
//var tab = mw.util.addPortletLink( 'p-views', '#', 'KartoEditor', 'ca-kartoeditor', 'Edit this map using KartoEditor', 'k', $( '#ca-history' ) );
$kartoEditorPortlet.click( function( e ) {
e.preventDefault();
$kartoEditorPortlet.off( 'click' );
$( '#ca-view' ).removeClass( 'selected' );
$( '#ca-edit' ).removeClass( 'selected' );
$( '#ca-history' ).removeClass( 'selected' );
$kartoEditorPortlet.addClass( 'selected' );
if ( mw.config.get( 'wgArticleId' ) !== 0 ) {
var api = new mw.Api();
api.get( {
action: 'query',
prop: 'revisions',
rvprop: [ 'content' ],
titles: mw.config.get( 'wgPageName' ),
formatversion: '2',
} ).then( function( data ) {
var geojson = JSON.parse( data.query.pages[ 0 ].revisions[ 0 ].content );
ke = new KartoEditor( $( '#bodyContent' ).empty()[ 0 ], ( geojson.license || "CC0-1.0" ), ( geojson.description || JSON.parse('{ "en":"No description" }') ), ( geojson.sources || "" ), ( geojson.latitude || 30 ), ( geojson.longitude || 10 ), ( geojson.zoom || 3 ), geojson.data );
} );
}
else {
ke = new KartoEditor( $( '#bodyContent' ).empty()[ 0 ], "CC0-1.0", JSON.parse('{ "en":"No description" }'), "", 30, 10, 3 );
}
} );
}
else if ( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Blankpage' && mw.config.get( 'wgPageName' ).split( '/' ).slice( -1 )[ 0 ] === 'KartoEditor' ) {
$( '#firstHeading' ).text( 'KartoEditor' );
ke = new KartoEditor( $( '#bodyContent' ).empty()[ 0 ], "CC0-1.0", JSON.parse('{ "en":"No description" }'), "", 30, 10, 3 );
document.title = 'KartoEditor';
}
portletLink = mw.util.addPortletLink( 'p-tb', mw.util.getUrl( 'Special:Blankpage/KartoEditor' ), 'KartoEditor', 't-kartoeditor' );
$( portletLink ).append( ' <a href="' + mw.util.getUrl( ':fr:Projet:JavaScript/Notices/KartoEditor' ) + '"><small>(aide)</small></a>' );
window.KartoEditor = KartoEditor;
} )();
//</nowiki>