Drupal 6: Inserting a form in a lightbox window and submitting it with AJAX

The purpose of this code snippet is to show you how you can use the lightmodal functionality in the Lightbox2 module to embed a form in a fancy css popup window. But why would you want to do this? Because it looks great and it improves usability.

The first thing you'll need to do is register a menu item for the page callback that you'd like to appear in the lightbox window.

<?php
function MYMODULE_menu() {
  $items[] = array();

  $items['MY/URL'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('MYCALLBACK_form'),
    'type' => MENU_CALLBACK,
    'title' => t('MY TITLE')
  );

  return $items;
}
?>

Next define a function to create the form:

<?php
function MYCALLBACK_form($form_state) {
  $form = array();

  // add your form elements here. for example:
  $form['MYTEXTFIELD'] = array(
    '#type' => 'textfield',
    '#title' => t('MY TEXT FIELD'),
  );

  // add submit button
  $form['submit'] = array(
    '#value' => 'Submit',
    '#type' => 'button'
  );

  // add cancel button
  // NOTE: the cancel button simply closes the lightbox window
  $form['cancel'] = array(
    '#value' => 'Cancel',
    '#type' => 'button',
    '#attributes' => array(
      'onClick' => "Lightbox.end('forceClose'); return false;"
    )
  );

  return $form;
}
?>

Next add a link to your page content to open up the lightbox window with your new form in it. By adding the rel=lightmodal property onto an A tag, you'll automatically load the contents of the href in a fancy lightbox window.

<?php
// NOTE: you should use the l() function here to properly generate your A tag
$page_contents .= '<a href="/MY/URL" rel="lightmodal">MY LINK TEXT</a>';
?>

I made my lightbox form more usable by using ajax to submit the form to another page callback. First I had to add an onSubmit javascript event handler to my form to prevent it from submitting.

<?php
function MYCALLBACK_form($form_state) {
  // ...code...
  $form['#attributes'] = array(
    'onsubmit' => 'return my_js_submit_function(this);'
  );
  // ...code...
}
?>

Now define a javascript function to validate and submit the form using AJAX.

function my_js_submit_function(whichThis) {
  // validate your form here

  // define arguments to pass to ajax page callback
  // you'll actually want to collect the user submitted form data here
  var args = {
    myArg1: 'blah',
    myArg2: 'blah',
  };

  // submit the data using jQuery
  // in this case, I'm using the getJSON function which uses GET and expects a JSON object in return
  $.getJSON('/MY/URL/SUBMIT', args,
    function(json){
      // check for a return status, show a message, close the lightbox window, etc
      alert(json.message);
      if (json.status == true) {
        Lightbox.end('forceClose');
      }
    }
  );
}

You'll need a final page callback and menu item to process the AJAX

<?php
function MYMODULE_menu() {
  // ...code...
  $items['MY/URL/SUBMIT'] = array(
    'page callback' => 'MYMODULE_CALLBACK_SUBMIT',
    'type' => MENU_CALLBACK,
  );
  // ...code...
}

function MYMODULE_CALLBACK_SUBMIT() {
  // 1. validate $_GET (not shown, use your imagination)
  // 2. process $_GET (not shown, use your imagination)
  // 3. return a JSON object

  // create return object
  $returnO = new StdClass();
  $returnO->status = true;
  $returnO->message = 'MY INFORMATIVE MESSAGE HERE';

  // output json result
  print drupal_json($returnO);

  // NOTE: if you don't die here, then the theme will be processed. we only want to return a JSON object
  die;
}
?>

In the end what we have is a link that opens up a lightbox window that contains a form that is submitted via ajax.

My last thoughts: because the lightmodal functionality loads the URL from the href in the A tag, you might want to create a template file for your page layout that is simplified to prevent your normal page layout from being rendered. For instance, you could create a theme file called, page-MY-URL.tpl.php that contains the following:

<?php
if ($title) print "<h1>$title</h1>";
if ($messages) print $messages;
if ($help) print $help;
if ($content) print $content;
?>