diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 90f751a..ab15281 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -3,6 +3,14 @@ JavaScript callback handler x.x-x.x, xxxx-xx-xx
 -----------------------------------------------
 
 
+JavaScript callback handler 7.x-2.x, xxxx-xx-xx
+-----------------------------------------------
+
+Rework of the 6.x version to make it work with Drupal 7 with some addition 
+- enabled the js url's to be used in autocomplete
+- added api documentation
+
+
 JavaScript callback handler 6.x-2.x, xxxx-xx-xx
 -----------------------------------------------
 Complete rewrite of JS callback handler.  Added a requirement for hook_js() in
diff --git a/README.txt b/README.txt
index 4fdee3b..3be094b 100644
--- a/README.txt
+++ b/README.txt
@@ -116,3 +116,12 @@ Specialized in consulting and planning of Drupal powered sites, UNLEASHED
 MIND offers installation, development, theming, customization, and hosting
 to get you started. Visit http://www.unleashedmind.com for more information.
 
+- Drupal 7 -
+
+Authors:
+* Michiel Nugter (michielnugter) - http://drupal.org/user/1023784
+
+The Drupal 7 update has been sponsored by SYNETIC.
+Full service Drupal specialist. From custom made webapplications to content 
+management systems, intranet and e-commerce shops. Visit http://www.synetic.nl 
+for more information.
diff --git a/js.api.php b/js.api.php
new file mode 100644
index 0000000..0ef2c44
--- /dev/null
+++ b/js.api.php
@@ -0,0 +1,99 @@
+<?php 
+/**
+ * @file
+ * This file contains no working PHP code; it exists to provide additional documentation
+ * for doxygen as well as to document hooks in the standard Drupal manner.
+ */
+
+/**
+ * @mainpage JS API Manual
+ * 
+ * JavaScript callback handler is an interim solution for high-performance querying
+ * of contents including (but not limited to) AHAH, AJAX, JSON, XML, etc.
+ * 
+ * -- INSTALLATION --
+ * - Install as usual, see http://drupal.org/node/70151 for further information.
+ * - Copy js.php to the root directory of your Drupal installation.
+ * - Enable clean URLs.
+ * - Add the following lines in front of the existing RewriteRules in your
+ *   .htaccess file:
+ * <code>
+ * # Rewrite JavaScript callback URLs of the form 'js.php?q=x'.
+ * RewriteCond %{REQUEST_FILENAME} !-f
+ * RewriteCond %{REQUEST_FILENAME} !-d
+ * RewriteCond %{REQUEST_URI} ^\/js\/.*
+ * RewriteRule ^(.*)$ js.php?q=$1 [L,QSA]
+ * </code>
+ * 
+ * -- DEVELOPER INFORMATION --
+ * 
+ * This module requires an Apache RewriteRule in your .htaccess file to point all
+ * paths starting with js/ to js.php rather than index.php.  The 2nd argument
+ * following js/ determines the implementing module, which must implement hook_js()
+ * for security reasons.  Apart from security, modules may also specify another
+ * bootstrap level than the default DRUPAL_BOOTSTRAP_PATH, and additionally
+ * required includes files and module dependencies to load.
+ * 
+ * As an example, we'll let example.module expose its function
+ * example_somefunction() to js.php. Its hook_js() implementation might look like
+ * this:
+ * 
+ * <code>
+ * function example_js() {
+ *   return array(
+ *     'somefunction' => array(
+ *       'callback' => 'example_somefunction',
+ *       'includes' => array('theme', 'unicode'),
+ *       'dependencies' => array('locale', 'filter', 'user'),
+ *     ),
+ *   );
+ * }
+ * </code>
+ * 
+ * The hook_js() implementation above makes JS accept the following URL:
+ * 
+ *   http://example.com/js/example/somefunction.
+ *                         ^       ^
+ *            module name -|       |
+ *                 info array key -|
+ * 
+ * When called, it loads the requested include files and modules and calls the
+ * callback function.
+ * 
+ * Note that it is wise to also register a corresponding menu path in hook_menu()
+ * to provide fallback functionality when js.php is not available:
+ * 
+ * <code>
+ *   $items[] = array(
+ *     'path' => 'js/example/somefunction',
+ *     'callback' => 'example_somefunction',
+ *     'type' => MENU_CALLBACK,
+ *   );
+ * </code>
+ * 
+ * Please note that js.php does NOT perform access checks like Drupal's menu
+ * system.  If required, each callback function needs to do this on its own.
+ * 
+ * js.php outputs the return value of the callback function using drupal_json_output().
+ * To use a custom output format, output the data on your own and exit()
+ * afterwards, or simply return nothing.
+ */
+
+/**
+* Register JS callbacks.
+*
+* @return
+*   An array of callbacks with the following possible keys for each callback:
+*   - callback: (required) The function to call to display the results when an ajax call occurs on this path
+*   - includes: (optional) Load aditional files from the /includes directory
+*   - dependancies: (optional) Load additional modules for this callback
+*/
+function hook_js() {
+  return array(
+    'somefunction' => array(
+      'callback' => 'example_somefunction',
+      'includes' => array('includefile1', 'includefile2'),
+      'dependencies' => array('module1', 'module2'),
+    ),
+  );
+}
diff --git a/js.info b/js.info
index a7e8e11..8626a12 100644
--- a/js.info
+++ b/js.info
@@ -1,2 +1,9 @@
 name = JavaScript callback handler
 description = A high-performance JavaScript callback handler for 3rd party modules.
