| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: ctools_ajax_sample.module,v 1.1.2.2 2010/10/15 21:32:07 merlinofchaos Exp $ 3 4 /** 5 * @file 6 * Sample AJAX functionality so people can see some of the CTools AJAX 7 * features in use. 8 */ 9 10 // --------------------------------------------------------------------------- 11 // Drupal hooks. 12 13 /** 14 * Implementation of hook_menu() 15 */ 16 function ctools_ajax_sample_menu() { 17 $items['ctools_ajax_sample'] = array( 18 'title' => 'Chaos Tools AJAX Demo', 19 'page callback' => 'ctools_ajax_sample_page', 20 'access callback' => TRUE, 21 'type' => MENU_NORMAL_ITEM, 22 ); 23 $items['ctools_ajax_sample/%ctools_js/hello'] = array( 24 'title' => 'Hello World', 25 'page callback' => 'ctools_ajax_sample_hello', 26 'page arguments' => array(1), 27 'access callback' => TRUE, 28 'type' => MENU_CALLBACK, 29 ); 30 $items['ctools_ajax_sample/%ctools_js/tablenix/%'] = array( 31 'title' => 'Hello World', 32 'page callback' => 'ctools_ajax_sample_tablenix', 33 'page arguments' => array(1, 3), 34 'access callback' => TRUE, 35 'type' => MENU_CALLBACK, 36 ); 37 $items['ctools_ajax_sample/%ctools_js/login'] = array( 38 'title' => 'Login', 39 'page callback' => 'ctools_ajax_sample_login', 40 'page arguments' => array(1), 41 'access callback' => TRUE, 42 'type' => MENU_CALLBACK, 43 ); 44 $items['ctools_ajax_sample/%ctools_js/animal'] = array( 45 'title' => 'Animal', 46 'page callback' => 'ctools_ajax_sample_animal', 47 'page arguments' => array(1), 48 'access callback' => TRUE, 49 'type' => MENU_CALLBACK, 50 ); 51 $items['ctools_ajax_sample/%ctools_js/login/%'] = array( 52 'title' => 'Post-Login Action', 53 'page callback' => 'ctools_ajax_sample_login_success', 54 'page arguments' => array(1, 3), 55 'access callback' => TRUE, 56 'type' => MENU_CALLBACK, 57 ); 58 59 return $items; 60 } 61 62 /** 63 * Implementation of hook_theme() 64 * 65 * Render some basic output for this module. 66 */ 67 function ctools_ajax_sample_theme() { 68 return array( 69 // Sample theme functions. 70 'ctools_ajax_sample_container' => array( 71 'arguments' => array('content' => NULL), 72 ), 73 ); 74 } 75 76 // --------------------------------------------------------------------------- 77 // Page callbacks 78 79 /** 80 * Page callback to display links and render a container for AJAX stuff. 81 */ 82 function ctools_ajax_sample_page() { 83 global $user; 84 85 // Include the CTools tools that we need. 86 ctools_include('ajax'); 87 ctools_include('modal'); 88 89 // Add CTools' javascript to the page. 90 ctools_modal_add_js(); 91 92 // Create our own javascript that will be used to theme a modal. 93 $sample_style = array( 94 'ctools-sample-style' => array( 95 'modalSize' => array( 96 'type' => 'fixed', 97 'width' => 500, 98 'height' => 300, 99 'addWidth' => 20, 100 'addHeight' => 15, 101 ), 102 'modalOptions' => array( 103 'opacity' => .5, 104 'background-color' => '#000', 105 ), 106 'animation' => 'fadeIn', 107 'modalTheme' => 'CToolsSampleModal', 108 'throbber' => theme('image', ctools_image_path('ajax-loader.gif', 'ctools_ajax_sample'), t('Loading...'), t('Loading')), 109 ), 110 ); 111 112 drupal_add_js($sample_style, 'setting'); 113 114 // Since we have our js, css and images in well-known named directories, 115 // CTools makes it easy for us to just use them without worrying about 116 // using drupal_get_path() and all that ugliness. 117 ctools_add_js('ctools-ajax-sample', 'ctools_ajax_sample'); 118 ctools_add_css('ctools-ajax-sample', 'ctools_ajax_sample'); 119 120 // Create a list of clickable links. 121 $links = array(); 122 123 // Only show login links to the anonymous user. 124 if ($user->uid == 0) { 125 $links[] = ctools_modal_text_button(t('Modal Login (default style)'), 'ctools_ajax_sample/nojs/login', t('Login via modal')); 126 127 // The extra class points to the info in ctools-sample-style which we added to the settings. 128 $links[] = ctools_modal_text_button(t('Modal Login (custom style)'), 'ctools_ajax_sample/nojs/login', t('Login via modal'), 'ctools-modal-ctools-sample-style'); 129 } 130 131 // Three ways to do our animal picking wizard. 132 $links[] = l(t('Wizard (no modal)'), 'ctools_ajax_sample/nojs/animal'); 133 $links[] = ctools_modal_text_button(t('Wizard (default modal)'), 'ctools_ajax_sample/nojs/animal', t('Pick an animal')); 134 $links[] = ctools_modal_text_button(t('Wizard (custom modal)'), 'ctools_ajax_sample/nojs/animal', t('Pick an animal'), 'ctools-modal-ctools-sample-style'); 135 136 $links[] = ctools_ajax_text_button(t('Hello world!'), "ctools_ajax_sample/nojs/hello", t('Replace text with "hello world"')); 137 138 $output = theme('item_list', $links, t('Actions')); 139 140 // This container will have data AJAXed into it. 141 $output .= theme('ctools_ajax_sample_container', '<h1>' . t('Sample Content') . '</h1>'); 142 143 // Create a table that we can have data removed from via AJAX. 144 $header = array(t('Row'), t('Content'), t('Actions')); 145 $rows = array(); 146 for($i = 1; $i < 11; $i++) { 147 $rows[] = array( 148 'class' => 'ajax-sample-row-'. $i, 149 'data' => array( 150 $i, 151 md5($i), 152 ctools_ajax_text_button("remove", "ctools_ajax_sample/nojs/tablenix/$i", t('Delete this row')), 153 ), 154 ); 155 } 156 157 $output .= theme('table', $header, $rows, array('class' => 'ajax-sample-table')); 158 159 return $output; 160 } 161 162 /** 163 * Returns a "take it all over" hello world style request. 164 */ 165 function ctools_ajax_sample_hello($js = NULL) { 166 $output = '<h1>' . t('Hello World') . '</h1>'; 167 if ($js) { 168 ctools_include('ajax'); 169 $commands = array(); 170 $commands[] = ctools_ajax_command_html('#ctools-sample', $output); 171 ctools_ajax_render($commands); // this function exits. 172 } 173 else { 174 return $output;; 175 } 176 } 177 178 /** 179 * Nix a row from a table and restripe. 180 */ 181 function ctools_ajax_sample_tablenix($js, $row) { 182 if (!$js) { 183 // We don't support degrading this from js because we're not 184 // using the server to remember the state of the table. 185 return MENU_ACCESS_DENIED; 186 } 187 ctools_include('ajax'); 188 189 $commands = array(); 190 $commands[] = ctools_ajax_command_remove("tr.ajax-sample-row-$row"); 191 $commands[] = ctools_ajax_command_restripe("table.ajax-sample-table"); 192 ctools_ajax_render($commands); 193 } 194 195 /** 196 * A modal login callback. 197 */ 198 function ctools_ajax_sample_login($js = NULL) { 199 // Fall back if $js is not set. 200 if (!$js) { 201 return drupal_get_form('user_login'); 202 } 203 204 ctools_include('modal'); 205 ctools_include('ajax'); 206 $form_state = array( 207 'title' => t('Login'), 208 'ajax' => TRUE, 209 ); 210 $output = ctools_modal_form_wrapper('user_login', $form_state); 211 if (empty($output)) { 212 // empty $output signifies success, so we'll use it as our $commands 213 // array. 214 $output = array(); 215 $inplace = ctools_ajax_text_button(t('remain here'), 'ctools_ajax_sample/nojs/login/inplace', t('Go to your account')); 216 $account = ctools_ajax_text_button(t('your account'), 'ctools_ajax_sample/nojs/login/user', t('Go to your account')); 217 $output[] = ctools_modal_command_display(t('Login Success'), '<div class="modal-message">Login successful. You can now choose whether to '. $inplace .', or go to '. $account.'.</div>'); 218 } 219 ctools_ajax_render($output); 220 } 221 222 /** 223 * Post-login processor: should we go to the user account or stay in place? 224 */ 225 function ctools_ajax_sample_login_success($js, $action) { 226 if (!$js) { 227 // we should never be here out of ajax context 228 return MENU_NOT_FOUND; 229 } 230 231 ctools_include('ajax'); 232 $commands = array(); 233 if ($action == 'inplace') { 234 // stay here 235 $commands[] = ctools_ajax_command_reload(); 236 } 237 else { 238 // bounce bounce 239 $commands[] = ctools_ajax_command_redirect('user'); 240 } 241 ctools_ajax_render($commands); 242 } 243 244 /** 245 * A modal login callback. 246 */ 247 function ctools_ajax_sample_animal($js = NULL, $step = NULL) { 248 if ($js) { 249 ctools_include('modal'); 250 ctools_include('ajax'); 251 } 252 253 $form_info = array( 254 'id' => 'animals', 255 'path' => "ctools_ajax_sample/" . ($js ? 'ajax' : 'nojs') . "/animal/%step", 256 'show trail' => TRUE, 257 'show back' => TRUE, 258 'show cancel' => TRUE, 259 'show return' => FALSE, 260 'next callback' => 'ctools_ajax_sample_wizard_next', 261 'finish callback' => 'ctools_ajax_sample_wizard_finish', 262 'cancel callback' => 'ctools_ajax_sample_wizard_cancel', 263 // this controls order, as well as form labels 264 'order' => array( 265 'start' => t('Choose animal'), 266 ), 267 // here we map a step to a form id. 268 'forms' => array( 269 // e.g. this for the step at wombat/create 270 'start' => array( 271 'form id' => 'ctools_ajax_sample_start' 272 ), 273 ), 274 ); 275 276 // We're not using any real storage here, so we're going to set our 277 // object_id to 1. When using wizard forms, id management turns 278 // out to be one of the hardest parts. Editing an object with an id 279 // is easy, but new objects don't usually have ids until somewhere 280 // in creation. 281 // 282 // We skip all this here by just using an id of 1. 283 284 $object_id = 1; 285 286 if (empty($step)) { 287 // We reset the form when $step is NULL because that means they have 288 // for whatever reason started over. 289 ctools_ajax_sample_cache_clear($object_id); 290 $step = 'start'; 291 } 292 293 // This automatically gets defaults if there wasn't anything saved. 294 $object = ctools_ajax_sample_cache_get($object_id); 295 296 $animals = ctools_ajax_sample_animals(); 297 298 // Make sure we can't somehow accidentally go to an invalid animal. 299 if (empty($animals[$object->type])) { 300 $object->type = 'unknown'; 301 } 302 303 // Now that we have our object, dynamically add the animal's form. 304 if ($object->type == 'unknown') { 305 // If they haven't selected a type, add a form that doesn't exist yet. 306 $form_info['order']['unknown'] = t('Configure animal'); 307 $form_info['forms']['unknown'] = array('form id' => 'nothing'); 308 } 309 else { 310 // Add the selected animal to the order so that it shows up properly in the trail. 311 $form_info['order'][$object->type] = $animals[$object->type]['config title']; 312 } 313 314 // Make sure all animals forms are represented so that the next stuff can 315 // work correctly: 316 foreach ($animals as $id => $animal) { 317 $form_info['forms'][$id] = array('form id' => $animals[$id]['form']); 318 } 319 320 $form_state = array( 321 'ajax' => $js, 322 // Put our object and ID into the form state cache so we can easily find 323 // it. 324 'object_id' => $object_id, 325 'object' => &$object, 326 ); 327 328 // Send this all off to our form. This is like drupal_get_form only wizardy. 329 ctools_include('wizard'); 330 $output = ctools_wizard_multistep_form($form_info, $step, $form_state); 331 332 if ($output === FALSE || !empty($form_state['complete'])) { 333 // This creates a string based upon the animal and its setting using 334 // function indirection. 335 $animal = $animals[$object->type]['output']($object); 336 } 337 338 // If $output is FALSE, there was no actual form. 339 if ($js) { 340 // If javascript is active, we have to use a render array. 341 $commands = array(); 342 if ($output === FALSE || !empty($form_state['complete'])) { 343 // Dismiss the modal. 344 $commands[] = ctools_ajax_command_html('#ctools-sample', $animal); 345 $commands[] = ctools_modal_command_dismiss(); 346 } 347 else if (!empty($form_state['cancel'])) { 348 // If cancelling, return to the activity. 349 $commands[] = ctools_modal_command_dismiss(); 350 } 351 else { 352 $commands = ctools_modal_form_render($form_state, $output); 353 } 354 ctools_ajax_render($commands); 355 } 356 else { 357 if ($output === FALSE || !empty($form_state['complete'])) { 358 return $animal; 359 } 360 else if (!empty($form_state['cancel'])) { 361 drupal_goto('ctools_ajax_sample'); 362 } 363 else { 364 return $output; 365 } 366 } 367 } 368 369 // --------------------------------------------------------------------------- 370 // Themes 371 372 /** 373 * Theme function for main rendered output. 374 */ 375 function theme_ctools_ajax_sample_container($content) { 376 $output = '<div id="ctools-sample">'; 377 $output .= $content; 378 $output .= '</div>'; 379 380 return $output; 381 } 382 383 // --------------------------------------------------------------------------- 384 // Stuff needed for our little wizard. 385 386 /** 387 * Get a list of our animals and associated forms. 388 * 389 * What we're doing is making it easy to add more animals in just one place, 390 * which is often how it will work in the real world. If using CTools, what 391 * you would probably really have, here, is a set of plugins for each animal. 392 */ 393 function ctools_ajax_sample_animals() { 394 return array( 395 'sheep' => array( 396 'title' => t('Sheep'), 397 'config title' => t('Configure sheep'), 398 'form' => 'ctools_ajax_sample_configure_sheep', 399 'output' => 'ctools_ajax_sample_show_sheep', 400 ), 401 'lizard' => array( 402 'title' => t('Lizard'), 403 'config title' => t('Configure lizard'), 404 'form' => 'ctools_ajax_sample_configure_lizard', 405 'output' => 'ctools_ajax_sample_show_lizard', 406 ), 407 'raptor' => array( 408 'title' => t('Raptor'), 409 'config title' => t('Configure raptor'), 410 'form' => 'ctools_ajax_sample_configure_raptor', 411 'output' => 'ctools_ajax_sample_show_raptor', 412 ), 413 ); 414 } 415 416 // --------------------------------------------------------------------------- 417 // Wizard caching helpers. 418 419 /** 420 * Store our little cache so that we can retain data from form to form. 421 */ 422 function ctools_ajax_sample_cache_set($id, $object) { 423 ctools_include('object-cache'); 424 ctools_object_cache_set('ctools_ajax_sample', $id, $object); 425 } 426 427 /** 428 * Get the current object from the cache, or default. 429 */ 430 function ctools_ajax_sample_cache_get($id) { 431 ctools_include('object-cache'); 432 $object = ctools_object_cache_get('ctools_ajax_sample', $id); 433 if (!$object) { 434 // Create a default object. 435 $object = new stdClass; 436 $object->type = 'unknown'; 437 $object->name = ''; 438 } 439 440 return $object; 441 } 442 443 /** 444 * Clear the wizard cache. 445 */ 446 function ctools_ajax_sample_cache_clear($id) { 447 ctools_include('object-cache'); 448 ctools_object_cache_clear('ctools_ajax_sample', $id); 449 } 450 451 // --------------------------------------------------------------------------- 452 // Wizard in-between helpers; what to do between or after forms. 453 454 /** 455 * Handle the 'next' click on the add/edit pane form wizard. 456 * 457 * All we need to do is store the updated pane in the cache. 458 */ 459 function ctools_ajax_sample_wizard_next(&$form_state) { 460 ctools_ajax_sample_cache_set($form_state['object_id'], $form_state['object']); 461 } 462 463 /** 464 * Handle the 'finish' click on teh add/edit pane form wizard. 465 * 466 * All we need to do is set a flag so the return can handle adding 467 * the pane. 468 */ 469 function ctools_ajax_sample_wizard_finish(&$form_state) { 470 $form_state['complete'] = TRUE; 471 } 472 473 /** 474 * Handle the 'cancel' click on the add/edit pane form wizard. 475 */ 476 function ctools_ajax_sample_wizard_cancel(&$form_state) { 477 $form_state['cancel'] = TRUE; 478 } 479 480 // --------------------------------------------------------------------------- 481 // Wizard forms for our simple info collection wizard. 482 483 /** 484 * Wizard start form. Choose an animal. 485 */ 486 function ctools_ajax_sample_start(&$form, &$form_state) { 487 $form_state['title'] = t('Choose animal'); 488 489 $animals = ctools_ajax_sample_animals(); 490 foreach ($animals as $id => $animal) { 491 $options[$id] = $animal['title']; 492 } 493 494 $form['type'] = array( 495 '#title' => t('Choose your animal'), 496 '#type' => 'radios', 497 '#options' => $options, 498 '#default_value' => $form_state['object']->type, 499 '#required' => TRUE, 500 ); 501 } 502 503 /** 504 * They have selected a sheep. Set it. 505 */ 506 function ctools_ajax_sample_start_submit(&$form, &$form_state) { 507 $form_state['object']->type = $form_state['values']['type']; 508 // Override where to go next based on the animal selected. 509 $form_state['clicked_button']['#next'] = $form_state['values']['type']; 510 } 511 512 /** 513 * Wizard form to configure your sheep. 514 */ 515 function ctools_ajax_sample_configure_sheep(&$form, &$form_state) { 516 $form_state['title'] = t('Configure sheep'); 517 518 $form['name'] = array( 519 '#type' => 'textfield', 520 '#title' => t('Name your sheep'), 521 '#default_value' => $form_state['object']->name, 522 '#required' => TRUE, 523 ); 524 525 $form['sheep'] = array( 526 '#title' => t('What kind of sheep'), 527 '#type' => 'radios', 528 '#options' => array( 529 t('Wensleydale') => t('Wensleydale'), 530 t('Merino') => t('Merino'), 531 t('Corriedale') => t('Coriedale'), 532 ), 533 '#default_value' => !empty($form_state['object']->sheep) ? $form_state['object']->sheep : '', 534 '#required' => TRUE, 535 ); 536 } 537 538 /** 539 * Submit the sheep and store the values from the form. 540 */ 541 function ctools_ajax_sample_configure_sheep_submit(&$form, &$form_state) { 542 $form_state['object']->name = $form_state['values']['name']; 543 $form_state['object']->sheep = $form_state['values']['sheep']; 544 } 545 546 /** 547 * Provide some output for our sheep. 548 */ 549 function ctools_ajax_sample_show_sheep($object) { 550 return t('You have a @type sheep named "@name".', array( 551 '@type' => $object->sheep, 552 '@name' => $object->name, 553 )); 554 } 555 556 /** 557 * Wizard form to configure your lizard. 558 */ 559 function ctools_ajax_sample_configure_lizard(&$form, &$form_state) { 560 $form_state['title'] = t('Configure lizard'); 561 562 $form['name'] = array( 563 '#type' => 'textfield', 564 '#title' => t('Name your lizard'), 565 '#default_value' => $form_state['object']->name, 566 '#required' => TRUE, 567 ); 568 569 $form['lizard'] = array( 570 '#title' => t('Venomous'), 571 '#type' => 'checkbox', 572 '#default_value' => !empty($form_state['object']->lizard), 573 ); 574 } 575 576 /** 577 * Submit the lizard and store the values from the form. 578 */ 579 function ctools_ajax_sample_configure_lizard_submit(&$form, &$form_state) { 580 $form_state['object']->name = $form_state['values']['name']; 581 $form_state['object']->lizard = $form_state['values']['lizard']; 582 } 583 584 /** 585 * Provide some output for our raptor. 586 */ 587 function ctools_ajax_sample_show_lizard($object) { 588 return t('You have a @type lizard named "@name".', array( 589 '@type' => empty($object->lizard) ? t('non-venomous') : t('venomous'), 590 '@name' => $object->name, 591 )); 592 } 593 594 /** 595 * Wizard form to configure your raptor. 596 */ 597 function ctools_ajax_sample_configure_raptor(&$form, &$form_state) { 598 $form_state['title'] = t('Configure raptor'); 599 600 $form['name'] = array( 601 '#type' => 'textfield', 602 '#title' => t('Name your raptor'), 603 '#default_value' => $form_state['object']->name, 604 '#required' => TRUE, 605 ); 606 607 $form['raptor'] = array( 608 '#title' => t('What kind of raptor'), 609 '#type' => 'radios', 610 '#options' => array( 611 t('Eagle') => t('Eagle'), 612 t('Hawk') => t('Hawk'), 613 t('Owl') => t('Owl'), 614 t('Buzzard') => t('Buzzard'), 615 ), 616 '#default_value' => !empty($form_state['object']->raptor) ? $form_state['object']->raptor : '', 617 '#required' => TRUE, 618 ); 619 620 $form['domesticated'] = array( 621 '#title' => t('Domesticated'), 622 '#type' => 'checkbox', 623 '#default_value' => !empty($form_state['object']->domesticated), 624 ); 625 626 } 627 628 /** 629 * Submit the raptor and store the values from the form. 630 */ 631 function ctools_ajax_sample_configure_raptor_submit(&$form, &$form_state) { 632 $form_state['object']->name = $form_state['values']['name']; 633 $form_state['object']->raptor = $form_state['values']['raptor']; 634 $form_state['object']->domesticated = $form_state['values']['domesticated']; 635 } 636 637 /** 638 * Provide some output for our raptor. 639 */ 640 function ctools_ajax_sample_show_raptor($object) { 641 return t('You have a @type @raptor named "@name".', array( 642 '@type' => empty($object->domesticated) ? t('wild') : t('domesticated'), 643 '@raptor' => $object->raptor, 644 '@name' => $object->name, 645 )); 646 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |