ajaxcallbackdrupal-7drupal-theminggraphael

How to "print" a theme during AJAX request (Drupal)


When users click on a button (with id graph), I'd like to fill the default Drupal content div (<div class="content">) with a graphael instance.

The JavaScript:

jQuery(document).ready(function($) {

   $('#toggle #graph').click(function() {


    $.ajax({
      url: "http://www.mysite.com/?q=publications/callback",
      type: 'POST',
      data: {
        'format' : 'graph'
      },
      success: function(response) {
        $('div#content div.content').html(response);
      }
    });
  });
});

The PHP:

$items['publications/callback'] = array(
  'type' => MENU_CALLBACK,  
  'title' => 'All Publications Callback',
  'page callback' => '_process_publications',
  'page arguments' => array(t('journal')),
  'access callback' => TRUE,
);

which leads to the page callback: (I'm concerned with the if code block)

function _process_publications($venue) {

if( isset($_POST['format']) && $_POST['format'] == "graph" ){
    _make_bar_chart($venue);
}
elseif( isset($_POST['format']) && $_POST['format'] == "list" ) {
    _make_list($venue);
}
else{
    return("<p>blah</p>");
}

}

and finally the function called within the callback function:

function _make_bar_chart($venue) {

// get active database connection 
$mysql = Database::getConnection();

// if connection is successful, proceed
if($mysql){
       // do stuff


        $graphael = array(
            'method' => 'bar',
            'values' => $ycoordinates,

            'params' => array(
              'colors' => $colors,
              'font' => '10px Arial, sans-serif',
              'opts' => array(
                'gutter' => '20%',
                'type' => 'square',
              ),
              'label' => array(
                'values' => $xcoordinates,
                'isBottom' => true,
              ),
            ),

            'extend' => array(
              'label' => array(
                'values' => $ycoordinates,
                'params' => array('attrText' => array(
                  'fill' =>  '#aaa',
                  'font' => '10px Arial, sans-serif',
                )),
              ),
            ),
        );

    return theme('graphael', $graphael);

}

// else, connection was unsuccessful
else{
    print("<p>bad connection</p>");
}

} 

THE PROBLEM: returning a theme doesn't really send anything back to the AJAX request (unlike print statements). I tried to print the theme, but that produces a white screen of death. How would I generate the graph without printing something?


Solution

  • Much thanks to nevets on the Drupal forums for the helpful hint: http://drupal.org/node/1664798#comment-6177944

    If you want to use AJAX with Drupal, you are best off actually using Drupal-specific AJAX-related functions. In my theme's page.tpl.php file, I added the following to make the links which would call AJAX:

    <?php
        // drupal_add_library is invoked automatically when a form element has the
        // '#ajax' property, but since we are not rendering a form here, we have to
        // do it ourselves.
        drupal_add_library('system', 'drupal.ajax');
    
    
            // The use-ajax class is special, so that the link will call without causing
            // a page reload. Note the /nojs portion of the path - if javascript is
            // enabled, this part will be stripped from the path before it is called.
            $link1 = l(t('Graph'), 'ajax_link_callback/graph/nojs/', array('attributes' => array('class' => array('use-ajax'))));
            $link2 = l(t('List'), 'ajax_link_callback/list/nojs/', array('attributes' => array('class' => array('use-ajax'))));
            $link3 = l(t('Create Alert'), 'ajax_link_callback/alert/nojs/', array('attributes' => array('class' => array('use-ajax'))));
    
            $output = "<span>$link1</span><span>$link2</span><span>$link3</span><div id='myDiv'></div>";
            print $output;
    
    ?>
    

    When one of the links above is clicked, the callback function is called (e.g. ajax_link_callback/graph):

    // A menu callback is required when using ajax outside of the Form API.
      $items['ajax_link_callback/graph'] = array(
       'page callback' => 'ajax_link_response_graph',
       'access callback' => 'user_access',
       'access arguments' => array('access content'),
       'type' => MENU_CALLBACK,
      );
    

    .. and the callback to which it refers:

    function ajax_link_response_graph($type = 'ajax') {
      if ($type == 'ajax') {
       $output = _make_bar_chart('journal');
       $commands = array();
       // See ajax_example_advanced.inc for more details on the available commands
       // and how to use them.
       $commands[] = ajax_command_html('div#content div.content', $output);
       $page = array('#type' => 'ajax', '#commands' => $commands);
       ajax_deliver($page);
      }
     else {
       $output = t("This is some content delivered via a page load.");
       return $output;
     }
    }
    

    This replaces any HTML within <div class="content"> with the graphael chart returned from _make_bar_chart above.