11export class MapFeature extends HTMLElement {
22 static get observedAttributes ( ) {
3- return [ 'zoom' , 'onfocus ' , 'onclick' , 'onblur '] ;
3+ return [ 'zoom' , 'min ' , 'max ' ] ;
44 }
55
66 get zoom ( ) {
@@ -88,15 +88,6 @@ export class MapFeature extends HTMLElement {
8888 }
8989 break ;
9090 }
91- case 'onfocus' :
92- case 'onclick' :
93- case 'onblur' :
94- if ( this . _groupEl ) {
95- // "synchronize" the onevent properties (i.e. onfocus, onclick, onblur)
96- // between the mapFeature and its associated <g> element
97- this . _groupEl [ name ] = this [ name ] . bind ( this . _groupEl ) ;
98- break ;
99- }
10091 }
10192 }
10293
@@ -183,15 +174,15 @@ export class MapFeature extends HTMLElement {
183174 }
184175
185176 _addFeature ( ) {
186- let parentEl =
177+ this . _parentEl =
187178 this . parentNode . nodeName . toUpperCase ( ) === 'LAYER-' ||
188179 this . parentNode . nodeName . toUpperCase ( ) === 'MAP-EXTENT'
189180 ? this . parentNode
190181 : this . parentNode . host ;
191182
192183 // arrow function is not hoisted, define before use
193184 var _attachedToMap = ( e ) => {
194- if ( ! parentEl . _layer . _map ) {
185+ if ( ! this . _parentEl . _layer . _map ) {
195186 // if the parent layer- el has not yet added to the map (i.e. not yet rendered), wait until it is added
196187 this . _layer . once (
197188 'attached' ,
@@ -229,21 +220,21 @@ export class MapFeature extends HTMLElement {
229220 }
230221 } ;
231222
232- if ( ! parentEl . _layer ) {
223+ if ( ! this . _parentEl . _layer ) {
233224 // for custom projection cases, the MapMLLayer has not yet created and binded with the layer- at this point,
234225 // because the "createMap" event of mapml-viewer has not yet been dispatched, the map has not yet been created
235226 // the event will be dispatched after defineCustomProjection > projection setter
236227 // should wait until MapMLLayer is built
237228 let parentLayer =
238- parentEl . nodeName . toUpperCase ( ) === 'LAYER-'
239- ? parentEl
240- : parentEl . parentElement || parentEl . parentNode . host ;
229+ this . _parentEl . nodeName . toUpperCase ( ) === 'LAYER-'
230+ ? this . _parentEl
231+ : this . _parentEl . parentElement || this . _parentEl . parentNode . host ;
241232 parentLayer . parentNode . addEventListener ( 'createmap' , ( e ) => {
242233 this . _layer = parentLayer . _layer ;
243234 _attachedToMap ( ) ;
244235 } ) ;
245236 } else {
246- this . _layer = parentEl . _layer ;
237+ this . _layer = this . _parentEl . _layer ;
247238 _attachedToMap ( ) ;
248239 }
249240 }
@@ -274,28 +265,25 @@ export class MapFeature extends HTMLElement {
274265 }
275266
276267 _setUpEvents ( ) {
277- [ 'click' , 'focus' , 'blur' ] . forEach ( ( name ) => {
278- // onevent properties & onevent attributes
279- if ( this [ `on${ name } ` ] && typeof this [ `on${ name } ` ] === 'function' ) {
280- this . _groupEl [ `on${ name } ` ] = this [ `on${ name } ` ] ;
281- }
282- // handle event handlers set via addEventlistener
283- // for HTMLElement
268+ [ 'click' , 'focus' , 'blur' , 'keyup' , 'keydown' ] . forEach ( ( name ) => {
284269 // when <g> is clicked / focused / blurred
285270 // should dispatch the click / focus / blur event listener on **linked HTMLFeatureElements**
286271 this . _groupEl . addEventListener ( name , ( e ) => {
287- // this === mapFeature as arrow function does not have their own "this" pointer
288- // store onEvent handler of mapFeature if there is any to ensure that it will not be re-triggered when the cloned mouseevent is dispatched
289- // so that only the event handlers set on HTMLFeatureElement via addEventListener method will be triggered
290- const handler = this [ `on${ name } ` ] ; // a deep copy, var handler will not change when this.onevent is set to null (i.e. store the onevent property)
291- this [ `on${ name } ` ] = null ;
292272 if ( name === 'click' ) {
293273 // dispatch a cloned mouseevent to trigger the click event handlers set on HTMLFeatureElement
294- this . dispatchEvent ( new PointerEvent ( name , { ...e } ) ) ;
274+ let clickEv = new PointerEvent ( name , { cancelable : true } ) ;
275+ clickEv . originalEvent = e ;
276+ this . dispatchEvent ( clickEv ) ;
277+ } else if ( name === 'keyup' || name === 'keydown' ) {
278+ let keyEv = new KeyboardEvent ( name , { cancelable : true } ) ;
279+ keyEv . originalEvent = e ;
280+ this . dispatchEvent ( keyEv ) ;
295281 } else {
296- this . dispatchEvent ( new FocusEvent ( name , { ...e } ) ) ;
282+ // dispatch a cloned focusevent to trigger the focus/blue event handlers set on HTMLFeatureElement
283+ let focusEv = new FocusEvent ( name , { cancelable : true } ) ;
284+ focusEv . originalEvent = e ;
285+ this . dispatchEvent ( focusEv ) ;
297286 }
298- this [ `on${ name } ` ] = handler ;
299287 } ) ;
300288 } ) ;
301289 }
@@ -324,9 +312,7 @@ export class MapFeature extends HTMLElement {
324312 return this . _layer . _mapmlvectors . _getNativeVariables ( content ) ;
325313 } else if ( content . nodeName . toUpperCase ( ) === 'LAYER-' ) {
326314 // for inline features, read native zoom and cs from inline map-meta
327- let zoomMeta = this . parentElement . querySelectorAll (
328- 'map-meta[name=zoom]'
329- ) ,
315+ let zoomMeta = this . _parentEl . querySelectorAll ( 'map-meta[name=zoom]' ) ,
330316 zoomLength = zoomMeta ?. length ;
331317 nativeZoom = zoomLength
332318 ? + zoomMeta [ zoomLength - 1 ]
@@ -336,7 +322,7 @@ export class MapFeature extends HTMLElement {
336322 ?. split ( '=' ) [ 1 ]
337323 : 0 ;
338324
339- let csMeta = this . parentElement . querySelectorAll ( 'map-meta[name=cs]' ) ,
325+ let csMeta = this . _parentEl . querySelectorAll ( 'map-meta[name=cs]' ) ,
340326 csLength = csMeta ?. length ;
341327 nativeCS = csLength
342328 ? csMeta [ csLength - 1 ] . getAttribute ( 'content' )
@@ -567,68 +553,55 @@ export class MapFeature extends HTMLElement {
567553 }
568554
569555 // a method that simulates a click, or invoking the user-defined click event
570- // event (optional): a MouseEvent object, can be passed as an argument of the user-defined click event handlers
571- click ( event ) {
556+ click ( ) {
572557 let g = this . _groupEl ,
573558 rect = g . getBoundingClientRect ( ) ;
574- if ( ! event ) {
575- event = new MouseEvent ( 'click' , {
576- clientX : rect . x + rect . width / 2 ,
577- clientY : rect . y + rect . height / 2 ,
578- button : 0
579- } ) ;
559+ let event = new MouseEvent ( 'click' , {
560+ clientX : rect . x + rect . width / 2 ,
561+ clientY : rect . y + rect . height / 2 ,
562+ button : 0
563+ } ) ;
564+ let properties = this . querySelector ( 'map-properties' ) ;
565+ if ( g . getAttribute ( 'role' ) === 'link' ) {
566+ for ( let path of g . children ) {
567+ path . mousedown . call ( this . _featureGroup , event ) ;
568+ path . mouseup . call ( this . _featureGroup , event ) ;
569+ }
580570 }
581- if ( typeof this . onclick === 'function' ) {
582- this . onclick . call ( this . _groupEl , event ) ;
583- return ;
584- } else {
585- let properties = this . querySelector ( 'map-properties' ) ;
586- if ( g . getAttribute ( 'role' ) === 'link' ) {
587- for ( let path of g . children ) {
588- path . mousedown . call ( this . _featureGroup , event ) ;
589- path . mouseup . call ( this . _featureGroup , event ) ;
571+ // dispatch click event for map-feature to allow events entered by 'addEventListener'
572+ let clickEv = new PointerEvent ( 'click' , { cancelable : true } ) ;
573+ clickEv . originalEvent = event ;
574+ this . dispatchEvent ( clickEv ) ;
575+ // for custom projection, layer- element may disconnect and re-attach to the map after the click
576+ // so check whether map-feature element is still connected before any further operations
577+ if ( properties && this . isConnected ) {
578+ let featureGroup = this . _featureGroup ,
579+ shapes = featureGroup . _layers ;
580+ // close popup if the popup is currently open
581+ for ( let id in shapes ) {
582+ if ( shapes [ id ] . isPopupOpen ( ) ) {
583+ shapes [ id ] . closePopup ( ) ;
590584 }
591585 }
592- // for custom projection, layer- element may disconnect and re-attach to the map after the click
593- // so check whether map-feature element is still connected before any further operations
594- if ( properties && this . isConnected ) {
595- let featureGroup = this . _featureGroup ,
596- shapes = featureGroup . _layers ;
597- // close popup if the popup is currently open
598- for ( let id in shapes ) {
599- if ( shapes [ id ] . isPopupOpen ( ) ) {
600- shapes [ id ] . closePopup ( ) ;
601- }
602- }
603- if ( featureGroup . isPopupOpen ( ) ) {
604- featureGroup . closePopup ( ) ;
605- } else {
606- featureGroup . openPopup ( ) ;
607- }
586+ if ( featureGroup . isPopupOpen ( ) ) {
587+ featureGroup . closePopup ( ) ;
588+ } else if ( ! clickEv . originalEvent . cancelBubble ) {
589+ // If stopPropagation is not set on originalEvent by user
590+ featureGroup . openPopup ( ) ;
608591 }
609592 }
610593 }
611594
612595 // a method that sets the current focus to the <g> element, or invoking the user-defined focus event
613- // event (optional): a FocusEvent object, can be passed as an argument of the user-defined focus event handlers
614- // options (optional): as options parameter for native HTMLelemnt
596+ // options (optional): as options parameter for native HTMLElement
615597 // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
616- focus ( event , options ) {
617- let g = this . _groupEl ;
618- if ( typeof this . onfocus === 'function' ) {
619- this . onfocus . call ( this . _groupEl , event ) ;
620- return ;
621- } else {
622- g . focus ( options ) ;
623- }
598+ focus ( options ) {
599+ this . _groupEl . focus ( options ) ;
624600 }
625601
626602 // a method that makes the <g> element lose focus, or invoking the user-defined blur event
627- // event (optional): a FocusEvent object, can be passed as an argument of the user-defined blur event handlers
628- blur ( event ) {
629- if ( typeof this . onblur === 'function' ) {
630- this . onblur . call ( this . _groupEl , event ) ;
631- } else if (
603+ blur ( ) {
604+ if (
632605 document . activeElement . shadowRoot ?. activeElement === this . _groupEl ||
633606 document . activeElement . shadowRoot ?. activeElement . parentNode ===
634607 this . _groupEl
0 commit comments