MediaWiki:DataMaps.js: Difference between revisions
Jump to navigation
Jump to search
Minor labels appear after two zoom clicks instead of three |
Per-marker label direction override via id suffix (--l/--r/--t/--b) |
||
| Line 4: | Line 4: | ||
* and hides labels of the busier groups (towns, ruins, wilds, rumours) while zoomed far out. | * and hides labels of the busier groups (towns, ruins, wilds, rumours) while zoomed far out. | ||
* Styling lives in MediaWiki:DataMaps.css (.dn-map-label). | * Styling lives in MediaWiki:DataMaps.css (.dn-map-label). | ||
* | |||
* Label placement: by group (DIRECTION below), overridable per marker by ending its id with | |||
* --l, --r, --t or --b (left / right / top / bottom), e.g. "sc-elturel--l". | |||
*/ | */ | ||
mw.loader.using( 'ext.datamaps.bootstrap' ).then( function () { | mw.loader.using( 'ext.datamaps.bootstrap' ).then( function () { | ||
var MINOR_GROUPS = [ 'town', 'ruin', 'wilds', 'rumour' ], | var MINOR_GROUPS = [ 'town', 'ruin', 'wilds', 'rumour' ], | ||
DIRECTION = { stronghold: 'bottom', skarhald: 'bottom', party: 'top' }, | DIRECTION = { stronghold: 'bottom', skarhald: 'bottom', party: 'top' }, | ||
SUFFIX = { l: 'left', r: 'right', t: 'top', b: 'bottom' }, | |||
// Minor labels appear once the map is zoomed in this many levels past its fitted (initial) | // Minor labels appear once the map is zoomed in this many levels past its fitted (initial) | ||
// zoom. The zoom buttons step 0.25, so 0.45 = two clicks. | // zoom. The zoom buttons step 0.25, so 0.45 = two clicks. | ||
| Line 19: | Line 22: | ||
var state = marker.apiInstance && marker.apiInstance[ 2 ], | var state = marker.apiInstance && marker.apiInstance[ 2 ], | ||
group = marker.attachedLayers && marker.attachedLayers[ 0 ], | group = marker.attachedLayers && marker.attachedLayers[ 0 ], | ||
direction = DIRECTION[ group ] || 'right', | uid = state && state.uid ? String( state.uid ) : '', | ||
suffix = /--([lrtb])$/.exec( uid ), | |||
direction = ( suffix && SUFFIX[ suffix[ 1 ] ] ) || DIRECTION[ group ] || 'right', | |||
size, half, offset, cls; | size, half, offset, cls; | ||
if ( !state || !state.label || typeof marker.bindTooltip !== 'function' ) { | if ( !state || !state.label || typeof marker.bindTooltip !== 'function' ) { | ||
| Line 28: | Line 33: | ||
half = ( size ? ( Array.isArray( size ) ? size[ 0 ] : size.x || 40 ) : 24 ) / 2; | half = ( size ? ( Array.isArray( size ) ? size[ 0 ] : size.x || 40 ) : 24 ) / 2; | ||
offset = direction === 'right' ? [ half + 2, 0 ] : | offset = direction === 'right' ? [ half + 2, 0 ] : | ||
direction === 'left' ? [ -( half + 2 ), 0 ] : | |||
direction === 'top' ? [ 0, -( half - 2 ) ] : [ 0, half - 2 ]; | direction === 'top' ? [ 0, -( half - 2 ) ] : [ 0, half - 2 ]; | ||
cls = 'dn-map-label dn-map-label-' + direction + ' dn-map-label-g-' + ( group || 'none' ); | cls = 'dn-map-label dn-map-label-' + direction + ' dn-map-label-g-' + ( group || 'none' ); | ||
Revision as of 19:03, 29 August 2026
/**
* Interactive maps (Extension:DataMaps) site script.
* Binds a permanent name label to every marker so the maps read like the printed ones,
* and hides labels of the busier groups (towns, ruins, wilds, rumours) while zoomed far out.
* Styling lives in MediaWiki:DataMaps.css (.dn-map-label).
*
* Label placement: by group (DIRECTION below), overridable per marker by ending its id with
* --l, --r, --t or --b (left / right / top / bottom), e.g. "sc-elturel--l".
*/
mw.loader.using( 'ext.datamaps.bootstrap' ).then( function () {
var MINOR_GROUPS = [ 'town', 'ruin', 'wilds', 'rumour' ],
DIRECTION = { stronghold: 'bottom', skarhald: 'bottom', party: 'top' },
SUFFIX = { l: 'left', r: 'right', t: 'top', b: 'bottom' },
// Minor labels appear once the map is zoomed in this many levels past its fitted (initial)
// zoom. The zoom buttons step 0.25, so 0.45 = two clicks.
NEAR_DELTA = 0.45;
mw.dataMaps.registerMapAddedHandler( function ( map ) {
var isMini = map.rootElement.classList.contains( 'ext-datamaps-mini-layout' );
map.on( 'markerReady', function ( marker ) {
var state = marker.apiInstance && marker.apiInstance[ 2 ],
group = marker.attachedLayers && marker.attachedLayers[ 0 ],
uid = state && state.uid ? String( state.uid ) : '',
suffix = /--([lrtb])$/.exec( uid ),
direction = ( suffix && SUFFIX[ suffix[ 1 ] ] ) || DIRECTION[ group ] || 'right',
size, half, offset, cls;
if ( !state || !state.label || typeof marker.bindTooltip !== 'function' ) {
return;
}
// Icons are anchored at their centre; push the label just clear of the icon edge.
size = marker.options && marker.options.icon && marker.options.icon.options.iconSize;
half = ( size ? ( Array.isArray( size ) ? size[ 0 ] : size.x || 40 ) : 24 ) / 2;
offset = direction === 'right' ? [ half + 2, 0 ] :
direction === 'left' ? [ -( half + 2 ), 0 ] :
direction === 'top' ? [ 0, -( half - 2 ) ] : [ 0, half - 2 ];
cls = 'dn-map-label dn-map-label-' + direction + ' dn-map-label-g-' + ( group || 'none' );
if ( isMini ) {
cls += ' dn-map-label-mini';
}
if ( MINOR_GROUPS.indexOf( group ) !== -1 ) {
cls += ' dn-map-label-minor';
}
marker.bindTooltip( state.label, {
permanent: true,
direction: direction,
offset: offset,
interactive: false,
opacity: 1,
className: cls
} );
} );
// Zoom tier → data attribute the CSS keys off. "far" = at or near the fitted zoom.
map.on( 'leafletLoaded', function () {
var leafletMap = map.viewport && map.viewport.getLeafletMap(),
baseZoom = null;
if ( !leafletMap ) {
return;
}
function updateTier() {
var z = leafletMap.getZoom();
if ( baseZoom === null || z < baseZoom ) {
baseZoom = z; // the most zoomed-out level seen is the fitted view
}
map.rootElement.dataset.dnZoom = z.toFixed( 2 );
map.rootElement.dataset.dnBaseZoom = baseZoom.toFixed( 2 );
map.rootElement.dataset.dnLabelTier = ( z - baseZoom ) < NEAR_DELTA ? 'far' : 'near';
}
leafletMap.on( 'zoomend', updateTier );
leafletMap.whenReady( updateTier );
} );
} );
} );