I wanted to show a page which displays only $content. I successfully got the output when I used this code in template.php inside my theme.

function THEMENAME_preprocess_page(&$vars) {   
  if (isset($_GET['ajax']) && $_GET['ajax'] == '1') {
    $vars['template_file'] = 'page-ajax';

In page-ajax.tpl.php, I used the following code.

  echo $content

Is there anyway to achieve the same thing using a custom module?


I think you all misunderstood my question, i want to override page.tpl with only $content, Not how to create a tpl using hook_theme! Currently i have used the same code in my module, but the problem is i have to manually copy page-ajax.tpl to my active theme directory. You can refer the module i created http://drupal.org/project/ajax_links_api


Drupal works its way down a function call stack to find and use hooks defined in other places. So, in much the same way that THEMENAME_preprocess_page() works, so does MODULENAME_preprocess_page - See http://drupal.org/node/223430 for the specific order that these preprocess functions are called.

Now, as for setting up the template. You define it using http://api.drupal.org/api/function/hook_theme - As an example from the block module:

function block_theme() {
return array(
'block' => array(
      'render element' => 'elements', 
      'template' => 'block',
    ), // Omitted remainder.

Notice the 'template' attribute. That maps to block.tpl.php. So assume the following:

function myModuleName_theme() {
return array(
    'my_themehook_special' => array(
        //notice I am setting this up to look for the file in a subdirectory of the module
        'template' => 'moduleSubdirectory/filenameOfTemplate',
        'arguments' => array('yourArgumentObject' => null),

That would register your template. Check out this blog post for more: http://www.trevorsimonton.com/blog/tplphp-hooktheme-drupal-variable-template-module

| improve this answer | |

Colorbox Node lets you load just content of a menu callback in a colorbox modal via Drupal ajax framework and works well in your case.

When you create your links manually, you will need to add the class "colorbox-node" to the link. That is the only class required and the module will handle the colorbox loading internally. Your link should look like this: <a class="colorbox-node" href="blogs/my-example?width=600&height=600">My Example</a>

| improve this answer | |
  • this is what i want , print content only, but not in a modal ..thanks anyway i will look into the module code to study how they implemented same – Serjas Aug 30 '12 at 5:39

As per your question update, if you would like to include your page-ajax.tpl.php using your module rather than copying it to your active theme you can do the following.

Function in your .module add the path so Drupal knows where to look for your template.

 * Implements hook_theme()
function MODULE_theme() {
  return array(
    'popup' => array(
      'arguments' => array('content' => null), //Array of variables in page-ajax.tpl.php
      'template' => 'ajax',
      'path' => drupal_get_path('module', 'MODULE') .'/theme',

Content in your MODULE/theme/popup.tpl.php file

<?php echo $content; ?>
| improve this answer | |
  • I think you all misunderstood my question, i want to override page.tpl with only $content, Not how to create a tpl using hook_theme! – Serjas Aug 30 '12 at 5:38
  • 1
    Easy enough then. You want to look into api.drupal.org/api/function/hook_page_alter - You can strip out whatever is needed and it will never make it to the page template. – webkenny Aug 31 '12 at 3:29
  • Updated to let template be loaded from module directory instead of needing to copy to theme. – Citricguy Sep 1 '12 at 5:58

This is going to be a long answer but I read your module and I understand what you're trying to do. Here it goes (FYI, I've done this before):

What you're trying to do should not be done with a theme function or a hook_preprocess_page(). What you should be looking at is implementing what is called a "Delivery Callback". If you want any link to be returned via AJAX no matter what the link is based on your query string.

You should really do something like :

 * Implements hook_page_delivery_callback_alter().
function hook_page_delivery_callback_alter(&$callback) {
  // jQuery sets a HTTP_X_REQUESTED_WITH header of 'XMLHttpRequest'.
  // If a page would normally be delivered as an html page, and it is called
  // from an ?ajax Javascript lets render it as ajax_deliver.
  if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
    $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' &&
    $callback == 'drupal_deliver_html_page'
    && $_GET['ajax'] == '1') {
    // Here we change the callback. Now In my example I'm using ajax_deliver
    // but if needed can create your own. That being said ajax_deliver should
    // be more than enough.
    $callback = 'ajax_deliver';

If for some reason you need to modify the content being returned, you can actually accomplish that by using hook_ajax_render_alter() like so:

function ugc_ajax_render_alter(&$commands) {
  if ($_GET['ajax'] == '1') {
   // Add my special ajax commands to render the data how I want.

But in your case you're only replacing content, a simple ajax command of "ajax_command_html" should work because that's what you're doing in your JavaScript.

Also some comments on the JavaScript file. You shouldn't have to do the $.ajax request yourself.

Instead you can easily simplify the whole thing by just adding a class to your links. The same way the use-ajax class works. So in your case you can look at http://drupalcode.org/project/drupal.git/blob/refs/heads/7.x:/misc/ajax.js#l40 for an example of how to generate your AJAX request. If you change your JavaScript to work like that you won't actually have to write your callback, since the Drupal Ajax framework would handle the ajax_commands being return and replace the content with wat ever selector is on the request.

I hope this is helpful and I know it's a lot but you can read the docs Drupal 7 AJAX Framework to learn more about how to work with AJAX requests and Drupal. Reading Drupal 6, the same concept can be accomplished by using the Ctools module.

Feel free to ask any questions. I know these aren't easy answers to implement. lol but the question wasn't an easy question ;-)

| improve this answer | |
  • FYI, I've done a very similar thing, where if a user added an ms-modal class to any link that link would be requested via ajax and display in a special modal. Sadly that code isn't public :-/ – ericduran Aug 31 '12 at 22:48

I think that you can use the same hook MODULENAME_preprocess_page but you need to register your template file using hook_theme read more about it here

I didn't do it before but I think it works that way. A quick search returns this which may help.

| improve this answer | |
  • we can use same thing in .module but the problem is if it should work , this popup.tpl must be in my active theme folder – Serjas Aug 30 '12 at 5:38

Finally found solution

 * Implements hook_theme_registry_alter().
function MODULE_theme_registry_alter(&$theme_registry) {
  // get tpl path in my custom module.
  $mod_path = drupal_get_path('module', 'MODULE') . '/tpl';
  $theme_registry_copy = $theme_registry; // Munge on a copy.
  _theme_process_registry($theme_registry_copy, 'phptemplate', 'theme_engine', 'pow', $mod_path);
  $theme_registry += array_diff_key($theme_registry_copy, $theme_registry);
  $hooks = array('page');
  foreach ($hooks as $h) {
    if (is_array($theme_registry[$h]['theme path'])) {
      $first_element = array_shift($theme_registry[$h]['theme path']);
      array_unshift($theme_registry[$h]['theme path'], $first_element, $mod_path);
| improve this answer | |

Just to add to the answers. If all you want is to output the node content (or any content) without going through Drupal templating engine, there is a much simpler way.

function <MODULE_NAME>_menu() {
    $items = array();

    $items['some_path/%node'] = array(
        'page callback' => '_output_content', // Name of the function to call
        'page arguments' => array(1),
        'access callback' => 'node_access',
        'access arguments' => array('view', 1)

    return $items;

function _output_content($node) {
    $node_view = node_view($node);
    print drupal_render($node_view);


NOTE: Replace "<MODULE_NAME>" with your module name, replace "some_path" with the path that you want to use with your service (you can check it with http://<YOUR_DRUPAL_SITE>/some_path/1234 ), and choose a good name for your callback function, something better then "_output_content", something that has less chance to clash with other module. It's a good practice to use your module name as a prefix.

You can also output arbitrary text content:

function _output_content($node) {


Or even output JSON:

function _output_content($node) {
        'key' => 'value'

| improve this answer | |

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.