? flexifilter_ui.patch
Index: flexifilter-admin-component-list.tpl.php
===================================================================
RCS file: flexifilter-admin-component-list.tpl.php
diff -N flexifilter-admin-component-list.tpl.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ flexifilter-admin-component-list.tpl.php	2 Feb 2008 05:39:57 -0000
@@ -0,0 +1,20 @@
+<?php
+// $Id$
+drupal_add_tabledrag('flexifilter-components', 'match', 'parent', 'flexifilter-pid', 'flexifilter-pid', 'flexifilter-cid', TRUE, 20);
+drupal_add_tabledrag('flexifilter-components', 'order', 'sibling', 'flexifilter-weight');
+drupal_add_js('misc/jquery.form.js');
+drupal_add_js('misc/ahah.js');
+
+?><table id="flexifilter-components">
+  <tbody>
+    <?php foreach ($table as $index => $row): ?>
+      <tr class="draggable <?php print $index % 2 == 0 ? 'odd' : 'even'; ?><?php print $row['comp'] ?>">
+        <td><?php print $row['label']; ?></td>
+        <td><?php print $row['key'] . $row['cid'] . $row['pid'] . $row['weight']; ?></td>
+      </tr>
+    <?php endforeach; ?>
+  </tbody>
+</table>
+<div id="flexifilter-component-settings">
+</div>
+<div class="clear-block"></div>
\ No newline at end of file
Index: flexifilter-admin-list.tpl.php
===================================================================
RCS file: flexifilter-admin-list.tpl.php
diff -N flexifilter-admin-list.tpl.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ flexifilter-admin-list.tpl.php	2 Feb 2008 05:39:58 -0000
@@ -0,0 +1,20 @@
+<?php
+// $Id$
+?><table id="flexifilter-admin-list">
+  <thead>
+    <th><?php print $label; ?></th>
+    <th><?php print $description; ?></th>
+    <th></th>
+    <th><?php print $status; ?></th>
+  </thead>
+  <tbody>
+    <?php foreach ($table as $index => $row): ?>
+      <tr class="<?php print $index % 2 == 0 ? 'odd' : 'even'; ?>">
+        <td><?php print $row['label']; ?></td>
+        <td><?php print $row['description']; ?></td>
+        <td><?php print $row['edit']; ?></td>
+        <td><?php print $row['status']; ?></td>
+      </tr>
+    <?php endforeach; ?>
+  </tbody>
+</table>
\ No newline at end of file
Index: flexifilter.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flexifilter/flexifilter.admin.inc,v
retrieving revision 1.13
diff -u -p -r1.13 flexifilter.admin.inc
--- flexifilter.admin.inc	24 Jan 2008 01:57:10 -0000	1.13
+++ flexifilter.admin.inc	2 Feb 2008 05:39:58 -0000
@@ -4,23 +4,53 @@
 /**
  * Generates the form for the admin overview page
  */
