0

I have added a js library and associated code to get all Location nodes onto a Map page

This code works fine if I paste it into the map.js file but if I use the drupalSettings variable, the code is appearing in the map.js file but doesn't appear to be executing

The map.js file

(function ($, Drupal, drupalSettings) {

    'use strict';

    Drupal.behaviors.mybehavior = {
        attach: function (context, settings) {

            var map = L.map('mapid').setView([-38.037511118801255, 176.41345152203002], 13);

            var googleSat = L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
                maxZoom: 20,
                subdomains:['mt0','mt1','mt2','mt3']
            }).addTo(map);

            // the data from basic.theme file, basic_page_attachments_alter function
            // console.log(settings.basic.nr_map.foo);
            settings.basic.nr_map.foo;

        }
    };

})(jQuery, Drupal, drupalSettings);

And the code from the theme function

function basic_page_attachments_alter(&$page) {
  $node = \Drupal::routeMatch()->getParameter('node');
  if (!empty($node)) { // if empty its a view and has no bundle - causing 503
    $bundle = $node->bundle();
    if($bundle == 'map') {
      $mapid = $node->id();
      $nids = \Drupal::entityQuery('node')->condition('type','location')->execute();
      $nodes = \Drupal\node\Entity\Node::loadMultiple($nids);

      $out = '';

      foreach ($nodes as $key => $location) {
        $map_title = $location->getTitle();

        // lat, lon
        $latlong_arr = $location->get('field_mahere_location')->getValue();
        $lat = $latlong_arr[0]['lat'];
        $lon = $latlong_arr[0]['lon'];

        $out .= 'var ' . strtolower($video_title) . ' = L.popup({ closeButton: false, closeOnClick: false, autoClose: false, className: "static" }).setLatLng([' . $lat . ', ' . $lon . ']).setContent("<p class=\'location static\'>' . $map_title . '</p>").openPopup().addTo(map);' . PHP_EOL;
      }

      $page['#attached']['drupalSettings']['basic']['nr_map']['foo'] = $out;
      $page['#attached']['library'][] = 'basic/nr_map';
    }
  }
}

If I copy the code from the console i.e. console.log(settings.basic.nr_map.foo) and paste it into the map.js file it runs perfectly and creates all of the map markers I'm after, but if it comes from the variable i.e. settings.basic.nr_map.foo it doesn't execute, and doesn't create any map markers

Any ideas? It seems like it should be simple!

Apologies for the duplicate post but I haven't had any joy on drupal forum.

Thanks

EDIT: And the libraries yml file

nr_map: 
  js:
    js/map.js: {}
  dependencies:
    - core/drupal
    - core/jquery
    - core/drupalSettings
2
  • What does your libraries.yml look like? Does it have core/drupalSettings listed as a dependency? – anonymous Apr 22 '20 at 3:22
  • I have added the libraries yml section at the bottom of the question. Thanks – dave t Apr 22 '20 at 20:49
1

Use drupalSettings.basic.nr_map.foo instead of settings.basic.nr_map.foo in your JavaScript.

3
  • Thanks for the response, but unfortunately it didn't make a difference. The code is showing in the console when I write to console.log, but it still doesn't execute! – dave t Apr 21 '20 at 22:55
  • 1
    Wait ... it looks like you are storing a string in drupalSettings.basic.nr_map.foo and expecting that to be executed as a line of code in your JavaScript? Don't you have to use eval() or something in order to do that? Using eval() is a Bad Idea in general. Why don't you just put that line of code (the popup() call) directly into your JavaScript then pass in only the variables you will need in drupalSettings instead? Looks like you just need to pass $lat $long and $map_title then you can use those values where needed in your JavaScript. – anonymous Apr 22 '20 at 21:38
  • Ah well yes that is what I was expecting, as I thought that was how it worked. It seems that you are correct, I will need to pass a whole bunch of variables as this is for a loop. Anyway this is the right track to be on, so I thank you profusely – dave t Apr 23 '20 at 22:42
1

Just to clarify the answer, which is in Anonymous' comment, the variable passed is text and will not execute as I expected. What I need to do is pass several variables and inject them into the js. Final code:

function basic_page_attachments_alter(&$page) {
  $node = \Drupal::routeMatch()->getParameter('node');
  if (!empty($node)) { // its a view??
    $bundle = $node->bundle();
    if($bundle == 'map') {
      $mapid = $node->id();
      $nids = \Drupal::entityQuery('node')->condition('type','location')->execute();
      $count = count($nids);
      $nodes = \Drupal\node\Entity\Node::loadMultiple($nids);

      $map_data = array();

      foreach ($nodes as $key => $location) {
        $map_title = $location->getTitle();

        // lat, lon
        $latlong_arr = $location->get('field_mahere_location')->getValue();
        $lat = $latlong_arr[0]['lat'];
        $lon = $latlong_arr[0]['lon'];

        $map_data[] = array($map_title, $lat, $lon);
      }

      $page['#attached']['library'][] = 'basic/nr_map';
      $page['#attached']['drupalSettings']['basic']['nr_map']['map_data'] = $map_data;
      $page['#attached']['drupalSettings']['basic']['nr_map']['count'] = $count;
    }
  }
}

And the js:

(function ($, Drupal, drupalSettings) {

'use strict';

Drupal.behaviors.mybehavior = {
    attach: function (context, drupalSettings) {
        if($('body').hasClass("page-mahere")) {

            var map = L.map('mapid').setView([-38.037511118801255, 176.41345152203002], 13);

            var googleSat = L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
                maxZoom: 20,
                subdomains:['mt0','mt1','mt2','mt3']
            }).addTo(map);

            // map_data array -> [0]=>Title, [1]=>Lat, [2]=>Lon
            for (var i = 0; i <= drupalSettings.basic.nr_map.count; i++) {
                var map_point = drupalSettings.basic.nr_map.map_data[i][0];
                map_point = L.popup({ closeButton: false, closeOnClick: false, autoClose: false, className: "static" }).setLatLng([drupalSettings.basic.nr_map.map_data[i][1], drupalSettings.basic.nr_map.map_data[i][2]]).setContent("<p class='location static'>" + drupalSettings.basic.nr_map.map_data[i][0] + "</p>").openPopup().addTo(map);
            }

        }
    }
};

})(jQuery, Drupal, drupalSettings);

Thanks heaps to Anonymous for putting me straight!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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