I am confused why this is considered an AJAX request, it looks no different from a normal 'hook_menu()' and what usually entails it's callbacks and corresponding arguments. So why is this considered an AJAX request, and other callbacks aren't -- or, are all callbacks in hook_menu() considered 'AJAX requests'?

Let's look at a typical AJAX menu callback use case. Suppose we want a module that allows users to add or delete items from a list via a dynamic AJAX callback. The module might set up something like the following:

-Drupal Module Development, pg. 236

Also, this example seems rather ugly. You would goto this long url address:

http://yoursite.com/example-ajax/%item/add/%user/[whatever]

to simply get a link that says, "add to my list", if you have the "permissions" to do so.

1. Our hook looks like the following:

function example_menu() {
  $items = array();
  $items['example-ajax/%item/add/%user/%'] = array (
    'title' => 'Example AJAX add to list',
    'page callback' => 'example_ajax_add',
    'page_arguments' => array(1, 3),
    'access callback' => 'example_access_ajax_add',
    'access arguments' => array(3, 4),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

2. This allows us to pass a Drupal authentication token to our access callback. To make this work, we modify our link creation code to include a token:

if ($user->uid > 0) {
  $output = l(t('Add to my list'), 'example-ajax/', . $item->id . '/add/' . $user->uid . '/' drupal_get_toekn($user->uid);
  return $output;
}

3. This will generate a link similar to:

<a href='/example-ajax/3/add/10/c342324924cd2342'>Add to my list</a>

4. Then in our access callback, we check the token string in addition to the user:

function example_access_ajax_add($account, $token = null) {
  global $user;
// check the validity of the user account.
  if ($account ->uid == 0 || $account->uid != $user->uid) {
    return false;
  }
// check the validity of the callback token
  if (empty($token) || !drupal_valid_token($token, $account->uid)) {
    return false;
  }
  return true;
}

Comments

jmm42’s picture

I guess I would like some closure as to why:

http://yoursite.com/example-ajax/%item/add/%user/[whatever]

is not an ugly URL, that just outputs a link 'add to my list', and why this is an AJAX example.

Jaypan’s picture

1) What is an 'ugly' URL?
2) Any URL can be an AJAX callback. The only thing that makes an AJAX callback an AJAX callback, is the fact that the URL is called using AJAX. For example, I could use www.drupal.org as an AJAX callback in a function if I wanted, though of course I'd have to parse it for any data I wanted.
3) There is nothing that says 'add to my list' in that code at all, so I'm not sure what you are talking about.

jmm42’s picture

No worries Jaypan, hopefully you see the code above, if one were to have sufficient permissions, then the Drupal l() function creates the link. See the code under 2.

I believe the author assumes the code 2. is contained within 'example_ajax_add' callback

Jaypan’s picture

Ok, I see that. So what are your remaining questions then?

jmm42’s picture

2) Any URL can be an AJAX callback. The only thing that makes an AJAX callback an AJAX callback, is the fact that the URL is called using AJAX. For example, I could use www.drupal.org as an AJAX callback in a function if I wanted, though of course I'd have to parse it for any data I wanted.

If possible, I'd like to be pointed to the corresponding function / file in core that's responsible for making the AJAX process in this callback.

Jaypan’s picture

Well, the function that is called is example_ajax_add(), as can be seen from your menu definition, but I think that's not what you are asking. What do you mean?

jmm42’s picture

The function 'example_ajax_add()' defines a page callback. I'd like to know why this specific page callback 'example_ajax_add()' is considered an AJAX callback. The book I'm reading has gone through great lengths utilizing page callbacks in various 'hook_menu()' scenarios. But, now -- this is considered an AJAX example. How is this different from any other page callbacks that can be found in 'hook_menu()' -- or, are all page callbacks in 'hook_menu()' considered AJAX request?

If I can see the file in core (and corresponding core functions) responsible for this AJAX request / callback, I would be able to understand the connection. But, if you can provide an explanation, I'd appreciate it!

Jaypan’s picture

As I said earlier, the only thing that makes it an AJAX callback is the fact that the URL is called using JavaScript. Ajax is the method of using JavaScript to retrieve data, rather than using the browser to do a full page reload. But whether you access a URL directly through your browser, or using JavaScript, the URL is still the same regardless. That is to say, there is absolutely no difference between a regular URL and an AJAX callback URL. Both are accessed using the http protocol, which returns data from the given URL.

So as I said, I could even use www.drupal.org as an AJAX callback. I could even use google.com as an AJAX callback. Though it's unlikely that either of these would be particularly useful as callbacks.

jmm42’s picture

I don't see any javascript associated with this module (all I see is a page callback labeled 'example_ajax_add'). This is the reason why I wanted to see the core function / file associated with this instance of the AJAX callback.

Jaypan’s picture

Here you go: http://api.drupal.org/api/drupal/includes!ajax.inc/7

You can dig through there to find the internals.

steven.wichers’s picture

When defining a menu item in hook_menu you can specify a delivery callback of "ajax_deliver". A combination of this and use of the ajax_ prefixed commands is what makes a page callback an AJAX callback.

Jaypan is also correct in that a regular menu callback with all the extra page html can be used by javascript, but it is not the correct way. You can also call drupal_exit() at the end of your regular page callback (assuming you output the correct headers) and create an "ajax callback" that way.

darrenwh’s picture

page_argument should be 'page arguments'

BaniMelhem’s picture

Hi,

There is a typo in step 2 : drupal_get_toekn($user->uid);

should be: drupal_get_token($user->uid);

and in step 4 line 4 there is a space between $account and -> after it , which should be removed
before : if ($account ->uid == 0 ||
after    : if ($account->uid == 0 ||

Thanks for this code , it helped me too much. :)