[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/ctools/includes/ -> ajax.inc (source)

   1  <?php
   2  // $Id: ajax.inc,v 1.14.2.14 2010/10/15 20:56:03 merlinofchaos Exp $
   3  
   4  // Set this so we can tell that the file has been included at some point.
   5  define('CTOOLS_AJAX_INCLUDED', 1);
   6  
   7  /**
   8   * @file
   9   * Utilize the CTools AJAX responder.
  10   *
  11   * The AJAX responder is a javascript tool to make it very easy to do complicated
  12   * operations as a response to AJAX requests. When links are attached to the ajax
  13   * responder, the server sends back a packet of JSON data; this packet is an
  14   * array of commands to carry out.
  15   *
  16   * The command names correlate to functions in the responder space, making it
  17   * relatively easy for applications to provide their own commands to do whatever
  18   * spiffy functionality is necessary.
  19   *
  20   * Each command is an object. $object->command is the type of command and
  21   * will be used to find the function (it will correllate directly to
  22   * a function in the Drupal.CTools.AJAX.Command space). The object can
  23   * contain any other data that the command needs to process.
  24   *
  25   * Built in commands include:
  26   * - replace
  27   *   - selector: The CSS selector. This can be any selector jquery uses in $().
  28   *   - data: The data to use with the jquery replace() function.
  29   *
  30   * - prepend
  31   *   - selector: The CSS selector. This can be any selector jquery uses in $().
  32   *   - data: The data to use with the jquery prepend() function.
  33   *
  34   * - append
  35   *   - selector: The CSS selector. This can be any selector jquery uses in $().
  36   *   - data: The data to use with the jquery append() function.
  37   *
  38   * - after
  39   *   - selector: The CSS selector. This can be any selector jquery uses in $().
  40   *   - data: The data to use with the jquery after() function.
  41   *
  42   * - before
  43   *   - selector: The CSS selector. This can be any selector jquery uses in $().
  44   *   - data: The data to use with the jquery before() function.
  45   *
  46   * - remove
  47   *   - selector: The CSS selector. This can be any selector jquery uses in $().
  48   *
  49   * - changed
  50   *   - selector: The CSS selector. This selector will have 'changed' added as a clas.
  51   *   - star: If set, will add a star to this selector. It must be within the 'selector' above.
  52   *
  53   * - alert
  54   *   - title: The title of the alert.
  55   *   - data: The data in the alert.
  56   *
  57   * - css
  58   *   - selector: The CSS selector to add CSS to.
  59   *   - argument: An array of 'key': 'value' CSS selectors to set.
  60   *
  61   * - attr
  62   *   - selector: The CSS selector. This can be any selector jquery uses in $().
  63   *   - name: The name or key of the data attached to this selector.
  64   *   - value: The value of the data.
  65   *
  66   * - settings
  67   *   - argument: An array of settings to add to Drupal.settings via $.extend
  68   *
  69   * - data
  70   *   - selector: The CSS selector. This can be any selector jquery uses in $().
  71   *   - name: The name or key of the data attached to this selector.
  72   *   - value: The value of the data. Not just limited to strings can be any format.
  73   *
  74   * - redirect
  75   *   - url: The url to be redirected to. This can be an absolute URL or a Drupal path.
  76   *
  77   * - reload
  78   *
  79   * - submit
  80   *   - selector: The CSS selector to identify the form for submission. This can
  81   *     be any selector jquery uses in $().
  82   *
  83   * Commands are usually created with a couple of helper functions, so they
  84   * look like this:
  85   *
  86   * @code
  87   *   $commands = array();
  88   *   $commands[] = ctools_ajax_command_replace('#ctools-object-1', 'some html here');
  89   *   $commands[] = ctools_ajax_command_changed('#ctools-object-1');
  90   *   ctools_ajax_render($commands); // this function exits.
  91   * @endcode
  92   */
  93  
  94  /**
  95   * Render an image as a button link. This will automatically apply an AJAX class
  96   * to the link and add the appropriate javascript to make this happen.
  97   *
  98   * @param $image
  99   *   The path to an image to use that will be sent to theme('image') for rendering.
 100   * @param $dest
 101   *   The destination of the link.
 102   * @param $alt
 103   *   The alt text of the link.
 104   * @param $class
 105   *   Any class to apply to the link. @todo this should be a options array.
 106   */
 107  function ctools_ajax_image_button($image, $dest, $alt, $class = '') {
 108    return ctools_ajax_text_button(theme('image', $image), $dest, $alt, $class);
 109  }
 110  
 111  /**
 112   * Render text as a link. This will automatically apply an AJAX class
 113   * to the link and add the appropriate javascript to make this happen.
 114   *
 115   * Note: 'html' => true so be sure any text is vetted! Chances are these kinds of buttons will
 116   * not use user input so this is a very minor concern.
 117   *
 118   * @param $image
 119   *   The path to an image to use that will be sent to theme('image') for rendering.
 120   * @param $dest
 121   *   The destination of the link.
 122   * @param $alt
 123   *   The alt text of the link.
 124   * @param $class
 125   *   Any class to apply to the link. @todo this should be a options array.
 126   * @param $type
 127   *   A type to use, in case a different behavior should be attached. Defaults
 128   *   to ctools-use-ajax.
 129   */
 130  function ctools_ajax_text_button($text, $dest, $alt, $class = '', $type = 'ctools-use-ajax') {
 131    return l($text, $dest, array('html' => TRUE, 'attributes' => array('class' => "$type $class", 'title' => $alt)));
 132  }
 133  
 134  /**
 135   * Create a command array for the error case.
 136   */
 137  function ctools_ajax_command_error($error = '') {
 138    return array(
 139      'command' => 'alert',
 140      'title' => t('Error'),
 141      'text' => $error ? $error : t('Server reports invalid input error.'),
 142    );
 143  }
 144  
 145  /**
 146   * Create a replace command for the AJAX responder.
 147   *
 148   * The replace command will replace a portion of the current document
 149   * with the specified HTML.
 150   *
 151   * @param $selector
 152   *   The CSS selector. This can be any selector jquery uses in $().
 153   * @param $html
 154   *   The data to use with the jquery replace() function.
 155   */
 156  function ctools_ajax_command_replace($selector, $html) {
 157    return array(
 158      'command' => 'replace',
 159      'selector' => $selector,
 160      'data' => $html,
 161    );
 162  }
 163  
 164  /**
 165   * Set the HTML of a given selector to the given data.
 166   *
 167   * @param $selector
 168   *   The CSS selector. This can be any selector jquery uses in $().
 169   * @param $html
 170   *   The data to use with the jquery replace() function.
 171   */
 172  function ctools_ajax_command_html($selector, $html) {
 173    return array(
 174      'command' => 'html',
 175      'selector' => $selector,
 176      'data' => $html,
 177    );
 178  }
 179  
 180  /**
 181   * Create a prepend command for the AJAX responder.
 182   *
 183   * This will prepend the HTML to the specified selector.
 184   *
 185   * @param $selector
 186   *   The CSS selector. This can be any selector jquery uses in $().
 187   * @param $html
 188   *   The data to use with the jquery prepend() function.
 189   */
 190  function ctools_ajax_command_prepend($selector, $html) {
 191    return array(
 192      'command' => 'prepend',
 193      'selector' => $selector,
 194      'data' => $html,
 195    );
 196  }
 197  
 198  /**
 199   * Create an append command for the AJAX responder.
 200   *
 201   * This will append the HTML to the specified selector.
 202   *
 203   * @param $selector
 204   *   The CSS selector. This can be any selector jquery uses in $().
 205   * @param $html
 206   *   The data to use with the jquery append() function.
 207   */
 208  function ctools_ajax_command_append($selector, $html) {
 209    return array(
 210      'command' => 'append',
 211      'selector' => $selector,
 212      'data' => $html,
 213    );
 214  }
 215  
 216  /**
 217   * Create an after command for the AJAX responder.
 218   *
 219   * This will add the HTML after the specified selector.
 220   *
 221   * @param $selector
 222   *   The CSS selector. This can be any selector jquery uses in $().
 223   * @param $html
 224   *   The data to use with the jquery after() function.
 225   */
 226  function ctools_ajax_command_after($selector, $html) {
 227    return array(
 228      'command' => 'after',
 229      'selector' => $selector,
 230      'data' => $html,
 231    );
 232  }
 233  
 234  /**
 235   * Create a before command for the AJAX responder.
 236   *
 237   * This will add the HTML before the specified selector.
 238   *
 239   * @param $selector
 240   *   The CSS selector. This can be any selector jquery uses in $().
 241   * @param $html
 242   *   The data to use with the jquery before() function.
 243   */
 244  function ctools_ajax_command_before($selector, $html) {
 245    return array(
 246      'command' => 'before',
 247      'selector' => $selector,
 248      'data' => $html,
 249    );
 250  }
 251  
 252  /**
 253   * Create a remove command for the AJAX responder.
 254   *
 255   * This will remove the specified selector and everything within it.
 256   *
 257   * @param $selector
 258   *   The CSS selector. This can be any selector jquery uses in $().
 259   */
 260  function ctools_ajax_command_remove($selector) {
 261    return array(
 262      'command' => 'remove',
 263      'selector' => $selector,
 264    );
 265  }
 266  
 267  /**
 268   * Create a changed command for the AJAX responder.
 269   *
 270   * This will mark an item as 'changed'.
 271   *
 272   * @param $selector
 273   *   The CSS selector. This can be any selector jquery uses in $().
 274   * @param $star
 275   *   An optional CSS selector which must be inside $selector. If specified,
 276   *   a star will be appended.
 277   */
 278  function ctools_ajax_command_changed($selector, $star = '') {
 279    return array(
 280      'command' => 'changed',
 281      'selector' => $selector,
 282      'star' => $star,
 283    );
 284  }
 285  
 286  /**
 287   * Create a css command for the AJAX responder.
 288   *
 289   * This will directly add CSS to the page.
 290   *
 291   * @param $selector
 292   *   The CSS selector. This can be any selector jquery uses in $().
 293   * @param $argument
 294   *   An array of key: value pairs to set in the CSS for the selector.
 295   */
 296  function ctools_ajax_command_css($selector, $argument) {
 297    return array(
 298      'command' => 'css',
 299      'selector' => $selector,
 300      'argument' => $argument,
 301    );
 302  }
 303  
 304  /**
 305   * Create a settings command for the AJAX responder.
 306   *
 307   * This will add CSS files to the output. Files that have already
 308   * been processed will not be processed again.
 309   *
 310   * @param $argument
 311   *   An array of CSS files.
 312   */
 313  function ctools_ajax_command_css_files($argument) {
 314    return array(
 315      'command' => 'css_files',
 316      'argument' => $argument,
 317    );
 318  }
 319  
 320  /**
 321   * Create a settings command for the AJAX responder.
 322   *
 323   * This will extend Drupal.settings with the given array.
 324   *
 325   * @param $argument
 326   *   An array of key: value pairs to add to the settings.
 327   */
 328  function ctools_ajax_command_settings($argument) {
 329    return array(
 330      'command' => 'settings',
 331      'argument' => $argument,
 332    );
 333  }
 334  
 335  /**
 336   * Create a settings command for the AJAX responder.
 337   *
 338   * This will add javascript files to the output. Files that have already
 339   * been processed will not be processed again.
 340   *
 341   * @param $argument
 342   *   An array of javascript files.
 343   */
 344  function ctools_ajax_command_scripts($argument) {
 345    return array(
 346      'command' => 'scripts',
 347      'argument' => $argument,
 348    );
 349  }
 350  
 351  /**
 352   * Create a data command for the AJAX responder.
 353   *
 354   * This will attach the name=value pair of data to the selector via
 355   * jquery's data cache.
 356   *
 357   * @param $selector
 358   *   The CSS selector. This can be any selector jquery uses in $().
 359   * @param $name
 360   *   The name or key: of the data attached to this selector.
 361   * @param $value
 362   *  The value of the data. Not just limited to strings can be any format.
 363   */
 364  function ctools_ajax_command_data($selector, $name, $value) {
 365    return array(
 366      'command' => 'data',
 367      'selector' => $selector,
 368      'name' => $name,
 369      'value' => $value,
 370    );
 371  }
 372  
 373   /**
 374    * Set a single property to a value, on all matched elements.
 375    *
 376    * @param $selector
 377    *   The CSS selector. This can be any selector jquery uses in $().
 378    * @param $name
 379    *   The name or key: of the data attached to this selector.
 380    * @param $value
 381    *  The value of the data.
 382    */
 383   function ctools_ajax_command_attr($selector, $name, $value) {
 384     return array(
 385       'command' => 'attr',
 386       'selector' => $selector,
 387       'name' => $name,
 388       'value' => $value,
 389     );
 390   }
 391  
 392  /**
 393   * Force a table to be restriped.
 394   *
 395   * This is usually used after a table has been modifed by a replace or append
 396   * command.
 397   *
 398   * @param $selector
 399   *   The CSS selector. This can be any selector jquery uses in $().
 400   */
 401  function ctools_ajax_command_restripe($selector) {
 402    return array(
 403      'command' => 'restripe',
 404      'selector' => $selector,
 405    );
 406  }
 407  
 408  /**
 409   * Force a client-side redirect.
 410   *
 411   * @param $url
 412   *   The url to be redirected to. This can be an absolute URL or a
 413   *   Drupal path.
 414   * @param $delay
 415   *   A delay before applying the redirection, in milliseconds.
 416   * @param $options
 417   *   An array of options to pass to the url() function.
 418   */
 419  function ctools_ajax_command_redirect($url, $delay = 0, $options = array()) {
 420    return array(
 421      'command' => 'redirect',
 422      'url' => url($url, $options),
 423      'delay' => $delay,
 424    );
 425  }
 426  
 427  /**
 428   * Force a reload of the current page.
 429   */
 430  function ctools_ajax_command_reload() {
 431    return array(
 432      'command' => 'reload',
 433    );
 434  }
 435  
 436  /**
 437   * Submit a form.
 438   *
 439   * This is useful for submitting a parent form after a child form has finished
 440   * processing in a modal overlay.
 441   *
 442   * @param $selector
 443   *   The CSS selector to identify the form for submission. This can be any
 444   *   selector jquery uses in $().
 445   */
 446  function ctools_ajax_command_submit($selector) {
 447    return array(
 448      'command' => 'submit',
 449      'selector' => $selector,
 450    );
 451  }
 452  
 453  /**
 454   * Render a commands array into JSON and immediately hand this back
 455   * to the AJAX requester.
 456   */
 457  function ctools_ajax_render($commands = array()) {
 458    $js_files = array();
 459    $settings = ctools_process_js_files($js_files, 'header');
 460    $settings += ctools_process_js_files($js_files, 'footer');
 461  
 462    $query_string = '?'. substr(variable_get('css_js_query_string', '0'), 0, 1);
 463    $css = drupal_add_css();
 464    foreach ($css as $media => $types) {
 465      // If CSS preprocessing is off, we still need to output the styles.
 466      // Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones.
 467      foreach ($types as $type => $files) {
 468        if ($type == 'module') {
 469          // Setup theme overrides for module styles.
 470          $theme_styles = array();
 471          foreach (array_keys($css[$media]['theme']) as $theme_style) {
 472            $theme_styles[] = basename($theme_style);
 473          }
 474        }
 475        // The theme stuff should already be added and because of admin themes,
 476        // this could cause different CSS to be added.
 477        if ($type != 'theme') {
 478          foreach ($types[$type] as $file => $preprocess) {
 479            // If the theme supplies its own style using the name of the module style, skip its inclusion.
 480            // This includes any RTL styles associated with its main LTR counterpart.
 481            if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {
 482              // Unset the file to prevent its inclusion when CSS aggregation is enabled.
 483              unset($types[$type][$file]);
 484              continue;
 485            }
 486            // Only include the stylesheet if it exists.
 487            if (file_exists($file)) {
 488              $css_files[] = array(
 489                'file' => base_path() . $file . $query_string,
 490                'media' => $media,
 491              );
 492            }
 493          }
 494        }
 495      }
 496    }
 497  
 498    if (!empty($js_files)) {
 499      array_unshift($commands, ctools_ajax_command_scripts(array_keys($js_files)));
 500    }
 501  
 502    if (!empty($css_files)) {
 503      array_unshift($commands, ctools_ajax_command_css_files($css_files));
 504    }
 505  
 506    if (!empty($settings)) {
 507      array_unshift($commands, ctools_ajax_command_settings(call_user_func_array('array_merge_recursive', $settings)));
 508    }
 509  
 510    if (!empty($_REQUEST['ctools_multipart'])) {
 511      // We don't use drupal_json here because the header is not true. We're not really
 512      // returning JSON, strictly-speaking, but rather JSON content wrapped in a <textarea>
 513      // as per the "file uploads" example here: http://malsup.com/jquery/form/#code-samples
 514      echo '<textarea>' . drupal_to_js($commands) . '</textarea>';
 515    }
 516    else {
 517      drupal_json($commands);
 518    }
 519    exit;
 520  }
 521  
 522  /**
 523   * Send an error response back via AJAX and immediately exit.
 524   */
 525  function ctools_ajax_render_error($error = '') {
 526    $commands = array();
 527    $commands[] = ctools_ajax_command_error($error);
 528    ctools_ajax_render($commands);
 529  }
 530  
 531  /**
 532   * Associate a URL to a form element with a hidden form.
 533   *
 534   * This is a helper function to easily associate a URL with a form element
 535   * which can be used for different ajax functionality.
 536   *
 537   * You would call this function on a form element in the form function like this:
 538   *
 539   * @code
 540   *   $form['example'] = array(
 541   *     '#title' => t('Example'),
 542   *     '#type' => 'select',
 543   *     '#options' => array(1 => 'One', 2 => 'Two', 3 => 'Three'),
 544   *     '#default_value' => 1,
 545   *   );
 546   *   ctools_ajax_associate_url_to_element($form, $form['example'], 'example/ajax/urlpath');
 547   * @endcode
 548   *
 549   * The AJAX request will POST the value of the form element in the
 550   * "ctools_changed" parameter (i.e. $_POST['ctools_changed']).
 551   *
 552   * @param &$form
 553   *   Reference to the form element. This is required to have the #id and
 554   *   #attribute elements populated and to create the hidden form element for
 555   *   each select.
 556   * @param &$form_element
 557   *   The form element we are going to take action on.
 558   * @param $dest
 559   *   The URL to associate the form element to.
 560   * @param $type
 561   *   Optional; A type to use, in case a different behavior should be attached.
 562   *   If empty the type will be set to "ctools-use-ajax" for submit elements and
 563   *   "ctools-use-ajax-onchange" for other elements.
 564   */
 565  function ctools_ajax_associate_url_to_element(&$form, &$form_element, $dest, $type = '') {
 566    drupal_add_js('misc/jquery.form.js', 'core');
 567    if (!isset($form_element['#id'])) {
 568      //Create a unique ID to associate $form_element and hidden elements since we dont have an ID
 569      $form_element['#id'] = uniqid('ctools-ajax-url-');
 570  
 571      if (empty($type)) {
 572        $type = $form_element['#type'] == 'submit' ? 'ctools-use-ajax' : 'ctools-use-ajax-onchange';
 573      }
 574  
 575      if (empty($form_element['#attributes']['class'])) {
 576        $form_element['#attributes']['class'] = $type;
 577      }
 578      else {
 579        $form_element['#attributes']['class'] .= " $type";
 580      }
 581    }
 582  
 583    //Add hidden form element to hold base URL
 584    $form[$form_element['#id'] . '-url'] = array(
 585      '#type' => 'hidden',
 586      '#value' => $dest,
 587      '#attributes' => array('class' =>  $form_element['#id'] . '-url'),
 588    );
 589  }
 590  
 591  function ctools_ajax_page_preprocess(&$variables) {
 592    $js_files = $css_files = array();
 593    ctools_process_js_files($js_files, 'header');
 594    ctools_process_js_files($js_files, 'footer');
 595    ctools_process_css_files($css_files, $variables['css']);
 596  
 597    // Add loaded JS and CSS information to the footer, so that an AJAX
 598    // request knows if they are already loaded.
 599    // For inline Javascript to validate as XHTML, all Javascript containing
 600    // XHTML needs to be wrapped in CDATA. To make that backwards compatible
 601    // with HTML 4, we need to comment out the CDATA-tag.
 602    $loaded = array('CToolsAJAX' => array('scripts' => $js_files, 'css' => $css_files));
 603    $embed_prefix = "\n<!--//--><![CDATA[//><!--\n";
 604    $embed_suffix = "\n//--><!]]>\n";
 605    $variables['closure'].= '<script type="text/javascript">' . $embed_prefix . 'jQuery.extend(Drupal.settings, ' . drupal_to_js($loaded) . ");" . $embed_suffix . "</script>\n";
 606  }
 607  
 608  /**
 609   * Create a list of javascript files that are on the page.
 610   */
 611  function ctools_process_js_files(&$js_files, $scope) {
 612    // Automatically extract any 'settings' added via drupal_add_js() and make
 613    // them the first command.
 614    $scripts = drupal_add_js(NULL, NULL, $scope);
 615  
 616    // Get replacements that are going to be made by contrib modules and take
 617    // them into account so we don't double-load scripts.
 618    static $replacements = NULL;
 619    if (!isset($replacements)) {
 620      $replacements = module_invoke_all('js_replacements');
 621    }
 622  
 623    $settings = array();
 624    foreach ($scripts as $type => $data) {
 625      switch ($type) {
 626        case 'setting':
 627          $settings = $data;
 628          break;
 629        case 'inline':
 630        case 'theme':
 631          // Presently we ignore inline javascript.
 632          // Theme JS is already added and because of admin themes, this could add
 633          // improper JS to the page.
 634          break;
 635        default:
 636          // If JS preprocessing is off, we still need to output the scripts.
 637          // Additionally, go through any remaining scripts if JS preprocessing is on and output the non-cached ones.
 638          foreach ($data as $path => $info) {
 639            // If the script is being replaced, take that replacment into account.
 640            $final_path = isset($replacements[$type][$path]) ? $replacements[$type][$path] : $path;
 641            $js_files[base_path() . $final_path] = TRUE;
 642          }
 643      }
 644    }
 645  
 646    return $settings;
 647  }
 648  
 649  /**
 650   * Create a list of CSS files to add to the page.
 651   */
 652  function ctools_process_css_files(&$css_files, $css) {
 653    // Go through all CSS files that are being added to the page and catalog them.
 654    $css_files = array();
 655    foreach ($css as $media => $types) {
 656      // If CSS preprocessing is off, we still need to output the styles.
 657      // Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones.
 658      foreach ($types as $type => $files) {
 659        if ($type == 'module') {
 660          // Setup theme overrides for module styles.
 661          $theme_styles = array();
 662          foreach (array_keys($css[$media]['theme']) as $theme_style) {
 663            $theme_styles[] = basename($theme_style);
 664          }
 665        }
 666        foreach ($types[$type] as $file => $preprocess) {
 667          // If the theme supplies its own style using the name of the module style, skip its inclusion.
 668          // This includes any RTL styles associated with its main LTR counterpart.
 669          if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {
 670            // Unset the file to prevent its inclusion when CSS aggregation is enabled.
 671            unset($types[$type][$file]);
 672            continue;
 673          }
 674          // Only include the stylesheet if it exists.
 675          if (file_exists($file)) {
 676            $css_files[base_path() . $file] = TRUE;
 677          }
 678        }
 679      }
 680    }
 681  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7