Create a component with two tag functions

I want to extend the Map Field Plugin with the functionality to create a map from the field data. But I really want two tag functions (simplified below). Is there a way to achieve this ?

public function tag($long, $lat) { ... }

and

public function tag($field) { 
    return tag($field->getLong(), $field->getLat());
}

You can do it like that:

public function tag($long, $lat = null) {
  // get data from fields
  if(is_object($long) {
    $lat = $long->getLat();
    $long = $long->getLong();
  }

  // ...
}
1 Like

But isn’t the purpose of the Map Field Plugin to find the coordinates? And the map is only a tool for this?

As I understand it the Map Field Plugin has two parts

  1. Map Fieldtype - to select coordinates
  2. Map Plugin - to do something with those coordinates

Hey, @mxst! Thanks for your comments on GitHub—

I think what you’re looking for can be solved in a few ways:

  1. A static method of a MapPlugin class that outputs the requisite HTML for a give page and field name
  2. A Kirbytext “Tag”, for using maps in-line, like (map: my-field-slug) (and perhaps some additional options passed as Kirbytag params)
  3. A Field method, so you could call $page->my_map_field()->toMap() and have it output (roughly) what either of the above functions do.

My hunch is that #1 is the first place where we should look— then, we can quickly build out the other two.

This has been on my to-do list for a while, but I’ve planned to focus more on documentation than rendering a quick map.

For reference, the quickest way to a rendered map from a field is based on Google’s own basic map tutorial:

<!-- Somewhere in `<head>`, perhaps -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=<?= c::get('map.key') ?>&callback=initMap"></script>

<!-- Your Map -->
<? $location = $page->my_map_field()->yaml() ?>

<div
  id="map"
  data-lat="<?= $location['lat'] ?>"
  data-lng="<?= $location['lng'] ?>"
  data-zoom="<?= c::get('map.zoom') ?>"
  data-marker-title="<?= $page->title()->html() ?>"></div>

<script>
  function initMap() {
    var mapElement = document.getElementById('map');
    var center = {
      lat: mapElement.getAttribute('data-lat'),
      lng: mapElement.getAttribute('data-lng')
    };

    var map = new google.maps.Map(mapElement, {
      zoom: mapElement.getAttribute('data-zoom'),
      center: center
    });

    var marker = new google.maps.Marker({
      position: center,
      map: map,
      title: mapElement.getAttribute('data-marker-title')
    });
  }
</script>

The above initMap could accept the mapElement as an argument, so it’d be a recyclable initializer.

This is also just about what I imagine being output by, say, a MapPlugin::render() function— except for the Google Maps script tag, which should be included just once.

All to say— the implementation is simple, and I’m not sure bundling this with the plugin would be useful. I’d prefer to keep this kind of starting example in the docs.

Let me know your thoughts!

1 Like