Load a page with drupal ajax from javascript

2.1k views Asked by At

I am working on a Drupal module that provides a jvectormap node type. Everything works fine except the drupal .load(). I use

jQuery("#content").load(Drupal.settings.jvectormapnode.url+'/'+ code +'?ajax=1');

The following happens i click a country on the map and this calls /content/institutes/BE

/content/institutes is an views page with a contextual filter witch grabs the last part of the url and displays some data.

The jvectormap node is included on this same page trough a mini-panel and blocks (the view resides in div #content and the jvectormap in a mini-panel block)

Up to this point everything is ok. Now when i click a second region the URL suddenly switches to /content/undefined.

Let me clarify with an example: I click on Belgium the URL changes to /content/institutes/BE and the view picks this up, then I click France and the URL changes to /content/undefined but the view still reacts correctly and shows the France info. Now I hit F5 to refresh the browser and drupal says that /content/undefined does not exist. If I hit F5 after the first click (Belgium) it reloads the page correctly. The problem seems to happen with consecutive ajax requests. I coud fix this with an url alias so this would handle the F5 refresh edge case seeing everything else works correctly, but if some one else needs more than one node they have a (small) problem.

I suspect the .load is the reason why this is happening.

Any help is welcome thanks.

jvectormapnode.js

(function ($) 
{
  Drupal.behaviors.jvectormapnode = 
  {
    attach: function (context, settings) 
    {
    $('#jvectormapnode').once('jvectormapnode', function() {  //fix duplicating behavior when using ajax

        highlighted=JSON.parse(Drupal.settings.jvectormapnode.coloredregions);
        //console.log(Drupal.settings.jvectormapnode.coloredregions);
        //console.log(highlighted);

            //change color of clicked region ==> todo
            /*
            currentSelected = '';
            defaultColor = '#00FF00';
            selectedColor = '#FF00FF'; 
            maphandle = $('#map-teste'); 

            maphandle.vectorMap({
                map: 'br_en',
                onRegionClick: function(event, code){
                    if(currentSelected !== code) {
                        if(currentSelected !== ''){
                            // Deselect, then select new choice
                            maphandle.vectorMap('set', 'colors', currentSelected, defaultColor);
                            maphandle.vectorMap('set', 'colors', code, selectedColor);
                            currentSelected = code;
                        } else {
                            // Nothing currently selected, go ahead and select
                            maphandle.vectorMap('set', 'colors', code, selectedColor);
                            currentSelected = code;
                        }
                    } else {
                        // Deselect
                        maphandle.vectorMap('set', 'colors', code, defaultColor);
                        currentSelected = '';
                    }
                    alert(code); // return the state
                }
            });*/

          $('#jvectormapnode').vectorMap({
                                        map: 'world_mill_en',
                                        focusOn: {
                                          x: Drupal.settings.jvectormapnode.x,
                                          y: Drupal.settings.jvectormapnode.y,
                                          scale: Drupal.settings.jvectormapnode.scale
                                        },
                                        color: '#aaaaaa',
                                        hoverColor: false,
                                        hoverOpacity: 0.5,
                                        backgroundColor: 'false',
                                        onRegionClick: function (event, code)   {

                                                                                //if(typeof(afunctiontodo!='undefined') afunctiontodo();
                                                                                //else
                                                                                //{
                                                                                    //window.location = Drupal.settings.jvectormapnode.url+'/'+ code;
                                                                                    jQuery("#content").load(Drupal.settings.jvectormapnode.url+'/'+ code +'?ajax=1');
                                                                                    //$('#jvectormapnode').vectorMap('set', 'focus', code);
                                                                                    //showSelectedCountry;
                                                                                //}
                                                                                },  
                                        series: {
                                        regions: [{
                                            values: highlighted ,
                                            attribute: 'fill'
                                        }]
                                    }

                                    });
        });
    }
  };
}(jQuery));

jvectormapnode.module

<?php
/**
 * @file 
 */

/**
 * @defgroup jvectormapnode : Node
 * @ingroup jvectormapnode
 * @{
 * 20130812 pieterm
 * Integrates jvectormapnode into Drupal through the node type system
 */


 /**
 * Implements hook_libraries_info().
 */
function jvectormapnode_libraries_info() {
  $libraries['jvectormap'] = array(
    'name' => 'jVectorMap',
    'vendor url' => 'http://jvectormap.com/',
    'download url' => 'http://jvectormap.com/download/',
    'version arguments' => array(
      'file' => 'jquery.jvectormap.min.js',
      'pattern' => '@jVectorMap version ([0-9\.]+)@',
      'lines' => 2,
      'cols' => 30,
    ),
    'versions' => array(
      '1.2.2' => array(
        'files' => array(
          'js' => array('jquery.jvectormap.min.js'),
          'css' => array('jquery.jvectormap.css'),
        ),
      ),
    ),
  );

  return $libraries;
}

/**
 * Implements hook_view().
 */
function jvectormapnode_view($node, $view_mode) {
      $node->content['jvectormapnodebody'] = array(
    '#markup' => _jvectormapnode_page($node),
    '#weight' => 1,
  );
    return $node;
}


/**
 * Implements hook_theme().
 * Overriding the default node template for jvectormapnode pages
 */
function jvectormapnode_theme($existing, $type, $theme, $path) {
    $items = array(
        'node__jvectormapnode' => array(
            // Don't specify the path in the template name.
            // Unless you have your template inside a directory within this module.
            'template' =>  'templates/node--jvectormapnode',
            'variables' => array('node' => (object)array()),
            // If you want to put the tpl in another location, you can use this key.
            //'theme path' => drupal_get_path('module', 'another_module'),
        ),
    );
    return $items;
}

/**
 * Implements hook_node_info().
 *
 * We use hook_node_info() to define our node content type.
 */
function jvectormapnode_node_info() {
  // We define the node type as an associative array.
  return array(
    'jvectormapnode' => array(
      'name' => t('jvectormapnode'),
      'base' => 'jvectormapnode', //function prefix hooks
      'description' => t('This is the jvectormapnode node type. It can display interactive maps.'),
      'title_label' => t('jvectormapnode page title'),
      'locked' => FALSE, //TODO SET TRUE
    ),
  );
}

/**
 * Implements hook_node_type_insert().
 * lets us know that a new content type has been inserted.
 * this gives us a chance to add the fields we want. (called for all node isnert!==>check type)
 */
function jvectormapnode_node_type_insert($content_type) {
  if ($content_type->type == 'jvectormapnode') {
    // Add default body field
    $body_instance = node_add_body_field($content_type, t('Information you want to show on each page before the content of the jvectormapnode module'));
    $body_instance['display']['example_node_list'] = array(
      'label' => 'hidden',
      'type' => 'text_summary_or_trimmed',
    );
    // Save our changes to the body field instance.
    field_update_instance($body_instance);

    // Create all the fields we are adding to our content type.
    foreach (_jvectormapnode_installed_fields() as $field) {
      field_create_field($field);
    }

    // Create all the instances for our fields.
    foreach (_jvectormapnode_installed_instances() as $instance) {
      $instance['entity_type'] = 'node';
      $instance['bundle'] = 'jvectormapnode';
      field_create_instance($instance);
    }
  }
}

/**
 * Define the fields for our content type.
 *
 * This big array is factored into this function for readability.
 *
 * @return
 *  An associative array specifying the fields we wish to add to our
 *  new node type.
 */
function _jvectormapnode_installed_fields() {
  return array(
      'jvectormapnode_field_color' => array(
      'field_name'  => 'jvectormapnode_field_color',
      'cardinality' => 1,
      'type'        => 'text',
    ),
      'jvectormapnode_field_url' => array(
      'field_name'  => 'jvectormapnode_field_url',
      'cardinality' => 1,
      'type'        => 'text',
    ),
      'jvectormapnode_field_width' => array(
      'field_name'  => 'jvectormapnode_field_width',
      'cardinality' => 1,
      'type'        => 'text',
    ),
      'jvectormapnode_field_height' => array(
      'field_name'  => 'jvectormapnode_field_height',
      'cardinality' => 1,
      'type'        => 'text',
    ),  
      'jvectormapnode_field_regions' => array(
      'field_name'  => 'jvectormapnode_field_regions',
      'cardinality' => 1,
      'type'        => 'text',
    ),  
          'jvectormapnode_field_scale' => array(
      'field_name'  => 'jvectormapnode_field_scale',
      'cardinality' => 1,
      'type'        => 'text',
    ),
          'jvectormapnode_field_x' => array(
      'field_name'  => 'jvectormapnode_field_x',
      'cardinality' => 1,
      'type'        => 'text',
    ),
          'jvectormapnode_field_y' => array(
      'field_name'  => 'jvectormapnode_field_y',
      'cardinality' => 1,
      'type'        => 'text',
    ),
  );
}

/**
 * Define the field instances for our content type.
 *
 * The instance lets Drupal know which widget to use to allow the user to enter
 * data and how to react in different view modes. 
 *
 * This big array is factored into this function for readability.
 *
 * @return
 *  An associative array specifying the instances we wish to add to our new
 *  node type.
 */
function _jvectormapnode_installed_instances() {
  return array(

    'jvectormapnode_field_url' => array(
      'field_name' => 'jvectormapnode_field_url',
      'label'       => t('URL, format http://www.vliz.be/en/...'),
      'widget'      => array(
        'type'    => 'text_textfield',
      ),
      ),
     'jvectormapnode_field_width' => array(
     'field_name' => 'jvectormapnode_field_width',
     'label'       => t('Map width, format px or %'),
     'widget'      => array(
     'type'    => 'text_textfield',
      ),
      ),
        'jvectormapnode_field_height' => array(
     'field_name' => 'jvectormapnode_field_height',
     'label'       => t('Map height, format px or %'),
     'widget'      => array(
     'type'    => 'text_textfield',
      ),
    ),
         'jvectormapnode_field_regions' => array(
     'field_name' => 'jvectormapnode_field_regions',
     'label'       => t('Regions to be highlighted'),
     'widget'      => array(
     'type'    => 'text_textfield',
      ),
      ),

          'jvectormapnode_field_color' => array(
      'field_name' => 'jvectormapnode_field_color',
      'label'       => t('Highlight color, HEX format #ffffff.'),
      'widget'      => array(
        'type'    => 'text_textfield',
      ),
    ),
              'jvectormapnode_field_scale' => array(
      'field_name' => 'jvectormapnode_field_scale',
      'label'       => t('Initial zoom, nummeric format.'),
      'widget'      => array(
        'type'    => 'text_textfield',
      ),
    ),
              'jvectormapnode_field_x' => array(
      'field_name' => 'jvectormapnode_field_x',
      'label'       => t('Initial x-axis focus, nummeric format.'),
      'widget'      => array(
        'type'    => 'text_textfield',
      ),
    ),
              'jvectormapnode_field_y' => array(
      'field_name' => 'jvectormapnode_field_y',
      'label'       => t('Initial y-axis focus, nummeric format.'),
      'widget'      => array(
        'type'    => 'text_textfield',
      ),
    ),
  );
}

/**
 * Implements hook_entity_info_alter().
 *
 * We need to modify the default node entity info by adding a new view mode to
 * be used in functions like node_view() or node_build_content().
 */
function jvectormapnode_entity_info_alter(&$entity_info) {
  // Add our new view mode to the list of view modes...
  $entity_info['node']['view modes']['example_node_list'] = array(
    'label' => t('Example Node List'),
    'custom settings' => TRUE,
  );
}

/**
 * Implement hook_form().
 *
 * Drupal needs for us to provide a form that lets the user
 * add content. This is the form that the user will see if
 * they go to node/add/node-example.
 */
function jvectormapnode_form($node, $form_state) {
  return node_content_form($node, $form_state);
}

/**
 * Implements hook_field_formatter_info().
 */
function jvectormapnode_field_formatter_info() {
  return array(
    'jvectormapnode_field_color' => array(
      'label' => t('jvectormapnode color Handle'),
      'field types' => array('text'),
    ),
    'jvectormapnode_field_url' => array(
      'label' => t('jvectormapnode url Handle'),
      'field types' => array('text'),
    ),
        'jvectormapnode_field_width' => array(
      'label' => t('jvectormapnode width Handle'),
      'field types' => array('text'),
    ),
        'jvectormapnode_field_height' => array(
      'label' => t('jvectormapnode height Handle'),
      'field types' => array('text'),
    ),
        'jvectormapnode_field_regions' => array(
      'label' => t('jvectormapnode regions Handle'),
      'field types' => array('text'),
    ),  
            'jvectormapnode_field_scale' => array(
      'label' => t('jvectormapnode scale Handle'),
      'field types' => array('text'),
    ),          
    'jvectormapnode_field_x' => array(
      'label' => t('jvectormapnode x Handle'),
      'field types' => array('text'),
    ),
        'jvectormapnode_field_y' => array(
      'label' => t('jvectormapnode y Handle'),
      'field types' => array('text'),
    ),      
  );
}

/**
 * Implements hook_help().
 */
function jvectormapnode_help($path, $arg) {
  switch ($path) {
    case 'examples/jvectormapnode':
      return "<p>" . t("The Node Example module provides a custom node type.
        You can create new Example Node nodes using the <a href='!nodeadd'>node add form</a>.",
        array('!nodeadd' => url('node/add/node-example'))) . "</p>";
  }
}

/**
 * Page callback to show jvectormapnode
 */
function _jvectormapnode_page($n) {
    //get params from drupal entity created by user in add content
    $dcolor= field_get_items('node', $n, 'jvectormapnode_field_color');
    $dcolor=render(field_view_value('node', $n, 'jvectormapnode_field_color',$dcolor[0]));

    $durl= field_get_items('node', $n, 'jvectormapnode_field_url');
    $durl=render(field_view_value('node', $n, 'jvectormapnode_field_url',$durl[0]));

    $dwidth= field_get_items('node', $n, 'jvectormapnode_field_width');
    $dwidth=render(field_view_value('node', $n, 'jvectormapnode_field_width',$dwidth[0]));

    $dheight= field_get_items('node', $n, 'jvectormapnode_field_height');
    $dheight=render(field_view_value('node', $n, 'jvectormapnode_field_height',$dheight[0]));   

    $dregions= field_get_items('node', $n, 'jvectormapnode_field_regions');
    $dregions=render(field_view_value('node', $n, 'jvectormapnode_field_regions',$dregions[0]));    

    $dscale= field_get_items('node', $n, 'jvectormapnode_field_scale');
    $dscale=render(field_view_value('node', $n, 'jvectormapnode_field_scale',$dscale[0]));  

        $dx= field_get_items('node', $n, 'jvectormapnode_field_x');
    $dx=render(field_view_value('node', $n, 'jvectormapnode_field_x',$dx[0]));  

        $dy= field_get_items('node', $n, 'jvectormapnode_field_y');
    $dy=render(field_view_value('node', $n, 'jvectormapnode_field_y',$dy[0]));  

    //$coloredregions=array();

    $exploderegions = explode(",", $dregions);

    $coloredregions=array();
    foreach ($exploderegions as $region) 
        {
        $coloredregions[$region] = $dcolor ;
        }

    $coloredregions_object = json_encode($coloredregions);

    $jvectormapnodebody.= '<div style="width: '.$dwidth.'; height: '.$dheight.'" id="jvectormapnode"></div>';


    libraries_load('jvectormap');

    drupal_add_js('/sites/all/modules/vliz/jvectormapnode/js/maps/jquery-jvectormap-world-mill-en.js');

    drupal_add_js(array('jvectormapnode' => array('url' => $durl,'coloredregions'=> $coloredregions_object,'scale' => $dscale,'x' => $dx,'y' => $dy)), 'setting');

    drupal_add_js('/sites/all/modules/vliz/jvectormapnode/js/jvectormapnode.js');

    return $jvectormapnodebody;
}



/**
 * @} End of "defgroup jvectormapnode".
 */
2

There are 2 answers

2
Mike Vranckx On

It seems that the code argument passed within the onRegionClick callback is undefined.

Can you do a console.log() of that argument to know the exact value? Normally this should be the region code as a string. (i.e.: 'BE', 'NL', ...)

onRegionClick: function (event, code) {
     console.log(code);
}
0
Pieter Maes On

I found out what was causing the undefined, here's the code that works

jQuery("#content").load(Drupal.settings.jvectormapnode.url+'/'+ code ,'ajax=1' ,
function() {Drupal.attachBehaviors('#content');});

hope this helps someone else