I’ve created a form field that includes the form list field.
It’s working perfectly but I’d like to interact with the list (add, modify and delete list items) without using the built-in buttons…
How familiar are you with JS?
I believe these are your lines:
list.on('click', '> .collection-actions [data-action="add"]', (event) => this.addItem(event));
list.on('click', '> ul > li > .item-actions [data-action="confirm"]', (event) => this.confirmRemove(event));
list.on('click', '> ul > li > .item-actions [data-action="delete"]', (event) => this.removeItem(event));
list.on('click', '> ul > li > .item-actions [data-action="collapse"]', (event) => this.collapseItem(event));
list.on('click', '> ul > li > .item-actions [data-action="expand"]', (event) => this.expandItem(event));
list.on('click', '> .collection-actions [data-action-sort="date"]', (event) => this.sortItems(event));
list.on('click', '> .collection-actions [data-action="collapse_all"]', (event) => this.collapseItems(event));
list.on('click', '> .collection-actions [data-action="expand_all"]', (event) => this.expandItems(event));
list.on('input change', '[data-key-observe]', (event) => this.observeKey(event));
But all these methods are available only inside CollectionsField class. So if you want to have your own logic, I’m afraid you might have to extend the class and methods. Just not sure how you would hook your child class to load and init instead of this original (if it’s even possible).
I’ve written a piece of JavaScript which loads the map et enable interactions : when clicking on the map, a marker is added and the coordinates field input is populated with its coordinates.
The main issue is that the input can contains multiples coordinates… Hence, the idea of using the list form field, something like that :
The idea is to add a fields collection to the list when cllcking on the map and adding the marker.
But I don’t really see how to interact with the list field…
You want to have a list of markers (where marker has an ID, a longitude and a latitude), right? So you should use List field as it is and add your Coordinates (or maybe better yet - LeafletMarker) field as a list item. All JS should be done in the scope of coordinates field. List field should have nothing to do with coordinates
P. S. If you plan to publish this, please don’t name it as ..._new (I think I already mentioned that somewhere). What if someone else or you yourself decides after a couple of years to make a better plugin, what would be the name then? ..._new_new?
Your LeafletMarker field (I’ll call it that way, because it makes more sense to me) should be as a standalone field like any other (Text for example). List field deals with adding/removing markers.
Then marker field I imagine would display a map where you can pin the point and pinning or changing the point would save 3 values - ID, lat, long. You could probably show these values bellow the map as a text (just an idea).
So basically you would have a list of unlimited markers.
My point is, you should create a standalone single marker field and then use it in the list
BTW, benefit of a standalone field would make it usable for those who don’t need a list of markers, but just a single marker on a page. So I would strongly recommend making a plugin with a standalone field and then you can use it yourself however you want
OK, looking at the code I get confused. There are two parts - backend (Admin) and frontend (output on page). So you need to decide how you want to do it.
I believe on frontend you want to show multiple markers on a single map and it kinda does it, but you don’t have multiple markers saved on backend (or even a structure on page frontmatter)
I understand on backend there must be a map shown, where you click on it and marker gets added. So there are two ways, both of which involve JS and hidden form fields. My suggestion was to have a single map for single marker and use list field to add multiple markers. Other way would be having single map and every time you click, marker gets added. In this case list field wouldn’t help much and you’d need to implement your own solution.
Currently your code prevents having multiple maps shown working on same page (backend or frontend), so I would try to solve that first (JS and HTML/Twig). Then make it work in backend so you could save multiple maps each having multiple markers (JS, field HTML, frontmatter structure, etc.). And only then solve output to frontend when you already have the frontmatter (also try to output multiple maps each having multiple markers).
Basically in backend depending which way you go, you’d have either a field for a map with multiple markers or a field for a single marker. Either way saved frontmatter should have a structure like:
maps:
-
mapName: Some name maybe
markers:
-
id: randomStringOrWhatever
lat: 0.0
lng: 0.0
-
id: otherRandomStringOrWhatever
lat: 10.0
lng: 10.0
-
mapName: Some other name probably
markers:
-
id: orMaybeUUID
lat: 50.0
lng: 50.0
-
id: otherUUID
lat: 60.0
lng: 60.0
Then have a separate template (can extend default if you wish to have a description and media) - not default - where you output all maps with their markers on frontend.
First of all, I haven’t work on the frontend at the moment… But my idea is that geolocation is dealt with in the backend.
At this moment, the plugin can deals with multiple markers : the idea is to associate one or more coordinates to a content ; I don’t see any reason why more than one map would be needed (on the backend) for this need.
Multiple coordinates are saved within a single text field :
I’ve extended the default.yaml blueprint, as the Quark theme does ; I think that if you activate the plugin, it’s because you need the feature : it simply adds a field you can use or not. I won’t propose a default template for the frontend, that’s up to a theme I think.
For the frontend, the idea is to supply something like {{ gis }} that adds the map with all markers.
And then to work on the shortcode way to insert maps within the content.
You never know what other use cases might be. It’s better to at least plan ahead, that someone might want to have multiple maps. For example store locations around the country as a list.
How do I add a title for each of these coordinates? Or any other additional info IMO marker should have it’s own set of fields also
Currently you’re extending the default blueprint itself. I’m not even sure what takes priority - theme or plugin. Or are they merged… And don’t know what happens if multiple plugins extend it this way. Quark does this, because it’s a theme (not a plugin) and it adds body_classes text field to it, which is necessary for theme to function as intended. Plugin should have its own template and separate blueprint for it. You can check an example on one of my own plugins to see what I try to say. There’s a separate page template and a blueprint for it, which extends the default as you want to.
Current approach eliminates an option of having a page without a map. If default blueprint is merged from theme and all the plugins (as I would expect), then most of the pages (I suspect even of other plugins, that are extending default for their own custom page blueprint) would have a map.
I mean my plugin linked above - image_comparer template page would also have a map (probably, because I extend default; need to test). I definitely wouldn’t want that to happen. Even if it doesn’t mess up things, I would still want to have an option to add a default page without a map.
My suggestion is to at least prepare for multiple maps solution
And here we have a problem if user decides to insert multiple maps in the content. There’s basically no way to prevent user doing that. If user will try and it won’t work, at least I would consider it as a bug.
TBH, if I needed such a plugin, I’d probably took quite a few parts of what you have already done, give you credit, but create my own with all the features I could think of, that anyone might find a use case for. Marker without at least a title for me would be a deal breaker.
Don’t get me wrong. You already did a good job, but in the current direction I don’t really see how it can’t be used in a variety of different cases.
Why would you need that? Same way how you’re adding now coordinates to one text field, instead add coordinates to some hidden fields (better separate for lat and lng) and create a text field for title. Do your own simple list of markers with specific fields for each of them instead of using List field, which deals with almost any other field inside it.
And yet you already pointed out the problem ahead of even realising it Users can think of using your plugin in ways we can’t even guess Especially if you give a shortcode to use
The task of building my own custom form field is currently out my sight, I’m afraid…
So, I’ve found a way that seems to do what you suggested, I suppose… I’ll try to show you.
First, we declare a new page blueprint that extends the default one, using an @import declaration. This way, anyone can use the geolocation fields in their own page blueprints.
Then, with Javascript, we add an observer to the list <ul> and every time an item is added, we append an interactive map. Each item already saved has it’s own map.
Here is the page frontmatter:
title: Test
markers:
-
name: test
icon: null
latitude: '46.48628983293442'
longitude: '2.759275841232225'
-
name: test
icon: null
latitude: '51.51763080199815'
longitude: '-0.06712918926202739'
Looks much much better. But I’d still try to implement multiple maps. I don’t think there’s a need for such long name default_with_geolocation - just geolocation would be enough I suppose, but it’s up to you. Also maybe better to use a plugin name for a template - less chance of collision with some other plugins. And I noticed observer currently doesn’t watch for removed markers. Oh, nevermind, you currently generate a map for each marker…
I mean it’s definitely much better now. If it works for you and I assume you’re already running out of time, then probably it’s usable. There’s still plenty of room for improvement though
I’ll close this topic because its initial question has been answered
I’ll keep posting about my progress on another topic ; but I take advantage of this post to let you know that I worked on the frontend part of the plugin and developed a Twig function : {{ gis() }} :