| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |