Skip to content

Commit

Permalink
feat: require confirmation prior to interactions
Browse files Browse the repository at this point in the history
Issue: #64
  • Loading branch information
alex4401 committed Dec 5, 2022
1 parent 2d8f185 commit 66e1c28
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 4 deletions.
8 changes: 7 additions & 1 deletion extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,17 @@
"vendor/leaflet/leaflet.js",
"leafletPkg/iconMarker.js",
"leafletPkg/circleMarker.js",
"leafletPkg/popup.js"
"leafletPkg/popup.js",
"leafletPkg/interaction.js"
],
"styles": [
"vendor/leaflet/leaflet.css"
],
"messages": [
"datamap-interact-touch",
"datamap-interact-scroll",
"datamap-interact-scroll-mac"
],
"targets": [ "desktop", "mobile" ]
},

Expand Down
6 changes: 4 additions & 2 deletions i18n/core/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,17 @@
"datamap-loading-data": "Please wait, loading data",
"datamap-error-dataload": "<b>Couldn't load data</b><br/>please refresh or try again later",
"datamap-lazy-click-to-load": "Click to load the data map",

"datamap-legend-tab-locations": "Markers",
"datamap-toggle-show-all": "Show all",
"datamap-toggle-hide-all": "Hide all",
"datamap-layer-control": "Toggle",

"datamap-legend-tab-checklist": "Checklists",
"datamap-checklist-prelude": "These are the items you can mark as collected:",

"datamap-interact-touch": "Use two fingers to move the map",
"datamap-interact-scroll": "Use CTRL + Scroll to zoom the map",
"datamap-interact-scroll-mac": "Use \u2318 + Scroll to zoom the map",

"datamap-layer-surface": "Surface",
"datamap-layer-cave": "Caves",

Expand Down
4 changes: 3 additions & 1 deletion resources/leafletPkg/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ module.exports = require( '../vendor/leaflet/leaflet.js' );
module.exports.Ark = {
CircleMarker: require( './circleMarker.js' ),
IconMarker: require( './iconMarker.js' ),
Popup: require( './popup.js' )

Popup: require( './popup.js' ),
InteractionControl: require( './interaction.js' )
};


Expand Down
161 changes: 161 additions & 0 deletions resources/leafletPkg/interaction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
const Leaflet = require( '../vendor/leaflet/leaflet.js' ),
DomEvent = Leaflet.DomEvent,
DomUtil = Leaflet.DomUtil;


