Closed Malvoz closed 4 years ago
When a layer is in the checked state, it should be visible or disabled. That is it can be checked and disabled and therefore not visible.
I'm going to pretend I'm not confused and just say that if I have:
<label>
Show cats
<input type="checkbox" checked>
</label>
I would assume cats are available to me.
The way I understand it is that the checkbox represents whether a layer is enabled (able to display when possible) not if its in the current map viewport.
If it were the other way around I think you would run into the issue of not being able to disable a layer as it would re-enable whenever the layer is back in the map's viewport.
When a layer is in the checked state, it should be visible or disabled. That is it can be checked and disabled and therefore not visible. I'm going to pretend I'm not confused:
Sorry I gave kind of an incomplete answer, and the correct answer is that your image is pointing to a bug: the checked attribute should be present when the checkbox is checked, and not present when the checkbox is cleared.
@Malvoz if the <layer->
element got into that state by you removing the checked attribute in devtools, I can confirm the behavior.
The intent is that the layer checked
attribute should be in lock-step with the checkbox state in the layer control, and the JavaScript on the page should be able to control that by adding and removing the checked
attribute on the <layer->
element. In that way the developer has a 'DOM api' without having to access the actual layer control, which might be in shadow DOM, like <video>
's.
This has been a source of programming frustration for me; it used to work (better, just checked now, wasn't perfect) in Polymer 1.0, but I may have not put enough effort into getting this api working in the new custom element.
In your raising this point, I've realized that this is not covered in the explainer, and only a little bit in my recent presentation. I will beef those up on this / these points.
To summarize: layer checked
is the intended way that a developer can turn on/off a layer in the map, without removing it from the DOM. It will remain in the layer control with its checkbox cleared / unchecked.
The checked
property / attribute is not related at all to the layer hidden
attribute. "hidden" in this case means that while the element and its contents are in the DOM, the layer itself is "hidden" from the user by being not present in the layer control. Again, toggling or removing that value should toggle the presence of the layer in the layer control, in the order it is found in its dom layer- siblings.
Finally, the disabled
property is intended to be a read-only property that is set / removed by the user agent, when the layer content has failed in some way to be "visible" on the map, for any reason. "visible" is not a keyword, it just means that in principle, if the coordinate system of the layer conforms to that of the map, and if the bounds of the layer intersect the bounds of the map, then the layer is visible in principle (it might not be in fact, e.g. might be a single pixel in size or some bad condition but anyway). Normally, a layer should not sport a disabled
property, if it is functional.
All of these things are supposed to be part of the "DOM API" of a layer, and I believe they will relate to the use cases, if we look carefully.
Thanks @prushforth for the thorough explanation, it confirms how I thought they should work. I think it's mostly the discussion/my thinking around https://github.com/Maps4HTML/MapML/issues/83 that got me confused.
if the
<layer->
element got into that state by you removing the checked attribute in devtools
I'm fairly certain I only viewed the HTML in the browser.
Ok well Ahmad and I should prioritize fixing this and then covering it with tests. I'll chat with him next week about it.
Some relevant reading here
https://developers.google.com/web/fundamentals/web-components/customelements#reflectattr
That article shows how to reflect properties to attributes, but avoids the thorny issue of bidirectional reflection, where the observed attribute reaction sets the property, which can set up an infinite loop.
Update: reentrancy discussion: https://developers.google.com/web/fundamentals/web-components/best-practices#avoid-reentrancy
The other challenge for the checked attribute is that it needs to be reflected to the checkbox in the layer control and the checkbox in the layer control should probably be set up to use / reflect to the attroproperty on the custom element.
So... just need to think about a general architecture / approach for this.
For future reference, and documentation in MapML, the way we handled this is as follows. @ahmadayubi please correct me if I miss anything.
The layer control is hidden in shadow DOM. We need a way to reflect when a user gesture changes the <input type=checkbox>
in the shadow DOM to the <layer- checked>
attroproperty, and a way to propagate changes to the <layer- checked>
attroproperty to the shadow DOM-embedded <input type=checkbox>
(for the specific layer that is targeted).
The <layer->
elements will generate 'change' events when the checked attroproperty changes, via the attributeChangedCallback. This aligns with the CE advice to use the get / set CE properties to set / create the attribute, while using the attributeChangedCallback to apply side effects (the side effect being 1) adding or removing the Leaflet layer from the Leaflet map and 2) the change
event generation).
The <mapml-viewer>
or <map>
element listens for <layer->
-generated change
events (because change
is an actual event name from HTML <input>
, so we have to be specific). When it receives a change
event from any of its layers, it will wrap the change
event in a new layerchange
event. The onAdd
handler of the custom MapMLLayerControl
was modified to listen for the layerchange
event, which is handled by executing the private _validateExtents
function. The _validateExtents
function is normally run on moveend
, but we did not want to trigger a moveend
, which has other impacts across all layers on the map. So the new event layerchange
seemed like the right approach. The _validateExtents
function iterates over all map layers and enables/disables checks/unchecks the child input
elements for each as appropriate to the state of the layer. So there's a bit of overhead there, but it should be ok. TBD.
When a
layer
's visibility status is "off", i.e. notchecked
:the
input
element in the layer control is stillchecked
, is this intentional?