Index: flag.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/Attic/flag.module,v
retrieving revision 1.11.2.45
diff -u -F^[^a-z]*function -r1.11.2.45 flag.module
--- flag.module	3 Oct 2008 15:32:07 -0000	1.11.2.45
+++ flag.module	8 Oct 2008 10:21:37 -0000
@@ -651,7 +651,10 @@ function flag_page($action, $flag_name, 
   if (!$result) {
     if ($js) {
       drupal_set_header('Content-Type: text/javascript; charset=utf-8');
-      print drupal_to_js(array('status' => FALSE));
+      print drupal_to_js(array(
+        'status' => FALSE,
+        'errorMessage' => t('You are not allowed to flag, or unflag, this content.'),
+      ));
       exit;
     }
     else {
@@ -662,7 +665,11 @@ function flag_page($action, $flag_name, 
 
   if ($js) {
     drupal_set_header('Content-Type: text/javascript; charset=utf-8');
-    print drupal_to_js(array('status' => TRUE));
+    $flag = flag_get_flag($flag_name);
+    print drupal_to_js(array(
+      'status' => TRUE,
+      'newLink' => $flag->theme($flag->is_flagged($content_id) ? 'unflag' : 'flag', $content_id, TRUE),
+    ));
     exit;
   }
   else {
@@ -816,37 +823,6 @@ function template_preprocess_flag(&$vari
 }
 
 /**
- * Helper function for adding extra JavaScript behaviour to the page. (The
- * basic JavaScript file is added in flag.tpl.php.)
- */
-function flag_add_extra_js(&$flag, $action, $content_id, $after_flagging) {
-  static $added_flags, $js_added;
-
-  if ($after_flagging) {
-    // Since flag.tpl.php calls this function, and since we ourselves trigger
-    // flag.tpl.php here (when we do $flag->theme(), to generate the links to
-    // store in some JS array), we need to guard against recursion:
-    return;
-  }
-
-  // Add initial JS/CSS to the page.
-  if (!isset($js_added)) {
-    drupal_add_js(array('flag' => array('cleanUrl' => variable_get('clean_url', 0))), 'setting');
-    $js_added = TRUE;
-  }
-
-  // Add JavaScript copies of the links so we can swap them out when the user clicks.
-  if (!(isset($added_flags[$flag->name][$content_id]))) {
-    $flag_html = $flag->theme('flag', $content_id, TRUE);
-    $unflag_html = $flag->theme('unflag', $content_id, TRUE);
-    // Note the 'cid_' we're prefixing to the numeric content ID. That's
-    // because numeric strings can't serve as object properties in javascript.
-    drupal_add_js(array('flag' => array('flags' => array($flag->name => array('cid_' . $content_id => array('flag' => $flag_html, 'unflag' => $unflag_html))))), 'setting');
-    $added_flags[$flag->name][$content_id] = TRUE;
-  }
-}
-
-/**
  * Format a string containing a count of items.
  *
  * _flag_format_plural() is a version of format_plural() which
Index: theme/flag.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/theme/Attic/flag.css,v
retrieving revision 1.1.2.2
diff -u -F^[^a-z]*function -r1.1.2.2 flag.css
--- theme/flag.css	22 Jul 2008 07:13:08 -0000	1.1.2.2
+++ theme/flag.css	8 Oct 2008 10:21:37 -0000
@@ -12,3 +12,16 @@
 .flag-wrapper {
   position: relative;
 }
+
+/* The rest deals with indicating the waiting state. */
+
+.flag-waiting a {
+  /* Give an impression of a disabled link. */
+  opacity: 0.5;
+  filter: alpha(opacity=50); /* IE */
+}
+
+.flag-waiting .flag-throbber {
+  background: url(flag-throbber.gif) no-repeat right center;
+  padding-right: 13px;
+}
Index: theme/flag.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/theme/Attic/flag.js,v
retrieving revision 1.1.2.3
diff -u -F^[^a-z]*function -r1.1.2.3 flag.js
--- theme/flag.js	19 Aug 2008 08:50:26 -0000	1.1.2.3
+++ theme/flag.js	8 Oct 2008 10:21:37 -0000
@@ -1,40 +1,34 @@
 // $Id: flag.js,v 1.1.2.3 2008/08/19 08:50:26 mooffie Exp $
+
+/**
+ * Terminology:
+ *
+ *   "Link" means "Everything which is in flag.tpl.php" --and this may contain
+ *   much more than the <A> element. On the other hand, when we speak
+ *   specifically of the <A> element, we say "element" or "the <A> element".
+ */
+
 Drupal.behaviors.flag = function() {
   // Note, extra indentation left here to maintain ease of patching for D5 version.
 
     /**
-     * Flips a link. 'Flag this!' links turn into 'Unflag this!' and
-     * vice versa.
-     */
-    function flipLink(element, settings) {
-      // If this is a 'flag this' link...
-      if ($(element).is('.flag-action')) {
-        // ...then turn it into an 'unflag this' link;
-        var newHtml = settings.unflag;
-      }
-      else {
-        // else, turn it into a 'flag this' link.
-        var newHtml = settings.flag;
-      }
-      updateLink(element, newHtml, settings);
-    }
-
-    /**
      * Helper function. Updates a link's HTML with a new one.
+     *
+     * @param element
+     *   The <A> element.
+     * @return
+     *   The new <A> elemenet.
      */
-    function updateLink(element, newHtml, settings) {
+    function updateLink(element, newHtml) {
       var $newLink = $(newHtml);
 
       // Initially hide the message so we can fade it in.
       $('.flag-message', $newLink).css('display', 'none');
 
-      // Reattach the behavior to the new link.
-      if ($('a', $newLink).size() > 0) {
-        $('a', $newLink).bind('click', function() { return flagClick(this, settings) });
-      }
-      else {
-        $newLink.bind('click', function() { return flagClick(this, settings) });
-      }
+      // Reattach the behavior to the new <A> element. This element
+      // is either whithin the wrapper or it is the outer element itself.
+      var $nucleus = $newLink.is('a') ? $newLink : $newLink.find('a.flag');
+      $nucleus.addClass('flag-processed').click(flagClick);
 
       // Find the wrapper of the old link.
       var $wrapper = $(element).parents('.flag-wrapper:first');
@@ -46,11 +40,33 @@     function updateLink(element, newHtml
       // Replace the old link with the new one.
       $wrapper.after($newLink).remove();
 
+      if (Drupal.attachBehaviors) { // So it won't crash on Drupal 5.
+        Drupal.attachBehaviors($newLink);
+      }
+
       $('.flag-message', $newLink).fadeIn();
+
+      return $nucleus.get(0);
     }
     
-    // Click function for each Flag link.
-    function flagClick(element, settings) {
+    /**
+     * A click handler that is attached to all <A class="flag"> elements.
+     */
+    function flagClick() {
+      // 'this' won't point to the element when it's inside the ajax closures,
+      // so we reference it using a variable.
+      var element = this;
+
+      // While waiting for a server response, the wrapper will have a
+      // 'flag-waiting' class. Themers are thus able to style the link
+      // differently, e.g., by displaying a throbber.
+      var $wrapper = $(element).parents('.flag-wrapper');
+      if ($wrapper.is('.flag-waiting')) {
+        // Guard against double-clicks.
+        return false;
+      }      
+      $wrapper.addClass('flag-waiting');
+      
       // Hide any other active messages.
       $('span.flag-message:visible').fadeOut();
 
@@ -61,59 +77,25 @@     function flagClick(element, settings
         data: { js: true },
         dataType: 'json',
         success: function (data) {
-          // Display errors
-          if (!data.status) {
-            // Change link back
-            flipLink(element, settings);
-            return;
+          if (data.status) {
+	    // Success
+            updateLink(element, data.newLink);
+          }
+          else {
+            // Failure
+            alert(data.errorMessage);
+            $wrapper.removeClass('flag-waiting');
           }
         },
         error: function (xmlhttp) {
           alert('An HTTP error '+ xmlhttp.status +' occurred.\n'+ element.href);
-          // Change link back
-          flipLink(element, settings);
         }
       });
-      // Swap out the links.
-      flipLink(element, settings);
       return false;
     }
 
-    /**
-     * Like alert(), but displays only once, to keep user from losing sanity.
-     */
-    var warn = function(message) {
-      if (!Drupal.settings.flag.alertShown) {
-        alert('Flag module: ' + message);
-        Drupal.settings.flag.alertShown = true;
-      }
-    }
-
-    /**
-     * Returns the settings for a certain link element.
-     */
-    function getLinkSettings(element) {
-      // The link URL is of the form ?q=flag/unflag/bookmarks/23,
-      // so let's parse it to extract the flag name and the content ID.
-      var matches = element.href.match(/flag\/(un)?flag\/(\w+)\/(\d+)/);
-      if (!matches) {
-        warn("Error: Invalid flag URL '" + element.href + "'");
-      }
-      var flagName  = matches[2];
-      var contentId = matches[3];
-      var slot = 'cid_' + contentId;
-
-      if (!Drupal.settings.flag.flags[flagName][slot]) {
-        // Slot does not exist. Create.
-        Drupal.settings.flag.flags[flagName][slot] = {};
-      }
-      // Return a reference to the settings slot.
-      return Drupal.settings.flag.flags[flagName][slot];
-    }
-
     // On load, bind the click behavior for all links on the page.
-    $('a.flag').click(function() {
-      return flagClick(this, getLinkSettings(this));
-    });
+    $('a.flag:not(.flag-processed)').addClass('flag-processed').click(flagClick);
+
   // Intentional extra indention.
 }
Index: theme/flag.tpl.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/theme/Attic/flag.tpl.php,v
retrieving revision 1.1.2.2
diff -u -F^[^a-z]*function -r1.1.2.2 flag.tpl.php
--- theme/flag.tpl.php	5 Sep 2008 15:36:11 -0000	1.1.2.2
+++ theme/flag.tpl.php	8 Oct 2008 10:21:37 -0000
@@ -39,10 +39,9 @@
     drupal_add_css(drupal_get_path('module', 'flag') .'/theme/flag.css');
     drupal_add_js(drupal_get_path('module', 'flag') .'/theme/flag.js');
   }
-  flag_add_extra_js($flag, $action, $content_id, $after_flagging);
 ?>
 <span class="flag-wrapper flag-<?php echo $flag_name_css; ?>">
-  <a href="<?php echo $link_href; ?>" title="<?php echo $link_title; ?>" class="flag <?php echo $action; ?>-action <?php echo $after_flagging ? $last_action : ''; ?>"><?php echo $link_text; ?></a>
+  <a href="<?php echo $link_href; ?>" title="<?php echo $link_title; ?>" class="flag <?php echo $action; ?>-action <?php echo $after_flagging ? $last_action : ''; ?>"><?php echo $link_text; ?></a><span class="flag-throbber">&nbsp;</span>
   <?php if ($after_flagging): ?>
     <span class="flag-message flag-<?php echo $last_action; ?>-message">
       <?php echo $message_text; ?>
