Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 16
map-feature bug fixes#841
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
f71c229
remove map-feature bug
AliyanH c425770
Merge branch 'main' of https://github.com/Maps4HTML/Web-Map-Custom-El…
AliyanH 3956180
fix/update Event implementation
AliyanH 65bfe1e
stopPropagation attempt
AliyanH 97cd6ce
Finalize map-feature Event handling
AliyanH 468e81d
revert index.html
AliyanH a1e7cc3
Add test for stopPropagation
AliyanH 9ff535a
update observed attributes + add test for click method
AliyanH c804bbe
remove non-standard event parameter for click,focus,blur methods
AliyanH c8ac48e
add support/link for keyup+keydown event
AliyanH 8ae334b
close popup on zoom to here link, closes #855
AliyanH File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| export class MapFeature extends HTMLElement { | ||
| static get observedAttributes() { | ||
| return ['zoom', 'onfocus', 'onclick', 'onblur']; | ||
| return ['zoom', 'min', 'max']; | ||
| } | ||
| get zoom() { | ||
| @@ -88,15 +88,6 @@ export class MapFeature extends HTMLElement { | ||
| } | ||
| break; | ||
| } | ||
| case 'onfocus': | ||
| case 'onclick': | ||
| case 'onblur': | ||
| if (this._groupEl) { | ||
| // "synchronize" the onevent properties (i.e. onfocus, onclick, onblur) | ||
| // between the mapFeature and its associated <g> element | ||
| this._groupEl[name] = this[name].bind(this._groupEl); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| @@ -183,15 +174,15 @@ export class MapFeature extends HTMLElement { | ||
| } | ||
| _addFeature() { | ||
| let parentEl = | ||
| this._parentEl = | ||
| this.parentNode.nodeName.toUpperCase() === 'LAYER-' || | ||
| this.parentNode.nodeName.toUpperCase() === 'MAP-EXTENT' | ||
| ? this.parentNode | ||
| : this.parentNode.host; | ||
| // arrow function is not hoisted, define before use | ||
| var _attachedToMap = (e) => { | ||
| if (!parentEl._layer._map) { | ||
| if (!this._parentEl._layer._map) { | ||
| // if the parent layer- el has not yet added to the map (i.e. not yet rendered), wait until it is added | ||
| this._layer.once( | ||
| 'attached', | ||
| @@ -229,21 +220,21 @@ export class MapFeature extends HTMLElement { | ||
| } | ||
| }; | ||
| if (!parentEl._layer) { | ||
| if (!this._parentEl._layer) { | ||
| // for custom projection cases, the MapMLLayer has not yet created and binded with the layer- at this point, | ||
| // because the "createMap" event of mapml-viewer has not yet been dispatched, the map has not yet been created | ||
| // the event will be dispatched after defineCustomProjection > projection setter | ||
| // should wait until MapMLLayer is built | ||
| let parentLayer = | ||
| parentEl.nodeName.toUpperCase() === 'LAYER-' | ||
| ? parentEl | ||
| : parentEl.parentElement || parentEl.parentNode.host; | ||
| this._parentEl.nodeName.toUpperCase() === 'LAYER-' | ||
| ? this._parentEl | ||
| : this._parentEl.parentElement || this._parentEl.parentNode.host; | ||
| parentLayer.parentNode.addEventListener('createmap', (e) => { | ||
| this._layer = parentLayer._layer; | ||
| _attachedToMap(); | ||
| }); | ||
| } else { | ||
| this._layer = parentEl._layer; | ||
| this._layer = this._parentEl._layer; | ||
| _attachedToMap(); | ||
| } | ||
| } | ||
| @@ -274,28 +265,25 @@ export class MapFeature extends HTMLElement { | ||
| } | ||
| _setUpEvents() { | ||
| ['click', 'focus', 'blur'].forEach((name) => { | ||
| // onevent properties & onevent attributes | ||
| if (this[`on${name}`] && typeof this[`on${name}`] === 'function') { | ||
| this._groupEl[`on${name}`] = this[`on${name}`]; | ||
| } | ||
| // handle event handlers set via addEventlistener | ||
| // for HTMLElement | ||
| ['click', 'focus', 'blur', 'keyup', 'keydown'].forEach((name) => { | ||
| // when <g> is clicked / focused / blurred | ||
| // should dispatch the click / focus / blur event listener on **linked HTMLFeatureElements** | ||
| this._groupEl.addEventListener(name, (e) => { | ||
| // this === mapFeature as arrow function does not have their own "this" pointer | ||
| // store onEvent handler of mapFeature if there is any to ensure that it will not be re-triggered when the cloned mouseevent is dispatched | ||
| // so that only the event handlers set on HTMLFeatureElement via addEventListener method will be triggered | ||
| 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) | ||
| this[`on${name}`] = null; | ||
| if (name === 'click') { | ||
| // dispatch a cloned mouseevent to trigger the click event handlers set on HTMLFeatureElement | ||
| this.dispatchEvent(new PointerEvent(name, { ...e })); | ||
| let clickEv = new PointerEvent(name, { cancelable: true }); | ||
| clickEv.originalEvent = e; | ||
| this.dispatchEvent(clickEv); | ||
| } else if (name === 'keyup' || name === 'keydown') { | ||
| let keyEv = new KeyboardEvent(name, { cancelable: true }); | ||
| keyEv.originalEvent = e; | ||
| this.dispatchEvent(keyEv); | ||
| } else { | ||
| this.dispatchEvent(new FocusEvent(name, { ...e })); | ||
| // dispatch a cloned focusevent to trigger the focus/blue event handlers set on HTMLFeatureElement | ||
| let focusEv = new FocusEvent(name, { cancelable: true }); | ||
| focusEv.originalEvent = e; | ||
| this.dispatchEvent(focusEv); | ||
| } | ||
| this[`on${name}`] = handler; | ||
| }); | ||
| }); | ||
| } | ||
| @@ -324,9 +312,7 @@ export class MapFeature extends HTMLElement { | ||
| return this._layer._mapmlvectors._getNativeVariables(content); | ||
| } else if (content.nodeName.toUpperCase() === 'LAYER-') { | ||
| // for inline features, read native zoom and cs from inline map-meta | ||
| let zoomMeta = this.parentElement.querySelectorAll( | ||
| 'map-meta[name=zoom]' | ||
| ), | ||
| let zoomMeta = this._parentEl.querySelectorAll('map-meta[name=zoom]'), | ||
| zoomLength = zoomMeta?.length; | ||
| nativeZoom = zoomLength | ||
| ? +zoomMeta[zoomLength - 1] | ||
| @@ -336,7 +322,7 @@ export class MapFeature extends HTMLElement { | ||
| ?.split('=')[1] | ||
| : 0; | ||
| let csMeta = this.parentElement.querySelectorAll('map-meta[name=cs]'), | ||
| let csMeta = this._parentEl.querySelectorAll('map-meta[name=cs]'), | ||
| csLength = csMeta?.length; | ||
| nativeCS = csLength | ||
| ? csMeta[csLength - 1].getAttribute('content') | ||
| @@ -567,68 +553,55 @@ export class MapFeature extends HTMLElement { | ||
| } | ||
| // a method that simulates a click, or invoking the user-defined click event | ||
| // event (optional): a MouseEvent object, can be passed as an argument of the user-defined click event handlers | ||
| click(event) { | ||
| click() { | ||
| let g = this._groupEl, | ||
| rect = g.getBoundingClientRect(); | ||
| if (!event) { | ||
| event = new MouseEvent('click', { | ||
| clientX: rect.x + rect.width / 2, | ||
| clientY: rect.y + rect.height / 2, | ||
| button: 0 | ||
| }); | ||
| let event = new MouseEvent('click', { | ||
| clientX: rect.x + rect.width / 2, | ||
| clientY: rect.y + rect.height / 2, | ||
| button: 0 | ||
| }); | ||
| let properties = this.querySelector('map-properties'); | ||
| if (g.getAttribute('role') === 'link') { | ||
| for (let path of g.children) { | ||
| path.mousedown.call(this._featureGroup, event); | ||
| path.mouseup.call(this._featureGroup, event); | ||
| } | ||
| } | ||
| if (typeof this.onclick === 'function') { | ||
| this.onclick.call(this._groupEl, event); | ||
| return; | ||
| } else { | ||
| let properties = this.querySelector('map-properties'); | ||
| if (g.getAttribute('role') === 'link') { | ||
| for (let path of g.children) { | ||
| path.mousedown.call(this._featureGroup, event); | ||
| path.mouseup.call(this._featureGroup, event); | ||
| // dispatch click event for map-feature to allow events entered by 'addEventListener' | ||
| let clickEv = new PointerEvent('click', { cancelable: true }); | ||
| clickEv.originalEvent = event; | ||
| this.dispatchEvent(clickEv); | ||
| // for custom projection, layer- element may disconnect and re-attach to the map after the click | ||
| // so check whether map-feature element is still connected before any further operations | ||
| if (properties && this.isConnected) { | ||
| let featureGroup = this._featureGroup, | ||
| shapes = featureGroup._layers; | ||
| // close popup if the popup is currently open | ||
| for (let id in shapes) { | ||
| if (shapes[id].isPopupOpen()) { | ||
| shapes[id].closePopup(); | ||
| } | ||
| } | ||
| // for custom projection, layer- element may disconnect and re-attach to the map after the click | ||
| // so check whether map-feature element is still connected before any further operations | ||
| if (properties && this.isConnected) { | ||
| let featureGroup = this._featureGroup, | ||
| shapes = featureGroup._layers; | ||
| // close popup if the popup is currently open | ||
| for (let id in shapes) { | ||
| if (shapes[id].isPopupOpen()) { | ||
| shapes[id].closePopup(); | ||
| } | ||
| } | ||
| if (featureGroup.isPopupOpen()) { | ||
| featureGroup.closePopup(); | ||
| } else { | ||
| featureGroup.openPopup(); | ||
| } | ||
| if (featureGroup.isPopupOpen()) { | ||
| featureGroup.closePopup(); | ||
| } else if (!clickEv.originalEvent.cancelBubble) { | ||
AliyanH marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| // If stopPropagation is not set on originalEvent by user | ||
| featureGroup.openPopup(); | ||
| } | ||
| } | ||
| } | ||
| // a method that sets the current focus to the <g> element, or invoking the user-defined focus event | ||
| // event (optional): a FocusEvent object, can be passed as an argument of the user-defined focus event handlers | ||
| // options (optional): as options parameter for native HTMLelemnt | ||
| // options (optional): as options parameter for native HTMLElement | ||
| // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus | ||
| focus(event, options) { | ||
| let g = this._groupEl; | ||
| if (typeof this.onfocus === 'function') { | ||
| this.onfocus.call(this._groupEl, event); | ||
| return; | ||
| } else { | ||
| g.focus(options); | ||
| } | ||
| focus(options) { | ||
| this._groupEl.focus(options); | ||
| } | ||
| // a method that makes the <g> element lose focus, or invoking the user-defined blur event | ||
| // event (optional): a FocusEvent object, can be passed as an argument of the user-defined blur event handlers | ||
| blur(event) { | ||
| if (typeof this.onblur === 'function') { | ||
| this.onblur.call(this._groupEl, event); | ||
| } else if ( | ||
| blur() { | ||
| if ( | ||
| document.activeElement.shadowRoot?.activeElement === this._groupEl || | ||
| document.activeElement.shadowRoot?.activeElement.parentNode === | ||
| this._groupEl | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <title>map-feature Event tests</title> | ||
| <meta charset="UTF-8"> | ||
| <script type="module" src="mapml-viewer.js"></script> | ||
| </head> | ||
| <body> | ||
| <mapml-viewer width="500" height="500" projection="OSMTILE" zoom="10" lon="-75.7" lat="45.4" controls> | ||
| <layer- label="Features" checked> | ||
| <map-meta name="projection" content="OSMTILE"></map-meta> | ||
| <map-feature> | ||
| <map-featurecaption>Polygon</map-featurecaption> | ||
| <map-geometry cs="gcrs"> | ||
| <map-polygon class="polygon"> | ||
| <map-coordinates>-75.5859375 45.4656690 -75.6813812 45.4533876 -75.6961441 45.4239978 | ||
| -75.7249832 45.4083331 -75.7792282 45.3772317 -75.7534790 45.3294614 -75.5831909 45.3815724 | ||
| -75.6024170 45.4273712 -75.5673981 45.4639834 -75.5859375 45.4656690</map-coordinates> | ||
| </map-polygon> | ||
| </map-geometry> | ||
| <map-properties> | ||
| <h2>This is a Polygon</h2> | ||
| </map-properties> | ||
| </map-feature> | ||
| <map-feature id="line"> | ||
| <map-featurecaption>Line</map-featurecaption> | ||
| <map-geometry cs="gcrs"> | ||
| <map-linestring class="line"> | ||
| <map-coordinates>-75.6168365 45.471929 -75.6855011 45.458445 -75.7016373 45.4391764 -75.7030106 | ||
| 45.4259255 -75.7236099 45.4208652 -75.7565689 45.4117074 -75.7833481 45.384225 -75.8197403 | ||
| 45.3714435 -75.8516693 45.377714</map-coordinates> | ||
| </map-linestring> | ||
| </map-geometry> | ||
| <map-properties> | ||
| <h2>This is a Line</h2> | ||
| </map-properties> | ||
| </map-feature> | ||
| <map-feature> | ||
| <map-featurecaption>Point</map-featurecaption> | ||
| <map-geometry cs="gcrs"> | ||
| <map-point class="point"> | ||
| <map-coordinates>-75.6916809 45.4186964</map-coordinates> | ||
| </map-point> | ||
| </map-geometry> | ||
| <map-properties> | ||
| <h2>This is a Point</h2> | ||
| </map-properties> | ||
| </map-feature> | ||
| </layer-> | ||
| </mapml-viewer> | ||
| <div id="property"></div> | ||
| <script> | ||
| function preventDefaultFunc(e) { | ||
| e.originalEvent.stopPropagation(); | ||
| let out = document.getElementById('property'); | ||
| out.innerHTML = e.srcElement.querySelector("map-properties").innerHTML; | ||
| } | ||
| // Replace map-feature click handling | ||
| document.querySelectorAll('map-feature').forEach((f) => { | ||
| f.onclick = preventDefaultFunc; | ||
| }); | ||
| </script> | ||
| </body> | ||
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.