If you want to make your pages dynamically loaded via AJAX and do not want to rewrite everything to be converted to JSON, there is a way to get any content you wish to get as JSON. Simply open your template.php file and add following code to the _phptemplate_variables function:


function _phptemplate_variables($hook, $vars) {
  switch ($hook) {
    case 'page':
      // If the page was requested with the jQuery ajax functionalities, an HTTP header (X-Requested-With: XMLHttpRequest) 
      // will be sent to the server, making it possible to identify if we should serve the content as JSON
      if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 'XmlHttpRequest' == $_SERVER['HTTP_X_REQUESTED_WITH']) {
          // Now that we know that the page was requested via remote scripting (AJAX) we can serve the content as JSON
          // by telling Drupal to use a different template for the page (in this case page-json.tpl.php)
          $vars['template_files'] = is_array($vars['template_files']) ? $vars['template_files'] : array();
          $vars['template_files'][] = 'page-json';
      }
      break;
  }
}

Now we can create our page-json.tpl.php in order to put out the content as JSON:

if($messages) {
  $content = $messages.$content;
}
echo drupal_to_js($content);

This is all you need to put out any content as JSON. You can apply the same concept to blocks.

Comments

Ocyrhoé’s picture

$_SERVER['HTTP_X_REQUESTED_WITH'] is XMLHttpRequest (and not XmlHttpRequest) with firefox at least.
Since I don't know if it's true for all of the browsers, I use:
.... && 'xmlhttprequest' == strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) ...

seanburlington’s picture

this is the way it's done for user autocomplete

function user_autocomplete($string = '') {
  $matches = array();
  if ($string) {
    $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10);
    while ($user = db_fetch_object($result)) {
      $matches[$user->name] = check_plain($user->name);
   }
  }
  print drupal_to_js($matches);
  exit();
}

no need for any extra templates etc

It's all in one function

Sean Burlington
www.practicalweb.co.uk
London

grobemo’s picture

The Component module can easily be modified to return JSON-formatted nodes to be retrieved with an AJAX call.

The quick and dirty way to do this is to go into component.module and find the component_get_node function, which should look like this:

function component_get_node($nid) {
  return node_show(node_load($nid), $cid);
}

Replace 'node_show' with 'drupal_to_js' and get rid of the ', $cid' in the second line, giving you this:

function component_get_node($nid) {
  return drupal_to_js(node_load($nid));
}

Voila. Any call to example.com/component/node/2001 will get you node 2001 in JSON.

Here's a little jQuery so you can use this from the client side:

$(foo).click(function_1() { 
     $.getJSON($(this).attr('href'), function_2(json) { $(bar).empty().html(json.title); } );
     return false;
});

For this code, foo should select the link(s) that you want to AJAXify. These links should point to the node(s) that you want to get in JSON. bar should select the element into which you want to write content. (Of course, you could do anything else you want with function_2, as well.)

bennash’s picture

Yeah grobemo's method works great for my json needs. But how does this compare to Views JSON found here http://drupal.org/project/views_json ?

jefkin’s picture

I'm sorry, for as simple as many things are in Drupal, this was so complicated and convoluted, that I was picturing rewriting themes, rewriting menu, even digging deep into the internals of index.php to solve this for a 5.2 Drupal site. I was just about to try xml or something else when I found your comment.

After 2 days of playing with stuff just trying to get a simple anwer, your solution:

#1) print(drupal_to_js($for_json_data));
#2) exit();

Was just what the doctor ordered, many thanks Sean, kudos!

Jeff

Mozzy’s picture

The snippet I posted is not for use in auto-complete or the like. Its purpose is to put out already themed content for AJAX use, for example in AJAX pagers or Tabbed AJAX pages etc.

interfaced’s picture

It should be "XMLHttpRequest"== $_SERVER['HTTP_X_REQUESTED_WITH'], not "XmlHttpRequest"

Thanks for the tip! It works great!

zeezack’s picture

Can this work for Drupal 7?

julien66’s picture

Just in case it interests someone, this is also working on D7 off course although it's probably less usefull since ajax is now better supported :

<?php
theme_preprocess_page(){
  switch ($hook) {
    case 'page':
      // If the page was requested with the jQuery ajax functionalities, an HTTP header (X-Requested-With: XMLHttpRequest)
      // will be sent to the server, making it possible to identify if we should serve the content as JSON
      if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 'XmlHttpRequest' == $_SERVER['HTTP_X_REQUESTED_WITH']) {
          // Now that we know that the page was requested via remote scripting (AJAX) we can serve the content as JSON
          // by telling Drupal to use a different template for the page (in this case page-json.tpl.php)
          $variables['theme_hook_suggestions'] = is_array($variables['theme_hook_suggestions']) ? $vars['theme_hook_suggestions'] : array();
          $variables['theme_hook_suggestions'][] = 'page-json';
      }
      break;
  }
}
?>

With the same bit inside json-page.tpl.php

<?php
if($messages) {
  $content = $messages.$content;
}
echo drupal_to_js($content);
?>
ari-meetai’s picture

function [THEME]_preprocess(&$variables, $hook){
    switch ($hook) {
        case 'page':
            // If the page was requested with the jQuery ajax functionalities, an HTTP header (X-Requested-With: XMLHttpRequest)
            // will be sent to the server, making it possible to identify if we should serve the content as JSON
            if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 'XMLHttpRequest' == $_SERVER['HTTP_X_REQUESTED_WITH']) {
                // Now that we know that the page was requested via remote scripting (AJAX) we can serve the content as JSON
                // by telling Drupal to use a different template for the page (in this case page-json.tpl.php)
                $variables['theme_hook_suggestions'] = is_array($variables['theme_hook_suggestions']) ? $variables['theme_hook_suggestions'] : array();
                $variables['theme_hook_suggestions'][] = 'page-json';
            }
            break;
    }
}