+
+; Information added by drupal.org packaging script on 2011-02-25
+version = "7.x-2.x-dev"
+core = "7.x"
+project = "js"
+datestamp = "1298619508"
+
diff --git a/js.module b/js.module
index 60a3f57..bc9a241 100644
--- a/js.module
+++ b/js.module
@@ -1,9 +1,27 @@
 <?php
-
 /**
  * @file
  * JavaScript callback handler module.
- *
- * Dummy file needed for Drupal's module system.
  */
 
+/**
+ * Implements hook_menu()
+ * 
+ * Add a basic menu callback for each module implementing a js hook. This makes 
+ * Drupal recognize the urls as valid so that they can be used in e.g. 
+ * autocomplete.
+ */
+function js_menu() {
+  //Get all modules implementing the js hook
+  $modules = module_implements('js');
+  
+  //Add menu callback for each module with the js prefix.
+  foreach($modules AS $module) {
+    $items['js/'.$module] = array(
+      'page callback' => 'drupal_access_denied',
+      'access arguments' => array('access content'),
+      'type' => MENU_CALLBACK
+    );
+  }
+  return $items;
+}
diff --git a/js.php b/js.php
index a922d28..8344b57 100644
--- a/js.php
+++ b/js.php
@@ -1,37 +1,54 @@
 <?php
-
 /**
  * @file
  * Callback page that serves custom JavaScript requests on a Drupal installation.
  */
 
 /**
- * @name JavaScript callback status codes.
- * @{
- * Status codes for JavaScript callbacks.
- *
- * @todo Use regular defines from menu.inc.
+ * @var The Drupal root
  */
+define('DRUPAL_ROOT', getcwd());
 
-define('JS_FOUND', 1);
-define('JS_NOT_FOUND', 2);
-define('JS_ACCESS_DENIED', 3);
-define('JS_SITE_OFFLINE', 4);
-
 /**
- * @} End of "Menu status codes".
+ * @name Required core files
+ * @{
+ * The minimal core files required to be able to run a js request
+ */
+require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
+require_once DRUPAL_ROOT . '/includes/common.inc';
+require_once DRUPAL_ROOT . '/includes/locale.inc';
+require_once DRUPAL_ROOT . '/includes/module.inc';
+require_once DRUPAL_ROOT . '/includes/path.inc';
+require_once DRUPAL_ROOT . '/includes/unicode.inc';
+require_once DRUPAL_ROOT . '/includes/file.inc';
+require_once DRUPAL_ROOT . '/includes/menu.inc';
+/**
+ * @} End of "Required core files".
  */
 
-require_once './includes/bootstrap.inc';
-drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);
-require_once './includes/common.inc';
-require_once './includes/locale.inc';
+//Do basic bootstrap to make sure the database can be accessed
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
 
-// Prevent caching of JS output.
-$GLOBALS['conf']['cache'] = FALSE;
 // Prevent Devel from hi-jacking our output in any case.
 $GLOBALS['devel_shutdown'] = FALSE;
 
