bozdoz / wp-plugin-leaflet-map

Add leaflet maps to Wordpress with shortcodes
https://wordpress.org/plugins/leaflet-map/
GNU General Public License v2.0
140 stars 71 forks source link

geojson bindPopup(text) not filtering empty values #248

Open goodyis opened 4 months ago

goodyis commented 4 months ago

Using the Wordpress plugin, and the geojson mapping is working. So long as all the fields I call are either populated and/or present. Meaning I'll locations that might have all 8 data-properties, but some locations will only have 5 data-points. The shortcode template is calling all data points. But I can't have locations showing the empty 'key/value' pair for data that is not assigned to the property.

I'm hoping I'm over thinking this; maybe there is a way to tell the shortcode to check for empty values and to not display that section, or there is a better way then editing the 'GeoJSON Shortcode Class' file. Because I've been able to check that value/key pairs and remove any that are empty, but then 'feeding' them back into the text var isn't allowing the shortcode to function properly.

So with no filtering/edits, the shortcode works and pulls the geojson and displays as I would like, expect it displays values that are empty. With the edits, the geojson value is still pushed through and without empty values, but then ignores the shortcode 'instructions.'

Here is wordpress shortcode entry:

[leaflet-map fitbounds scrollwheel  zoomcontrol !detect-retina show_scale draggable height="500"]
[leaflet-geojson src="xxxx" fitbounds="1" iconUrl="xxxx" iconSize="80,50" iconAnchor="40,60"]
<b>{location-name}</b></br><span class="map-link">{loc-address}</span>
</br>Manager: {loc-manager}
<a href="tel:{loc-number}"/>{loc-number}</a> Direct
<a href="tel:{manager-cell}"/>{manager-cell}</a> Cell</br>
</hr>
Assistant Manager: {loc-assistant}
<a href="tel:{assist-cell}"/>{assist-cell}</a> Cell</br>
</hr>
More Info: {popup-text}
[/leaflet-geojson]

Here is the json sample data:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "location-name": "Name",
        "loc-address": "1122 South, State US 12345",
        "loc-number": "888-888-8888",
        "loc-manager": "Manager Name",
        "manager-cell": "111-111-1111",
        "loc-assistant": "Assistant Name",
        "assist-cell": "111-111-1111",
        "popup-text": "This Location accepts Cash Only"
        },
      "geometry": {
        "type": "Point",
        "coordinates": [
        -xx.xxxxxx,
        xx.xxxxxx
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "location-name": "Location2",
        "loc-address": "2211 North, State US 12345",
        "loc-number": "888-888-8882",
        "loc-manager": "Second Manager",
        "manager-cell": ""
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
        -xx.xxxxxx,
        xx.xxxxxx
        ]
      }
    }

  ]
}

Here is the js I've been editing:

function checkProperties(obj) {
    for (var key in obj) {
        if (obj[key] !== null && obj[key] != "")
            return false;
    }
    return true;
}
function onEachFeature (feature, layer) {
    var props = feature.properties || {};
    var text;
    console.log(text);
    if (<?php echo $table_view; ?>) {
        text = window.WPLeafletMapPlugin.propsToTable(props);
    } else {

        Object.keys(window.WPLeafletMapPlugin.template(feature.properties)).forEach(function(key, index) {
            //removeEmpty(this[key]);
            if ( checkProperties(this[key]) )
            {
                //given key does not exist or it has "" or NULL value
                console.log("other: " +this[key]);
                text += "<span class='hide'>"+this[key]+"</span>";
            } else {
                console.log("happy: " + this[key]);
                text += "<span class='show'>"+this[key]+"</span>";
            }

}, window.WPLeafletMapPlugin.template(feature.properties));
    console.log(text);

        /* text = popup_property
            ? props[ popup_property ]
            : window.WPLeafletMapPlugin.template(
                popup_text, 
                feature.properties
            ); */

    }
    if (text) {
        layer.bindPopup( text );

    }
}
bozdoz commented 4 months ago

You're looking for something like a full template engine for the geojson? Like having an if statement to conditionally show the assistant info?

