--- ./graphviz_filter.module.orig	2010-04-14 04:29:03.218466483 +0200
+++ ./graphviz_filter.module	2010-04-21 03:37:48.000000000 +0200
@@ -9,6 +9,8 @@
 
 define('GRAPHVIZ_REGEX', '/\[graphviz\](.*?)\[\/graphviz\]/si');
 define('GRAPHVIZ_FILTER_SUPPORTED_COMMANDS', 'dot, neato, twopi, fdp, circo');
+define('GRAPHVIZ_FILTER_FILES_PATH', file_directory_path() .'/graphviz');
+
 
 /**
  * Implementation of hook_requirements().
@@ -29,6 +31,50 @@
       'severity' => $return != 0 ? REQUIREMENT_ERROR : REQUIREMENT_OK,
     );
 
+    // Check for presence respectively download canvis javascript files.
+    $errors = 0;
+    $requirements['canviz'] = array('title' => $t('Canviz, Excanvas and Prototype Javascript files'));
+    $canviz_path = drupal_get_path('module', 'graphviz_filter') .'/canviz';
+    if (file_check_directory($canviz_path, FILE_CREATE_DIRECTORY, 'canviz')) {
+      $js_urls = array(
+        'canviz.js' => 'http://canviz.googlecode.com/svn/canviz/trunk/canviz.js',
+        'excanvas.js' => 'http://explorercanvas.googlecode.com/svn/trunk/excanvas.js',
+        'path.js' => 'http://canviz.googlecode.com/svn/path/trunk/libs/path.js',
+        'prototype.js' => 'http://prototypejs.org/assets/2010/4/1/prototype.js',
+      );
+      foreach ($js_urls as $filename => $url) {
+        $filepath = "$canviz_path/$filename";
+        if (!is_file($filepath)) {
+          if ($file = fopen($filepath, 'w')) {
+            // download javascript
+            $result = drupal_http_request($url);
+            if (in_array($result->code, array(200, 302, 307))) {
+              //replace $() with $$$() for jquery compability
+              fwrite($file, preg_replace('/(?<!\$)\$\(/', '$$$(', $result->data));
+              fclose($file);
+            }
+            else {
+              $errors++;
+            }
+          }
+          else {
+            $errors++;
+          }
+        }
+      }
+    }
+    else {
+      $errors++;
+    }
+    if ($errors) {
+      $requirements['canviz']['value'] = $t('Javascript files could not be downloaded to !path. MIST.', array('!path' => $canviz_path));
+      $requirements['canviz']['severity'] = REQUIREMENT_ERROR;
+    }
+    else {
+      $requirements['canviz']['value'] = $t('Javascript files successfully downloaded to !path.', array('!path' => $canviz_path));
+      $requirements['canviz']['severity'] = REQUIREMENT_OK;
+    }
+
     // Check for availability of PEAR::Image_GraphViz.
     $pear = (bool)(($handle = @fopen(_graphviz_create_filepath(variable_get('graphviz_filter_pear_path', ''), 'Image/GraphViz.php'), 'r', TRUE)) && fclose($handle));
     $requirements['pear'] = array(
@@ -203,7 +249,7 @@
   }
 
   // Create a temporary file with the DOT script.
-  $outdir = file_directory_path() .'/graphviz';
+  $outdir = GRAPHVIZ_FILTER_FILES_PATH;
   file_check_directory($outdir, FILE_CREATE_DIRECTORY);
   $inpath = file_create_path($outdir .'/'. md5($text) .'.dot');
   if (!file_exists($inpath)) {
@@ -221,16 +267,17 @@
       watchdog('graphviz filter', $msg, $arg, WATCHDOG_ERROR);
       continue;
     }
+
     $outpath = file_create_path($outdir .'/'. md5($text) .'.out.'. $formats[$format]['format']);
     if (file_exists($outpath) || _graphviz_filter_render($inpath, $outpath, $formats[$format]['format'], $args['command']['value'])) {
-      $output .= '<div class="graphviz graphviz-"'. $format .'>';
+      $output .= '<span class="graphviz graphviz-'. $format .'">';
       if ($args['link-output']['value']) {
         $output .= l(t($args['title']['value']), file_create_url($outpath), array('attributes' => array('class' => 'graphviz-link-output')));
       }
       else {
         $output .= module_invoke($formats[$format]['module'], 'graphviz_render', $inpath, $outpath, $format, $args);
       }
-      $output .= '</div>';
+      $output .= '</span>';
       if ($args['link-input']['value']) {
         $output .= '<div class="graphviz graphviz-"'. $format .'>';
         $output .= l(t('Download input script for %title', array('%title' => $args['title']['value'])), file_create_url($inpath),
@@ -349,36 +396,71 @@
     'description' => t('Fully-laid-out DOT rendering of the graph.'),
     'format' => 'dot',
   );
+  $formats['canviz'] = array(
+    'description' => t('Dynamic client-side graph rendering via JavaScript and Canviz'),
+    'format' => 'xdot',
+  );
   return $formats;
 }
 
 /**
+ * Loads Canviz (Javascript GraphViz renderer) JS and dependencies.
+ */
+function graphviz_filter_add_canviz_js() {
+  static $canviz_added = FALSE;
+
+  if (!$canviz_added) {
+    $path = drupal_get_path('module', 'graphviz_filter');
+    drupal_add_js($path .'/canviz/excanvas.js');
+    drupal_add_js($path .'/canviz/prototype.js');
+    drupal_add_js($path .'/canviz/path.js');
+    drupal_add_js($path .'/canviz/canviz.js');
+    drupal_add_js(array('graphviz_filter' => array('files_path' => GRAPHVIZ_FILTER_FILES_PATH)), 'setting');
+    $js = <<<JS
+Drupal.behaviors.canvizInit = function (context) {
+  $('.canviz:not(.canviz-processed)').each(function() {
+    var id = $(this).attr('id');
+    var path = '/' +  Drupal.settings.graphviz_filter.files_path;
+    new Canviz(id, path + '/' + id);
+  }).addClass('canviz-processed');
+}
+JS;
+    drupal_add_js($js, 'inline', 'footer');
+    $canviz_added = TRUE;
+  }
+}
+
+/**
  * Implementation of hook_graphviz_render().
  */
 function graphviz_filter_graphviz_render($inpath, $outpath, $format, $args) {
-  if ($format == 'dot' ) {
-    $output = '<pre>' . file_get_contents($outpath) . '</pre>' . "\n";
-  }
-  else {
-    $output = '<img src="'. file_create_url($outpath) .'" title="'. check_plain(t($args['title']['value'])) .'" ';
-    $mappath = file_create_path($outpath .'.map');
-    if ($args['imagemap']['value'] && _graphviz_filter_render($inpath, $mappath, 'cmapx', $args['command']['value'])) {
-      $map = file_get_contents($mappath);
-      $id = 'G';
-      $match = array();
-      if (preg_match('/<map[^>]*id\s*=\s*"(.*?)"/', $map, $match)) {
-        $id = $match[1];
+  switch ($format) {
+    case 'dot':
+      return '<pre>' . file_get_contents($outpath) . "</pre>\n";
+    case 'canviz':
+      graphviz_filter_add_canviz_js();
+      $filename = basename($outpath);
+      return '<div id="debug_output"></div><div id="'. $filename .'" class="canviz"></div>';
+    default:
+      $output = '<img src="'. file_create_url($outpath) .'" title="'. check_plain(t($args['title']['value'])) .'" ';
+      $mappath = file_create_path($outpath .'.map');
+      if ($args['imagemap']['value'] && _graphviz_filter_render($inpath, $mappath, 'cmapx', $args['command']['value'])) {
+        $map = file_get_contents($mappath);
+        $id = 'G';
+        $match = array();
+        if (preg_match('/<map[^>]*id\s*=\s*"(.*?)"/', $map, $match)) {
+          $id = $match[1];
+        }
+        $output .= 'usemap="#'. $id .'" />';
+        $output .= $map;
+        $output .= "\n";
+      }
+      else {
+        $output .= ' />';
       }
-      $output .= 'usemap="#'. $id .'" />';
-      $output .= $map;
       $output .= "\n";
-    }
-    else {
-      $output .= ' />';
-    }
-    $output .= "\n";
+      return $output;
   }
-  return $output;
 }
 
 /**