+$return = js_execute_callback();
+
+// Menu status constants are integers; page content is a string.
+if (is_int($return)) {
+  //Make sure the full bootstrap has ran
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+  
+  //Deliver error page
+  drupal_deliver_page($return);
+}
+elseif (isset($return)) {
+  // If JavaScript callback did not exit, print any value (including an empty
+  // string) except NULL or undefined:
+  drupal_json_output($return);
+}
+
 /**
  * Loads the requested module and executes the requested callback.
  *
@@ -39,8 +56,6 @@ $GLOBALS['devel_shutdown'] = FALSE;
  *   The callback function's return value or one of the JS_* constants.
  */
 function js_execute_callback() {
-  global $locale;
-
   $args = explode('/', $_GET['q']);
 
   // Strip first argument 'js'.
@@ -49,13 +64,14 @@ function js_execute_callback() {
   // Determine module to load.
   $module = check_plain(array_shift($args));
   if (!$module || !drupal_load('module', $module)) {
-    return JS_ACCESS_DENIED;
+
+    return MENU_ACCESS_DENIED;
   }
 
   // Get info hook function name.
   $function = $module .'_js';
   if (!function_exists($function)) {
-    return JS_NOT_FOUND;
+    return MENU_NOT_FOUND;
   }
 
   // Get valid callbacks.
@@ -63,7 +79,7 @@ function js_execute_callback() {
 
   $callback = check_plain(array_shift($args));
   if (!isset($valid_callbacks[$callback]) || !function_exists($valid_callbacks[$callback]['callback'])) {
-    return JS_NOT_FOUND;
+    return MENU_NOT_FOUND;
   }
 
   $info = $valid_callbacks[$callback];
@@ -77,9 +93,10 @@ function js_execute_callback() {
 
   if (!$full_boostrap) {
     // The following mimics the behavior of _drupal_bootstrap_full().
+    //The difference is that not all modules and includes are loaded
     // @see _drupal_bootstrap_full(), common.inc
 
-    // Load required include files.
+    // Load required include files based on the callback
     if (isset($info['includes']) && is_array($info['includes'])) {
       foreach ($info['includes'] as $include) {
         if (file_exists("./includes/$include.inc")) {
@@ -87,25 +104,23 @@ function js_execute_callback() {
         }
       }
     }
-    // Always load locale.inc.
-    require_once "./includes/locale.inc";
 
-    // Set the Drupal custom error handler.
-    set_error_handler('drupal_error_handler');
     // Detect string handling method.
-    if (function_exists('unicode_check')) {
-      unicode_check();
-    }
+    unicode_check();
+
     // Undo magic quotes.
     fix_gpc_magic();
 
+    // Make sure all stream wrappers are registered.
+    file_get_stream_wrappers();
+
     // Load required modules.
     $modules = array($module => 0);
     if (isset($info['dependencies']) && is_array($info['dependencies'])) {
-      // Intersect list with active modules to avoid loading uninstalled ones.
-      $dependencies = array_intersect(module_list(TRUE, FALSE), $info['dependencies']);
-      foreach ($dependencies as $dependency) {
-        drupal_load('module', $dependency);
+      foreach ($info['dependencies'] as $dependency) {
+        if(!drupal_load('module', $dependency)) {
+          throw new Exception(t('Error, the dependancy (!module) for this callback is not installed.', array('!module' => $dependency)));
+        }
         $modules[$dependency] = 0;
       }
     }
@@ -113,9 +128,8 @@ function js_execute_callback() {
     module_list(FALSE, TRUE, FALSE, $modules);
 
     // Initialize the localization system.
-    // @todo We actually need to query the database whether the site has any
-    // localization module enabled, and load it automatically.
-    $locale = drupal_init_language();
+    drupal_bootstrap(DRUPAL_BOOTSTRAP_LANGUAGE);
+
     // Invoke implementations of hook_init().
     module_invoke_all('init');
   }
@@ -123,67 +137,3 @@ function js_execute_callback() {
   // Invoke callback function.
   return call_user_func_array($info['callback'], $args);
 }
-
-/**
- * l() calls check_url(), which needs to check for XSS attacks.
- */
-function filter_xss_bad_protocol($string, $decode = TRUE) {
-  static $allowed_protocols;
-  if (!isset($allowed_protocols)) {
-    $allowed_protocols = array_flip(variable_get('filter_allowed_protocols', array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal')));
-  }
-
-  // Get the plain text representation of the attribute value (i.e. its meaning).
-  if ($decode) {
-    $string = decode_entities($string);
-  }
-
-  // Iteratively remove any invalid protocol found.
-
-  do {
-    $before = $string;
-    $colonpos = strpos($string, ':');
-    if ($colonpos > 0) {
-      // We found a colon, possibly a protocol. Verify.
-      $protocol = substr($string, 0, $colonpos);
-      // If a colon is preceded by a slash, question mark or hash, it cannot
-      // possibly be part of the URL scheme. This must be a relative URL,
-      // which inherits the (safe) protocol of the base document.
-      if (preg_match('![/?#]!', $protocol)) {
-        break;
-      }
-      // Per RFC2616, section 3.2.3 (URI Comparison) scheme comparison must be case-insensitive.
-      // Check if this is a disallowed protocol.
-      if (!isset($allowed_protocols[strtolower($protocol)])) {
-        $string = substr($string, $colonpos + 1);
-      }
-    }
-  } while ($before != $string);
-  return check_plain($string);
-}
-
-$return = js_execute_callback();
-
-// Menu status constants are integers; page content is a string.
-if (is_int($return)) {
-  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-  switch ($return) {
-    case JS_NOT_FOUND:
-      drupal_not_found();
-      break;
-
-    case JS_ACCESS_DENIED:
-      drupal_access_denied();
-      break;
-
-    case JS_SITE_OFFLINE:
-      drupal_site_offline();
-      break;
-  }
-}
-elseif (isset($return)) {
-  // If JavaScript callback did not exit, print any value (including an empty
-  // string) except NULL or undefined:
-  print drupal_to_js($return);
-}
-