-function flexifilter_filter_list_form() {
+function flexifilter_admin_list_form($form_state) {
   drupal_set_title("Flexifilters overview");
   $path = drupal_get_path('module', 'flexifilter') .'/flexifilter.css';
   drupal_add_css($path, 'module', 'all', FALSE);
+  if (isset($form_state['values']['enabled'])) {
+    foreach ($form_state['values']['enabled']['statuses'] as $fid => $value) {
+      if ($value == 'disabled') {
+        db_query('UPDATE {flexifilters} SET enabled = 0 WHERE fid = %d', $fid);
+      }
+    }
+  }
+  if (isset($form_state['values']['disabled'])) {
+    foreach ($form_state['values']['disabled']['statuses'] as $fid => $value) {
+      if ($value == 'enabled') {
+        db_query('UPDATE {flexifilters} SET enabled = 1 WHERE fid = %d', $fid);
+      }
+    }
+  }
 
   $form = array();
   $form['enabled_header'] = array(
     '#value' => '<h3>'. t('Enabled Flexifilters') .'</h3>',
     '#suffix' => t('If a flexifilter is enabled, then it can be used within input formats, however there can only be 128 enabled at any one time.') .'<br/>',
   );
-  $form['enabled'] = flexifilter_filter_list_form_table(TRUE);
+  $form['enabled'] = flexifilter_admin_list_form_table(TRUE);
 
   $form['disabled_header'] = array(
     '#value' => '<h3>'. t('Disabled Flexifilters') .'</h3>',
     '#suffix' => t('If a flexifilter is disabled, then it cannot be used within input formats, although it can be used within other flexifilters.') .'<br/>',
   );
-  $form['disabled'] = flexifilter_filter_list_form_table(FALSE);
+  $form['disabled'] = flexifilter_admin_list_form_table(FALSE);
+
+  $form['submit'] = array(
+    '#type'  => 'submit', 
+    '#value' => t('Save'),
+    '#ahah'  => array(
+      'path'     => 'admin/build/flexifilters/js/list_form',
+      'selector' => '.flexifilter-status',
+      'wrapper'  => 'flexifilter-admin-list-form',
+      'event'    => 'change',
+      'effect'   => 'none',
+      'method'   => 'replace',
+    ),
+  );
+  if (!isset($form_state['values'])) {
+    $form['#theme'] = 'flexifilter_filter_admin_form';
+  }
 
   return $form;
 }
@@ -29,87 +59,223 @@ function flexifilter_filter_list_form() 
  * Helper function for flexifilter_filter_list_form. Returns the table for the overview page.
  *
  * @param $enabled
- *   Is TRUE if we're theming the currently enabled filters.s
+ *   Is TRUE if we're theming the currently enabled filters.
  */
-function flexifilter_filter_list_form_table($enabled) {
-  $show_disable_link = $enabled;
-  $show_enable_link  = !$enabled && flexifilter_get_number_enabled_filters() < FLEXIFILTER_MAX_FILTERS;
-  $header            = array(t('Label'), t('Description'), t('Edit'), t('Delete'), t($enabled ? 'Disable' : 'Enable'));
-  $rows              = array();
-  $filters           = flexifilter_get_filters();
+function flexifilter_admin_list_form_table($enabled) {
+  $options = array();
+  if (flexifilter_get_number_enabled_filters() < FLEXIFILTER_MAX_FILTERS) {
+    $options['enabled'] = t('Enabled');
+  }
+  $options['disabled'] = t('Disabled');
+  $rowinfo  = array();
+  $statuses = array();
+  $filters  = flexifilter_get_filters();
   foreach ($filters as $id => $filter) {
     if ($filter['enabled'] == $enabled) {
-      $row   = array($filter['label'], $filter['description']);
-      $row[] = l(t('Edit'), 'admin/build/flexifilters/'. $id .'/edit', array(), drupal_get_destination());
-      $row[] = l(t('Delete'), 'admin/build/flexifilters/'. $id .'/delete', array(), drupal_get_destination());
-      if ($show_disable_link) {
-        $row[] = l(t('Disable'), 'admin/build/flexifilters/'. $id .'/disable', array(), drupal_get_destination());
-      }
-      else if ($show_enable_link) {
-        $row[] = l(t('Enable'), 'admin/build/flexifilters/'. $id .'/enable', array(), drupal_get_destination());
-      }
-      else {
-        $row[] = '';
-      }
-      $rows[] = $row;
+      $rowinfo[] = array(
+        'label' => $filter['label'],
+        'description' => $filter['description'],
+        'edit' => l(t('Edit'), 'admin/build/flexifilters/'. $id .'/edit', array(), drupal_get_destination()),
+      );
+      $statuses[$filter['id']] = array(
+        '#type' => 'select',
+        '#title' => t('Status'),
+        '#options' => $options,
+        '#default_value' => ($enabled? 'enabled' : 'disabled'),
+        '#attributes' => array('class' => 'flexifilter-status'),
+      );
     }
   }
-  if (count($rows)) {
-    return array('#value' => theme('table', $header, $rows, array('class' => 'flexifilters-list')));
+  if (count($rowinfo)) {
+    return array('#theme' => 'flexifilter_admin_list', '#rowinfo' => $rowinfo, 'statuses' => $statuses, '#tree' => TRUE);
   }
   else {
-    return array('#value' => t('None.'));
+    return array('#value' => '<strong>'. t('There are no @status filters at this moment.', array('@status' => ($enabled? t('enabled') : t('disabled')))) .'</strong><br />');
   }
 }
 
 /**
- * Helper function for flexifilter_filter_edit_form; removes the automatic
- * naming of submit controls.
- * Our forms are complex and have submit controls nested within fieldsets,
- * and when pressed, we want the 'op' field to be set within the fieldset,
- * not at the top level, so we have to undo the automatic naming of submit
- * fields.
- * This function is a brutal rip of code from _form_builder_handle_input_element
- *
- * @param $form A form element to reset to the normal name.
- *
- * @return The updated form element
+ * Preprocess for the admin list table
+ * 
+ * Takes the separate row info and statuses and combines them into a table.
  */
-function flexifilter_undo_submit_default_name($form) {
-  $name = array_shift($form['#parents']);
-  $form['#name'] = $name;
-  if ($form['#type'] == 'file') {
-    // To make it easier to handle $_FILES in file.inc, we place all
-    // file fields in the 'files' array. Also, we do not support
-    // nested file names.
-    $form['#name'] = 'files['. $form['#name'] .']';
+function template_preprocess_flexifilter_admin_list(&$variables) {
+  $variables['table'] = array();
+  foreach ($variables['form']['#rowinfo'] as $index => $rowinfo) {
+    $variables['table'][$index] = $rowinfo;
   }
-  elseif (count($form['#parents'])) {
-    $form['#name'] .= '['. implode('][', $form['#parents']) .']';
+  $count = 0;
+  foreach (element_children($variables['form']['statuses']) as $key) {
+    unset($variables['form']['statuses'][$key]['#title']);
+    $variables['table'][$count]['status'] = drupal_render($variables['form']['statuses'][$key]);
+    $count++;
   }
-  array_unshift($form['#parents'], $name);
-  return $form;
+  $variables['label']       = t('Label');
+  $variables['description'] = t('Description');
+  $variables['status']      = t('Status');
+}
+
+function theme_flexifilter_filter_admin_form($form) {
+  unset($form['submit']);
+  return '<div id="flexifilter-admin-list-form">'. drupal_render($form) .'</div>';
 }
 
 /**
- * Helper function for flexifilter_filter_edit_components_data; converts a condition
- * array from a flexifilter into a form data styled array.
+ * The add/edit form for flexifilters.
  */
-function flexifilter_filter_edit_condition_data($data) {
-  $condition = array(
-    'class' => $data['class'],
+function flexifilter_admin_edit_form($form_state, $flexifilter = 'new') {
+  drupal_add_js(drupal_get_path('module', 'flexifilter') .'/flexifilter.js');
+  drupal_add_css(drupal_get_path('module', 'flexifilter') .'/flexifilter.css');
+  if (!isset($form_state['post']) || !isset($form_state['post']['fid'])) {
+    $data = array();
+    $data['fid']   = $flexifilter == 'new' ? 'new' : $flexifilter['id'];
+    $data['basic'] = array();
+    $data['basic']['label']       = $flexifilter == 'new' ? '' : $flexifilter['label'];
+    $data['basic']['description'] = $flexifilter == 'new' ? '' : $flexifilter['description'];
+    $data['basic']['advanced']    = $flexifilter == 'new' ? 0 : $flexifilter['advanced'];
+    $data['components']           = $flexifilter == 'new' ? array() : flexifilter_filter_edit_components_data($flexifilter['components']);
+    if (!isset($data['components']['id_prefix']) || $data['components']['id_prefix'] === 'component_new_') {
+      $data['components']['id_prefix'] = 'component_'. $data['fid'] .'_';
+    }
+    if (!isset($data['components']['id_next'])) {
+      $data['components']['id_next'] = 0;
+    }
+  }
+  else {
+    $data = $form_state['post'];
+    if (!isset($data['basic']['advanced'])) {
+      $data['basic']['advanced'] = 0;
+    }
+  }
+  $form = array();
+  $form['fid'] = array(
+    '#type' => 'hidden',
+    '#value' => $data['fid'],
   );
-  foreach ($data['settings'] as $key => $value) {
-    if ($key == 'conditions') {
-      foreach ($value as $cond_key => $cond_value) {
-        $condition['condition_'. $cond_key] = flexifilter_filter_edit_condition_data($cond_value);
-      }
+  $form['basic'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Settings'),
+    '#collapsible' => FALSE,
+    '#tree' => TRUE,
+  );
+  $form['basic']['label'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Label'),
+    '#required' => TRUE,
+    '#maxlength' => 127,
+    '#description' => t('Choose an appropriate label for this flexifilter.'),
+    '#default_value' => $data['basic']['label'],
+  );
+  $form['basic']['description'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Description'),
+    '#required' => TRUE,
+    '#maxlength' => 255,
+    '#description' => t('A short description of what this flexifilter does.'),
+    '#default_value' => $data['basic']['description'],
+  );
+  $form['basic']['advanced'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Show advanced options'),
+    '#default_value' => $data['basic']['advanced'],
+    '#description' => t('Advanced options currently only include the processing step option, which allows you to place some components into the filtering preparation step. You should only do so if it is critical that they be performed in the preparation step rather than the processing step.'),
+  );
+  $form['components'] = _flexifilter_filter_edit_form_components($data['components'], $data['components'], $data['basic']['advanced'] == 1);
+  $form['components']['id_prefix'] = array('#type' => 'hidden', '#value' => $data['components']['id_prefix']);
+  $form['components']['id_next'] = array('#type' => 'hidden', '#value' => $data['components']['id_next']);
+  $form['create'] = array(
+    '#type' => 'submit',
+    '#value' => $data['fid'] === 'new' ? t('Create') : t('Save'),
+  );
+  $form['create_edit'] = array(
+    '#type' => 'submit',
+    '#value' => $data['fid'] === 'new' ? t('Create and edit') : t('Save and edit'),
+  );
+  $form['#redirect'] = FALSE;
+  return $form;
+}
+
+/**
+ * Generates an FAPI array for a component list
+ *
+ * @param $data FAPI values for the component list. Use flexifilter_filter_edit_components_data to
+ * convert a components array into coresponding FAPI values.
+ * @param $data_base FAPI values for the top-level component list
+ */
+function _flexifilter_filter_edit_form_components($data, $data_base, $show_advanced, $parent = 0, $indentation = 0) {
+  $components = array();
+  $flexifilter_components = flexifilter_get_component_list();
+  $form = array();
+  foreach ($data as $key => $component) {
+    if (strncmp($key, $data_base['id_prefix'], strlen($data_base['id_prefix'])) == 0) {
+      $components[$key] = $component;
+    }
+  }
+  $weight = 0;
+  foreach ($components as $key => $component) {
+    $weight++;
+    $cid               = str_replace($data_base['id_prefix'], '', $key);
+    $_component        = $flexifilter_components[$component['class']];
+    $form['labels'][]  = array('#value' => theme('indentation', $indentation) . '<a href="#" class="flexifilter-edit">'. $_component['label'] .'</a>');
+    $form['keys'][]    = array('#type' => 'hidden', '#value' => $key);
+    $form['cids'][]    = array('#type' => 'textfield', '#attributes' => array('class' => 'flexifilter-cid'), '#value' => $cid);
+    $form['pids'][]    = array('#type' => 'textfield', '#attributes' => array('class' => 'flexifilter-pid'), '#value' => $parent);
+    $form['weights'][] = array('#type' => 'weight', '#attributes' => array('class' => 'flexifilter-weight'), '#value' => $weight);
+    if (!isset($_component['contains_components']) || $_component['contains_components'] == FALSE) {
+      $form['comps'][] = array('#type' => 'markup', '#value' => ' tabledrag-leaf');
     }
     else {
-      $condition['setting_'. $key] = $value;
+      $form['comps'][] = array('#type' => 'markup', '#value' => '');
+    }
+    if (isset($component['components'])) {
+      $children = _flexifilter_filter_edit_form_components($component['components'], $data_base, $show_advanced, $cid, $indentation + 1);
+      foreach (array('labels', 'keys', 'cids', 'pids', 'weights', 'comps') as $key) {
+        foreach ($children[$key] as $value) {
+          $form[$key][] = $value;
+        }
+      }
     }
   }
-  return $condition;
+  if ($parent == 0) {
+    $form['#theme'] = 'flexifilter_admin_component_list';
+    $form['#tree'] = TRUE;
+  }
+  return $form;
+}
+
+function template_preprocess_flexifilter_admin_component_list(&$variables) {
+  $form = $variables['form'];
+  $table = array();
+  foreach (array('labels', 'keys', 'cids', 'pids', 'weights', 'comps') as $index) {
+    foreach (element_children($form[$index]) as $key) {
+      $table[$key][substr($index, 0, -1)] = drupal_render($form[$index][$key]);
+    }
+  }
+  $variables['table'] = $table;
+}
+
+
+function flexifilter_admin_edit_component($form_state, $data) {
+  $components = flexifilter_get_component_list();
+  $component  = $components[$data['class']];
+  $form['class'] = array(
+    '#type' => 'hidden',
+    '#value' => $data['class'],
+  );
+  $custom_settings = array();
+  foreach ($data as $key => $value) {
+    if (strncmp($key, 'setting_', 8) == 0) {
+      $custom_settings[substr($key, 8)] = $value;
+    }
+  }
+  $custom_elements = flexifilter_invoke_component($component, 'settings', $custom_settings);
+  if (is_array($custom_elements)) {
+    foreach ($custom_elements as $key => $element) {
+      $form['setting_'. $key] = $element;
+    }
+  }
+  
+  return $form;
 }
 
 /**
@@ -153,6 +319,34 @@ function flexifilter_filter_edit_compone
   return $data;
 }
 
+//-----------------------------------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------------------------------
+//----------------------------- I AM NOT USING ANY FUNCTIONS BELOW THIS POINT! ------------------------------------
+//-----------------------------------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------------------------------
+
+
+/**
+ * Helper function for flexifilter_filter_edit_components_data; converts a condition
+ * array from a flexifilter into a form data styled array.
+ */
+function flexifilter_filter_edit_condition_data($data) {
+  $condition = array(
+    'class' => $data['class'],
+  );
+  foreach ($data['settings'] as $key => $value) {
+    if ($key == 'conditions') {
+      foreach ($value as $cond_key => $cond_value) {
+        $condition['condition_'. $cond_key] = flexifilter_filter_edit_condition_data($cond_value);
+      }
+    }
+    else {
+      $condition['setting_'. $key] = $value;
+    }
+  }
+  return $condition;
+}
+
 /**
  * Creates an FAPI values array for a newly created component
  *
@@ -283,288 +477,6 @@ function flexifilter_filter_edit_form_co
 }
 
 /**
- * Helper function for flexifilter_filter_edit_form_components; generates an FAPI array for a
- * single component.
- */
-function flexifilter_filter_edit_form_component($data, $new_weight, $is_first, $is_last, &$data_base, $show_advanced) {
-  $components = flexifilter_get_component_list();
-  $component  = $components[$data['class']];
-  $form       = array(
-    '#type' => 'fieldset',
-    '#collapsible' => TRUE,
-    '#collapsed' => (isset($data['op']) || isset($data['op_c']) || isset($data['is_new'])) ? FALSE : TRUE,
-    '#tree' => TRUE,
-    '#title' => $component['label'],
-    '#description' => $component['description'],
-  );
-  $form['class'] = array(
-    '#type' => 'hidden',
-    '#value' => $data['class'],
-  );
-  $form['weight'] = array(
-    '#type' => 'hidden',
-    '#value' => $new_weight,
-  );
-  $custom_settings = array();
-  foreach ($data as $key => $value) {
-    if (strncmp($key, 'setting_', 8) == 0) {
-      $custom_settings[substr($key, 8)] = $value;
-    }
-  }
-  $custom_elements = flexifilter_invoke_component($component, 'settings', $custom_settings);
-  if (is_array($custom_elements)) {
-    foreach ($custom_elements as $key => $element) {
-      $form['setting_'. $key] = $element;
-    }
-  }
-  if ($component['is_container']) {
-    if ($component['contains_condition']) {
-      if (isset($data['op_c'])) {
-        $data['condition'] = flexifilter_filter_edit_form_new_condition_data($data['set_condition']);
-      }
-      if (isset($data['condition']) && isset($data['condition']['op'])) {
-        $data['condition'] = array(
-          'class' => '',
-        );
-        $form['#collapsed'] = FALSE;
-      }
-      $form['condition'] = flexifilter_filter_edit_form_condition($data['condition'], $show_advanced);
-      if ($form['condition']['#collapsed'] == FALSE) {
-        $form['#collapsed'] = FALSE;
-      }
-      $conditions = flexifilter_get_condition_list($show_advanced);
-      $form['set_condition'] = array(
-        '#type' => 'select',
-        '#title' => t('Change condition'),
-        '#options' => flexifilter_get_grouped_labels($conditions),
-        '#description' => t('Changes the condition assocated with this component.'),
-      );
-      $form['op_c'] = array(
-        '#type' => 'submit',
-        '#value' => t('Change'),
-        '#process' => array('flexifilter_undo_submit_default_name', 'form_expand_ahah'),
-      );
-    }
-    if ($component['contains_components']) {
-      $form['components'] = flexifilter_filter_edit_form_components($data['components'], $data_base, $show_advanced);
-      if ($form['components']['#collapsed'] == FALSE) {
-        $form['#collapsed'] = FALSE;
-      }
-    }
-  }
-  if ($component['step'] == 'either') {
-    if ($show_advanced) {
-      $form['step'] = array(
-        '#type' => 'select',
-        '#title' => t('Step'),
-        '#options' => array(
-          'process' => t('Processing'),
-          'prepare' => t('Preparation'),
-        ),
-        '#description' => t('The filtering step to perform this action in.'),
-        '#default_value' => $data['step'],
-      );
-    }
-    else {
-      $form['step'] = array(
-        '#type' => 'hidden',
-        '#value' => $data['step'],
-      );
-    }
-  }
-  $form['move'] = array(
-    '#type' => 'select',
-    '#title' => t('Re/move this'),
-    '#options' => array(),
-    // If the element at the bottom is moved to the top, then the #value of 'top' will no longer be in the downdown
-    // and the FAPI throws a nasty validation error. Hence mark it already validated and we will do our own validation.
-    '#validated' => true,
-  );
-  if (!$is_first) {
-    $form['move']['#options']['top'] = t('Move to top');
-    $form['move']['#options']['up'] = t('Move up');
-  }
-  if (!$is_last) {
-    $form['move']['#options']['down'] = t('Move down');
-    $form['move']['#options']['bottom'] = t('Move to bottom');
-  }
-  $form['move']['#options']['remove'] = t('Remove');
-  $form['op'] = array(
-    '#type' => 'submit',
-    '#value' => t('Re/move'),
-    '#process' => array('flexifilter_undo_submit_default_name', 'form_expand_ahah'),
-  );
-
-  return $form;
-}
-
-/**
- * Helper function; sorts components by weight.
- */
-function _flexifilter_components_sort_weight($a, $b) {
-  return ((float)$a['weight']) > ((float)$b['weight']);
-}
-
-/**
- * Generates an FAPI array for a component list
- *
- * @param $data FAPI values for the component list. Use flexifilter_filter_edit_components_data to
- * convert a components array into coresponding FAPI values.
- * @param $data_base FAPI values for the top-level component list
- */
-function flexifilter_filter_edit_form_components($data, &$data_base, $show_advanced) {
-  $form = array(
-    '#type' => 'fieldset',
-    '#title' => t('Components'),
-    '#collapsed' => TRUE,
-    '#collapsible' => TRUE,
-    '#tree' => TRUE,
-  );
-  $components = array();
-  foreach ($data as $key => $component) {
-    if (strncmp($key, $data_base['id_prefix'], strlen($data_base['id_prefix'])) == 0) {
-      $components[$key] = $component;
-    }
-  }
-  if (isset($data['op'])) {
-    $components[$data_base['id_prefix'] . $data_base['id_next']] = flexifilter_filter_edit_form_new_component_data($data['new_list']);
-    $data_base['id_next'] = $data_base['id_next'] + 1;
-  }
-  foreach ($components as $key => $component) {
-    if (isset($component['op'])) {
-      switch ($component['move']) {
-        /*
-          Careful; this component is NOT VALIDATED by the FAPI. We only act upon certain
-          values ('top', 'up', 'down', 'bottom', 'remove'), which are always valid (even
-          if they have no effect). Other values are silently ignored.
-        */
-
-        case 'top':
-          $components[$key]['weight'] = -1000;
-          break;
-
-        case 'up':
-          $components[$key]['weight'] = $component['weight'] - 1.5;
-          break;
-
-        case 'down':
-          $components[$key]['weight'] = $component['weight'] + 1.5;
-          break;
-
-        case 'bottom':
-          $components[$key]['weight'] = 10001;
-          break;
-
-        case 'remove':
-          unset($components[$key]);
-          break;
-      }
-      $form['#collapsed'] = FALSE;
-    }
-  }
-  uasort($components, '_flexifilter_components_sort_weight');
-  $new_weight = 0;
-  $last_component_weight = count($components);
-  foreach ($components as $key => $component) {
-    $new_weight = $new_weight + 1;
-    $form[$key] = flexifilter_filter_edit_form_component($component, $new_weight, $new_weight == 1, $new_weight == $last_component_weight, $data_base, $show_advanced);
-    if ($form[$key]['#collapsed'] == FALSE) {
-      $form['#collapsed'] = FALSE;
-    }
-  }
-  $form['new_list'] = array(
-    '#type' => 'select',
-    '#options' => flexifilter_get_grouped_labels(flexifilter_get_component_list($show_advanced)),
-    '#title' => t('Add component'),
-  );
-  $form['op'] = array(
-    '#type' => 'submit',
-    '#value' => t('Add'),
-    '#process' => array('flexifilter_undo_submit_default_name', 'form_expand_ahah'),
-  );
-  return $form;
-}
-
-/**
- * The add/edit form for flexifilters.
- */
-function flexifilter_filter_edit_form($form_state, $flexifilter = 'new') {
-  if (!isset($form_state['post']) || !isset($form_state['post']['fid'])) {
-    $data = array();
-    $data['fid'] = $flexifilter === 'new' ? 'new' : $flexifilter['id'];
-    $data['basic'] = array();
-    $data['basic']['label'] = $flexifilter === 'new' ? '' : $flexifilter['label'];
-    $data['basic']['description'] = $flexifilter === 'new' ? '' : $flexifilter['description'];
-    $data['basic']['advanced'] = $flexifilter === 'new' ? 0 : $flexifilter['advanced'];
-    $data['components'] = $flexifilter === 'new' ? array() : flexifilter_filter_edit_components_data($flexifilter['components']);
-    if (!isset($data['components']['id_prefix']) || $data['components']['id_prefix'] === 'component_new_') {
-      $data['components']['id_prefix'] = 'component_'. $data['fid'] .'_';
-    }
-    if (!isset($data['components']['id_next'])) {
-      $data['components']['id_next'] = 0;
-    }
-    $expand_root_levels = TRUE;
-  }
-  else {
-    $data = $form_state['post'];
-    if (!isset($data['basic']['advanced'])) {
-      $data['basic']['advanced'] = 0;
-    }
-  }
-  $form = array();
-  $form['fid'] = array(
-    '#type' => 'hidden',
-    '#value' => $data['fid'],
-  );
-  $form['basic'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Basic settings'),
-    '#collapsed' => TRUE,
-    '#collapsible' => TRUE,
-    '#tree' => TRUE,
-  );
-  $form['basic']['label'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Label'),
-    '#required' => TRUE,
-    '#maxlength' => 127,
-    '#description' => t('Choose an appropriate label for this flexifilter.'),
-    '#default_value' => $data['basic']['label'],
-  );
-  $form['basic']['description'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Description'),
-    '#required' => TRUE,
-    '#maxlength' => 255,
-    '#description' => t('A short description of what this flexifilter does.'),
-    '#default_value' => $data['basic']['description'],
-  );
-  $form['basic']['advanced'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Show advanced options'),
-    '#default_value' => $data['basic']['advanced'],
-    '#description' => t('Advanced options currently only include the processing step option, which allows you to place some components into the filtering preparation step. You should only do so if it is critical that they be performed in the preparation step rather than the processing step.'),
-  );
-  $form['components'] = flexifilter_filter_edit_form_components($data['components'], $data['components'], $data['basic']['advanced'] == 1);
-  $form['components']['id_prefix'] = array('#type' => 'hidden', '#value' => $data['components']['id_prefix']);
-  $form['components']['id_next'] = array('#type' => 'hidden', '#value' => $data['components']['id_next']);
-  if (isset($expand_root_levels) && $expand_root_levels) {
-    $form['basic']['#collapsed'] = FALSE;
-    $form['components']['#collapsed'] = FALSE;
-  }
-  $form['submit1'] = array(
-    '#type' => 'submit',
-    '#value' => $data['fid'] === 'new' ? t('Create') : t('Save'),
-  );
-  $form['submit2'] = array(
-    '#type' => 'submit',
-    '#value' => $data['fid'] === 'new' ? t('Create and edit') : t('Save and edit'),
-  );
-  $form['#redirect'] = FALSE;
-  return $form;
-}
-
-/**
  * Helper function for flexifilter_filter_edit_form_components_from_data; converts a condition's
  * FAPI values back into a condition array.
  */
@@ -728,42 +640,6 @@ function flexifilter_filter_delete_form_
   $form_state['redirect'] = 'admin/build/flexifilters';
 }
 
-function flexifilter_filter_disable_form($form_state, $flexifilter) {
-  $form = array();
-  $form['fid'] = array('#type' => 'hidden', '#value' => $flexifilter['id']);
-
-  return confirm_form($form, t('Are you sure you want to disable the flexifilter "%flexifilter"?', array('%flexifilter' => $flexifilter['label'])), 'admin/build/flexifilters', t('If you disable the flexifilter, then it cannot be used in any Input Formats.'), t('Disable'), t('Cancel'));
-}
-
-function flexifilter_filter_disable_form_submit($form, &$form_state) {
-  $fid     = $form_state['values']['fid'];
-  $filters = flexifilter_get_filters();
-  $filter  = $filters[$fid];
-  if ($filter['enabled']) {
-    flexifilter_remove_from_filters($filter['delta']);
-    db_query('UPDATE {flexifilters} SET enabled = 0 WHERE fid = %d', $fid);
-    drupal_set_message(t('Flexifilter disabled.'));
-  }
-  $form_state['redirect'] = 'admin/build/flexifilters';
-}
-
-function flexifilter_filter_enable_form($form_state, $flexifilter) {
-  $form = array();
-  $form['fid'] = array('#type' => 'hidden', '#value' => $flexifilter['id']);
-
-  return confirm_form($form, t('Are you sure you want to enable the flexifilter "%flexifilter"?', array('%flexifilter' => $flexifilter['label'])), 'admin/build/flexifilters', t(''), t('Enable'), t('Cancel'));
-}
-
-function flexifilter_filter_enable_form_submit($form, &$form_state) {
-  $fid     = $form_state['values']['fid'];
-  $filters = flexifilter_get_filters();
-  $filter  = $filters[$fid];
-  if (!$filter['enabled'] && flexifilter_get_number_enabled_filters() < FLEXIFILTER_MAX_FILTERS) {
-    db_query('UPDATE {flexifilters} SET enabled = 1, delta = %d WHERE fid = %d', flexifilter_get_unused_delta(), $fid);
-    drupal_set_message(t('Flexifilter enabled.'));
-  }
-  $form_state['redirect'] = 'admin/build/flexifilters';
-}
 
 function flexifilter_filter_export_form($form_state, $flexifilter) {
   $form = array();
@@ -847,4 +723,52 @@ function flexifilter_filter_default_form
   }
   flexifilter_install_flexifilters('flexifilter', $to_be_saved);
   $form_state['redirect'] = 'admin/build/flexifilters';
-}
\ No newline at end of file
+}
+
+function flexifilter_js($parameter = '') {
+  switch ($parameter) {
+    case 'list_form':
+      $form = _flexifilter_js();
+      $output = '<div id="flexifilter-admin-list-form">';
+      foreach (element_children($form) as $key) {
+        $output .= drupal_render($form[$key]);
+      }
+      drupal_json(array('status' => TRUE, 'data' => $output .'</div>'));
+      break;
+    case 'component_edit':
+      $part = db_fetch_array(db_query('SELECT * FROM flexifilters_parts WHERE pid = %d', arg(5)));
+      $part['class'] = $part['class_name'];
+      print drupal_get_form('flexifilter_admin_edit_component', $part);
+      exit;
+      break;
+  }
+}
+
+function _flexifilter_js() {
+  $form_state = array('storage' => NULL, 'submitted' => FALSE);
+  $form_build_id = $_POST['form_build_id'];
+  $form = form_get_cache($form_build_id, &$form_state);
+  // #parameters has $form_id, $form_state and then whatever was passed to
+  // drupal_get_form.
+  $args = $form['#parameters'];
+  $form_id = array_shift($args);
+  $form['#post'] = $_POST;
+  $form['#redirect'] = FALSE;
+  // This will set up $form_state['clicked_button'] and
+  // $form_state['storage']['mlid'].
+  drupal_process_form($form_id, $form, $form_state);
+  // Recreate and re-cache the form.
+  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
+  // Pick up the parents of the pressed button.
+  $array_parents = $form_state['clicked_button']['#array_parents'];
+  // The last parent is the button itself, we need the wrapper instead.
+  $button_index = array_pop($array_parents);
+  while ($array_parents) {
+    $parent = array_shift($array_parents);
+    $form = $form[$parent];
+  }
+  // Remove the button.
+  unset($form[$button_index]);
+  // Render messages and selects.
+  return $form;
+}
Index: flexifilter.components.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flexifilter/flexifilter.components.inc,v
retrieving revision 1.12
diff -u -p -r1.12 flexifilter.components.inc
--- flexifilter.components.inc	22 Jan 2008 00:48:28 -0000	1.12
+++ flexifilter.components.inc	2 Feb 2008 05:39:58 -0000
@@ -21,7 +21,7 @@ function flexifilter_flexifilter_compone
   $components = array();
   // If, While, etc.
   $components['flexifilter_control_if'] = array(
-    'label' => t('If'),
+    'label' => t('If statement'),
     'description' => t('If and only if the condition is true, then the actions are performed.'),
     'contains_condition' => TRUE,
     'contains_components' => TRUE,
@@ -30,7 +30,7 @@ function flexifilter_flexifilter_compone
     'step' => 'both',
   );
   $components['flexifilter_control_while'] = array(
-    'label' => t('While'),
+    'label' => t('While statement'),
     'description' => t('While the condition is true, the actions are performed.'),
     'contains_condition' => TRUE,
     'contains_components' => TRUE,
@@ -111,7 +111,7 @@ function flexifilter_flexifilter_compone
 
   // Chunks!
   $components['flexifilter_chunk_grab'] = array(
-    'label' => t('Chunk grabber.'),
+    'label' => t('Chunk grabber'),
     'description' => t('Grabs chunks of text for further filtering and then sticks the filtered version back into the text.'),
     'callback' => 'flexifilter_component_chunk_grab',
     'group' => t('Chunks'),
Index: flexifilter.css
===================================================================
RCS file: flexifilter.css
diff -N flexifilter.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ flexifilter.css	2 Feb 2008 05:39:58 -0000
@@ -0,0 +1,8 @@
+#flexifilter-components {
+  width: 49%;
+  float: left;
+}
+#flexifilter-component-settings {
+  width: 49%;
+  float: right;
+}
\ No newline at end of file
Index: flexifilter.js
===================================================================
RCS file: flexifilter.js
diff -N flexifilter.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ flexifilter.js	2 Feb 2008 05:39:58 -0000
@@ -0,0 +1,13 @@
+(function($) {
+  $(function() {
+    $('#flexifilter-components tbody tr').each(function() {
+      $(this).find('td:first').bind('click', function() {
+        component_id = $(this).parent().find('td:last .flexifilter-cid').val();
+        $('#flexifilter-component-settings').load(Drupal.settings.basePath +'admin/build/flexifilters/js/component_edit/'+ component_id, function() {
+          Drupal.attachBehaviors($('#flexifilter-component-settings'));
+        });
+        return false;
+      });
+    });
+  });
+})(jQuery);
\ No newline at end of file
Index: flexifilter.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flexifilter/flexifilter.module,v
retrieving revision 1.14
diff -u -p -r1.14 flexifilter.module
--- flexifilter.module	23 Jan 2008 22:43:16 -0000	1.14
+++ flexifilter.module	2 Feb 2008 05:39:58 -0000
@@ -21,7 +21,7 @@ function flexifilter_menu() {
     'description' => t('Create new flexible input filters without writing any code.'),
     'page callback' => 'drupal_get_form',
     'access arguments' => array('administer flexifilter'),
-    'page arguments' => array('flexifilter_filter_list_form'),
+    'page arguments' => array('flexifilter_admin_list_form'),
     'file' => 'flexifilter.admin.inc',
   );
   $items['admin/build/flexifilters/list'] = array(
@@ -57,7 +57,7 @@ function flexifilter_menu() {
     'title arguments' => array(3, 'label'),
     'type' => MENU_CALLBACK,
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('flexifilter_filter_edit_form', 3),
+    'page arguments' => array('flexifilter_admin_edit_form', 3),
     'file' => 'flexifilter.admin.inc',
   );
   $items['admin/build/flexifilters/%flexifilter/edit'] = array(
@@ -78,23 +78,23 @@ function flexifilter_menu() {
     'page arguments' => array('flexifilter_filter_delete_form', 3),
     'file' => 'flexifilter.admin.inc',
   );
-  $items['admin/build/flexifilters/%flexifilter/enable'] = array(
-    'title' => t('Enable'),
+  $items['admin/build/flexifilters/js'] = array(
+    'title' => t('JavaScript Callback'),
     'type' => MENU_CALLBACK,
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('flexifilter_filter_enable_form', 3),
-    'file' => 'flexifilter.admin.inc',
-  );
-  $items['admin/build/flexifilters/%flexifilter/disable'] = array(
-    'title' => t('Disable'),
-    'type' => MENU_CALLBACK,
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('flexifilter_filter_disable_form', 3),
+    'page callback' => 'flexifilter_js',
     'file' => 'flexifilter.admin.inc',
   );
   return $items;
 }
 
+function flexifilter_theme() {
+  return array(
+    'flexifilter_admin_list' => array('template' => 'flexifilter-admin-list', 'file' => 'flexifilter.admin.inc', 'arguments' => array('form' => NULL)),
+    'flexifilter_admin_component_list' => array('template' => 'flexifilter-admin-component-list', 'file' => 'flexifilter.admin.inc', 'arguments' => array('form' => NULL)),
+    'flexifilter_filter_admin_form' => array('file' => 'flexifilter.admin.inc', 'arguments' => array('form' => NULL)),
+  );
+}
+
 /**
  * Implementation of hook_help()
  */