goodyis commented 4 months ago

@bozdoz Not really a full templating system, just a way to check if a json key/pair is empty before showing it.

so something like::

[leaflet-map fitbounds scrollwheel  zoomcontrol !detect-retina show_scale draggable height="500"]
[leaflet-geojson src="xxxx" fitbounds="1" iconUrl="xxxx" iconSize="80,50" iconAnchor="40,60"]
<b>{location-name}</b></br><span class="map-link">{loc-address}</span>
</br>Manager: {loc-manager}
<a href="tel:{loc-number}"/>{loc-number}</a> Direct
<a href="tel:{manager-cell}"/>{manager-cell}</a> Cell</br>
</hr>

if ({loc-assistant} & {assist-cell}) {
   Assistant Manager: {loc-assistant}
   <a href="tel:{assist-cell}"/>{assist-cell}</a> Cell</br>
}

if ({popup-text}) {
  </hr>
  More Info: {popup-text}
}
[/leaflet-geojson]

The goal being this popup below would not show the "More Info: {popup-text}" Because the json for that element is "popup-text": "", While the same thing happens if the element doesn't have popup-text listed as a parameter.

Screenshot 2024-03-04 at 1 43 29 PM
goodyis commented 4 months ago

@bozdoz So a weird work around, if I could get the javascript to actually run after the elements are loaded is to change someof the 'class.geojson-shortcode.php' code to the following:

function checkProperties(obj) {
    for (var key in obj) {
        if (obj[key] !== null && obj[key] !== "") {
            return false;
        }
    }
    return true;
}

function removeEmpty(obj) {
    return Object.entries(obj)
        .filter(([_, v]) => v !== null && v !== "")
        .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});
}
function onEachFeature (feature, layer) {
    var props = feature.properties || {};
    //console.log(props);
    var text;
    //console.log(text);
    if (<?php echo $table_view; ?>) {
        text = window.WPLeafletMapPlugin.propsToTable(props);
    } else {

        var text = "";  // Initialize text variable

// Assuming window.WPLeafletMapPlugin.template(feature.properties) returns an object
var templateProperties = window.WPLeafletMapPlugin.template(feature.properties);

Object.keys(templateProperties).forEach(function (key) {
    var value = templateProperties[key];

    if (checkProperties(value)) {
        // Given key does not exist or it has "" or NULL value
        //console.log("other: " + value);
        // If you want to remove empty properties, use removeEmpty function
        //templateProperties[key] = removeEmpty(value);
        templateProperties[key] = "<span class='removeMe'>n\/a</span>";

    } else {
        //console.log("happy: " + value);
        // Add the non-empty value to the text variable
        //text += value;
    }
});
            text = popup_property
            ? props[ popup_property ]
            : window.WPLeafletMapPlugin.template(
                popup_text, 
                feature.properties
            );
    }
    if (text) {
        layer.bindPopup( text );

    }
}

Then change the shortcode to have the section wrapped in a span with class like:

<span class="parent"><hr/>More Info: {popup-text}</span>[/leaflet-geojson]

Then have the following js added:

<script>
jQuery( document ).ready(function($) {
    console.log( "ready!" );
  $('.removeMe').closest('.parent').remove();
});
</script>

This seems like non-scalable workaround.

I'm hoping you have a cleaner idea.

goodyis commented 4 months ago

@bozdoz I've get it working. I don't think you would call this a 'template engine'

Could you add a hook where I/others could override this file or functions?

bozdoz commented 4 months ago

I think all you may need is a hook in the onEachFeature function

bozdoz commented 4 months ago

What do you think of this? https://github.com/bozdoz/wp-plugin-leaflet-map/pull/249

goodyis commented 4 months ago

@bozdoz That did the trick; thank you sir. Since that passed tests on the pull request, will you be pushing that on your next update?

bozdoz commented 4 months ago

actually on second thought, it should just be a javascript implementation, instead of php

bozdoz commented 4 months ago

On third thought, it may be way less maintainable to move it to javascript. I'll reconsider