Index: nodereference_url.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/nodereference_url/nodereference_url.module,v
retrieving revision 1.9
diff -u -r1.9 nodereference_url.module
--- nodereference_url.module	17 May 2009 00:57:38 -0000	1.9
+++ nodereference_url.module	17 May 2009 02:03:40 -0000
@@ -7,6 +7,22 @@
  */
 
 /**
+ * Implementation of hook_menu().
+ */
+function nodereference_url_menu() {
+  $items = array();
+
+  $items['nodereference/url_widget_change/%/%/%'] = array(
+    'page callback' => 'nodereference_url_change_js',
+    'page arguments' => array(2, 3, 4),
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
  * Implementation of hook_theme().
  */
 function nodereference_url_theme() {
@@ -238,6 +254,7 @@
     $element[0]['nid'] = array(
       '#title' => $field['widget']['label'],
       '#type' => 'nodereference_url',
+      '#type_name' => $field['type_name'],
       '#field_name' => $field['field_name'],
       '#default_value' => $referenced_nid,
     );
@@ -255,6 +272,8 @@
  * The $fields array is in $form['#field_info'][$element['#field_name']].
  */
 function nodereference_url_process($element, $edit, $form_state, $form) {
+  drupal_add_css(drupal_get_path('module', 'nodereference_url') .'/nodereference_url.css');
+
   $field_key = $element['#columns'][0];
   $field = $form['#field_info'][$element['#field_name']];
 
@@ -271,10 +290,78 @@
     '#parents' => $element['#parents'],
   );
 
+  $element['change'] = array(
+    '#type' => 'submit',
+    '#value' => t('Change'),
+    '#ahah' => array(
+      'path' => 'nodereference/url_widget_change/'. $element['#type_name'] .'/'. $element['#field_name'] .'/'. $element['#delta'],
+      'wrapper' => $element['#id'] .'-ahah-wrapper',
+    ),
+  );
+
+  $element['#attributes']['id'] = $element['#id'] .'-ahah-wrapper';
+  $element['#prefix'] = '<div '. drupal_attributes($element['#attributes']) .'>';
+  $element['#suffix'] = '</div>';
+
   return $element;
 }
 
 /**
+ * Menu callback; switch the widget to the fallback behavior.
+ */
+function nodereference_url_change_js($type_name, $field_name, $delta) {
+  $field = content_fields($field_name, $type_name);
+
+  if (empty($field) || empty($_POST['form_build_id'])) {
+    // Invalid request.
+    drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array('@size' => format_size(file_upload_max_size()))), 'error');
+    print drupal_to_js(array('data' => theme('status_messages')));
+    exit;
+  }
+
+  // Build the new form.
+  $form_state = array('submitted' => FALSE);
+  $form_build_id = $_POST['form_build_id'];
+  $form = form_get_cache($form_build_id, $form_state);
+
+  if (!$form) {
+    // Invalid form_build_id.
+    drupal_set_message(t('An unrecoverable error occurred. This form was missing from the server cache. Try reloading the page and submitting again.'), 'error');
+    print drupal_to_js(array('data' => theme('status_messages')));
+    exit;
+  }
+
+  // Build the form.
+  $args = $form['#parameters'];
+  $form_id = array_shift($args);
+  $form['#post'] = $_POST;
+  $form = form_builder($form_id, $form, $form_state);
+
+  // Update the cached form with the new element at the right place in the form.
+  if (module_exists('fieldgroup') && ($group_name = _fieldgroup_field_get_group($type_name, $field_name))) {
+    if (isset($form['#multigroups']) && isset($form['#multigroups'][$group_name][$field_name])) {
+      $form_element = $form[$group_name][$delta][$field_name];
+    }
+    else {
+      $form_element = $form[$group_name][$field_name][$delta];
+    }
+  }
+  else {
+    $form_element = $form[$field_name][$delta];
+  }
+
+  if (isset($form_element['_weight'])) {
+    unset($form_element['_weight']);
+  }
+
+  $output = theme('status_messages') . drupal_render($form_element);
+
+  $GLOBALS['devel_shutdown'] = FALSE;
+  print drupal_to_js(array('status' => TRUE, 'data' => $output));
+  exit;
+}
+
+/**
  * An #after_build function used to add an empty value to the list of options.
  *
  * Normally CCK would do this in optionwidgets_options(), but since the widget
@@ -302,5 +389,9 @@
  * $element['#delta]  is the position of this element in the group
  */
 function theme_nodereference_url($element) {
-  return theme('form_element', $element, $element['#display_title']);
+  $output = '';
+  $output .= '<div class="nodereference-url-widget">';
+  $output .= theme('form_element', $element, $element['#display_title'] .' '. $element['#children']);
+  $output .= '</div>';
+  return $output;
 }
Index: nodereference_url.css
===================================================================
RCS file: nodereference_url.css
diff -N nodereference_url.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ nodereference_url.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,16 @@
+.nodereference-url-widget input.form-submit {
+  margin: 0 6px;
+}
+
+.nodereference-url-widget input.progress-disabled {
+  float: none;
+  display: inline;
+}
+
+.nodereference-url-widget div.ahah-progress,
+.nodereference-url-widget div.throbber {
+  display: inline;
+  float: none;
+  padding: 1px 13px 2px 3px; /* RTL */
+}
+
