Index: INSTALL.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/img_assist/INSTALL.txt,v
retrieving revision 1.14.2.9
diff -u -p -r1.14.2.9 INSTALL.txt
--- INSTALL.txt	6 Apr 2008 16:45:05 -0000	1.14.2.9
+++ INSTALL.txt	29 Jun 2008 22:27:45 -0000
@@ -6,7 +6,7 @@
 
 * Image module <http://drupal.org/project/image>
 
-* TinyMCE module (optional) <http://drupal.org/project/tinymce>
+* Wysiwyg Editor module (optional) <http://drupal.org/project/wysiwyg>
 
 
 -- PRE-REQUISITES --
@@ -59,32 +59,7 @@
   want your users to be able to easily choose images from their galleries, select
   for example "Acidfree albums" as the vocabulary to use for Image assist.
 
-
--- TINYMCE PLUGIN INSTALLATION --
-
-If you use the TinyMCE WYSIWYG editor, you need to install a plugin for Image
-Assist.
-
-* Move or copy the folder 'drupalimage' in the img_assist directory to
-
-  [sites/all/]modules/tinymce/tinymce/jscripts/tiny_mce/plugins/
-   
-  Edit the file plugin_reg.php in the tinymce directory. It's located in:
-
-  [sites/all/]modules/tinymce/plugin_reg.php
-
-  Add the following lines anywhere above the 'return' statement (without the
-  <code> tags):
-<code>
-  $plugins['drupalimage'] = array();
-  $plugins['drupalimage']['theme_advanced_buttons1'] = array('drupalimage');
-  $plugins['drupalimage']['extended_valid_elements'] = array('img[class|src|border=0|alt|title|width|height|align|name]');
-</code>
-
-  Next, go to
-
-  Administer > Site configuration > TinyMCE
-
-  and enable the drupalimage plugin in your TinyMCE profile.
+* If Wysiwyg Editor module is installed, you need to edit your Wysiwyg profile
+  configuration and enable the plugin for Image Assist.
 
 
Index: img_assist.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/img_assist/img_assist.module,v
retrieving revision 1.68.2.49
diff -u -p -r1.68.2.49 img_assist.module
--- img_assist.module	6 Apr 2008 17:46:15 -0000	1.68.2.49
+++ img_assist.module	29 Jun 2008 22:35:28 -0000
@@ -132,8 +132,12 @@ function img_assist_elements() {
  * Add image link underneath textareas.
  */
 function img_assist_textarea($element) {
+  // FAPI #wysiwyg support.
+  if (isset($element['#wysiwyg']) && $element['#wysiwyg']) {
+    return $element;
+  }
   $link = variable_get('img_assist_link', 'icon');
-  if (($link == 'icon') || ($link == 'text')) {
+  if ($link == 'icon' || $link == 'text') {
     if (_img_assist_textarea_match($element['#id']) && _img_assist_page_match() && !strstr($_GET['q'], 'img_assist')) {
       if (user_access('access img_assist')) {
         $output = theme('img_assist_textarea_link', $element, $link);
@@ -486,7 +490,7 @@ function img_assist_loader() {
   $path = drupal_get_path('module', 'img_assist');
   $output .= '<script type="text/javascript" src="'. base_path() . $path .'/img_assist.js"></script>'."\n";
   if ($editor == 'tinymce') {
-    $tinymce_path = drupal_get_path('module', 'tinymce');
+    $tinymce_path = drupal_get_path('module', 'wysiwyg_editor');
     $tinymce_js = base_path() . $tinymce_path .'/tinymce/jscripts/tiny_mce/tiny_mce_popup.js';
     $output .= '<script type="text/javascript" src="'. $tinymce_js .'"></script>' . "\n";
   }
@@ -1761,6 +1765,23 @@ function theme_img_assist_page($content,
  */
 
 /**
+ * Implementation of hook_wysiwyg_plugin().
+ */
+function img_assist_wysiwyg_plugin($editor) {
+  switch ($editor) {
+    case 'tinymce':
+      return array(
+        'drupalimage' => array(
+          'path' => drupal_get_path('module', 'img_assist') .'/drupalimage',
+          'buttons' => array('drupalimage' => t('Image Assist')),
+          'url' => 'http://drupal.org/project/img_assist',
+          'extended_valid_elements' => array('img[class|src|border=0|alt|title|width|height|align|name]'),
+        ),
+      );
+  }
+}
+
+/**
  * @defgroup img_assist_legacy Image Assist Legacy functions
  * @{
  * Used for backwards compatibility with original img_assist module.
Index: drupalimage/drupalimage.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/img_assist/drupalimage/drupalimage.css,v
retrieving revision 1.1.4.1
diff -u -p -r1.1.4.1 drupalimage.css
--- drupalimage/drupalimage.css	9 Apr 2007 22:57:22 -0000	1.1.4.1
+++ drupalimage/drupalimage.css	23 Jun 2008 22:35:10 -0000
@@ -1,4 +1,5 @@
 /* $Id: drupalimage.css,v 1.1.4.1 2007/04/09 22:57:22 darrenoh Exp $ */
+
 .mceItemDrupalImage {
 	border: 1px dotted #cc0000;
 	background-image: url('images/drupalimage.gif');
Index: drupalimage/editor_plugin.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/img_assist/drupalimage/editor_plugin.js,v
retrieving revision 1.1.4.4
diff -u -p -r1.1.4.4 editor_plugin.js
--- drupalimage/editor_plugin.js	30 Sep 2007 23:05:20 -0000	1.1.4.4
+++ drupalimage/editor_plugin.js	23 Jun 2008 22:11:13 -0000
@@ -1,260 +1,248 @@
-// $Id: editor_plugin.js,v 1.1.4.4 2007/09/30 23:05:20 sun Exp $
-/* Import plugin specific language pack */
+// $Id: editor_plugin_src.js,v 1.1.4.4 2007/09/30 23:05:20 sun Exp $
+
+// Import plugin language.
 tinyMCE.importPluginLanguagePack('drupalimage', 'en');
 
 var TinyMCE_DrupalImagePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'DrupalImage',
-			author : 'Benjamin Shell',
-			authorurl : 'http://www.benjaminshell.com',
-			infourl : 'http://drupal.org/project/img_assist',
-			version : tinyMCE.majorVersion +'.'+ tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function(inst) {
-		if (!tinyMCE.settings['drupalimage_skip_plugin_css'])
-			tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + '/plugins/drupalimage/drupalimage.css');
-	},
-
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case 'drupalimage':
-				return tinyMCE.getButtonHTML(cn, 'lang_drupalimage_desc', '{$pluginurl}/images/drupalimage.gif', 'mceDrupalImage');
-		}
-
-		return '';
-	},
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case 'mceDrupalImage':
-				var name = '';
-				var nid = '', alt = '', captionTitle = '', captionDesc = '', link = '', url = '', align = '', width = '', height = '';
-				var action   = 'insert';
-				var template = new Array();
-				var inst     = tinyMCE.getInstanceById(editor_id);
-				var focusElm = inst.getFocusElement();
-				
-				template['file']   = BASE_URL + 'index.php?q=img_assist/load/tinymce';
-				template['width']  = 600;
-				template['height'] = 350;
-				template['html']   = false;
-				
-				// Is selection a image
-				if (focusElm != null && focusElm.nodeName.toLowerCase() == 'img') {
-					name = tinyMCE.getAttrib(focusElm, 'class');
-
-					if (name.indexOf('mceItemDrupalImage') == -1)
-						// Not a DrupalImage
-						return true;
-
-					// Get the rest of the DrupalImage attributes
-					align  = tinyMCE.getAttrib(focusElm, 'align');
-					width  = tinyMCE.getAttrib(focusElm, 'width');
-					height = tinyMCE.getAttrib(focusElm, 'height');
-					// using 'title' because this doesn't seem to work with 'alt'
-					alt    = decodeURIComponent(tinyMCE.getAttrib(focusElm, 'title'));
-					// parse the deliminated attributes in the alt tag
-					var miscAttribs = TinyMCE_DrupalImagePlugin._parsePipeAttributes(alt);
-					nid          = miscAttribs['nid'];
-					captionTitle = miscAttribs['title'];
-					captionDesc  = miscAttribs['desc'];
-					link         = miscAttribs['link'];
-					if(typeof miscAttribs['url'] != 'undefined') {
-						url = miscAttribs['url'];
-					}
-					
-					action = 'update';
-				}
-				
-				tinyMCE.openWindow(template, {editor_id: editor_id, nid: nid, captionTitle: captionTitle, captionDesc: captionDesc, link: link, url: url, align: align, width: width, height: height, action: action});
-				return true;
-	   }
-
-	   // Pass to next handler in chain
-	   return false;
-	},
-	
-	cleanup : function(type, content) {
-		switch (type) {
-			case 'insert_to_editor_dom':
-				break;
-			
-			case 'get_from_editor_dom':
-				break;
-			
-			case 'insert_to_editor':
-				// called when TinyMCE loads existing data or when updating code using
-				// Edit HTML Source plugin.
-				// Parse all drupalimage filter tags and replace them with image placeholders
-				var startPos = 0;
-				var index = 0;
-				while ((startPos = content.indexOf('[img_assist|', startPos)) != -1) {
-					// Find end of object
-					var endPos = content.indexOf(']', startPos);
-					var attribs = TinyMCE_DrupalImagePlugin._parsePipeAttributes(content.substring(startPos + 12, endPos));
-					endPos++;
-					
-					// TinyMCE_DrupalImagePlugin._parsePipeAttributes() parses the piped
-					// string completely, but in this case we want to keep the nid, title,
-					// and desc in piped format, so we have to rebuild a partial piped string.
-					// Backwards compatibility: Also parse link/url in the format link=url,foo.
-					var miscAttribs = 'nid=' + attribs['nid'] + '|title=' + attribs['title'] + '|desc=' + attribs['desc'];
-					if(attribs['link'].indexOf(',') != -1) {
-						link = attribs['link'].split(',', 2);
-						miscAttribs += '|link=' + link[0] + '|url=' + link[1];
-					}
-					else {
-						miscAttribs += '|link=' + attribs['link'];
-					}
-					if(typeof attribs['url'] != 'undefined') {
-						miscAttribs += '|url=' + attribs['url'];
-					}
-					// ordinarily piped strings wouldn't need to have HTML entities
-					// converted, but we are building an HTML tag that just happens to use
-					// a piped string as one of its' attribute values. The easiest way to
-					// take care of HTML entities is with the Javascript escape() function.
-					// It escapes more than necessary, but that's okay.  We'll use unescape()
-					// to go back when we need to.
-					miscAttribs = encodeURIComponent(miscAttribs);
-					
-					// Insert image
-					var contentAfter = content.substring(endPos);
-					content = content.substring(0, startPos);
-					// Reference: these are the default parameters that are valid for the
-					// TinyMCE image tags:
-					// img[class|src|border=0|alt|title|hspace|vspace|width|height|align]
-					content += '<img src="' + (tinyMCE.getParam('theme_href') + '/images/spacer.gif') + '"';
-					content += ' width="' + attribs['width'] + '" height="' + attribs['height'] + '" align="' + attribs['align'] + '"';
-					content += ' alt="' + miscAttribs + '" title="' + miscAttribs + '" name="mceItemDrupalImage" class="mceItemDrupalImage" />';
-					content += contentAfter;
-					index++;
-					
-					startPos++;
-				}
-				break;
-
-			case 'get_from_editor':
-				// Called when TinyMCE exits or when the Edit HTML Source plugin is clicked
-				// Parse all image placeholders and replace them with drupalimage filter tags
-				var startPos = -1;
-				while ((startPos = content.indexOf('<img', startPos+1)) != -1) {
-					var endPos = content.indexOf('/>', startPos);
-					var attribs = TinyMCE_DrupalImagePlugin._parseHTMLAttributes(content.substring(startPos + 4, endPos));
-					endPos += 2;
-					
-					// Is not drupalimage, skip it
-					if (attribs['name'] != "mceItemDrupalImage") {
-						continue;
-					}
-					
-					// Insert drupalimage filter code
-					// At this point all attribute values should have any pipes | or
-					// closing square brackets ] escaped with backslashes. When this
-					// filter code is parsed, it will look for the closing bracket to
-					// find the end and the pipe symbol to explode the rest of the
-					// attributes. However, since we just parsed from HTML tag, HTML
-					// entities should be unescaped at this time.
-					var miscAttribs = decodeURIComponent(attribs['alt']);
-					
-					var contentBefore = content.substring(0, startPos);
-					var contentAfter = content.substring(endPos);
-					var drupalHTML = '';
-					drupalHTML += '[img_assist|' + miscAttribs + '|align=' + attribs['align'];
-					drupalHTML += '|width=' + attribs['width'] + '|height=' + attribs['height'] + ']';
-					content = contentBefore + drupalHTML + contentAfter;
-				}
-				break;
-		}
-
-		// Pass through to next handler in chain
-		return content;
-	},
-	
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (node == null)
-			return;
-
-		do {
-			// This code looks at the name of the image to see if the drupalimage
-			// button should be selected. However, by default 'name' is not accepted
-			// by TinyMCE as a parameter for the img tag, so it must be added using
-			// the initialization string. As far as THIS code goes, it could look at
-			// 'className' instead, therefore avoiding this requirement, however the
-			// regular image button looks at the 'name' value to see if it starts with
-			// 'mce_'. If it does, it considers it an internal image and does not
-			// highlight the regular image button. If 'className' is used here
-			// instead, BOTH buttons highlight when a drupalimage is selected.
-			if (node.nodeName == 'IMG' && tinyMCE.getAttrib(node, 'class').indexOf('mceItemDrupalImage') == 0) {
-				tinyMCE.switchClass(editor_id + '_drupalimage', 'mceButtonSelected');
-				return true;
-			}
-		} while ((node = node.parentNode));
-
-		tinyMCE.switchClass(editor_id + '_drupalimage', 'mceButtonNormal');
-
-		return true;
-	},
-	
-	// pipes | must be escaped with a backslash like this: \|
-	// note: values also cannot contain ] because the functions that call 
-	// this function use the ] symbol to find the end of the drupalimage filter code
-	_parsePipeAttributes : function(attribute_string) {
-		var attributes = new Array();
-		var keyvalue_arr = new Array();
-		// if it weren't for the escaping, the regExp string would look like this:
-		// var regExp = new RegExp('([a-zA-Z]*)=([^\|]*)', 'g');
-		var regExp = new RegExp('([a-zA-Z]*)=([^|](?:\\.|[^\\|]*)*)*', 'g');
-		var matches = attribute_string.match(regExp);
-		for (var i = 0; i < matches.length; i++ ) {
-			keyvalue_arr = matches[i].split('=');
-			attributes[keyvalue_arr[0]] = keyvalue_arr[1];
-		}
-		return attributes;
-	},
-	
-	/* 
-	 * Parses HTML attributes into a key=>value array.
-	 * Take a look at the example strings and see how standard HTML entities
-	 * within any value, such as the title and desc (which are combined in the
-	 * alt tag as a piped string) need to be converted to: &quot; &amp; &lt; &gt;
-	 *
-	 * Simple example:
-	 *     name="mceItemDrupalImage" width="200" height="150" src="/images/spacer.gif" 
-	 *     alt="nid=123|title=My Photos|desc=" class="mceItemDrupalImage" align="right"
-	 *
-	 * Advanced example:
-	 *     name="mceItemDrupalImage" width="200" height="150" src="/images/spacer.gif" 
-	 *     alt="nid=123|title=&quot;To be or not to be&quot;|desc=That is the question."
-	 *     class="mceItemDrupalImage" align="right"
-	 *
-	 * Any pipes | or closing brackets would also be a problem, not for this
-	 * parsing function, but when parsing the pipe deliminated string. These
-	 * characters need to be escaped with a backslash. Unlike the quotes, this
-	 * cannot be accomplished automatically within this TinyMCE plugin. Any user
-	 * or Drupal module that inserts drupalimage filter strings in a post, whether
-	 * using TinyMCE or not, must backslash any pipes or closing brackets.
-	*/
-	_parseHTMLAttributes : function(attribute_string) {
-		var attributes = new Array();
-		var innerMatches = new Array();
-		var regExp = '([a-zA-Z0-9]+)[\s]*=[\s]*"([^"](?:\\.|[^\\"]*)*)"';
-	
-		// doesn't work without global (g)
-		var outerRegExp = new RegExp(regExp, 'g');
-		var outerMatches = attribute_string.match(outerRegExp);
-		// doesn't work with global (g)
-		var innerRegExp = new RegExp(regExp);
-		for (var i = 0; i < outerMatches.length; i++ ) {
-			innerMatches = innerRegExp.exec(outerMatches[i]);
-			attributes[innerMatches[1]] = innerMatches[2];
-		}
-		return attributes;
-	}
+  getInfo: function() {
+    return {
+      longname: 'Image Assist',
+      author: 'Benjamin Shell',
+      authorurl: 'http://www.benjaminshell.com',
+      infourl : 'http://drupal.org/project/img_assist'
+    };
+  },
+
+  initInstance : function(inst) {
+    if (!tinyMCE.settings['drupalimage_skip_plugin_css'])
+      tinyMCE.importCSS(inst.getDoc(), this.baseURL + '/drupalimage.css');
+  },
+
+  getControlHTML: function (control_name) {
+    switch (control_name) {
+      case 'drupalimage':
+        return tinyMCE.getButtonHTML(control_name, 'lang_drupalimage_desc', '{$pluginurl}/images/drupalimage.gif', 'mceDrupalImage');
+    }
+    return '';
+  },
+
+  execCommand: function(editor_id, element, command, user_interface, value) {
+    switch (command) {
+      case 'mceDrupalImage':
+        var name = '';
+        var nid = '', alt = '', captionTitle = '', captionDesc = '', link = '', url = '', align = '', width = '', height = '';
+        var action   = 'insert';
+        var template = new Array();
+        var inst = tinyMCE.getInstanceById(editor_id);
+        var focusElm = inst.getFocusElement();
+
+        template['file']   = BASE_URL + 'index.php?q=img_assist/load/tinymce';
+        template['width']  = 600;
+        template['height'] = 350;
+        template['html']   = false;
+
+        // Check whether selection is an image and belongs to this plugin.
+        if (focusElm != null && focusElm.nodeName.toLowerCase() == 'img') {
+          name = tinyMCE.getAttrib(focusElm, 'class');
+
+          if (name.indexOf('mceItemDrupalImage') == -1)
+            return true;
+
+          // Get the rest of the DrupalImage attributes
+          align  = tinyMCE.getAttrib(focusElm, 'align');
+          width  = tinyMCE.getAttrib(focusElm, 'width');
+          height = tinyMCE.getAttrib(focusElm, 'height');
+          // using 'title' because this doesn't seem to work with 'alt'
+          alt    = decodeURIComponent(tinyMCE.getAttrib(focusElm, 'title'));
+          // parse the deliminated attributes in the alt tag
+          var miscAttribs = TinyMCE_DrupalImagePlugin._parsePipeAttributes(alt);
+          nid          = miscAttribs['nid'];
+          captionTitle = miscAttribs['title'];
+          captionDesc  = miscAttribs['desc'];
+          link         = miscAttribs['link'];
+          if(typeof miscAttribs['url'] != 'undefined') {
+            url = miscAttribs['url'];
+          }
+          action = 'update';
+        }
+        
+        tinyMCE.openWindow(template, {editor_id: editor_id, nid: nid, captionTitle: captionTitle, captionDesc: captionDesc, link: link, url: url, align: align, width: width, height: height, action: action});
+        return true;
+    }
+    // Pass to next handler in chain.
+    return false;
+  },
+
+  cleanup: function(type, content) {
+    switch (type) {
+      case 'insert_to_editor_dom':
+        break;
+
+      case 'get_from_editor_dom':
+        break;
+
+      case 'insert_to_editor':
+        // called when TinyMCE loads existing data or when updating code using
+        // Edit HTML Source plugin.
+        // Parse all drupalimage filter tags and replace them with image placeholders
+        var startPos = 0;
+        var index = 0;
+        while ((startPos = content.indexOf('[img_assist|', startPos)) != -1) {
+          // Find end of object
+          var endPos = content.indexOf(']', startPos);
+          var attribs = TinyMCE_DrupalImagePlugin._parsePipeAttributes(content.substring(startPos + 12, endPos));
+          endPos++;
+          
+          // TinyMCE_DrupalImagePlugin._parsePipeAttributes() parses the piped
+          // string completely, but in this case we want to keep the nid, title,
+          // and desc in piped format, so we have to rebuild a partial piped string.
+          // Backwards compatibility: Also parse link/url in the format link=url,foo.
+          var miscAttribs = 'nid=' + attribs['nid'] + '|title=' + attribs['title'] + '|desc=' + attribs['desc'];
+          if(attribs['link'].indexOf(',') != -1) {
+            link = attribs['link'].split(',', 2);
+            miscAttribs += '|link=' + link[0] + '|url=' + link[1];
+          }
+          else {
+            miscAttribs += '|link=' + attribs['link'];
+          }
+          if(typeof attribs['url'] != 'undefined') {
+            miscAttribs += '|url=' + attribs['url'];
+          }
+          // ordinarily piped strings wouldn't need to have HTML entities
+          // converted, but we are building an HTML tag that just happens to use
+          // a piped string as one of its' attribute values. The easiest way to
+          // take care of HTML entities is with the Javascript escape() function.
+          // It escapes more than necessary, but that's okay.  We'll use unescape()
+          // to go back when we need to.
+          miscAttribs = encodeURIComponent(miscAttribs);
+          
+          // Insert image.
+          var contentAfter = content.substring(endPos);
+          content = content.substring(0, startPos);
+          // Reference: these are the default parameters that are valid for the
+          // TinyMCE image tags:
+          // img[class|src|border=0|alt|title|hspace|vspace|width|height|align]
+          content += '<img src="' + (tinyMCE.getParam('theme_href') + '/images/spacer.gif') + '"';
+          content += ' width="' + attribs['width'] + '" height="' + attribs['height'] + '" align="' + attribs['align'] + '"';
+          content += ' alt="' + miscAttribs + '" title="' + miscAttribs + '" name="mceItemDrupalImage" class="mceItemDrupalImage" />';
+          content += contentAfter;
+          index++;
+          startPos++;
+        }
+        break;
+
+      case 'get_from_editor':
+        // Parse all image placeholders and replace them with drupalimage filter tags
+        var startPos = -1;
+        while ((startPos = content.indexOf('<img', startPos + 1)) != -1) {
+          var endPos = content.indexOf('/>', startPos);
+          var attribs = TinyMCE_DrupalImagePlugin._parseHTMLAttributes(content.substring(startPos + 4, endPos));
+          endPos += 2;
+          if (attribs['name'] != "mceItemDrupalImage") {
+            continue;
+          }
+
+          // Insert drupalimage filter code
+          // At this point all attribute values should have any pipes | or
+          // closing square brackets ] escaped with backslashes. When this
+          // filter code is parsed, it will look for the closing bracket to
+          // find the end and the pipe symbol to explode the rest of the
+          // attributes. However, since we just parsed from HTML tag, HTML
+          // entities should be unescaped at this time.
+          var miscAttribs = decodeURIComponent(attribs['alt']);
+
+          var contentBefore = content.substring(0, startPos);
+          var contentAfter = content.substring(endPos);
+          var drupalHTML = '';
+          drupalHTML += '[img_assist|' + miscAttribs + '|align=' + attribs['align'];
+          drupalHTML += '|width=' + attribs['width'] + '|height=' + attribs['height'] + ']';
+          content = contentBefore + drupalHTML + contentAfter;
+        }
+        break;
+    }
+    // Pass through to next handler in chain
+    return content;
+  },
+
+  handleNodeChange: function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
+    if (node == null) {
+      return;
+    }
+    do {
+      // This code looks at the name of the image to see if the drupalimage
+      // button should be selected. However, by default 'name' is not accepted
+      // by TinyMCE as a parameter for the img tag, so it must be added using
+      // the initialization string. As far as THIS code goes, it could look at
+      // 'className' instead, therefore avoiding this requirement, however the
+      // regular image button looks at the 'name' value to see if it starts with
+      // 'mce_'. If it does, it considers it an internal image and does not
+      // highlight the regular image button. If 'className' is used here
+      // instead, BOTH buttons highlight when a drupalimage is selected.
+      if (node.nodeName == 'IMG' && tinyMCE.getAttrib(node, 'class').indexOf('mceItemDrupalImage') == 0) {
+        tinyMCE.switchClass(editor_id + '_drupalimage', 'mceButtonSelected');
+        return true;
+      }
+    } while ((node = node.parentNode));
+    tinyMCE.switchClass(editor_id + '_drupalimage', 'mceButtonNormal');
+    return true;
+  },
+
+  // pipes | must be escaped with a backslash like this: \|
+  // note: values also cannot contain ] because the functions that call 
+  // this function use the ] symbol to find the end of the drupalimage filter code
+  _parsePipeAttributes : function(attribute_string) {
+    var attributes = new Array();
+    var keyvalue_arr = new Array();
+    // if it weren't for the escaping, the regExp string would look like this:
+    // var regExp = new RegExp('([a-zA-Z]*)=([^\|]*)', 'g');
+    var regExp = new RegExp('([a-zA-Z]*)=([^|](?:\\.|[^\\|]*)*)*', 'g');
+    var matches = attribute_string.match(regExp);
+    for (var i = 0; i < matches.length; i++ ) {
+      keyvalue_arr = matches[i].split('=');
+      attributes[keyvalue_arr[0]] = keyvalue_arr[1];
+    }
+    return attributes;
+  },
+  
+  /**
+   * Parses HTML attributes into a key=>value array.
+   * Take a look at the example strings and see how standard HTML entities
+   * within any value, such as the title and desc (which are combined in the
+   * alt tag as a piped string) need to be converted to: &quot; &amp; &lt; &gt;
+   *
+   * Simple example:
+   *     name="mceItemDrupalImage" width="200" height="150" src="/images/spacer.gif" 
+   *     alt="nid=123|title=My Photos|desc=" class="mceItemDrupalImage" align="right"
+   *
+   * Advanced example:
+   *     name="mceItemDrupalImage" width="200" height="150" src="/images/spacer.gif" 
+   *     alt="nid=123|title=&quot;To be or not to be&quot;|desc=That is the question."
+   *     class="mceItemDrupalImage" align="right"
+   *
+   * Any pipes | or closing brackets would also be a problem, not for this
+   * parsing function, but when parsing the pipe deliminated string. These
+   * characters need to be escaped with a backslash. Unlike the quotes, this
+   * cannot be accomplished automatically within this TinyMCE plugin. Any user
+   * or Drupal module that inserts drupalimage filter strings in a post, whether
+   * using TinyMCE or not, must backslash any pipes or closing brackets.
+   */
+  _parseHTMLAttributes : function(attribute_string) {
+    var attributes = new Array();
+    var innerMatches = new Array();
+    var regExp = '([a-zA-Z0-9]+)[\s]*=[\s]*"([^"](?:\\.|[^\\"]*)*)"';
+
+    // doesn't work without global (g)
+    var outerRegExp = new RegExp(regExp, 'g');
+    var outerMatches = attribute_string.match(outerRegExp);
+    // doesn't work with global (g)
+    var innerRegExp = new RegExp(regExp);
+    for (var i = 0; i < outerMatches.length; i++ ) {
+      innerMatches = innerRegExp.exec(outerMatches[i]);
+      attributes[innerMatches[1]] = innerMatches[2];
+    }
+    return attributes;
+  }
 };
 
-tinyMCE.addPlugin("drupalimage", TinyMCE_DrupalImagePlugin);
+tinyMCE.addPlugin('drupalimage', TinyMCE_DrupalImagePlugin);
 
Index: drupalimage/editor_plugin_src.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/img_assist/drupalimage/editor_plugin_src.js,v
retrieving revision 1.1.4.4
diff -u -p -r1.1.4.4 editor_plugin_src.js
--- drupalimage/editor_plugin_src.js	30 Sep 2007 23:05:20 -0000	1.1.4.4
+++ drupalimage/editor_plugin_src.js	23 Jun 2008 22:11:13 -0000
@@ -1,260 +1,248 @@
 // $Id: editor_plugin_src.js,v 1.1.4.4 2007/09/30 23:05:20 sun Exp $
-/* Import plugin specific language pack */
+
+// Import plugin language.
 tinyMCE.importPluginLanguagePack('drupalimage', 'en');
 
 var TinyMCE_DrupalImagePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'DrupalImage',
-			author : 'Benjamin Shell',
-			authorurl : 'http://www.benjaminshell.com',
-			infourl : 'http://drupal.org/project/img_assist',
-			version : tinyMCE.majorVersion +'.'+ tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function(inst) {
-		if (!tinyMCE.settings['drupalimage_skip_plugin_css'])
-			tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + '/plugins/drupalimage/drupalimage.css');
-	},
-
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case 'drupalimage':
-				return tinyMCE.getButtonHTML(cn, 'lang_drupalimage_desc', '{$pluginurl}/images/drupalimage.gif', 'mceDrupalImage');
-		}
-
-		return '';
-	},
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case 'mceDrupalImage':
-				var name = '';
-				var nid = '', alt = '', captionTitle = '', captionDesc = '', link = '', url = '', align = '', width = '', height = '';
-				var action   = 'insert';
-				var template = new Array();
-				var inst     = tinyMCE.getInstanceById(editor_id);
-				var focusElm = inst.getFocusElement();
-				
-				template['file']   = BASE_URL + 'index.php?q=img_assist/load/tinymce';
-				template['width']  = 600;
-				template['height'] = 350;
-				template['html']   = false;
-				
-				// Is selection a image
-				if (focusElm != null && focusElm.nodeName.toLowerCase() == 'img') {
-					name = tinyMCE.getAttrib(focusElm, 'class');
-
-					if (name.indexOf('mceItemDrupalImage') == -1)
-						// Not a DrupalImage
-						return true;
-
-					// Get the rest of the DrupalImage attributes
-					align  = tinyMCE.getAttrib(focusElm, 'align');
-					width  = tinyMCE.getAttrib(focusElm, 'width');
-					height = tinyMCE.getAttrib(focusElm, 'height');
-					// using 'title' because this doesn't seem to work with 'alt'
-					alt    = decodeURIComponent(tinyMCE.getAttrib(focusElm, 'title'));
-					// parse the deliminated attributes in the alt tag
-					var miscAttribs = TinyMCE_DrupalImagePlugin._parsePipeAttributes(alt);
-					nid          = miscAttribs['nid'];
-					captionTitle = miscAttribs['title'];
-					captionDesc  = miscAttribs['desc'];
-					link         = miscAttribs['link'];
-					if(typeof miscAttribs['url'] != 'undefined') {
-						url = miscAttribs['url'];
-					}
-					
-					action = 'update';
-				}
-				
-				tinyMCE.openWindow(template, {editor_id: editor_id, nid: nid, captionTitle: captionTitle, captionDesc: captionDesc, link: link, url: url, align: align, width: width, height: height, action: action});
-				return true;
-	   }
-
-	   // Pass to next handler in chain
-	   return false;
-	},
-	
-	cleanup : function(type, content) {
-		switch (type) {
-			case 'insert_to_editor_dom':
-				break;
-			
-			case 'get_from_editor_dom':
-				break;
-			
-			case 'insert_to_editor':
-				// called when TinyMCE loads existing data or when updating code using
-				// Edit HTML Source plugin.
-				// Parse all drupalimage filter tags and replace them with image placeholders
-				var startPos = 0;
-				var index = 0;
-				while ((startPos = content.indexOf('[img_assist|', startPos)) != -1) {
-					// Find end of object
-					var endPos = content.indexOf(']', startPos);
-					var attribs = TinyMCE_DrupalImagePlugin._parsePipeAttributes(content.substring(startPos + 12, endPos));
-					endPos++;
-					
-					// TinyMCE_DrupalImagePlugin._parsePipeAttributes() parses the piped
-					// string completely, but in this case we want to keep the nid, title,
-					// and desc in piped format, so we have to rebuild a partial piped string.
-					// Backwards compatibility: Also parse link/url in the format link=url,foo.
-					var miscAttribs = 'nid=' + attribs['nid'] + '|title=' + attribs['title'] + '|desc=' + attribs['desc'];
-					if(attribs['link'].indexOf(',') != -1) {
-						link = attribs['link'].split(',', 2);
-						miscAttribs += '|link=' + link[0] + '|url=' + link[1];
-					}
-					else {
-						miscAttribs += '|link=' + attribs['link'];
-					}
-					if(typeof attribs['url'] != 'undefined') {
-						miscAttribs += '|url=' + attribs['url'];
-					}
-					// ordinarily piped strings wouldn't need to have HTML entities
-					// converted, but we are building an HTML tag that just happens to use
-					// a piped string as one of its' attribute values. The easiest way to
-					// take care of HTML entities is with the Javascript escape() function.
-					// It escapes more than necessary, but that's okay.  We'll use unescape()
-					// to go back when we need to.
-					miscAttribs = encodeURIComponent(miscAttribs);
-					
-					// Insert image
-					var contentAfter = content.substring(endPos);
-					content = content.substring(0, startPos);
-					// Reference: these are the default parameters that are valid for the
-					// TinyMCE image tags:
-					// img[class|src|border=0|alt|title|hspace|vspace|width|height|align]
-					content += '<img src="' + (tinyMCE.getParam('theme_href') + '/images/spacer.gif') + '"';
-					content += ' width="' + attribs['width'] + '" height="' + attribs['height'] + '" align="' + attribs['align'] + '"';
-					content += ' alt="' + miscAttribs + '" title="' + miscAttribs + '" name="mceItemDrupalImage" class="mceItemDrupalImage" />';
-					content += contentAfter;
-					index++;
-					
-					startPos++;
-				}
-				break;
-
-			case 'get_from_editor':
-				// Called when TinyMCE exits or when the Edit HTML Source plugin is clicked
-				// Parse all image placeholders and replace them with drupalimage filter tags
-				var startPos = -1;
-				while ((startPos = content.indexOf('<img', startPos+1)) != -1) {
-					var endPos = content.indexOf('/>', startPos);
-					var attribs = TinyMCE_DrupalImagePlugin._parseHTMLAttributes(content.substring(startPos + 4, endPos));
-					endPos += 2;
-					
-					// Is not drupalimage, skip it
-					if (attribs['name'] != "mceItemDrupalImage") {
-						continue;
-					}
-					
-					// Insert drupalimage filter code
-					// At this point all attribute values should have any pipes | or
-					// closing square brackets ] escaped with backslashes. When this
-					// filter code is parsed, it will look for the closing bracket to
-					// find the end and the pipe symbol to explode the rest of the
-					// attributes. However, since we just parsed from HTML tag, HTML
-					// entities should be unescaped at this time.
-					var miscAttribs = decodeURIComponent(attribs['alt']);
-					
-					var contentBefore = content.substring(0, startPos);
-					var contentAfter = content.substring(endPos);
-					var drupalHTML = '';
-					drupalHTML += '[img_assist|' + miscAttribs + '|align=' + attribs['align'];
-					drupalHTML += '|width=' + attribs['width'] + '|height=' + attribs['height'] + ']';
-					content = contentBefore + drupalHTML + contentAfter;
-				}
-				break;
-		}
-
-		// Pass through to next handler in chain
-		return content;
-	},
-	
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (node == null)
-			return;
-
-		do {
-			// This code looks at the name of the image to see if the drupalimage
-			// button should be selected. However, by default 'name' is not accepted
-			// by TinyMCE as a parameter for the img tag, so it must be added using
-			// the initialization string. As far as THIS code goes, it could look at
-			// 'className' instead, therefore avoiding this requirement, however the
-			// regular image button looks at the 'name' value to see if it starts with
-			// 'mce_'. If it does, it considers it an internal image and does not
-			// highlight the regular image button. If 'className' is used here
-			// instead, BOTH buttons highlight when a drupalimage is selected.
-			if (node.nodeName == 'IMG' && tinyMCE.getAttrib(node, 'class').indexOf('mceItemDrupalImage') == 0) {
-				tinyMCE.switchClass(editor_id + '_drupalimage', 'mceButtonSelected');
-				return true;
-			}
-		} while ((node = node.parentNode));
-
-		tinyMCE.switchClass(editor_id + '_drupalimage', 'mceButtonNormal');
-
-		return true;
-	},
-	
-	// pipes | must be escaped with a backslash like this: \|
-	// note: values also cannot contain ] because the functions that call 
-	// this function use the ] symbol to find the end of the drupalimage filter code
-	_parsePipeAttributes : function(attribute_string) {
-		var attributes = new Array();
-		var keyvalue_arr = new Array();
-		// if it weren't for the escaping, the regExp string would look like this:
-		// var regExp = new RegExp('([a-zA-Z]*)=([^\|]*)', 'g');
-		var regExp = new RegExp('([a-zA-Z]*)=([^|](?:\\.|[^\\|]*)*)*', 'g');
-		var matches = attribute_string.match(regExp);
-		for (var i = 0; i < matches.length; i++ ) {
-			keyvalue_arr = matches[i].split('=');
-			attributes[keyvalue_arr[0]] = keyvalue_arr[1];
-		}
-		return attributes;
-	},
-	
-	/* 
-	 * Parses HTML attributes into a key=>value array.
-	 * Take a look at the example strings and see how standard HTML entities
-	 * within any value, such as the title and desc (which are combined in the
-	 * alt tag as a piped string) need to be converted to: &quot; &amp; &lt; &gt;
-	 *
-	 * Simple example:
-	 *     name="mceItemDrupalImage" width="200" height="150" src="/images/spacer.gif" 
-	 *     alt="nid=123|title=My Photos|desc=" class="mceItemDrupalImage" align="right"
-	 *
-	 * Advanced example:
-	 *     name="mceItemDrupalImage" width="200" height="150" src="/images/spacer.gif" 
-	 *     alt="nid=123|title=&quot;To be or not to be&quot;|desc=That is the question."
-	 *     class="mceItemDrupalImage" align="right"
-	 *
-	 * Any pipes | or closing brackets would also be a problem, not for this
-	 * parsing function, but when parsing the pipe deliminated string. These
-	 * characters need to be escaped with a backslash. Unlike the quotes, this
-	 * cannot be accomplished automatically within this TinyMCE plugin. Any user
-	 * or Drupal module that inserts drupalimage filter strings in a post, whether
-	 * using TinyMCE or not, must backslash any pipes or closing brackets.
-	*/
-	_parseHTMLAttributes : function(attribute_string) {
-		var attributes = new Array();
-		var innerMatches = new Array();
-		var regExp = '([a-zA-Z0-9]+)[\s]*=[\s]*"([^"](?:\\.|[^\\"]*)*)"';
-	
-		// doesn't work without global (g)
-		var outerRegExp = new RegExp(regExp, 'g');
-		var outerMatches = attribute_string.match(outerRegExp);
-		// doesn't work with global (g)
-		var innerRegExp = new RegExp(regExp);
-		for (var i = 0; i < outerMatches.length; i++ ) {
-			innerMatches = innerRegExp.exec(outerMatches[i]);
-			attributes[innerMatches[1]] = innerMatches[2];
-		}
-		return attributes;
-	}
+  getInfo: function() {
+    return {
+      longname: 'Image Assist',
+      author: 'Benjamin Shell',
+      authorurl: 'http://www.benjaminshell.com',
+      infourl : 'http://drupal.org/project/img_assist'
+    };
+  },
+
+  initInstance : function(inst) {
+    if (!tinyMCE.settings['drupalimage_skip_plugin_css'])
+      tinyMCE.importCSS(inst.getDoc(), this.baseURL + '/drupalimage.css');
+  },
+
+  getControlHTML: function (control_name) {
+    switch (control_name) {
+      case 'drupalimage':
+        return tinyMCE.getButtonHTML(control_name, 'lang_drupalimage_desc', '{$pluginurl}/images/drupalimage.gif', 'mceDrupalImage');
+    }
+    return '';
+  },
+
+  execCommand: function(editor_id, element, command, user_interface, value) {
+    switch (command) {
+      case 'mceDrupalImage':
+        var name = '';
+        var nid = '', alt = '', captionTitle = '', captionDesc = '', link = '', url = '', align = '', width = '', height = '';
+        var action   = 'insert';
+        var template = new Array();
+        var inst = tinyMCE.getInstanceById(editor_id);
+        var focusElm = inst.getFocusElement();
+
+        template['file']   = BASE_URL + 'index.php?q=img_assist/load/tinymce';
+        template['width']  = 600;
+        template['height'] = 350;
+        template['html']   = false;
+
+        // Check whether selection is an image and belongs to this plugin.
+        if (focusElm != null && focusElm.nodeName.toLowerCase() == 'img') {
+          name = tinyMCE.getAttrib(focusElm, 'class');
+
+          if (name.indexOf('mceItemDrupalImage') == -1)
+            return true;
+
+          // Get the rest of the DrupalImage attributes
+          align  = tinyMCE.getAttrib(focusElm, 'align');
+          width  = tinyMCE.getAttrib(focusElm, 'width');
+          height = tinyMCE.getAttrib(focusElm, 'height');
+          // using 'title' because this doesn't seem to work with 'alt'
+          alt    = decodeURIComponent(tinyMCE.getAttrib(focusElm, 'title'));
+          // parse the deliminated attributes in the alt tag
+          var miscAttribs = TinyMCE_DrupalImagePlugin._parsePipeAttributes(alt);
+          nid          = miscAttribs['nid'];
+          captionTitle = miscAttribs['title'];
+          captionDesc  = miscAttribs['desc'];
+          link         = miscAttribs['link'];
+          if(typeof miscAttribs['url'] != 'undefined') {
+            url = miscAttribs['url'];
+          }
+          action = 'update';
+        }
+        
+        tinyMCE.openWindow(template, {editor_id: editor_id, nid: nid, captionTitle: captionTitle, captionDesc: captionDesc, link: link, url: url, align: align, width: width, height: height, action: action});
+        return true;
+    }
+    // Pass to next handler in chain.
+    return false;
+  },
+
+  cleanup: function(type, content) {
+    switch (type) {
+      case 'insert_to_editor_dom':
+        break;
+
+      case 'get_from_editor_dom':
+        break;
+
+      case 'insert_to_editor':
+        // called when TinyMCE loads existing data or when updating code using
+        // Edit HTML Source plugin.
+        // Parse all drupalimage filter tags and replace them with image placeholders
+        var startPos = 0;
+        var index = 0;
+        while ((startPos = content.indexOf('[img_assist|', startPos)) != -1) {
+          // Find end of object
+          var endPos = content.indexOf(']', startPos);
+          var attribs = TinyMCE_DrupalImagePlugin._parsePipeAttributes(content.substring(startPos + 12, endPos));
+          endPos++;
+          
+          // TinyMCE_DrupalImagePlugin._parsePipeAttributes() parses the piped
+          // string completely, but in this case we want to keep the nid, title,
+          // and desc in piped format, so we have to rebuild a partial piped string.
+          // Backwards compatibility: Also parse link/url in the format link=url,foo.
+          var miscAttribs = 'nid=' + attribs['nid'] + '|title=' + attribs['title'] + '|desc=' + attribs['desc'];
+          if(attribs['link'].indexOf(',') != -1) {
+            link = attribs['link'].split(',', 2);
+            miscAttribs += '|link=' + link[0] + '|url=' + link[1];
+          }
+          else {
+            miscAttribs += '|link=' + attribs['link'];
+          }
+          if(typeof attribs['url'] != 'undefined') {
+            miscAttribs += '|url=' + attribs['url'];
+          }
+          // ordinarily piped strings wouldn't need to have HTML entities
+          // converted, but we are building an HTML tag that just happens to use
+          // a piped string as one of its' attribute values. The easiest way to
+          // take care of HTML entities is with the Javascript escape() function.
+          // It escapes more than necessary, but that's okay.  We'll use unescape()
+          // to go back when we need to.
+          miscAttribs = encodeURIComponent(miscAttribs);
+          
+          // Insert image.
+          var contentAfter = content.substring(endPos);
+          content = content.substring(0, startPos);
+          // Reference: these are the default parameters that are valid for the
+          // TinyMCE image tags:
+          // img[class|src|border=0|alt|title|hspace|vspace|width|height|align]
+          content += '<img src="' + (tinyMCE.getParam('theme_href') + '/images/spacer.gif') + '"';
+          content += ' width="' + attribs['width'] + '" height="' + attribs['height'] + '" align="' + attribs['align'] + '"';
+          content += ' alt="' + miscAttribs + '" title="' + miscAttribs + '" name="mceItemDrupalImage" class="mceItemDrupalImage" />';
+          content += contentAfter;
+          index++;
+          startPos++;
+        }
+        break;
+
+      case 'get_from_editor':
+        // Parse all image placeholders and replace them with drupalimage filter tags
+        var startPos = -1;
+        while ((startPos = content.indexOf('<img', startPos + 1)) != -1) {
+          var endPos = content.indexOf('/>', startPos);
+          var attribs = TinyMCE_DrupalImagePlugin._parseHTMLAttributes(content.substring(startPos + 4, endPos));
+          endPos += 2;
+          if (attribs['name'] != "mceItemDrupalImage") {
+            continue;
+          }
+
+          // Insert drupalimage filter code
+          // At this point all attribute values should have any pipes | or
+          // closing square brackets ] escaped with backslashes. When this
+          // filter code is parsed, it will look for the closing bracket to
+          // find the end and the pipe symbol to explode the rest of the
+          // attributes. However, since we just parsed from HTML tag, HTML
+          // entities should be unescaped at this time.
+          var miscAttribs = decodeURIComponent(attribs['alt']);
+
+          var contentBefore = content.substring(0, startPos);
+          var contentAfter = content.substring(endPos);
+          var drupalHTML = '';
+          drupalHTML += '[img_assist|' + miscAttribs + '|align=' + attribs['align'];
+          drupalHTML += '|width=' + attribs['width'] + '|height=' + attribs['height'] + ']';
+          content = contentBefore + drupalHTML + contentAfter;
+        }
+        break;
+    }
+    // Pass through to next handler in chain
+    return content;
+  },
+
+  handleNodeChange: function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
+    if (node == null) {
+      return;
+    }
+    do {
+      // This code looks at the name of the image to see if the drupalimage
+      // button should be selected. However, by default 'name' is not accepted
+      // by TinyMCE as a parameter for the img tag, so it must be added using
+      // the initialization string. As far as THIS code goes, it could look at
+      // 'className' instead, therefore avoiding this requirement, however the
+      // regular image button looks at the 'name' value to see if it starts with
+      // 'mce_'. If it does, it considers it an internal image and does not
+      // highlight the regular image button. If 'className' is used here
+      // instead, BOTH buttons highlight when a drupalimage is selected.
+      if (node.nodeName == 'IMG' && tinyMCE.getAttrib(node, 'class').indexOf('mceItemDrupalImage') == 0) {
+        tinyMCE.switchClass(editor_id + '_drupalimage', 'mceButtonSelected');
+        return true;
+      }
+    } while ((node = node.parentNode));
+    tinyMCE.switchClass(editor_id + '_drupalimage', 'mceButtonNormal');
+    return true;
+  },
+
+  // pipes | must be escaped with a backslash like this: \|
+  // note: values also cannot contain ] because the functions that call 
+  // this function use the ] symbol to find the end of the drupalimage filter code
+  _parsePipeAttributes : function(attribute_string) {
+    var attributes = new Array();
+    var keyvalue_arr = new Array();
+    // if it weren't for the escaping, the regExp string would look like this:
+    // var regExp = new RegExp('([a-zA-Z]*)=([^\|]*)', 'g');
+    var regExp = new RegExp('([a-zA-Z]*)=([^|](?:\\.|[^\\|]*)*)*', 'g');
+    var matches = attribute_string.match(regExp);
+    for (var i = 0; i < matches.length; i++ ) {
+      keyvalue_arr = matches[i].split('=');
+      attributes[keyvalue_arr[0]] = keyvalue_arr[1];
+    }
+    return attributes;
+  },
+  
+  /**
+   * Parses HTML attributes into a key=>value array.
+   * Take a look at the example strings and see how standard HTML entities
+   * within any value, such as the title and desc (which are combined in the
+   * alt tag as a piped string) need to be converted to: &quot; &amp; &lt; &gt;
+   *
+   * Simple example:
+   *     name="mceItemDrupalImage" width="200" height="150" src="/images/spacer.gif" 
+   *     alt="nid=123|title=My Photos|desc=" class="mceItemDrupalImage" align="right"
+   *
+   * Advanced example:
+   *     name="mceItemDrupalImage" width="200" height="150" src="/images/spacer.gif" 
+   *     alt="nid=123|title=&quot;To be or not to be&quot;|desc=That is the question."
+   *     class="mceItemDrupalImage" align="right"
+   *
+   * Any pipes | or closing brackets would also be a problem, not for this
+   * parsing function, but when parsing the pipe deliminated string. These
+   * characters need to be escaped with a backslash. Unlike the quotes, this
+   * cannot be accomplished automatically within this TinyMCE plugin. Any user
+   * or Drupal module that inserts drupalimage filter strings in a post, whether
+   * using TinyMCE or not, must backslash any pipes or closing brackets.
+   */
+  _parseHTMLAttributes : function(attribute_string) {
+    var attributes = new Array();
+    var innerMatches = new Array();
+    var regExp = '([a-zA-Z0-9]+)[\s]*=[\s]*"([^"](?:\\.|[^\\"]*)*)"';
+
+    // doesn't work without global (g)
+    var outerRegExp = new RegExp(regExp, 'g');
+    var outerMatches = attribute_string.match(outerRegExp);
+    // doesn't work with global (g)
+    var innerRegExp = new RegExp(regExp);
+    for (var i = 0; i < outerMatches.length; i++ ) {
+      innerMatches = innerRegExp.exec(outerMatches[i]);
+      attributes[innerMatches[1]] = innerMatches[2];
+    }
+    return attributes;
+  }
 };
 
-tinyMCE.addPlugin("drupalimage", TinyMCE_DrupalImagePlugin);
+tinyMCE.addPlugin('drupalimage', TinyMCE_DrupalImagePlugin);
 
