3

I have a map generated in JS.

I need to set the country-id and url for each country. Both 'country-idandurlare fields in my Craft categories groupcountries`.

{
  "country-id": "FR",
  "url": "http://mysite/country/france"
},

I know (basically) how to output to JS for use in my templates. Here is a link to an earlier question I asked on how to output to JS. This time my question is not how to include JS, but how do I generate a specific output.

How do I incorporate a for loop that produces the desired output for each member of the category country.

{% set nations = craft.categories.group('country') %}
{for country in nations %}
{
"country-id": "{{country.CountryCode}}",
"url": "{{country.url}}",
},
{% endfor %}

Part of the problem is how to I get the loop to also output the script brackets, quotes, commas and attributes that surround the data for each country?

UPDATE -- MORE INFO --- This is the full JS that the above is taken.

<script type="text/javascript">
var map = AmCharts.makeChart( "chartdiv", {
  "type": "map",
    "theme": "light",
    "dataProvider": {
    "map": "worldLow",
    "areas": [ 

              {
                "id": "FR",
                "url": "http://fmysite.dev/country/france"
              },
              {
                "id": "JP",
                "url": "http://mysite.dev/country/japan"
              },
               {
                "id": "SA",
                "url": "http://mysite.dev/country/saudi-arabia"
              },
               {
                "id": "GB",
                "url": "http://mysite.dev/country/united-kingdom"
              },
              ]
  },
   "smallMap":{},
  "areasSettings": {
    // color of areas listed
    "color": "#71d1d7",
    // color of area's outline
    "outlineColor": "#4e93aa",
    // Color of area's outline when user rolls-over it.
    "rollOverOutlineColor": "#000",
    // Color of all areas which are in the map svg file, but not listed as areas in DataSet
    "unlistedAreasColor": "#c7ecf4",
    // Color of all areas' outline which are in the map svg file, but not listed as areas in DataSet 
    "unlistedAreasOutlineColor": "#c7ecf4"
  },

  "listeners": [ {
    "event": "clickMapObject",
    "method": function( e ) {
      // check if clicked map object contains "ajaxUrl" parameter
      if ( e.mapObject.ajaxUrl !== undefined ) {
        // add "description" if it was empty
        if ( e.mapObject.description === undefined )
          e.mapObject.description = "<div id='mapcontent'>Loading...</div>";

        // delay loading by a bit so that map can finish displaying description box and zoom
        setTimeout( function() {
          $( "#mapcontent" ).load( e.mapObject.ajaxUrl );
        }, 1000 );
      }
    }
  } ]


} );
</script>

2 Answers 2

2

It'd probably be easier to assemble the items the way you need them in Twig, and then JSON encode them. Try something like this:

{% set nations = craft.categories.group('country') %}
{% set countries = [] %}
{% for country in nations %}
    {% set thisCountry = {
        'country-id' : country.countryCode,
        'url' : country.url
    } %}
    {% set countries = countries|merge([thisCountry]) %}
{% endfor %}

{% set countryJs %}         
var countries = {{ countries|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}
{% endset %}

{% includeJs countryJs %}
1
  • The output is almost there. As above, the URLs output includes extra slashes http:\/\/mysite.dev\/country\/brazil instead of http:/mysite.dev/country/brazil. Also, do I integrate this back into the larger JS?
    – Hellyar
    Commented Jul 25, 2017 at 22:57
2

There is a much better way to compose a JSON string from Twig templates: the json_encode filter.

To build the data array from your array of category models, you need to loop over them and merge to an empty array row by row. When you are ready with your Twig array, you pipe it through json_encode.

{% set data = {} %}
{% for country in craft.categories.group('country') %}
    {% set data = data|merge([{
        'country-id': country.CountryCode,
        'url': country.url,
    }]) %}
{% endfor %}

<script type="text/javascript">
    window.countryData = {{ data|json_encode|raw }};
</script>

<script src="/js/app.js"></script>
3
  • The output is almost there. Like below, the URLs output includes extra slashes http:\/\/mysite.dev\/country\/brazil instead of http:/mysite.dev/country/brazil. Also, do I integrate this back into the larger JS?
    – Hellyar
    Commented Jul 25, 2017 at 22:57
  • @Hellyar for the backslashes see my answer here: craftcms.stackexchange.com/questions/13458/…
    – carlcs
    Commented Jul 26, 2017 at 1:05
  • @Hellyar in your main JavaScript file app.js, you have access to the data from the windows object. To log it to the console you’d do console.log(countryData). Updated my answer to show where to load the file.
    – carlcs
    Commented Jul 26, 2017 at 1:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.