From 0e3fda75df2279ab867452b04908144438dcf067 Mon Sep 17 00:00:00 2001
From: Angie Byron <webchick@24967.no-reply.drupal.org>
Date: Fri, 8 Jan 2010 07:27:32 +0000
Subject: [PATCH] #645822 by sun: Fixed #ajax is not extensible (and partially
 buggy).

---
 includes/ajax.inc | 58 ++++++++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 23 deletions(-)

diff --git a/includes/ajax.inc b/includes/ajax.inc
index c7c32ce92bb1..93d9e8b919ec 100644
--- a/includes/ajax.inc
+++ b/includes/ajax.inc
@@ -369,6 +369,11 @@ function ajax_deliver($page_callback_result) {
 function ajax_process_form($element, &$form_state) {
   $js_added = &drupal_static(__FUNCTION__, array());
 
+  // Nothing to do if there is neither a callback nor a path.
+  if (!(isset($element['#ajax']['callback']) || isset($element['#ajax']['path']))) {
+    return $element;
+  }
+
   // Add a reasonable default event handler if none was specified.
   if (isset($element['#ajax']) && !isset($element['#ajax']['event'])) {
     switch ($element['#type']) {
@@ -403,38 +408,45 @@ function ajax_process_form($element, &$form_state) {
 
   // Adding the same JavaScript settings twice will cause a recursion error,
   // we avoid the problem by checking if the JavaScript has already been added.
-  if (!isset($js_added[$element['#id']]) && (isset($element['#ajax']['callback']) || isset($element['#ajax']['path'])) && isset($element['#ajax']['event'])) {
-    drupal_add_library('system', 'form');
-    $element['#attached']['js'][] = 'misc/ajax.js';
-
-    $ajax_binding = array(
-      'url'      => isset($element['#ajax']['callback']) ? url('system/ajax') : url($element['#ajax']['path']),
-      'event'    => $element['#ajax']['event'],
-      'keypress' => empty($element['#ajax']['keypress']) ? NULL : $element['#ajax']['keypress'],
-      'wrapper'  => empty($element['#ajax']['wrapper']) ? NULL : $element['#ajax']['wrapper'],
-      'selector' => empty($element['#ajax']['selector']) ? '#' . $element['#id'] : $element['#ajax']['selector'],
-      'effect'   => empty($element['#ajax']['effect']) ? 'none' : $element['#ajax']['effect'],
-      'speed'    => empty($element['#ajax']['effect']) ? 'none' : $element['#ajax']['effect'],
-      'method'   => empty($element['#ajax']['method']) ? 'replace' : $element['#ajax']['method'],
-      'progress' => empty($element['#ajax']['progress']) ? array('type' => 'throbber') : $element['#ajax']['progress'],
-      'button'   => isset($element['#executes_submit_callback']) ? array($element['#name'] => $element['#value']) : FALSE,
+  if (!isset($js_added[$element['#id']]) && isset($element['#ajax']['event'])) {
+    $element['#attached']['library'][] = array('system', 'form');
+    $element['#attached']['js']['misc/ajax.js'] = array('weight' => JS_LIBRARY + 2);
+
+    $settings = $element['#ajax'];
+
+    // Assign default settings.
+    $settings += array(
+      'selector' => '#' . $element['#id'],
+      'effect' => 'none',
+      'speed' => 'none',
+      'method' => 'replace',
+      'progress' => array('type' => 'throbber'),
       'formPath' => implode('/', $element['#array_parents']),
     );
 
-    // Convert a simple #ajax['progress'] type string into an array.
-    if (is_string($ajax_binding['progress'])) {
-      $ajax_binding['progress'] = array('type' => $ajax_binding['progress']);
+    // Process special settings.
+    $settings['url'] = isset($settings['path']) ? url($settings['path']) : url('system/ajax');
+    unset($settings['path']);
+    $settings['button'] = isset($element['#executes_submit_callback']) ? array($element['#name'] => $element['#value']) : FALSE;
+
+    // Convert a simple #ajax['progress'] string into an array.
+    if (is_string($settings['progress'])) {
+      $settings['progress'] = array('type' => $settings['progress']);
     }
     // Change progress path to a full URL.
-    if (isset($ajax_binding['progress']['path'])) {
-      $ajax_binding['progress']['url'] = url($ajax_binding['progress']['path']);
+    if (isset($settings['progress']['path'])) {
+      $settings['progress']['url'] = url($settings['progress']['path']);
+      unset($settings['progress']['path']);
     }
     // Add progress.js if we're doing a bar display.
-    if ($ajax_binding['progress']['type'] == 'bar') {
-      drupal_add_js('misc/progress.js', array('cache' => FALSE));
+    if ($settings['progress']['type'] == 'bar') {
+      $element['#attached']['js']['misc/progress.js'] = array('cache' => FALSE);
     }
 
-    drupal_add_js(array('ajax' => array($element['#id'] => $ajax_binding)), 'setting');
+    // @todo This is incompatible with drupal_render() caching, but cannot be
+    //   assigned to #attached, because AJAX callbacks render the form in a way
+    //   so that #attached settings are not taken over.
+    drupal_add_js(array('ajax' => array($element['#id'] => $settings)), 'setting');
 
     $js_added[$element['#id']] = TRUE;
     $form_state['cache'] = TRUE;
-- 
GitLab