module.exports = Leaflet.Handler.extend( {
addHooks() {
this._pane = this._map.createPane( 'interactionWarningPane', this._map._container );
// eslint-disable-next-line mediawiki/class-doc
DomUtil.addClass( this._pane, 'datamap-overlay-status' );

this._disableHandlers();

this._onTouch = this._onTouch.bind( this );
for ( const eventName of [ 'touchmove', 'touchend', 'touchcancel', 'click' ] ) {
this._map._container.addEventListener( eventName, this._onTouch );
}

DomEvent.on( this._map._container, 'wheel', this._onScroll, this );

DomEvent.on( this._map._container, 'mouseenter', this._onMouseOver, this );
DomEvent.on( this._map._container, 'mouseleave', this._onMouseOut, this );
for ( const eventName of [ 'movestart', 'move', 'moveend' ] ) {
DomEvent.on( this._map, eventName, this._onDrag, this );
}

this._enableHandlers( [ 'scrollWheelZoom' ] );
},


removeHooks() {
this._enableHandlers();

for ( const eventName of [ 'touchmove', 'touchend', 'touchcancel', 'click' ] ) {
this._map._container.removeEventListener( eventName, this._onTouch );
}

DomEvent.off( this._map._container, 'wheel', this._onScroll, this );
DomEvent.off( this._map._container, 'mouseenter', this._onMouseOver, this );
DomEvent.off( this._map._container, 'mouseleave', this._onMouseOut, this );

for ( const eventName of [ 'movestart', 'move', 'moveend' ] ) {
DomEvent.off( this._map, eventName, this._onDrag, this );
}
},


showWarning( reason ) {
// Messages that can be used here:
// * datamap-interact-scroll
// * datamap-interact-scroll-mac
// * datamap-interact-touch
this._pane.innerText = mw.msg( `datamap-interact-${reason}${Leaflet.Browser.mac && reason === 'scroll' ? '-mac' : ''}` );
// eslint-disable-next-line mediawiki/class-doc
DomUtil.addClass( this._pane, 'datamap-is-interaction-rejected' );

if ( this._isRejectingInteraction ) {
clearTimeout( this._isRejectingInteraction );
}
this._isRejectingInteraction = setTimeout( () => this.removeWarning( reason ), 1000 );

switch ( reason ) {
case 'scroll':
this._disableHandlers( [ 'scrollWheelZoom' ] );
break;
case 'touch':
this._disableHandlers();
break;
}
},


removeWarning( reason ) {
if ( this._isRejectingInteraction ) {
// eslint-disable-next-line mediawiki/class-doc
DomUtil.removeClass( this._pane, 'datamap-is-interaction-rejected' );
clearTimeout( this._isRejectingInteraction );
this._isRejectingInteraction = null;

switch ( reason ) {
case 'scroll':
this._enableHandlers( [ 'scrollWheelZoom' ] );
break;
case 'touch':
// this._enableHandlers();
break;
}
}
},


_onMouseOver() {
this._enableHandlers();
},


_onMouseOut() {
if ( !this._isDragging ) {
this._disableHandlers();
}
},


_enableHandlers( list ) {
for ( const name of ( list || [ 'dragging', 'scrollWheelZoom', 'tapHold' ] ) ) {
if ( this._map.options[ name ] && this._map[ name ] ) {
this._map[ name ].enable();
}
}
},


_disableHandlers( list ) {
for ( const name of ( list || [ 'dragging', 'scrollWheelZoom', 'tapHold' ] ) ) {
if ( this._map.options[ name ] && this._map[ name ] ) {
this._map[ name ].disable();
}
}
},


_onDrag( e ) {
if ( e.type === 'movestart' || e.type === 'move' ) {
this._isDragging = true;
} else if ( e.type === 'moveend' ) {
this._isDragging = false;
}
},


_onTouch( e ) {
if ( DomUtil.hasClass( e.target, 'leaflet-interactive' ) ) {
if ( e.type === 'touchmove' && e.touches.length === 1 ) {
this.showWarning( 'touch' );
} else {
this.removeWarning( 'touch' );
}
} else
if ( e.type !== 'touchmove' && e.type !== 'touchstart' ) {
this.removeWarning( 'touch' );
} else if ( e.touches.length === 1 ) {
this.showWarning( 'touch' );
} else {
e.preventDefault();
this.removeWarning( 'touch' );
this._enableHandlers();
}
},


_onScroll( e ) {
if ( this._map.scrollWheelZoom && this._map.scrollWheelZoom.enabled() ) {
if ( e.metaKey || e.ctrlKey ) {
e.preventDefault();
this.removeWarning( 'scroll' );
} else {
this.showWarning( 'scroll' );
}
}
}
} );
6 changes: 6 additions & 0 deletions resources/loader/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@ class DataMap extends EventEmitter {
rendererSettings: {
padding: 1/3
},

// Enable bundled interaction rejection control
interactionControl: true
}, this.config.leafletSettings );
// Specify the coordinate reference system and initialise the renderer
leafletConfig.crs = Leaflet.CRS.Simple;
Expand Down Expand Up @@ -621,6 +624,9 @@ class DataMap extends EventEmitter {
// Build extra controls
this._buildControls();

// Install the interaction rejection controller
this.leaflet.addHandler( 'interactionControl', Leaflet.Ark.InteractionControl );

// Notify other components that the Leaflet component has been loaded, and remove all subscribers. All future
// subscribers will be invoked right away.
this.fireMemorised( 'leafletLoaded' );
Expand Down
15 changes: 15 additions & 0 deletions resources/styles/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
background: #e1e4ead4;
color: #000;
font-size: 2.3em;
text-align: center;
backdrop-filter: blur(5px);

&.error {
Expand All @@ -51,4 +52,18 @@
height: 75vh;
}
}

.leaflet-interactionWarning-pane {
opacity: 0;
transition: opacity .1s;
pointer-events: none;
backdrop-filter: none;
z-index: 990;
background: #383939d4;
color: #fff;

&.datamap-is-interaction-rejected {
opacity: 0.9;
}
}
}

0 comments on commit 66e1c28

Please sign in to comment.