Index: t3lib/config_default.php
===================================================================
--- t3lib/config_default.php	(revision 2875)
+++ t3lib/config_default.php	(working copy)
@@ -171,6 +171,10 @@
 		'flexFormXMLincludeDiffBase' => TRUE,	// If set, an additional tag with index "vXX.vDEFbase" is created for translations in flexforms holding the value of the default language when translation was changed. Used to show diff of value. This setting will change whether the system thinks flexform XML looks clean. For example when FALSE XX.vDEFbase fields will be removed in cleaning while accepted if TRUE (of course)
 		'compactFlexFormXML' => 0,				// If set, the flexform XML will not contain indentation spaces making XML more compact
 		'elementVersioningOnly' => FALSE,		// If true, only element versioning is allowed in the backend. This is recommended for new installations of TYPO3 4.2+ since "page" and "branch" versioning types are known for the drawbacks of loosing ids and "element" type versions supports moving now.
+		'AJAX' => array(				// array of key-value pairs for a unified use of AJAX calls in the TYPO3 backend. Keys are the unique ajaxIDs where the value will be resolved to call a method in an object. See ajax.php and the classes/class.typo3ajax.php for more information.
+			'pagetreeExpandCollapse'   => 'typo3/alt_db_navframe.php:SC_alt_db_navframe->ajaxExpandCollapse',
+			'foldertreeExpandCollapse' => 'typo3/alt_file_navframe.php:SC_alt_file_navframe->ajaxExpandCollapse',
+		),
 	),
 	'FE' => Array(			// Configuration for the TypoScript frontend (FE). Nothing here relates to the administration backend!
 		'png_to_gif' => 0,						// Boolean. Enables conversion back to gif of all png-files generated in the frontend libraries. Notice that this leaves an increased number of temporary files in typo3temp/
@@ -390,6 +394,17 @@
 }
 
 
+// setting the request type so devs exactly know what type of request it is
+define('TYPO3_REQUESTTYPE_FE', 1);
+define('TYPO3_REQUESTTYPE_BE', 2);
+define('TYPO3_REQUESTTYPE_CLI', 4);
+define('TYPO3_REQUESTTYPE_AJAX', 8);
+define('TYPO3_REQUESTTYPE',
+	(TYPO3_MODE == 'FE' ? TYPO3_REQUESTTYPE_FE : 0) |
+	(TYPO3_MODE == 'BE' ? TYPO3_REQUESTTYPE_BE : 0) |
+	((defined('TYPO3_cliMode') && TYPO3_cliMode) ? TYPO3_REQUESTTYPE_CLI : 0) |
+	($TYPO3_AJAX ? TYPO3_REQUESTTYPE_AJAX : 0)
+);
 
 // Load extensions:
 if (TYPO3_MODE=='FE' && is_object($TT)) $TT->push('Loading localconf.php extensions','');
@@ -430,6 +445,7 @@
 unset($TBE_MODULES_EXT);
 unset($TCA_DESCR);
 unset($LOCAL_LANG);
+unset($TYPO3_AJAX);
 
 
 	// Setting some global vars:
Index: t3lib/class.t3lib_div.php
===================================================================
--- t3lib/class.t3lib_div.php	(revision 2875)
+++ t3lib/class.t3lib_div.php	(working copy)
@@ -3961,11 +3961,12 @@
 	 * @param	mixed		Reference to be passed along (typically "$this" - being a reference to the calling object) (REFERENCE!)
 	 * @param	string		Required prefix of class or function name
 	 * @param	boolean		If set, no debug() error message is shown if class/function is not present.
-	 * @return	mixed		Content from method/function call
+	 * @return	mixed		Content from method/function call or false if the class/method/function was not found
 	 * @see getUserObj()
 	 */
 	function callUserFunction($funcName,&$params,&$ref,$checkPrefix='user_',$silent=0)	{
 		global $TYPO3_CONF_VARS;
+		$content = false;
 
 			// Check persistent object and if found, call directly and exit.
 		if (is_array($GLOBALS['T3_VAR']['callUserFunction'][$funcName]))	{
Index: typo3/class.filelistfoldertree.php
===================================================================
--- typo3/class.filelistfoldertree.php	(revision 2875)
+++ typo3/class.filelistfoldertree.php	(working copy)
@@ -148,7 +148,7 @@
 		$PM = t3lib_div::_GP('PM');
 		if(($PMpos = strpos($PM, '#')) !== false) { $PM = substr($PM, 0, $PMpos); }
 		$PM = explode('_', $PM);
-		if(($isAjaxCall = t3lib_div::_GP('ajax')) && is_array($PM) && count($PM)==4)	{
+		if((TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) && is_array($PM) && count($PM)==4) {
 			if($PM[1])	{
 				$expandedFolderUid = $PM[2];
 				$ajaxOutput = '';
@@ -429,4 +429,4 @@
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.filelistfoldertree.php'])	{
 	include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.filelistfoldertree.php']);
 }
-?>
\ No newline at end of file
+?>
Index: typo3/class.webpagetree.php
===================================================================
--- typo3/class.webpagetree.php	(revision 2875)
+++ typo3/class.webpagetree.php	(working copy)
@@ -177,7 +177,9 @@
 	 */
 	function printTree($treeArr = '')   {
 		$titleLen = intval($this->BE_USER->uc['titleLen']);
-		if (!is_array($treeArr))	$treeArr = $this->tree;
+		if (!is_array($treeArr)) {
+			$treeArr = $this->tree;
+		}
 
 		$out = '
 			<!-- TYPO3 tree structure. -->
@@ -189,7 +191,7 @@
 		$PM = t3lib_div::_GP('PM');
 		if(($PMpos = strpos($PM, '#')) !== false) { $PM = substr($PM, 0, $PMpos); }
 		$PM = explode('_', $PM);
-		if(($isAjaxCall = t3lib_div::_GP('ajax')) && is_array($PM) && count($PM)==4)	{
+		if((TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) && is_array($PM) && count($PM)==4) {
 			if($PM[1])	{
 				$expandedPageUid = $PM[2];
 				$ajaxOutput = '';
Index: typo3/tree.js
===================================================================
--- typo3/tree.js	(revision 2875)
+++ typo3/tree.js	(working copy)
@@ -74,7 +74,8 @@
 
 
 var Tree = {
-	thisScript: null,
+	thisScript: 'ajax.php',
+	ajaxID: 'pagetreeExpandCollapse',	// has to be either "pagetreeExpandCollapse" or "foldertreeExpandCollapse"
 	frameSetModule: null,
 	activateDragDrop: true,
 	highlightClass: 'active',
@@ -83,7 +84,7 @@
 	load: function(params, isExpand, obj) {
 			// fallback if AJAX is not possible (e.g. IE < 6)
 		if (typeof Ajax.getTransport() != 'object') {
-			window.location.href = this.thisScript + '?PM=' + params;
+			window.location.href = this.thisScript + '?ajaxID=' + this.ajaxID + '&PM=' + params;
 			return;
 		}
 
@@ -104,16 +105,17 @@
 
 		new Ajax.Request(this.thisScript, {
 			method: 'get',
-			parameters: 'ajax=1&PM=' + params,
-			onComplete: function(xhr, status) {
-				// if this is not a valid ajax response, the whole page gets refreshed
-				if (!status) return this.refresh();
-
+			parameters: 'ajaxID=' + this.ajaxID + '&PM=' + params,
+			onComplete: function(xhr) {
 				// the parent node needs to be overwritten, not the object
 				$(obj.parentNode).replace(xhr.responseText);
 				this.registerDragDropHandlers();
 				this.reSelectActiveItem();
 				filter($('_livesearch').value);
+			}.bind(this),
+			onT3Error: function(xhr) {
+				// if this is not a valid ajax response, the whole page gets refreshed
+				this.refresh();
 			}.bind(this)
 		});
 	},
@@ -122,7 +124,7 @@
 	refresh: function() {
 		var r = new Date();
 		// randNum is useful so pagetree does not get cached in browser cache when refreshing
-		window.location.href = this.thisScript + '?randNum=' + r.getTime();
+		window.location.href = '?randNum=' + r.getTime();
 	},
 
 	// attaches the events to the elements needed for the drag and drop (for the titles and the icons)
Index: typo3/js/common.js
===================================================================
--- typo3/js/common.js	(revision 0)
+++ typo3/js/common.js	(revision 0)
@@ -0,0 +1,70 @@
+/***************************************************************
+*
+*  javascript functions regarding the TYPO3 wrapper
+*  for the javascript library "prototype".
+*
+*  Copyright notice
+*
+*  (c) 2008 Benjamin Mack <www.xnos.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 backend provided by
+*  Kasper Skaarhoj <kasper@typo3.com> together with TYPO3
+*
+*  Released under GNU/GPL (see license file in /typo3/)
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+*
+*  This copyright notice MUST APPEAR in all copies of this script
+*
+***************************************************************/
+
+// Please make sure that prototype.js is loaded before loading this
+// file in your script, the responder is only added if prototype was loaded
+
+if (Prototype) {
+	// adding generic a responder to use when a AJAX request is done
+	Ajax.Responders.register({
+		onCreate: function(request, transport) {
+
+			// if the TYPO3 AJAX backend is used, 
+			// the onSuccess & onComplete callbacks are hooked
+			if (request.url.indexOf("ajax.php") == -1) {
+				return;
+			}
+
+			var origSuccess = request.options.onSuccess, origComplete = request.options.onComplete;
+
+			// hooking "onSuccess"
+			if (origSuccess) {
+				request.options.onSuccess = function(xhr, json) {
+					if (!json) {
+						T3AJAX.showError(xhr, json);	
+					} else {
+						origSuccess(xhr, json);
+					}
+				}
+			}
+
+			// hooking "onComplete", using T3Error handler if available
+			if (origComplete) {
+				request.options.onComplete = function(xhr, json) {
+					if (!json && request.options.onT3Error) {
+						request.options.onT3Error(xhr, json);
+					} else if (!json) {
+						T3AJAX.showError(xhr, json);
+					} else {
+						origComplete(xhr, json);
+					}
+				}
+			}
+		}
+	});
+}
+
+var T3AJAX = new Object();
+T3AJAX.showError = function(xhr, json) {
+	alert(xhr.responseText);
+}
Index: typo3/classes/class.typo3ajax.php
===================================================================
--- typo3/classes/class.typo3ajax.php	(revision 0)
+++ typo3/classes/class.typo3ajax.php	(revision 0)
@@ -0,0 +1,224 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2008 Benjamin Mack <mack@xnos.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * class to hold all the information about an AJAX call and send
+ * the right headers for the request type
+ *
+ * @author	Benjamin Mack <mack@xnos.org>
+ * @package	TYPO3
+ * @subpackage	core
+ */
+class TYPO3AJAX {
+	private $id = null;
+	private $errorMessage = null;
+	private $isError = false;
+	private $content = array();
+	private $contentFormat = 'plain';	// could be 'plain' (default), 'xml' or 'json'
+	private $charset = 'utf-8';
+
+	/**
+	 * sets the charset and the ID for the AJAX call
+	 *
+	 * @param	string	the AJAX id
+	 * @return	void
+	 */
+	public function init($id) {
+		global $TYPO3_CONF_VARS;
+		
+		if (isset($TYPO3_CONF_VARS['BE']['forceCharset'])) {
+			$this->charset = $TYPO3_CONF_VARS['BE']['forceCharset'];
+		}
+
+		$this->id = $id;
+	}
+
+
+	/**
+	 * returns the ID for the AJAX call
+	 *
+	 * @return	string	the AJAX id
+	 */
+	public function getID() {
+		return $this->id;
+	}
+
+
+	/**
+	 * adds new content
+	 *
+	 * @param	string	the new content key where the content should be added in the content array
+	 * @param	string	the new content to add
+	 * @return	string	the old content
+	 */
+	public function addContent($key, $content) {
+		$oldcontent = '';
+		if (array_key_exists($key, $this->content)) {
+			$oldcontent = $this->content[$key];
+		}
+		if (!$content) {
+			unset($this->content[$key]);
+		} else {
+			$this->content[$key] = $content;
+		}
+		return $oldcontent;
+	}
+
+
+	/**
+	 * returns the content for the ajax call
+	 *
+	 * @return	mixed	the content for a specific key or the whole content
+	 */
+	public function getContent($key = '') {
+		return ($key && array_key_exists($key, $this->content) ? $this->content[$key] : $this->content);
+	}
+
+
+	/**
+	 * sets the content format for the ajax call
+	 * 
+	 * @param	string	can be one of the following keywords 'plain', '
+	 * @return	void
+	 */
+	public function setContentFormat($format) {
+		if (t3lib_div::inArray(array('plain', 'xml', 'json'), $format)) {
+			$this->contentFormat = $format;
+		}
+	}
+
+
+	/**
+	 * sets an error message and the error flag
+	 *
+	 * @param	string	the error message
+	 * @return	void
+	 */
+	public function setError($errorMsg = '') {
+		$this->errorMessage = $errorMsg;
+		$this->isError = true;
+	}
+
+
+	/**
+	 * checks whether an error occured during the execution or not
+	 *
+	 * @return	boolean	whether this AJAX call 
+	 */
+	public function isError() {
+		return $this->isError;
+	}
+
+
+	/**
+	 * renders the AJAX call based on the $contentFormat variable and exits the request
+	 *
+	 * @return	void
+	 */
+	public function render() {
+		if ($this->isError) {
+			$this->renderAsError();
+		} else {
+			switch ($this->contentFormat) {
+				case 'json':
+					$this->renderAsJSON();
+					break;
+				case 'xml':
+					$this->renderAsXML();
+					break;
+				default:
+					$this->renderAsPlain();
+			}
+		}
+		exit;
+	}
+
+
+	/**
+	 * renders the AJAX call in XML error style to handle with JS
+	 * the "responseXML" of the transport object will be filled with the error message then
+	 * 
+	 * @return	void
+	 */
+	private function renderAsError() {
+			header('Content-type: text/xml; charset='.$this->charset);
+			header('X-JSON: false');
+			die('<t3err>'.htmlspecialchars($this->errorMessage).'</t3err>');
+	}
+
+
+	/**
+	 * renders the AJAX call with text/html headers
+	 * the content will be available in the "responseText" value of the transport object
+	 * 
+	 * @return	void
+	 */
+	private function renderAsPlain() {
+			header('Content-type: text/html; charset='.$this->charset);
+			header('X-JSON: true');
+			echo implode('', $this->content);
+	}
+
+
+	/**
+	 * renders the AJAX call with text/xml headers
+	 * the content will be available in the "responseXML" value of the transport object
+	 * 
+	 * @return	void
+	 */
+	private function renderAsXML() {
+			header('Content-type: text/xml; charset='.$this->charset);
+			header('X-JSON: true');
+			echo implode('', $this->content);
+	}
+
+
+	/**
+	 * renders the AJAX call with JSON evaluated headers
+	 * note that you need to have requestHeaders: {Accept: 'application/json'},
+	 * in your AJAX options of your AJAX request object in JS
+	 * the content will be available in the second variable "json" variable of the transport object
+	 * 
+	 * @return	void
+	 */
+	private function renderAsJSON() {
+			require_once(PATH_typo3.'contrib/json/json.php');
+
+			$json = new Services_JSON();
+			$content = $json->encode($this->content);
+
+			header('Content-type: application/json; charset='.$this->charset);
+			header('X-JSON: '.$content);
+			echo $content;
+	}
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/classes/class.typo3ajax.php'])	{
+	include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/classes/class.typo3ajax.php']);
+}
+
+?>
Index: typo3/template.php
===================================================================
--- typo3/template.php	(revision 2875)
+++ typo3/template.php	(working copy)
@@ -1862,13 +1862,13 @@
 // The backend language engine is started (ext: "lang")
 // ******************************************************
 require_once(PATH_typo3.'sysext/lang/lang.php');
-$LANG = t3lib_div::makeInstance('language');
-$LANG->init($BE_USER->uc['lang']);
+$GLOBALS['LANG'] = t3lib_div::makeInstance('language');
+$GLOBALS['LANG']->init($BE_USER->uc['lang']);
 
 
 
 // ******************************
 // The template is loaded
 // ******************************
-$TBE_TEMPLATE = t3lib_div::makeInstance('template');
+$GLOBALS['TBE_TEMPLATE'] = t3lib_div::makeInstance('template');
 ?>
Index: typo3/alt_db_navframe.php
===================================================================
--- typo3/alt_db_navframe.php	(revision 2875)
+++ typo3/alt_db_navframe.php	(working copy)
@@ -53,7 +53,7 @@
 
 
 $BACK_PATH = '';
-require('init.php');
+require_once('init.php');
 require('template.php');
 require_once('class.webpagetree.php');
 
@@ -81,11 +81,11 @@
 	var $backPath;
 
 		// Internal, static: GPvar:
-	var $ajax;							// Is set, if an AJAX call should be handled.
 	var $currentSubScript;
 	var $cMR;
 	var $setTempDBmount;			// If not '' (blank) then it will clear (0) or set (>0) Temporary DB mount.
 
+
 	/**
 	 * Initialiation of the class
 	 *
@@ -98,7 +98,6 @@
 		$this->backPath = $BACK_PATH;
 
 			// Setting GPvars:
-		$this->ajax = t3lib_div::_GP('ajax');
 		$this->cMR = t3lib_div::_GP('cMR');
 		$this->currentSubScript = t3lib_div::_GP('currentSubScript');
 		$this->setTempDBmount = t3lib_div::_GP('setTempDBmount');
@@ -122,50 +121,58 @@
 
 			// Temporary DB mounts:
 		$this->initializeTemporaryDBmount();
+	}
 
-			// Use template rendering only if this is a non-AJAX call:
-		if (!$this->ajax) {
-				// Setting highlight mode:
-			$this->doHighlight = !$BE_USER->getTSConfigVal('options.pageTree.disableTitleHighlight');
 
-				// If highlighting is active, define the CSS class for the active item depending on the workspace
-			if ($this->doHighlight) {
-				if ($BE_USER->workspace === 0) $hlClass = 'active';
-				else $hlClass = 'active active-ws wsver'.$BE_USER->workspace; 
-			}
+	/**
+	 * initialization for the visual parts of the class
+	 * Use template rendering only if this is a non-AJAX call
+	 *
+	 * @return	void
+	 */
+	public function initPage() {
+ 		global $BE_USER;
 
-				// Create template object:
-			$this->doc = t3lib_div::makeInstance('template');
-			$this->doc->backPath = $BACK_PATH;
-			$this->doc->docType = 'xhtml_trans';
+			// Setting highlight mode:
+		$this->doHighlight = !$BE_USER->getTSConfigVal('options.pageTree.disableTitleHighlight');
 
-				// Adding javascript code for AJAX (prototype), drag&drop and the pagetree as well as the click menu code
-			$this->doc->getDragDropCode('pages');
-			$this->doc->getContextMenuCode();
+			// If highlighting is active, define the CSS class for the active item depending on the workspace
+		if ($this->doHighlight) {
+			$hlClass = ($BE_USER->workspace === 0 ? 'active' : 'active active-ws wsver'.$BE_USER->workspace); 
+		}
 
-			$this->doc->JScode .= $this->doc->wrapScriptTags(
-			($this->currentSubScript?'top.currentSubScript=unescape("'.rawurlencode($this->currentSubScript).'");':'').'
-			// setting prefs for pagetree and drag & drop
-			Tree.thisScript    = "'.$this->pagetree->thisScript.'";
-			'.($this->doHighlight ? 'Tree.highlightClass = "'.$hlClass.'";' : '').'
+			// Create template object:
+		$this->doc = t3lib_div::makeInstance('template');
+		$this->doc->backPath = $BACK_PATH;
+		$this->doc->docType  = 'xhtml_trans';
 
-			// Function, loading the list frame from navigation tree:
-			function jumpTo(id, linkObj, highlightID, bank)	{ //
-				var theUrl = top.TS.PATH_typo3 + top.currentSubScript + "?id=" + id;
-				top.fsMod.currentBank = bank;
 
-				if (top.condensedMode) top.content.location.href = theUrl;
-				else                   parent.list_frame.location.href=theUrl;
+			// Adding javascript code for AJAX (prototype), drag&drop and the pagetree as well as the click menu code
+		$this->doc->getDragDropCode('pages');
+		$this->doc->getContextMenuCode();
 
-				'.($this->doHighlight ? 'Tree.highlightActiveItem("web", highlightID + "_" + bank);' : '').'
-				'.(!$GLOBALS['CLIENT']['FORMSTYLE'] ? '' : 'if (linkObj) linkObj.blur(); ').'
-				return false;
-			}
-			'.($this->cMR?"jumpTo(top.fsMod.recentIds['web'],'');":'').'
-			');
 
-			$this->doc->bodyTagId = 'bodyTag';
+		$this->doc->JScode .= $this->doc->wrapScriptTags(
+		($this->currentSubScript?'top.currentSubScript=unescape("'.rawurlencode($this->currentSubScript).'");':'').'
+		// setting prefs for pagetree and drag & drop
+		'.($this->doHighlight ? 'Tree.highlightClass = "'.$hlClass.'";' : '').'
+
+		// Function, loading the list frame from navigation tree:
+		function jumpTo(id, linkObj, highlightID, bank)	{ //
+			var theUrl = top.TS.PATH_typo3 + top.currentSubScript + "?id=" + id;
+			top.fsMod.currentBank = bank;
+
+			if (top.condensedMode) top.content.location.href = theUrl;
+			else                   parent.list_frame.location.href=theUrl;
+
+			'.($this->doHighlight ? 'Tree.highlightActiveItem("web", highlightID + "_" + bank);' : '').'
+			'.(!$GLOBALS['CLIENT']['FORMSTYLE'] ? '' : 'if (linkObj) linkObj.blur(); ').'
+			return false;
 		}
+		'.($this->cMR?"jumpTo(top.fsMod.recentIds['web'],'');":'').'
+		');
+
+		$this->doc->bodyTagId = 'bodyTag';
 	}
 
 
@@ -180,12 +187,6 @@
 			// Produce browse-tree:
 		$tree = $this->pagetree->getBrowsableTree();
 
-			// Output only the tree if this is an AJAX call:
-		if ($this->ajax) {
-			$this->content = $LANG->csConvObj->utf8_encode($tree, $LANG->charSet);
-			return;
-		}
-
 			// Start page:
 		$this->content = $this->doc->startPage('TYPO3 Page Tree');
 		
@@ -261,15 +262,8 @@
 	 * @return	void
 	 */
 	function printContent()	{
-			// If we handle an AJAX call, send headers:
-		if ($this->ajax) {
-			header('X-JSON: ('.($this->pagetree->ajaxStatus?'true':'false').')');
-			header('Content-type: text/html; charset=utf-8');
-			// If it's the regular call to fully output the tree:
-		} else {
-			$this->content.= $this->doc->endPage();
-			$this->content = $this->doc->insertStylesAndJS($this->content);
-		}
+		$this->content.= $this->doc->endPage();
+		$this->content = $this->doc->insertStylesAndJS($this->content);
 		echo $this->content;
 	}
 
@@ -324,10 +318,33 @@
 	 * @return	void
 	 */
 	function settingTemporaryMountPoint($pageId)	{
-		global $BE_USER;
+		$GLOBALS['BE_USER']->setAndSaveSessionData('pageTree_temporaryMountPoint',intval($pageId));
+	}
 
-			// Setting temporary mount point ID:
-		$BE_USER->setAndSaveSessionData('pageTree_temporaryMountPoint',intval($pageId));
+
+	/**********************************
+	 *
+	 * AJAX Calls
+	 *
+	 **********************************/
+
+	/**
+	 * Makes the AJAX call to expand or collapse the pagetree.
+	 * Called by typo3/ajax.php
+	 * 
+	 * @param	array	additional parameters (not used here)
+	 * @param	object	the TYPO3AJAX object of this request
+	 */
+	public function ajaxExpandCollapse($params, &$ajaxObj) {
+		global $LANG;
+
+		$this->init();
+		$tree = $this->pagetree->getBrowsableTree();
+		if (!$this->pagetree->ajaxStatus) {
+			$ajaxObj->setError($tree);
+		} else	{
+			$ajaxObj->addContent('tree', $tree);
+		}
 	}
 }
 
@@ -338,13 +355,13 @@
 }
 
 
+// Make instance if it is not an AJAX call
+if (!(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX)) {
+	$SOBE = t3lib_div::makeInstance('SC_alt_db_navframe');
+	$SOBE->init();
+	$SOBE->initPage();
+	$SOBE->main();
+	$SOBE->printContent();
+}
 
-
-
-// Make instance:
-$SOBE = t3lib_div::makeInstance('SC_alt_db_navframe');
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
-
 ?>
Index: typo3/ajax.php
===================================================================
--- typo3/ajax.php	(revision 0)
+++ typo3/ajax.php	(revision 0)
@@ -0,0 +1,65 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2007-2008 Benjamin Mack
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * AJAX dispatcher
+ * @author	Benjamin Mack <mack@xnos.org>
+ * @package	TYPO3
+ */
+
+$TYPO3_AJAX = true;
+
+require('init.php');
+require('classes/class.typo3ajax.php');
+
+
+	// finding the script path from the variable
+$ajaxID = (string) t3lib_div::_GP('ajaxID');
+$ajaxScript = $TYPO3_CONF_VARS['BE']['AJAX'][$ajaxID];
+
+
+	// instantiating the AJAX object
+$ajaxObj =& t3lib_div::makeInstance('TYPO3AJAX');
+$ajaxObj->init($ajaxID);
+$ajaxParams = array();
+
+
+	// evaluating the arguments and calling the AJAX method/function
+if (empty($ajaxID)) {
+	$ajaxObj->setError('No valid ajaxID parameter given.');
+} else if (empty($ajaxScript)) {
+	$ajaxObj->setError('Registered backend function for ajaxID "'.$ajaxID.'" was not found.');
+} else {
+	$ret = t3lib_div::callUserFunction($ajaxScript, $ajaxParams, $ajaxObj, false, true);
+	if ($ret === false) {
+		$ajaxObj->setError('Registered backend function for ajaxID "'.$ajaxID.'" was not found.');
+	}
+}
+
+	// outputting the content (and setting the X-JSON-Header)
+$ajaxObj->render();
+
+?>
Index: typo3/alt_file_navframe.php
===================================================================
--- typo3/alt_file_navframe.php	(revision 2875)
+++ typo3/alt_file_navframe.php	(working copy)
@@ -55,7 +55,7 @@
  */
 
 $BACK_PATH = '';
-require('init.php');
+require_once('init.php');
 require('template.php');
 require_once('class.filelistfoldertree.php');
 
@@ -82,7 +82,6 @@
 	var $backPath;
 
 		// Internal, static: GPvar:
-	var $ajax;							// Is set, if an AJAX call should be handled.
 	var $currentSubScript;
 	var $cMR;
 
@@ -93,13 +92,12 @@
 	 * @return	void
 	 */
 	function init()	{
-		global $BE_USER,$BACK_PATH,$CLIENT;
+		global $BE_USER, $BACK_PATH;
 
 			// Setting backPath
 		$this->backPath = $BACK_PATH;
 
 			// Setting GPvars:
-		$this->ajax = t3lib_div::_GP('ajax');
 		$this->currentSubScript = t3lib_div::_GP('currentSubScript');
 		$this->cMR = t3lib_div::_GP('cMR');
 
@@ -107,45 +105,55 @@
 		$this->foldertree = t3lib_div::makeInstance('filelistFolderTree');
 		$this->foldertree->ext_IconMode = $BE_USER->getTSConfigVal('options.folderTree.disableIconLinkToContextmenu');
 		$this->foldertree->thisScript = 'alt_file_navframe.php';
+	}
 
-			// Use template rendering only if this is a non-AJAX call:
-		if (!$this->ajax) {
-				// Setting highlight mode:
-			$this->doHighlight = !$BE_USER->getTSConfigVal('options.pageTree.disableTitleHighlight');
 
-				// Create template object:
-			$this->doc = t3lib_div::makeInstance('template');
-			$this->doc->backPath = $BACK_PATH;
-			$this->doc->docType = 'xhtml_trans';
+	/**
+	 * initialization for the visual parts of the class
+	 * Use template rendering only if this is a non-AJAX call
+	 *
+	 * @return	void
+	 */
+	public function initPage() {
+		global $BE_USER, $BACK_PATH, $CLIENT;
 
-				// Adding javascript code for AJAX (prototype), drag&drop and the filetree as well as the click menu code
-			$this->doc->getDragDropCode('folders');
-			$this->doc->getContextMenuCode();
+			// Setting highlight mode:
+		$this->doHighlight = !$BE_USER->getTSConfigVal('options.pageTree.disableTitleHighlight');
 
-				// Setting JavaScript for menu.
-			$this->doc->JScode .= $this->doc->wrapScriptTags(
-			($this->currentSubScript?'top.currentSubScript=unescape("'.rawurlencode($this->currentSubScript).'");':'').'
+			// Create template object:
+		$this->doc = t3lib_div::makeInstance('template');
+		$this->doc->backPath = $BACK_PATH;
+		$this->doc->docType = 'xhtml_trans';
 
-			// setting prefs for pagetree and drag & drop
-			Tree.thisScript    = "'.$this->foldertree->thisScript.'";
+			// Adding javascript code for AJAX (prototype), drag&drop and the filetree as well as the click menu code
+		$this->doc->getDragDropCode('folders');
+		$this->doc->getContextMenuCode();
 
-			// Function, loading the list frame from navigation tree:
-			function jumpTo(id, linkObj, highlightID, bank)	{
-				var theUrl = top.TS.PATH_typo3 + top.currentSubScript + "?id=" + id;
-				top.fsMod.currentBank = bank;
+			// Setting JavaScript for menu.
+		$this->doc->JScode .= $this->doc->wrapScriptTags(
 
-				if (top.condensedMode) top.content.location.href = theUrl;
-				else                   parent.list_frame.location.href = theUrl;
+		($this->currentSubScript?'top.currentSubScript=unescape("'.rawurlencode($this->currentSubScript).'");':'').'
 
-				'.($this->doHighlight ? 'Tree.highlightActiveItem("file", highlightID + "_" + bank);' : '').'
-				'.(!$GLOBALS['CLIENT']['FORMSTYLE'] ? '' : 'if (linkObj) linkObj.blur(); ').'
-				return false;
-			}
-			'.($this->cMR ? " jumpTo(top.fsMod.recentIds['file'],'');" : '')
-			);
+		// setting prefs for foldertree
+		Tree.ajaxID = "foldertreeExpandCollapse";
+
+		// Function, loading the list frame from navigation tree:
+		function jumpTo(id, linkObj, highlightID, bank)	{
+			var theUrl = top.TS.PATH_typo3 + top.currentSubScript + "?id=" + id;
+			top.fsMod.currentBank = bank;
+
+			if (top.condensedMode) top.content.location.href = theUrl;
+			else                   parent.list_frame.location.href = theUrl;
+
+			'.($this->doHighlight ? 'Tree.highlightActiveItem("file", highlightID + "_" + bank);' : '').'
+			'.(!$CLIENT['FORMSTYLE'] ? '' : 'if (linkObj) linkObj.blur(); ').'
+			return false;
 		}
+		'.($this->cMR ? " jumpTo(top.fsMod.recentIds['file'],'');" : '')
+		);
 	}
 
+
 	/**
 	 * Main function, rendering the folder tree
 	 *
@@ -157,12 +165,7 @@
 			// Produce browse-tree:
 		$tree = $this->foldertree->getBrowsableTree();
 
-			// Output only the tree if this is an AJAX call:
-		if ($this->ajax) {
-			$this->content = $LANG->csConvObj->utf8_encode($tree, $LANG->charSet);
-			return;
-		}
-
+			// Start page
 		$this->content = $this->doc->startPage('TYPO3 Folder Tree');
 
 			// Outputting page tree:
@@ -188,23 +191,43 @@
 
 	}
 
+
 	/**
 	 * Outputting the accumulated content to screen
 	 *
 	 * @return	void
 	 */
 	function printContent()	{
-			// If we handle an AJAX call, send headers:
-		if ($this->ajax) {
-			header('X-JSON: ('.($this->foldertree->ajaxStatus?'true':'false').')');
-			header('Content-type: text/html; charset=utf-8');
-			// If it's the regular call to fully output the tree:
-		} else {
-			$this->content.= $this->doc->endPage();
-			$this->content = $this->doc->insertStylesAndJS($this->content);
-		}
+		$this->content.= $this->doc->endPage();
+		$this->content = $this->doc->insertStylesAndJS($this->content);
 		echo $this->content;
 	}
+
+
+	/**********************************
+	 *
+	 * AJAX Calls
+	 *
+	 **********************************/
+
+	/**
+	 * Makes the AJAX call to expand or collapse the foldertree.
+	 * Called by typo3/ajax.php
+	 * 
+	 * @param	array	additional parameters (not used here)
+	 * @param	object	the TYPO3AJAX object of this request
+	 */
+	public function ajaxExpandCollapse($params, &$ajaxObj)	{
+		global $LANG;
+
+		$this->init();
+		$tree = $this->foldertree->getBrowsableTree();
+		if (!$this->foldertree->ajaxStatus)	{
+			$ajaxObj->setError($tree);
+		} else	{
+			$ajaxObj->addContent('tree', $tree);
+		}
+	}
 }
 
 // Include extension?
@@ -213,19 +236,12 @@
 }
 
 
-
-
-
-
-
-
-
-
-
-
-// Make instance:
-$SOBE = t3lib_div::makeInstance('SC_alt_file_navframe');
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+// Make instance if it is not an AJAX call
+if (!(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX)) {
+	$SOBE = t3lib_div::makeInstance('SC_alt_file_navframe');
+	$SOBE->init();
+	$SOBE->initPage();
+	$SOBE->main();
+	$SOBE->printContent();
+}
 ?>
