Committed AJAX pagetree and filetree by Benjamin Mack
authorIngmar Schlecht <ingmar.schlecht@typo3.org>
Fri, 19 Jan 2007 12:18:51 +0000 (12:18 +0000)
committerIngmar Schlecht <ingmar.schlecht@typo3.org>
Fri, 19 Jan 2007 12:18:51 +0000 (12:18 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@1907 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
typo3/alt_db_navframe.php
typo3/alt_file_navframe.php
typo3/class.filelistfoldertree.php [new file with mode: 0644]
typo3/class.webpagetree.php [new file with mode: 0644]
typo3/stylesheet.css
typo3/sysext/t3skin/stylesheets/typo3-tree.css
typo3/tree.js [new file with mode: 0644]

index f619ae9..192c3e5 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
-2007-01-19 Andreas Otto <andreas.otto@dkd.de>
+2007-01-19  Ingmar Schlecht  <ingmar@typo3.org>
+
+       * Committed AJAX pagetree and filetree by Benjamin Mack <bmack@xnos.org>! (Thanks also to Stefan Regniet for his initial work!)
+
+2007-01-19  Andreas Otto  <andreas.otto@dkd.de>
 
        * Fixed feature request 4656: The feature config.sys_language_softMergeIfNotBlank sets the "mergeIfNotBlank" for a field in the frontend context through TypoScript. It can be useful to have the same for "exclude" localization mode so a field is always overlaid in the frontend output. This patch simply copies the code from "softMergeIfNotBlank" and does the same for "exclude".
 
index dff2353..1b3c4d5 100755 (executable)
  * [CLASS/FUNCTION INDEX of SCRIPT]
  *
  *
- *
- *   78: class localPageTree extends t3lib_browseTree
- *   88:     function localPageTree()
- *   99:     function wrapIcon($icon,&$row)
- *  142:     function wrapStop($str,$row)
- *  158:     function wrapTitle($title,$row,$bank=0)
- *
- *
  *  192: class SC_alt_db_navframe
  *  210:     function init()
  *  313:     function main()
  */
 
 
-$BACK_PATH='';
+$BACK_PATH = '';
 require('init.php');
 require('template.php');
-require_once(PATH_t3lib.'class.t3lib_browsetree.php');
-
-
-
-/**
- * Extension class for the t3lib_browsetree class, specially made for browsing pages in the Web module
- *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
- * @package TYPO3
- * @subpackage core
- * @see class t3lib_browseTree
- */
-class localPageTree extends t3lib_browseTree {
-
-       var $ext_showPageId;
-       var $ext_IconMode;
-
-       /**
-        * Calls init functions
-        *
-        * @return      void
-        */
-       function localPageTree() {
-               $this->init();
-       }
-
-       /**
-        * Wrapping icon in browse tree
-        *
-        * @param       string          Icon IMG code
-        * @param       array           Data row for element.
-        * @return      string          Page icon
-        */
-       function wrapIcon($icon,&$row)  {
-                       // If the record is locked, present a warning sign.
-               if ($lockInfo=t3lib_BEfunc::isRecordLocked('pages',$row['uid']))        {
-                       $aOnClick = 'alert('.$GLOBALS['LANG']->JScharCode($lockInfo['msg']).');return false;';
-                       $lockIcon='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.
-                               '<img'.t3lib_iconWorks::skinImg('','gfx/recordlock_warning3.gif','width="17" height="12"').' title="'.htmlspecialchars($lockInfo['msg']).'" alt="" />'.
-                               '</a>';
-               } else $lockIcon = '';
-
-                       // Add title attribute to input icon tag
-               $thePageIcon = $this->addTagAttributes($icon, $this->titleAttrib.'="'.$this->getTitleAttrib($row).'"');
-
-                       // Wrap icon in click-menu link.
-               if (!$this->ext_IconMode)       {
-                       $thePageIcon = $GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon($thePageIcon,'pages',$row['uid'],0,'&bank='.$this->bank);
-               } elseif (!strcmp($this->ext_IconMode,'titlelink'))     {
-                       $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->treeName.'\');';
-                       $thePageIcon='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.$thePageIcon.'</a>';
-               }
-
-                       // Wrap icon in a drag/drop span.
-               $spanOnDrag = htmlspecialchars('return dragElement("'.$row['uid'].'")');
-               $spanOnDrop = htmlspecialchars('return dropElement("'.$row['uid'].'")');
-               $dragDropIcon = '<span id="dragIconID_'.$row['uid'].'" ondragstart="'.$spanOnDrag.'" onmousedown="'.$spanOnDrag.'" onmouseup="'.$spanOnDrop.'">'.$thePageIcon.'</span>';
-
-                       // Add Page ID:
-               if ($this->ext_showPageId)      {
-                       $pageIdStr = '['.$row['uid'].']&nbsp;';
-               } else {
-                       $pageIdStr = '';
-               }
-
-               return $dragDropIcon.$lockIcon.$pageIdStr;
-       }
-
-       /**
-        * Adds a red "+" to the input string, $str, if the field "php_tree_stop" in the $row (pages) is set
-        *
-        * @param       string          Input string, like a page title for the tree
-        * @param       array           record row with "php_tree_stop" field
-        * @return      string          Modified string
-        * @access private
-        */
-       function wrapStop($str,$row)    {
-               if ($row['php_tree_stop'])      {
-                       $str.='<a href="'.htmlspecialchars(t3lib_div::linkThisScript(array('setTempDBmount' => $row['uid']))).'" class="typo3-red">+</a> ';
-               }
-               return $str;
-       }
-
-       /**
-        * Wrapping $title in a-tags.
-        *
-        * @param       string          Title string
-        * @param       string          Item record
-        * @param       integer         Bank pointer (which mount point number)
-        * @return      string
-        * @access private
-        */
-       function wrapTitle($title,$row,$bank=0) {
-               $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->domIdPrefix.$this->getId($row).'\','.$bank.');';
-               $CSM = '';
-               if ($GLOBALS['TYPO3_CONF_VARS']['BE']['useOnContextMenuHandler'])       {
-                       $CSM = ' oncontextmenu="'.htmlspecialchars($GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon('','pages',$row['uid'],0,'&bank='.$this->bank,'',TRUE)).'"';
-               }
-               $thePageTitle='<a href="#" onclick="'.htmlspecialchars($aOnClick).'"'.$CSM.'>'.$title.'</a>';
-
-                       // Wrap title in a drag/drop span.
-               $spanOnDrag = htmlspecialchars('return dragElement("'.$row['uid'].'")');
-               $spanOnDrop = htmlspecialchars('return dropElement("'.$row['uid'].'")');
-               $dragDropTitle = '<span id="dragTitleID_'.$row['uid'].'" ondragstart="'.$spanOnDrag.'" onmousedown="'.$spanOnDrag.'" onmouseup="'.$spanOnDrop.'">'.$thePageTitle.'</span>';
-               return $dragDropTitle;
-       }
-}
-
-
-
-
-
-
-
-
-
-
+require_once('class.webpagetree.php');
 
 
 /**
@@ -210,13 +86,15 @@ class SC_alt_db_navframe {
        function init() {
                global $BE_USER,$BACK_PATH;
 
+
                        // Setting GPvars:
                $this->currentSubScript = t3lib_div::_GP('currentSubScript');
                $this->cMR = t3lib_div::_GP('cMR');
                $this->setTempDBmount = t3lib_div::_GP('setTempDBmount');
 
+
                        // Create page tree object:
-               $this->pagetree = t3lib_div::makeInstance('localPageTree');
+               $this->pagetree = t3lib_div::makeInstance('webPageTree');
                $this->pagetree->ext_IconMode = $BE_USER->getTSConfigVal('options.pageTree.disableIconLinkToContextmenu');
                $this->pagetree->ext_showPageId = $BE_USER->getTSConfigVal('options.pageTree.showPageIdWithTitle');
                $this->pagetree->thisScript = 'alt_db_navframe.php';
@@ -228,7 +106,8 @@ class SC_alt_db_navframe {
                $this->pagetree->addField('nav_hide');
                $this->pagetree->addField('url');
 
-#              $this->settingTemporaryMountPoint(11);
+
+               // $this->settingTemporaryMountPoint(11);
                        // Temporary DB mounts:
                $this->initializeTemporaryDBmount();
 
@@ -237,59 +116,38 @@ class SC_alt_db_navframe {
 
                        // Create template object:
                $this->doc = t3lib_div::makeInstance('template');
-               $this->doc->docType='xhtml_trans';
+               $this->doc->docType = 'xhtml_trans';
 
                        // Setting backPath
                $this->doc->backPath = $BACK_PATH;
 
-                       // Setting JavaScript for menu.
-               $this->doc->JScode=$this->doc->wrapScriptTags(
-       ($this->currentSubScript?'top.currentSubScript=unescape("'.rawurlencode($this->currentSubScript).'");':'').'
 
-               // 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
+               $this->doc->JScode  = '
+               <script type="text/javascript" src="prototype.js"></script>
+               <script type="text/javascript" src="tree.js"></script>'."\n";
 
-               '.($this->doHighlight?'hilight_row("web",highLightID+"_"+bank);':'').'
+               $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.'";
+               DragDrop.changeURL = "'.$this->backPath.'alt_clickmenu.php";
+               DragDrop.backPath  = "'.t3lib_div::shortMD5(''.'|'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']).'";
+               DragDrop.table     = "pages";
 
-               '.(!$GLOBALS['CLIENT']['FORMSTYLE'] ? '' : 'if (linkObj) {linkObj.blur();}').'
-               return false;
-       }
-
-               // Call this function, refresh_nav(), from another script in the backend if you want to refresh the navigation frame (eg. after having changed a page title or moved pages etc.)
-               // See t3lib_BEfunc::getSetUpdateSignal()
-       function refresh_nav()  {       //
-               window.setTimeout("_refresh_nav();",0);
-       }
-       function _refresh_nav() {       //
-               window.location.href="'.$this->pagetree->thisScript.'?unique='.time().'";
-       }
+               // 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;
 
-               // Highlighting rows in the page tree:
-       function hilight_row(frameSetModule,highLightID) {      //
+                       if (top.condensedMode) top.content.location.href = theUrl;
+                       else                   parent.list_frame.location.href=theUrl;
 
-                       // Remove old:
-               theObj = document.getElementById(top.fsMod.navFrameHighlightedID[frameSetModule]);
-               if (theObj)     {
-                       theObj.className = "";
+                       '.($this->doHighlight ? 'Tree.highlightActiveItem("web", highlightID + "_" + bank);' : '').'
+                       '.(!$GLOBALS['CLIENT']['FORMSTYLE'] ? '' : 'if (linkObj) linkObj.blur(); ').'
+                       return false;
                }
-
-                       // Set new:
-               top.fsMod.navFrameHighlightedID[frameSetModule] = highLightID;
-               theObj = document.getElementById(highLightID);
-               if (theObj)     {
-                       theObj.className = "navFrameHL";
-               }
-       }
-
-       '.($this->cMR?"jumpTo(top.fsMod.recentIds['web'],'');":'').';
+               '.($this->cMR?"jumpTo(top.fsMod.recentIds['web'],'');":'').'
                ');
 
                        // Click menu code is added:
@@ -297,14 +155,9 @@ class SC_alt_db_navframe {
                $this->doc->bodyTagAdditions = $CMparts[1];
                $this->doc->JScode.= $CMparts[0];
                $this->doc->postCode.= $CMparts[2];
-
-                       // Drag and Drop code is added:
-               $DDparts=$this->doc->getDragDropCode('pages');
-               // ignore the $DDparts[1] for now
-               $this->doc->JScode.= $DDparts[0];
-               $this->doc->postCode.= $DDparts[2];
        }
 
+
        /**
         * Main function, rendering the browsable page tree
         *
@@ -316,10 +169,15 @@ class SC_alt_db_navframe {
                        // Produce browse-tree:
                $tree = $this->pagetree->getBrowsableTree();
 
-                       // Start page:
-               $this->content = '';
-               $this->content.= $this->doc->startPage('Page tree');
+                       // output only the tree if this is an ajax call
+               if (t3lib_div::_GP('ajax')) {
+                       $this->content = $tree;
+                       return;
+               }
 
+                       // Start page:
+               $this->content = $this->doc->startPage('TYPO3 Page Tree');
+               
                        // Outputting workspace info
                if ($GLOBALS['BE_USER']->workspace!==0 || $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.onlineWorkspaceInfo'))  {
                        switch($GLOBALS['BE_USER']->workspace)  {
@@ -360,23 +218,24 @@ class SC_alt_db_navframe {
                $this->content.= $tree;
 
                        // Outputting refresh-link
-               $refreshUrl = t3lib_div::getIndpEnv('REQUEST_URI');
                $this->content.= '
                        <p class="c-refresh">
-                               <a href="'.htmlspecialchars($refreshUrl).'">'.
+                               <a href="'.htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI')).'">'.
                                '<img'.t3lib_iconWorks::skinImg('','gfx/refresh_n.gif','width="14" height="14"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.refresh',1).'" alt="" />'.
-                               '</a><a href="'.htmlspecialchars($refreshUrl).'">'.
                                $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.refresh',1).'</a>
                        </p>
                        <br />';
 
+
                        // CSH icon:
                $this->content.= t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'pagetree', $GLOBALS['BACK_PATH']);
 
-                       // Adding highlight - JavaScript
-               if ($this->doHighlight) $this->content .=$this->doc->wrapScriptTags('
-                       hilight_row("",top.fsMod.navFrameHighlightedID["web"]);
-               ');
+
+                       // Adding javascript for drag & drop activation and highlighting
+               $this->content .=$this->doc->wrapScriptTags('
+                       '.($this->doHighlight ? 'Tree.highlightActiveItem("",top.fsMod.navFrameHighlightedID["web"]);' : '').'
+                       '.(!$this->doc->isCMlayers() ? 'Tree.activateDragDrop = false;' : 'Tree.registerDragDropHandlers();')
+               );
        }
 
        /**
@@ -385,8 +244,10 @@ class SC_alt_db_navframe {
         * @return      void
         */
        function printContent() {
-               $this->content.= $this->doc->endPage();
-               $this->content = $this->doc->insertStylesAndJS($this->content);
+               if (!t3lib_div::_GP('ajax')) {
+                       $this->content.= $this->doc->endPage();
+                       $this->content = $this->doc->insertStylesAndJS($this->content);
+               }
                echo $this->content;
        }
 
@@ -394,13 +255,6 @@ class SC_alt_db_navframe {
 
 
 
-
-
-
-
-
-
-
        /**********************************
         *
         * Temporary DB mounts
@@ -440,6 +294,7 @@ class SC_alt_db_navframe {
                }
        }
 
+
        /**
         * Setting temporary page id as DB mount
         *
@@ -454,6 +309,7 @@ class SC_alt_db_navframe {
        }
 }
 
+
 // Include extension?
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/alt_db_navframe.php'])      {
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/alt_db_navframe.php']);
@@ -463,17 +319,10 @@ if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/alt_d
 
 
 
-
-
-
-
-
-
-
 // Make instance:
 $SOBE = t3lib_div::makeInstance('SC_alt_db_navframe');
 $SOBE->init();
 $SOBE->main();
 $SOBE->printContent();
 
-?>
+?>
\ No newline at end of file
index 3428560..40bce6f 100755 (executable)
  *
  */
 
-
-$BACK_PATH='';
-require ('init.php');
-require ('template.php');
-require_once (PATH_t3lib.'class.t3lib_foldertree.php');
-
-
-/**
- * Extension class for the t3lib_filetree class, needed for drag and drop functionality
- *
- * @author     Sebastian Kurfuerst <sebastian@garbage-group.de>
- * @package TYPO3
- * @subpackage core
- * @see class t3lib_browseTree
- */
-class localFolderTree extends t3lib_folderTree {
-
-       var $ext_IconMode;
-
-       /**
-        * Calls init functions
-        *
-        * @return      void
-        */
-       function localFolderTree() {
-               parent::t3lib_folderTree();
-       }
-
-       /**
-        * Wrapping icon in browse tree
-        *
-        * @param       string          Icon IMG code
-        * @param       array           Data row for element.
-        * @return      string          Page icon
-        */
-       function wrapIcon($icon,&$row)  {
-
-                       // Add title attribute to input icon tag
-               $theFolderIcon = $this->addTagAttributes($icon,($this->titleAttrib ? $this->titleAttrib.'="'.$this->getTitleAttrib($row).'"' : ''));
-
-                       // Wrap icon in click-menu link.
-               if (!$this->ext_IconMode)       {
-                       $theFolderIcon = $GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon($theFolderIcon,$row['path'],'',0);
-               } elseif (!strcmp($this->ext_IconMode,'titlelink'))     {
-                       $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->domIdPrefix.$this->getId($row).'\','.$this->bank.');';
-                       $theFolderIcon='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.$theFolderIcon.'</a>';
-               }
-                       // Wrap icon in a drag/drop span.
-               $spanOnDrag = htmlspecialchars('return dragElement("'.$this->getJumpToParam($row).'", "'.$row['uid'].'")');
-               $spanOnDrop = htmlspecialchars('return dropElement("'.$this->getJumpToParam($row).'")');
-               $dragDropIcon = '<span id="dragIconID_'.$row['uid'].'" ondragstart="'.$spanOnDrag.'" onmousedown="'.$spanOnDrag.'" onmouseup="'.$spanOnDrop.'">'.$theFolderIcon.'</span>';
-
-               return $dragDropIcon;
-       }
-
-       /**
-        * Wrapping $title in a-tags.
-        *
-        * @param       string          Title string
-        * @param       string          Item record
-        * @param       integer         Bank pointer (which mount point number)
-        * @return      string
-        * @access private
-        */
-       function wrapTitle($title,$row,$bank=0) {
-               $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->domIdPrefix.$this->getId($row).'\','.$bank.');';
-               $CSM = '';
-               if ($GLOBALS['TYPO3_CONF_VARS']['BE']['useOnContextMenuHandler'])       {
-                       $CSM = ' oncontextmenu="'.htmlspecialchars($GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon('',$row['path'],'',0,'&bank='.$this->bank,'',TRUE)).'"';
-               }
-               $theFolderTitle='<a href="#" onclick="'.htmlspecialchars($aOnClick).'"'.$CSM.'>'.$title.'</a>';
-
-                       // Wrap title in a drag/drop span.
-               $spanOnDrag = htmlspecialchars('return dragElement("'.$this->getJumpToParam($row).'","'.$row['uid'].'")');
-               $spanOnDrop = htmlspecialchars('return dropElement("'.$this->getJumpToParam($row).'")');
-               $dragDropTitle = '<span id="dragTitleID_'.$row['uid'].'" ondragstart="'.$spanOnDrag.'" onmousedown="'.$spanOnDrag.'" onmouseup="'.$spanOnDrop.'">'.$theFolderTitle.'</span>';
-               return $dragDropTitle;
-       }
-}
-
+$BACK_PATH = '';
+require('init.php');
+require('template.php');
+require_once('class.filelistfoldertree.php');
 
 
 /**
@@ -168,7 +92,7 @@ class SC_alt_file_navframe {
                $this->cMR = t3lib_div::_GP('cMR');
 
                        // Create folder tree object:
-               $this->foldertree = t3lib_div::makeInstance('localFolderTree');
+               $this->foldertree = t3lib_div::makeInstance('filelistFolderTree');
                $this->foldertree->ext_IconMode = $BE_USER->getTSConfigVal('options.folderTree.disableIconLinkToContextmenu');
                $this->foldertree->thisScript = 'alt_file_navframe.php';
 
@@ -177,72 +101,46 @@ class SC_alt_file_navframe {
 
                        // Create template object:
                $this->doc = t3lib_div::makeInstance('template');
-               $this->doc->docType='xhtml_trans';
+               $this->doc->docType = 'xhtml_trans';
 
                        // Setting backPath
                $this->doc->backPath = $BACK_PATH;
 
-                       // Setting JavaScript for menu.
-               $this->doc->JScode=$this->doc->wrapScriptTags(
-       ($this->currentSubScript?'top.currentSubScript=unescape("'.rawurlencode($this->currentSubScript).'");':'').'
-
-               // 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
+               $this->doc->JScode  = '
+               <script type="text/javascript" src="prototype.js"></script>
+               <script type="text/javascript" src="tree.js"></script>'."\n";
 
-        '.($this->doHighlight?'hilight_row("file",highLightID+"_"+bank);':'').'
-               '.(!$CLIENT['FORMSTYLE'] ? '' : 'if (linkObj) {linkObj.blur();}').'
-               return false;
-       }
+                       // Setting JavaScript for menu.
+               $this->doc->JScode .= $this->doc->wrapScriptTags(
+               ($this->currentSubScript?'top.currentSubScript=unescape("'.rawurlencode($this->currentSubScript).'");':'').'
 
+               // setting prefs for pagetree and drag & drop
+               Tree.thisScript    = "'.$this->foldertree->thisScript.'";
+               DragDrop.changeURL = "'.$this->backPath.'alt_clickmenu.php";
+               DragDrop.backPath  = "'.t3lib_div::shortMD5(''.'|'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']).'";
+               DragDrop.table     = "folders";
 
-               // Call this function, refresh_nav(), from another script in the backend if you want to refresh the navigation frame (eg. after having changed a page title or moved pages etc.)
-               // See t3lib_BEfunc::getSetUpdateSignal()
-       function refresh_nav()  {       //
-               window.setTimeout("_refresh_nav();",0);
-       }
-       function _refresh_nav() {       //
-               window.location.href="'.$this->pagetree->thisScript.'?unique='.time().'";
-       }
-
-               // Highlighting rows in the folder tree:
-       function hilight_row(frameSetModule,highLightID) {      //
+               // 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;
 
-                       // Remove old:
-               theObj = document.getElementById(top.fsMod.navFrameHighlightedID[frameSetModule]);
-               if (theObj)     {
-                       theObj.style.backgroundColor="";
-               }
+                       if (top.condensedMode) top.content.location.href = theUrl;
+                       else                   parent.list_frame.location.href = theUrl;
 
-                       // Set new:
-               top.fsMod.navFrameHighlightedID[frameSetModule] = highLightID;
-               theObj = document.getElementById(highLightID);
-               if (theObj)     {
-                       theObj.style.backgroundColor="'.t3lib_div::modifyHTMLColorAll($this->doc->bgColor,-20).'";
+                       '.($this->doHighlight ? 'Tree.highlightActiveItem("file", highlightID + "_" + bank);' : '').'
+                       '.(!$GLOBALS['CLIENT']['FORMSTYLE'] ? '' : 'if (linkObj) linkObj.blur(); ').'
+                       return false;
                }
-       }
-
-       '.($this->cMR?"jumpTo(top.fsMod.recentIds['file'],'');":'').';
-               ');
+               '.($this->cMR ? " jumpTo(top.fsMod.recentIds['file'],'');" : '')
+               );
 
                        // Click menu code is added:
                $CMparts=$this->doc->getContextMenuCode();
                $this->doc->bodyTagAdditions = $CMparts[1];
-               $this->doc->JScode.=$CMparts[0];
+               $this->doc->JScode.= $CMparts[0];
                $this->doc->postCode.= $CMparts[2];
-
-                       // Drag and Drop code is added:
-               $DDparts=$this->doc->getDragDropCode('folders');
-                       // ignore the $DDparts[1] for now
-               $this->doc->JScode.= $DDparts[0];
-               $this->doc->postCode.= $DDparts[2];
        }
 
        /**
@@ -256,24 +154,35 @@ class SC_alt_file_navframe {
                        // Produce browse-tree:
                $tree = $this->foldertree->getBrowsableTree();
 
-               $this->content = '';
-               $this->content.= $this->doc->startPage('Folder tree');
+                       // output only the tree if this is an ajax call
+               if (t3lib_div::_GP('ajax')) {
+                       $this->content = $tree;
+                       return;
+               }
+
+               $this->content = $this->doc->startPage('TYPO3 Folder Tree');
+
+                       // Outputting page tree:
                $this->content.= $tree;
-               $refreshUrl = t3lib_div::getIndpEnv('REQUEST_URI');
+
+                       // Outputting refresh-link
                $this->content.= '
                        <p class="c-refresh">
-                               <a href="'.htmlspecialchars($refreshUrl).'">'.
+                               <a href="'.htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI')).'">'.
                                '<img'.t3lib_iconWorks::skinImg('','gfx/refresh_n.gif','width="14" height="14"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.refresh',1).'" alt="" />'.
-                               '</a><a href="'.htmlspecialchars($refreshUrl).'">'.
                                $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.refresh',1).'</a>
                        </p>
                        <br />';
+
+                       // CSH icon:
                $this->content.= t3lib_BEfunc::cshItem('xMOD_csh_corebe', 'filetree', $GLOBALS['BACK_PATH']);
 
-                       // Adding highlight - JavaScript
-               if ($this->doHighlight) $this->content .=$this->doc->wrapScriptTags('
-                       hilight_row("",top.fsMod.navFrameHighlightedID["file"]);
-               ');
+                       // Adding javascript for drag & drop activation and highlighting
+               $this->content .=$this->doc->wrapScriptTags('
+                       '.($this->doHighlight ? 'Tree.highlightActiveItem("", top.fsMod.navFrameHighlightedID["file"]);' : '').'
+                       '.(!$this->doc->isCMlayers() ? 'Tree.activateDragDrop = false;' : 'Tree.registerDragDropHandlers();')
+               );
+
        }
 
        /**
@@ -282,8 +191,10 @@ class SC_alt_file_navframe {
         * @return      void
         */
        function printContent() {
-               $this->content.= $this->doc->endPage();
-               $this->content = $this->doc->insertStylesAndJS($this->content);
+               if (!t3lib_div::_GP('ajax')) {
+                       $this->content.= $this->doc->endPage();
+                       $this->content = $this->doc->insertStylesAndJS($this->content);
+               }
                echo $this->content;
        }
 }
diff --git a/typo3/class.filelistfoldertree.php b/typo3/class.filelistfoldertree.php
new file mode 100644 (file)
index 0000000..521ee35
--- /dev/null
@@ -0,0 +1,424 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com)\r
+*  All rights reserved\r
+*\r
+*  This script is part of the TYPO3 project. The TYPO3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*  A copy is found in the textfile GPL.txt and important notices to the license\r
+*  from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * Folder navigation tree for the File main module\r
+ *\r
+ * @author     Benjamin Mack   <bmack@xnos.org>\r
+ *\r
+ *\r
+ * [CLASS/FUNCTION INDEX of SCRIPT]\r
+ *\r
+ *\r
+ *\r
+ *   71: class fileListTree extends t3lib_browseTree\r
+ *   81:     function webPageTree()\r
+ *   92:     function wrapIcon($icon,&$row)\r
+ *  130:     function wrapStop($str,$row)\r
+ *  146:     function wrapTitle($title,$row,$bank=0)\r
+ *  165:     function printTree($treeArr = '')\r
+ *  271:     function PMicon($row,$a,$c,$nextCount,$exp)\r
+ *  292:     function PMiconATagWrap($icon, $cmd, $isExpand = true)\r
+ *  309:     function getBrowsableTree()\r
+ *  377:     function getTree($uid, $depth=999, $depthData='',$blankLineCode='',$subCSSclass='')\r
+ *\r
+ *\r
+ * TOTAL FUNCTIONS: 9\r
+ * (This index is automatically created/updated by the extension "extdeveval")\r
+ *\r
+ */\r
+\r
+require_once (PATH_t3lib.'class.t3lib_foldertree.php');\r
+\r
+\r
+\r
+/**\r
+ * Extension class for the t3lib_filetree class, needed for drag and drop and ajax functionality\r
+ *\r
+ * @author     Sebastian Kurfuerst <sebastian@garbage-group.de>\r
+ * @author     Benjamin Mack   <bmack@xnos.org>\r
+ * @package TYPO3\r
+ * @subpackage core\r
+ * @see class t3lib_browseTree\r
+ */\r
+class filelistFolderTree extends t3lib_folderTree {\r
+\r
+       var $ext_IconMode;\r
+\r
+       /**\r
+        * Calls init functions\r
+        *\r
+        * @return      void\r
+        */\r
+       function filelistFolderTree() {\r
+               parent::t3lib_folderTree();\r
+       }\r
+\r
+       /**\r
+        * Wrapping icon in browse tree\r
+        *\r
+        * @param       string          Icon IMG code\r
+        * @param       array           Data row for element.\r
+        * @return      string          Page icon\r
+        */\r
+       function wrapIcon($icon,&$row)  {\r
+\r
+                       // Add title attribute to input icon tag\r
+               $theFolderIcon = $this->addTagAttributes($icon,($this->titleAttrib ? $this->titleAttrib.'="'.$this->getTitleAttrib($row).'"' : ''));\r
+\r
+                       // Wrap icon in click-menu link.\r
+               if (!$this->ext_IconMode)       {\r
+                       $theFolderIcon = $GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon($theFolderIcon,$row['path'],'',0);\r
+               } elseif (!strcmp($this->ext_IconMode,'titlelink'))     {\r
+                       $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->domIdPrefix.$this->getId($row).'\','.$this->bank.');';\r
+                       $theFolderIcon='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.$theFolderIcon.'</a>';\r
+               }\r
+                       // Wrap icon in a drag/drop span.\r
+               return '<span class="dragIcon" id="dragIconID_'.$this->getJumpToParam($row).'">'.$theFolderIcon.'</span>';\r
+       }\r
+\r
+\r
+       /**\r
+        * Wrapping $title in a-tags.\r
+        *\r
+        * @param       string          Title string\r
+        * @param       string          Item record\r
+        * @param       integer         Bank pointer (which mount point number)\r
+        * @return      string\r
+        * @access private\r
+        */\r
+       function wrapTitle($title,$row,$bank=0) {\r
+               $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->domIdPrefix.$this->getId($row).'\','.$bank.');';\r
+               $CSM = '';\r
+               if ($GLOBALS['TYPO3_CONF_VARS']['BE']['useOnContextMenuHandler'])       {\r
+                       $CSM = ' oncontextmenu="'.htmlspecialchars($GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon('',$row['path'],'',0,'&bank='.$this->bank,'',TRUE)).'"';\r
+               }\r
+               $theFolderTitle='<a href="#" onclick="'.htmlspecialchars($aOnClick).'"'.$CSM.'>'.$title.'</a>';\r
+\r
+                       // Wrap title in a drag/drop span.\r
+               return '<span class="dragTitle" id="dragTitleID_'.$this->getJumpToParam($row).'">'.$theFolderTitle.'</span>';\r
+       }\r
+\r
+\r
+\r
+\r
+       /**\r
+        * Compiles the HTML code for displaying the structure found inside the ->tree array\r
+        *\r
+        * @param       array           "tree-array" - if blank string, the internal ->tree array is used.\r
+        * @return      string          The HTML code for the tree\r
+        */\r
+       function printTree($treeArr='') {\r
+               $titleLen = intval($this->BE_USER->uc['titleLen']);\r
+               if (!is_array($treeArr))        $treeArr = $this->tree;\r
+\r
+               $out = '\r
+                       <!-- TYPO3 folder tree structure. -->\r
+                       <ul class="tree">\r
+               ';\r
+               $titleLen=intval($this->BE_USER->uc['titleLen']);\r
+               if (!is_array($treeArr))        $treeArr=$this->tree;\r
+\r
+                       // -- evaluate AJAX request\r
+                       // IE takes anchor as parameter\r
+               $PM = t3lib_div::_GP('PM');\r
+               if(($PMpos = strpos($PM, '#')) !== false) { $PM = substr($PM, 0, $PMpos); }\r
+               $PM = explode('_', $PM);\r
+               if(($isAjaxCall = t3lib_div::_GP('ajax')) && is_array($PM) && count($PM)==4)    {\r
+                       if($PM[1])      {\r
+                               $expandedFolderUid = $PM[2];\r
+                               $ajaxOutput = '';\r
+                               $invertedDepthOfAjaxRequestedItem = 0; // We don't know yet. Will be set later.\r
+                               $doExpand = true;\r
+                       } else  {\r
+                               $expandedFolderUid = $PM[2];\r
+                               $doCollapse = true;\r
+                       }\r
+               }\r
+\r
+\r
+               // we need to count the opened <ul>'s every time we dig into another level, \r
+               // so we know how many we have to close when all children are done rendering\r
+               $closeDepth = array();\r
+\r
+               foreach($treeArr as $k => $v)   {\r
+                       $classAttr = $v['row']['_CSSCLASS'];\r
+                       $uid       = $v['row']['uid'];\r
+                       $idAttr = htmlspecialchars($this->domIdPrefix.$this->getId($v['row']).'_'.$v['bank']);\r
+                       $itemHTML  = '';\r
+\r
+                       // if this item is the start of a new level, \r
+                       // then a new level <ul> is needed, but not in ajax mode\r
+                       if($v['isFirst'] && !($doCollapse) && !($doExpand && $expandedFolderUid == $uid))       {\r
+                               $itemHTML = "<ul>\n";\r
+                       }\r
+\r
+                       // add CSS classes to the list item\r
+                       if($v['hasSub']) { $classAttr = ($classAttr) ? ' expanded': 'expanded'; }\r
+                       if($v['isLast']) { $classAttr = ($classAttr) ? ' last'  : 'last';        }\r
+\r
+                       $itemHTML .='\r
+                               <li id="'.$idAttr.'"'.($classAttr ? ' class="'.$classAttr.'"' : '').'>'.\r
+                                       $v['HTML'].\r
+                                       $this->wrapTitle($this->getTitleStr($v['row'],$titleLen),$v['row'],$v['bank']);\r
+\r
+\r
+                       if(!$v['hasSub']) { $itemHTML .= "</li>\n"; }\r
+\r
+                       // we have to remember if this is the last one\r
+                       // on level X so the last child on level X+1 closes the <ul>-tag\r
+                       if($v['isLast'] && !($doExpand && $expandedFolderUid == $uid)) { $closeDepth[$v['invertedDepth']] = 1; }\r
+\r
+\r
+                       // if this is the last one and does not have subitems, we need to close\r
+                       // the tree as long as the upper levels have last items too\r
+                       if($v['isLast'] && !$v['hasSub'] && !$doCollapse && !($doExpand && $expandedFolderUid == $uid)) {\r
+                               for ($i = $v['invertedDepth']; $closeDepth[$i] == 1; $i++) {\r
+                                       $closeDepth[$i] = 0;\r
+                                       $itemHTML .= "</ul></li>\n";\r
+                               }\r
+                       }\r
+\r
+                       // ajax request: collapse\r
+                       if($doCollapse && $expandedFolderUid == $uid) { return $itemHTML; }\r
+\r
+                       // ajax request: expand\r
+                       if($doExpand && $expandedFolderUid == $uid) {\r
+                               $ajaxOutput .= $itemHTML;\r
+                               $invertedDepthOfAjaxRequestedItem = $v['invertedDepth'];\r
+                       } elseif($invertedDepthOfAjaxRequestedItem) { \r
+                               if($v['invertedDepth'] < $invertedDepthOfAjaxRequestedItem) {\r
+                                       $ajaxOutput .= $itemHTML;\r
+                               } else {\r
+                                       return $ajaxOutput;\r
+                               }\r
+                       }\r
+\r
+                       $out .= $itemHTML;\r
+               }\r
+\r
+               if($ajaxOutput) { return $ajaxOutput; }\r
+\r
+               // finally close the first ul\r
+               $out .= "</ul>\n";\r
+               return $out;\r
+       }\r
+\r
+\r
+       /**\r
+        * Generate the plus/minus icon for the browsable tree.\r
+        *\r
+        * @param       array           record for the entry\r
+        * @param       integer         The current entry number\r
+        * @param       integer         The total number of entries. If equal to $a, a "bottom" element is returned.\r
+        * @param       integer         The number of sub-elements to the current element.\r
+        * @param       boolean         The element was expanded to render subelements if this flag is set.\r
+        * @return      string          Image tag with the plus/minus icon.\r
+        * @access private\r
+        * @see t3lib_pageTree::PMicon()\r
+        */\r
+       function PMicon($row,$a,$c,$nextCount,$exp)     {\r
+               $PM   = $nextCount ? ($exp ? 'minus' : 'plus') : 'join';\r
+               $BTM  = ($a == $c) ? 'bottom' : '';\r
+               $icon = '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.$PM.$BTM.'.gif','width="18" height="16"').' alt="" />';\r
+\r
+               if ($nextCount) {\r
+                       $cmd = $this->bank.'_'.($exp?'0_':'1_').$row['uid'].'_'.$this->treeName;\r
+                       $icon = $this->PMiconATagWrap($icon,$cmd,!$exp);\r
+               }\r
+               return $icon;\r
+       }\r
+\r
+\r
+       /**\r
+        * Wrap the plus/minus icon in a link\r
+        *\r
+        * @param       string          HTML string to wrap, probably an image tag.\r
+        * @param       string          Command for 'PM' get var\r
+        * @return      string          Link-wrapped input string\r
+        * @access private\r
+        */\r
+       function PMiconATagWrap($icon, $cmd, $isExpand = true)  {\r
+               if ($this->thisScript) {\r
+                               // activate dynamic ajax-based tree\r
+                       $js = htmlspecialchars('Tree.load(\''.$cmd.'\', '.intval($isExpand).', this);');\r
+                       return '<a class="pm" onclick="'.$js.'">'.$icon.'</a>';\r
+               } else {\r
+                       return $icon;\r
+               }\r
+       }\r
+\r
+\r
+\r
+       /**\r
+        * Will create and return the HTML code for a browsable tree of folders.\r
+        * Is based on the mounts found in the internal array ->MOUNTS (set in the constructor)\r
+        *\r
+        * @return      string          HTML code for the browsable tree\r
+        */\r
+       function getBrowsableTree()     {\r
+\r
+                       // Get stored tree structure AND updating it if needed according to incoming PM GET var.\r
+               $this->initializePositionSaving();\r
+\r
+                       // Init done:\r
+               $titleLen = intval($this->BE_USER->uc['titleLen']);\r
+               $treeArr = array();\r
+\r
+                       // Traverse mounts:\r
+               foreach($this->MOUNTS as $key => $val)  {\r
+                       $specUID = t3lib_div::md5int($val['path']);\r
+                       $this->specUIDmap[$specUID] = $val['path'];\r
+\r
+                               // Set first:\r
+                       $this->bank = $val['nkey'];\r
+                       $isOpen = $this->stored[$val['nkey']][$specUID] || $this->expandFirst;\r
+                       $this->reset();\r
+\r
+                               // Set PM icon:\r
+                       $cmd = $this->bank.'_'.($isOpen ? '0_' : '1_').$specUID.'_'.$this->treeName;\r
+                       $icon='<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.($isOpen?'minus':'plus').'only.gif').' alt="" />';\r
+                       $firstHtml= $this->PM_ATagWrap($icon,$cmd);\r
+\r
+                       switch($val['type'])    {\r
+                               case 'user':    $icon = 'gfx/i/_icon_ftp_user.gif';     break;\r
+                               case 'group':   $icon = 'gfx/i/_icon_ftp_group.gif'; break;\r
+                               default:                $icon = 'gfx/i/_icon_ftp.gif'; break;\r
+                       }\r
+\r
+                               // Preparing rootRec for the mount\r
+                       $firstHtml.=$this->wrapIcon('<img'.t3lib_iconWorks::skinImg($this->backPath,$icon,'width="18" height="16"').' alt="" />',$val);\r
+                       $row=array();\r
+                       $row['uid']   = $specUID;\r
+                       $row['path']  = $val['path'];\r
+                       $row['title'] = $val['name'];\r
+\r
+                               // Add the root of the mount to ->tree\r
+                       $this->tree[] = array('HTML' => $firstHtml, 'row' => $row, 'bank' => $this->bank);\r
+\r
+                               // If the mount is expanded, go down:\r
+                       if ($isOpen)\r
+                               $this->getFolderTree($val['path'], 999);\r
+\r
+                               // Add tree:\r
+                       $treeArr = array_merge($treeArr, $this->tree);\r
+               }\r
+               return $this->printTree($treeArr);\r
+       }\r
+\r
+\r
+\r
+       /**\r
+        * Fetches the data for the tree\r
+        *\r
+        * @param       string          Abs file path\r
+        * @param       integer         Max depth (recursivity limit)\r
+        * @return      integer         The count of items on the level\r
+        * @see getBrowsableTree()\r
+        */\r
+       function getFolderTree($files_path, $depth=999) {\r
+\r
+                       // This generates the directory tree\r
+               $dirs = t3lib_div::get_dirs($files_path);\r
+               if (!is_array($dirs)) return 0;\r
+\r
+               sort($dirs);\r
+               $c = count($dirs);\r
+               \r
+               $depth = intval($depth);\r
+               $HTML = '';\r
+               $a = 0;\r
+\r
+               foreach($dirs as $key => $val)  {\r
+                       $a++;\r
+                       $this->tree[] = array();        // Reserve space.\r
+                       end($this->tree);\r
+                       $treeKey = key($this->tree);    // Get the key for this space\r
+\r
+                       $val = ereg_replace('^\./','',$val);\r
+                       $title = $val;\r
+                       $path = $files_path.$val.'/';\r
+\r
+                       $specUID = t3lib_div::md5int($path);\r
+                       $this->specUIDmap[$specUID] = $path;\r
+\r
+                       $row = array();\r
+                       $row['path']  = $path;\r
+                       $row['uid']   = $specUID;\r
+                       $row['title'] = $title;\r
+\r
+                       // Make a recursive call to the next level\r
+                       if ($depth > 1 && $this->expandNext($specUID))  {\r
+                               $nextCount = $this->getFolderTree(\r
+                                       $path,\r
+                                       $depth-1,\r
+                                       $this->makeHTML ? '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.($a == $c ? 'blank' : 'line').'.gif','width="18" height="16"').' alt="" />' : ''\r
+                               );\r
+                               $exp = 1;       // Set "did expand" flag\r
+                       } else {\r
+                               $nextCount = $this->getCount($path);\r
+                               $exp = 0;       // Clear "did expand" flag\r
+                       }\r
+\r
+                               // Set HTML-icons, if any:\r
+                       if ($this->makeHTML)    {\r
+                               $HTML = $this->PMicon($row,$a,$c,$nextCount,$exp);\r
+\r
+                               $icon = 'gfx/i/_icon_'.t3lib_BEfunc::getPathType_web_nonweb($path).'folders.gif';\r
+                               if ($val == '_temp_')   {\r
+                                       $icon = 'gfx/i/sysf.gif';\r
+                                       $row['title']='TEMP';\r
+                                       $row['_title']='<b>TEMP</b>';\r
+                               }\r
+                               if ($val == '_recycler_')       {\r
+                                       $icon = 'gfx/i/recycler.gif';\r
+                                       $row['title']='RECYCLER';\r
+                                       $row['_title']='<b>RECYCLER</b>';\r
+                               }\r
+                               $HTML .= $this->wrapIcon('<img'.t3lib_iconWorks::skinImg($this->backPath, $icon, 'width="18" height="16"').' alt="" />',$row);\r
+                       }\r
+\r
+                               // Finally, add the row/HTML content to the ->tree array in the reserved key.\r
+                       $this->tree[$treeKey] = Array(\r
+                               'row'    => $row,\r
+                               'HTML'   => $HTML,\r
+                               'hasSub' => $nextCount && $this->expandNext($specUID),\r
+                               'isFirst'=> ($a == 1),\r
+                               'isLast' => false,\r
+                               'invertedDepth'=> $depth,\r
+                               'bank'   => $this->bank\r
+                       );\r
+               }\r
+\r
+               if($a) { $this->tree[$treeKey]['isLast'] = true; }\r
+               return $c;\r
+       }\r
+}\r
+\r
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.filelistfoldertree.php'])     {\r
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.filelistfoldertree.php']);\r
+}\r
+?>
\ No newline at end of file
diff --git a/typo3/class.webpagetree.php b/typo3/class.webpagetree.php
new file mode 100644 (file)
index 0000000..9916bf3
--- /dev/null
@@ -0,0 +1,452 @@
+<?php\r
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com)\r
+*  All rights reserved\r
+*\r
+*  This script is part of the TYPO3 project. The TYPO3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*  A copy is found in the textfile GPL.txt and important notices to the license\r
+*  from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * Page navigation tree for the Web module\r
+ *\r
+ * Revised for TYPO3 3.6 2/2003 by Kasper Skaarhoj\r
+ * XHTML compliant\r
+ *\r
+ * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>\r
+ * @author     Benjamin Mack   <bmack@xnos.org>\r
+ *\r
+ *\r
+ * [CLASS/FUNCTION INDEX of SCRIPT]\r
+ *\r
+ *\r
+ *\r
+ *   71: class webPageTree extends t3lib_browseTree\r
+ *   81:     function webPageTree()\r
+ *   92:     function wrapIcon($icon,&$row)\r
+ *  130:     function wrapStop($str,$row)\r
+ *  146:     function wrapTitle($title,$row,$bank=0)\r
+ *  165:     function printTree($treeArr = '')\r
+ *  271:     function PMicon($row,$a,$c,$nextCount,$exp)\r
+ *  292:     function PMiconATagWrap($icon, $cmd, $isExpand = true)\r
+ *  309:     function getBrowsableTree()\r
+ *  377:     function getTree($uid, $depth=999, $depthData='',$blankLineCode='',$subCSSclass='')\r
+ *\r
+ *\r
+ * TOTAL FUNCTIONS: 9\r
+ * (This index is automatically created/updated by the extension "extdeveval")\r
+ *\r
+ */\r
+\r
+\r
+require_once(PATH_t3lib.'class.t3lib_browsetree.php');\r
+\r
+\r
+/**\r
+ * Extension class for the t3lib_browsetree class, specially made \r
+ * for browsing pages in the Web module\r
+ *\r
+ * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>\r
+ * @author     Benjamin Mack   <bmack@xnos.org>\r
+ * @package TYPO3\r
+ * @subpackage core\r
+ * @see class t3lib_browseTree\r
+ */\r
+class webPageTree extends t3lib_browseTree {\r
+\r
+       var $ext_showPageId;\r
+       var $ext_IconMode;\r
+\r
+       /**\r
+        * Calls init functions\r
+        *\r
+        * @return      void\r
+        */\r
+       function webPageTree() {\r
+               $this->init();\r
+       }\r
+\r
+       /**\r
+        * Wrapping icon in browse tree\r
+        *\r
+        * @param       string          Icon IMG code\r
+        * @param       array           Data row for element.\r
+        * @return      string          Page icon\r
+        */\r
+       function wrapIcon($icon,&$row)  {\r
+                       // If the record is locked, present a warning sign.\r
+               if ($lockInfo=t3lib_BEfunc::isRecordLocked('pages',$row['uid']))        {\r
+                       $aOnClick = 'alert('.$GLOBALS['LANG']->JScharCode($lockInfo['msg']).');return false;';\r
+                       $lockIcon='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.\r
+                               '<img'.t3lib_iconWorks::skinImg('','gfx/recordlock_warning3.gif','width="17" height="12"').' title="'.htmlspecialchars($lockInfo['msg']).'" alt="" />'.\r
+                               '</a>';\r
+               } else $lockIcon = '';\r
+\r
+                       // Add title attribute to input icon tag\r
+               $thePageIcon = $this->addTagAttributes($icon, $this->titleAttrib.'="'.$this->getTitleAttrib($row).'"');\r
+\r
+                       // Wrap icon in click-menu link.\r
+               if (!$this->ext_IconMode)       {\r
+                       $thePageIcon = $GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon($thePageIcon,'pages',$row['uid'],0,'&bank='.$this->bank);\r
+               } elseif (!strcmp($this->ext_IconMode,'titlelink'))     {\r
+                       $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->treeName.'\');';\r
+                       $thePageIcon='<a href="#" onclick="'.htmlspecialchars($aOnClick).'">'.$thePageIcon.'</a>';\r
+               }\r
+\r
+                       // Wrap icon in a drag/drop span.\r
+               $dragDropIcon = '<span class="dragIcon" id="dragIconID_'.$row['uid'].'">'.$thePageIcon.'</span>';\r
+\r
+                       // Add Page ID:\r
+               $pageIdStr = '';\r
+               if ($this->ext_showPageId) { $pageIdStr = '['.$row['uid'].']&nbsp;'; }\r
+\r
+               return $dragDropIcon.$lockIcon.$pageIdStr;\r
+       }\r
+\r
+       /**\r
+        * Adds a red "+" to the input string, $str, if the field "php_tree_stop" in the $row (pages) is set\r
+        *\r
+        * @param       string          Input string, like a page title for the tree\r
+        * @param       array           record row with "php_tree_stop" field\r
+        * @return      string          Modified string\r
+        * @access private\r
+        */\r
+       function wrapStop($str,$row)    {\r
+               if ($row['php_tree_stop'])      {\r
+                       $str.='<a href="'.htmlspecialchars(t3lib_div::linkThisScript(array('setTempDBmount' => $row['uid']))).'" class="typo3-red">+</a> ';\r
+               }\r
+               return $str;\r
+       }\r
+\r
+       /**\r
+        * Wrapping $title in a-tags.\r
+        *\r
+        * @param       string          Title string\r
+        * @param       string          Item record\r
+        * @param       integer         Bank pointer (which mount point number)\r
+        * @return      string\r
+        * @access      private\r
+        */\r
+       function wrapTitle($title,$row,$bank=0) {\r
+               $aOnClick = 'return jumpTo(\''.$this->getJumpToParam($row).'\',this,\''.$this->domIdPrefix.$this->getId($row).'\','.$bank.');';\r
+               $CSM = '';\r
+               if ($GLOBALS['TYPO3_CONF_VARS']['BE']['useOnContextMenuHandler'])       {\r
+                       $CSM = ' oncontextmenu="return '.htmlspecialchars($GLOBALS['TBE_TEMPLATE']->wrapClickMenuOnIcon('','pages',$row['uid'],0,'&bank='.$this->bank,'',TRUE)).';"';\r
+               }\r
+               $thePageTitle='<a href="#" onclick="'.htmlspecialchars($aOnClick).'"'.$CSM.'>'.$title.'</a>';\r
+\r
+                       // Wrap title in a drag/drop span.\r
+               return '<span class="dragTitle" id="dragTitleID_'.$row['uid'].'">'.$thePageTitle.'</span>';\r
+       }\r
+\r
+       \r
+       /**\r
+        * Compiles the HTML code for displaying the structure found inside the ->tree array\r
+        *\r
+        * @param       array           "tree-array" - if blank string, the internal ->tree array is used.\r
+        * @return      string          The HTML code for the tree\r
+        */\r
+       function printTree($treeArr = '')   {\r
+               $titleLen = intval($this->BE_USER->uc['titleLen']);\r
+               if (!is_array($treeArr))        $treeArr = $this->tree;\r
+\r
+               $out = '\r
+                       <!-- TYPO3 tree structure. -->\r
+                       <ul class="tree">\r
+               ';\r
+\r
+                       // -- evaluate AJAX request\r
+                       // IE takes anchor as parameter\r
+               $PM = t3lib_div::_GP('PM');\r
+               if(($PMpos = strpos($PM, '#')) !== false) { $PM = substr($PM, 0, $PMpos); }\r
+               $PM = explode('_', $PM);\r
+               if(($isAjaxCall = t3lib_div::_GP('ajax')) && is_array($PM) && count($PM)==4)    {\r
+                       if($PM[1])      {\r
+                               $expandedPageUid = $PM[2];\r
+                               $ajaxOutput = '';\r
+                               $invertedDepthOfAjaxRequestedItem = 0; // We don't know yet. Will be set later.\r
+                               $doExpand = true;\r
+                       } else  {\r
+                               $collapsedPageUid = $PM[2];\r
+                               $doCollapse = true;\r
+                       }\r
+               }\r
+\r
+               // we need to count the opened <ul>'s every time we dig into another level, \r
+               // so we know how many we have to close when all children are done rendering\r
+               $closeDepth = array();\r
+\r
+               foreach($treeArr as $k => $v)   {\r
+                       $classAttr = $v['row']['_CSSCLASS'];\r
+                       $uid       = $v['row']['uid'];\r
+                       $idAttr = htmlspecialchars($this->domIdPrefix.$this->getId($v['row']).'_'.$v['bank']);\r
+                       $itemHTML  = '';\r
+\r
+                       // if this item is the start of a new level, \r
+                       // then a new level <ul> is needed, but not in ajax mode\r
+                       if($v['isFirst'] && !($doCollapse) && !($doExpand && $expandedPageUid == $uid)) {\r
+                               $itemHTML = '<ul>';\r
+                       }\r
+\r
+                       // add CSS classes to the list item\r
+                       if($v['hasSub']) { $classAttr .= ($classAttr) ? ' expanded': 'expanded'; }\r
+                       if($v['isLast']) { $classAttr .= ($classAttr) ? ' last' : 'last';        }\r
+\r
+                       $itemHTML .='\r
+                               <li id="'.$idAttr.'"'.($classAttr ? ' class="'.$classAttr.'"' : '').'>'.\r
+                                       $v['HTML'].\r
+                                       $this->wrapTitle($this->getTitleStr($v['row'],$titleLen),$v['row'],$v['bank'])."\n";\r
+\r
+\r
+                       if(!$v['hasSub']) { $itemHTML .= '</li>'; }\r
+\r
+                       // we have to remember if this is the last one\r
+                       // on level X so the last child on level X+1 closes the <ul>-tag\r
+                       if($v['isLast'] && !($doExpand && $expandedPageUid == $uid)) { $closeDepth[$v['invertedDepth']] = 1; }\r
+\r
+\r
+                       // if this is the last one and does not have subitems, we need to close\r
+                       // the tree as long as the upper levels have last items too\r
+                       if($v['isLast'] && !$v['hasSub'] && !$doCollapse && !($doExpand && $expandedPageUid == $uid)) {\r
+                               for ($i = $v['invertedDepth']; $closeDepth[$i] == 1; $i++) {\r
+                                       $closeDepth[$i] = 0;\r
+                                       $itemHTML .= '</ul></li>';\r
+                               }\r
+                       }\r
+\r
+                       // ajax request: collapse\r
+                       if($doCollapse && $collapsedPageUid == $uid) { return $itemHTML; }\r
+\r
+                       // ajax request: expand\r
+                       if($doExpand && $expandedPageUid == $uid) {\r
+                               $ajaxOutput .= $itemHTML;\r
+                               $invertedDepthOfAjaxRequestedItem = $v['invertedDepth'];\r
+                       } elseif($invertedDepthOfAjaxRequestedItem) { \r
+                               if($v['invertedDepth'] < $invertedDepthOfAjaxRequestedItem) {\r
+                                       $ajaxOutput .= $itemHTML;\r
+                               } else {\r
+                                       return $ajaxOutput;\r
+                               }\r
+                       }\r
+\r
+                       $out .= $itemHTML;\r
+               }\r
+\r
+               if($ajaxOutput) { return $ajaxOutput; }\r
+\r
+               // finally close the first ul\r
+               $out .= '</ul>';\r
+               return $out;\r
+       }\r
+\r
+\r
+       /**\r
+        * Generate the plus/minus icon for the browsable tree.\r
+        *\r
+        * @param       array           record for the entry\r
+        * @param       integer         The current entry number\r
+        * @param       integer         The total number of entries. If equal to $a, a "bottom" element is returned.\r
+        * @param       integer         The number of sub-elements to the current element.\r
+        * @param       boolean         The element was expanded to render subelements if this flag is set.\r
+        * @return      string          Image tag with the plus/minus icon.\r
+        * @access private\r
+        * @see t3lib_pageTree::PMicon()\r
+        */\r
+       function PMicon($row,$a,$c,$nextCount,$exp)     {\r
+               $PM   = $nextCount ? ($exp ? 'minus' : 'plus') : 'join';\r
+               $BTM  = ($a == $c) ? 'bottom' : '';\r
+               $icon = '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.$PM.$BTM.'.gif','width="18" height="16"').' alt="" />';\r
+\r
+               if ($nextCount) {\r
+                       $cmd = $this->bank.'_'.($exp?'0_':'1_').$row['uid'].'_'.$this->treeName;\r
+                       $icon = $this->PMiconATagWrap($icon,$cmd,!$exp);\r
+               }\r
+               return $icon;\r
+       }\r
+\r
+\r
+       /**\r
+        * Wrap the plus/minus icon in a link\r
+        *\r
+        * @param       string          HTML string to wrap, probably an image tag.\r
+        * @param       string          Command for 'PM' get var\r
+        * @return      string          Link-wrapped input string\r
+        * @access private\r
+        */\r
+       function PMiconATagWrap($icon, $cmd, $isExpand = true)  {\r
+               if ($this->thisScript) {\r
+                               // activate dynamic ajax-based tree\r
+                       $js = htmlspecialchars('Tree.load(\''.$cmd.'\', '.intval($isExpand).', this);');\r
+                       return '<a class="pm" onclick="'.$js.'">'.$icon.'</a>';\r
+               } else {\r
+                       return $icon;\r
+               }\r
+       }\r
+\r
+\r
+       /**\r
+        * Will create and return the HTML code for a browsable tree\r
+        * Is based on the mounts found in the internal array ->MOUNTS (set in the constructor)\r
+        *\r
+        * @return      string          HTML code for the browsable tree\r
+        */\r
+       function getBrowsableTree() {\r
+\r
+                       // Get stored tree structure AND updating it if needed according to incoming PM GET var.\r
+               $this->initializePositionSaving();\r
+\r
+                       // Init done:\r
+               $titleLen = intval($this->BE_USER->uc['titleLen']);\r
+               $treeArr = array();\r
+               \r
+                       // Traverse mounts:\r
+               foreach($this->MOUNTS as $idx => $uid)  {\r
+\r
+                               // Set first:\r
+                       $this->bank = $idx;\r
+                       $isOpen = $this->stored[$idx][$uid] || $this->expandFirst;\r
+\r
+                               // Save ids while resetting everything else.\r
+                       $curIds = $this->ids;\r
+                       $this->reset();\r
+                       $this->ids = $curIds;\r
+\r
+                               // Set PM icon for root of mount:\r
+                       $cmd = $this->bank.'_'.($isOpen? "0_" : "1_").$uid.'_'.$this->treeName;\r
+                       $icon='<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.($isOpen?'minus':'plus').'only.gif').' alt="" />';\r
+                       $firstHtml = $this->PMiconATagWrap($icon,$cmd);\r
+\r
+                               // Preparing rootRec for the mount\r
+                       if ($uid)   {\r
+                               $rootRec = $this->getRecord($uid);\r
+                               $firstHtml.=$this->getIcon($rootRec);\r
+                       } else {\r
+                               // Artificial record for the tree root, id=0\r
+                               $rootRec = $this->getRootRecord($uid);\r
+                               $firstHtml.=$this->getRootIcon($rootRec);\r
+                       }\r
+\r
+                       if (is_array($rootRec)) {\r
+                                       // In case it was swapped inside getRecord due to workspaces.\r
+                               $uid = $rootRec['uid'];\r
+\r
+                                       // Add the root of the mount to ->tree\r
+                               $this->tree[] = array('HTML'=>$firstHtml, 'row'=>$rootRec, 'bank'=>$this->bank, 'hasSub'=>true, 'invertedDepth'=>1000);\r
+\r
+                                       // If the mount is expanded, go down:\r
+                               if ($isOpen)    {\r
+                                               // Set depth:\r
+                                       if ($this->addSelfId) { $this->ids[] = $uid; }\r
+                                       $this->getTree($uid, 999, '', $rootRec['_SUBCSSCLASS']);\r
+                               }\r
+                                       // Add tree:\r
+                               $treeArr=array_merge($treeArr,$this->tree);\r
+                       }\r
+               }\r
+               return $this->printTree($treeArr);\r
+       }\r
+\r
+\r
+       /**\r
+        * Fetches the data for the tree\r
+        *\r
+        * @param       integer         item id for which to select subitems (parent id)\r
+        * @param       integer         Max depth (recursivity limit)\r
+        * @param       string          ? (internal)\r
+        * @return      integer         The count of items on the level\r
+        */\r
+       function getTree($uid, $depth=999, $blankLineCode='', $subCSSclass='') {\r
+\r
+                       // Buffer for id hierarchy is reset:\r
+               $this->buffer_idH = array();\r
+\r
+                       // Init vars\r
+               $depth = intval($depth);\r
+               $HTML = '';\r
+               $a = 0;\r
+\r
+               $res = $this->getDataInit($uid, $subCSSclass);\r
+               $c = $this->getDataCount($res);\r
+               $crazyRecursionLimiter = 999;\r
+\r
+                       // Traverse the records:\r
+               while ($crazyRecursionLimiter > 0 && $row = $this->getDataNext($res,$subCSSclass))      {\r
+                       $a++;\r
+                       $crazyRecursionLimiter--;\r
+                       \r
+                       $newID = $row['uid'];\r
+                       $this->tree[]=array();    // Reserve space.\r
+                       end($this->tree);\r
+                       $treeKey = key($this->tree);    // Get the key for this space\r
+                       $LN = ($a==$c) ? 'blank' : 'line';\r
+\r
+                               // If records should be accumulated, do so\r
+                       if ($this->setRecs) { $this->recs[$row['uid']] = $row; }\r
+\r
+                               // Accumulate the id of the element in the internal arrays\r
+                       $this->ids[]=$idH[$row['uid']]['uid'] = $row['uid'];\r
+                       $this->ids_hierarchy[$depth][] = $row['uid'];\r
+\r
+                               // Make a recursive call to the next level\r
+                       if ($depth > 1 && $this->expandNext($newID) && !$row['php_tree_stop'])  {\r
+                               $nextCount=$this->getTree(\r
+                                       $newID,\r
+                                       $depth-1,\r
+                                       $blankLineCode.','.$LN,\r
+                                       $row['_SUBCSSCLASS']\r
+                               );\r
+                               if (count($this->buffer_idH)) { $idH[$row['uid']]['subrow']=$this->buffer_idH; }\r
+                               $exp = 1; // Set "did expand" flag\r
+                       } else {\r
+                               $nextCount = $this->getCount($newID);\r
+                               $exp = 0; // Clear "did expand" flag\r
+                       }\r
+\r
+                               // Set HTML-icons, if any:\r
+                       if ($this->makeHTML)    {\r
+                               $HTML = $this->PMicon($row,$a,$c,$nextCount,$exp);\r
+                               $HTML.= $this->wrapStop($this->getIcon($row),$row);\r
+                       }\r
+\r
+                               // Finally, add the row/HTML content to the ->tree array in the reserved key.\r
+                       $this->tree[$treeKey] = array(\r
+                               'row'    => $row,\r
+                               'HTML'   => $HTML,\r
+                               'hasSub' => $nextCount&&$this->expandNext($newID),\r
+                               'isFirst'=> $a==1,\r
+                               'isLast' => false,\r
+                               'invertedDepth'=> $depth,\r
+                               'blankLineCode'=> $blankLineCode,\r
+                               'bank' => $this->bank\r
+                       );\r
+               }\r
+\r
+               if($a) { $this->tree[$treeKey]['isLast'] = true; }\r
+\r
+               $this->getDataFree($res);\r
+               $this->buffer_idH = $idH;\r
+               return $c;\r
+       }\r
+}\r
+\r
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.webpagetree.php'])    {\r
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/class.webpagetree.php']);\r
+}\r
+?>
\ No newline at end of file
index 1334aed..7bd3481 100755 (executable)
@@ -255,6 +255,21 @@ P.c-refresh IMG { vertical-align: middle; margin-right: 7px; }
 BODY#typo3-alt-db-navframe-php DIV.c-notice { border: 1px solid black; padding: 5px 5px 5px 5px; margin-top: 5px; margin-bottom: 10px; width: 95%; }
 .navFrameHL { background-color: #ebebeb; }
 
+/* AJAX page tree */
+ul.tree { list-style: none; margin: 10px; padding: 0; }
+ul.tree a              { text-decoration: none; }
+ul.tree a.pm   { cursor: pointer; }
+ul.tree img            { vertical-align: middle;  }
+ul.tree ul             { list-style: none; margin: 0; padding: 0; padding-left: 12px; }
+ul.tree ul ul  { padding-left: 17px; }
+ul.tree ul li  { list-style: none; margin: 0; padding: 0; line-height: 10px; white-space: nowrap; }
+ul.tree ul li.expanded ul      { background: transparent url('gfx/ol/line.gif') repeat-y top left; }
+ul.tree ul li.last             { background: transparent url('gfx/ol/joinbottom.gif') no-repeat top left; } 
+ul.tree ul li.last ul  { background: none; }
+ul.tree ul li.active   { background-color: #ebebeb !important; }
+ul.tree ul li.active ul        { background-color: #f7f3ef; }
+#dragIcon { z-index: 1; position: absolute; visibility: hidden; filter: alpha(opacity=50); -moz-opacity:0.5; opacity:0.5; white-space: nowrap; }
+
 /* TCEforms */
 TABLE.typo3-TCEforms SPAN.typo3-TCEforms-recHeader { font-weight: bold; color: #333366; }
 TABLE.typo3-TCEforms SPAN.typo3-TCEforms-newToken { font-weight: bold; color: #990000; }
index 1545da3..3a8a45c 100644 (file)
@@ -5,4 +5,10 @@
 table#typo3-tree,
 table#typo3-browsetree {
        margin: 10px 0 20px 10px;
-}
\ No newline at end of file
+}
+
+ul.tree ul li.expanded ul { background: transparent url('../icons/gfx/ol/line.gif') top left repeat-y; }
+ul.tree ul li.last       { background: transparent url('../icons/gfx/ol/joinbottom.gif') no-repeat top left; } 
+ul.tree ul li.last ul     { background: none; }
+ul.tree ul li.active      { background-color: #f7f3ef !important; }
+ul.tree ul li.active ul   { background-color: #efeff4; }
diff --git a/typo3/tree.js b/typo3/tree.js
new file mode 100644 (file)
index 0000000..13876ae
--- /dev/null
@@ -0,0 +1,165 @@
+/***************************************************************
+*
+*  javascript functions regarding the page & folder tree
+*  relies on the javascript library "prototype"
+*
+*
+*  Copyright notice
+*
+*  (c) 2006    Benjamin Mack <bmack@xnos.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 t3lib/ library provided by
+*  Kasper Skaarhoj <kasper@typo3.com> together with TYPO3
+*
+*  Released under GNU/GPL (see license file in tslib/)
+*
+*  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
+***************************************************************/
+
+       // Call this function, refresh_nav(), from another script in the backend if you want
+       // to refresh the navigation frame (eg. after having changed a page title or moved pages etc.)\r
+       //              See t3lib_BEfunc::getSetUpdateSignal()\r
+function refresh_nav() { window.setTimeout('_refresh_nav();',0); }\r
+function _refresh_nav()        {
+       var r = new Date();
+       // randNum is useful so pagetree does not get cached in browser cache when refreshing
+       window.location.href = Tree.thisScript + '?randNum=' + r.getTime();
+}
+
+
+var Tree = {
+       thisScript: null,
+       frameSetModule: null,
+       activateDragDrop: true,
+
+       // reloads a part of the page tree (useful when "expand" / "collapse")
+       load: function(params, isExpand, obj) {
+               new Ajax.Request(this.thisScript, {\r
+                       method: 'get',\r
+                       parameters: 'ajax=1&PM=' + params,\r
+                       onComplete: function(xhr) {
+                                       // the parent node needs to be overwritten, not the object\r
+                               $(obj.parentNode).replace(xhr.responseText);
+                               Tree.registerDragDropHandlers();
+                               Tree.reSelectActiveItem();
+                       }\r
+               });
+       },
+
+       // attaches the events to the elements needed for the drag and drop (for the titles and the icons)
+       registerDragDropHandlers: function() {
+               if (!this.activateDragDrop) return;
+               this._registerDragDropHandlers('dragTitle');
+               this._registerDragDropHandlers('dragIcon');
+       },
+
+       _registerDragDropHandlers: function(className) {
+               var elements = document.getElementsByClassName(className, $('tree'));
+               for (var i = 0; i < elements.length; i++) {
+                       Event.observe(elements[i], 'mousedown', function(event) { DragDrop.dragElement(event); }, true);
+                       Event.observe(elements[i], 'dragstart', function(event) { DragDrop.dragElement(event); }, false);
+                       Event.observe(elements[i], 'mouseup',   function(event) { DragDrop.dropElement(event); }, false);
+               }
+       },
+
+       // selects the activated item again, in case it collapsed and got expanded again
+       reSelectActiveItem: function() {
+               obj = $(top.fsMod.navFrameHighlightedID[this.frameSetModule]);
+               if (obj) Element.addClassName(obj, 'active');
+       },
+
+       // highlights an active list item in the page tree and registers it to the top-frame
+       // used when loading the page for the first time
+       highlightActiveItem: function(frameSetModule, highlightID) {
+               this.frameSetModule = frameSetModule;\r
+
+               // Remove all items that are already highlighted
+               obj = $(top.fsMod.navFrameHighlightedID[frameSetModule]);
+               if (obj) Element.removeClassName(obj, 'active');\r
+
+               // Set the new item\r
+               top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID;\r
+               if ($(highlightID)) Element.addClassName(highlightID, 'active');\r       }
+
+}
+
+
+
+// new object-oriented drag and drop - code, 
+// tested in IE 6, Firefox 2, Opera 9
+var DragDrop = {
+       dragID: null,
+       dragIconCSS: null,
+
+       // options needed for doing the changes when dropping
+       table: null, // can be "pages" or "folders"
+       changeURL: null,
+       backPath: null,
+
+
+       dragElement: function(event, elementID) {
+               Event.stop(event); // stop bubbling
+               this.dragID = this.getIdFromEvent(event);
+               if (this.dragID == 0) return false;
+
+               if (!elementID) elementID = this.dragID;
+               if (!$('dragIcon')) this.addDragIcon();
+
+               $('dragIcon').innerHTML = $('dragIconID_'+elementID).innerHTML
+                                                               + $('dragTitleID_'+elementID).firstChild.innerHTML;
+
+               this.dragIconCSS = new GL_getObjCss('dragIcon');
+               this.dragIconCSS.whiteSpace = 'nowrap';
+               document.onmouseup   = function(event) { DragDrop.cancelDragEvent(event); };
+               document.onmousemove = function(event) { DragDrop.mouseMoveEvent(event); };
+               return false;
+       },
+
+       dropElement: function(event) {
+               var dropID = this.getIdFromEvent(event);
+               if ((this.dragID) && (this.dragID != dropID)) {
+                       var url = this.changeURL
+                                   + '?dragDrop=' + this.table
+                                       + '&srcId=' + this.dragID
+                                       + '&dstId=' + dropID;
+                                       + '&backPath=' + this.backPath;
+                       showClickmenu_raw(url);
+               }
+               this.cancelDragEvent();
+               return false;
+       },
+
+
+       cancelDragEvent: function(event) {
+               this.dragID = null;
+               if (this.dragIconCSS && this.dragIconCSS.visibility) { this.dragIconCSS.visibility = 'hidden'; }
+               document.onmouseup = null;
+               document.onmousemove = null;
+       },
+
+       mouseMoveEvent: function(event) {
+               this.dragIconCSS.left = (GLV_x + 5) + 'px';
+               this.dragIconCSS.top  = (GLV_y - 5) + 'px';
+               this.dragIconCSS.visibility = 'visible';
+               return false;
+       },
+
+
+       // -- helper functions --
+       getIdFromEvent: function(event) {
+               var obj = Event.element(event);
+               while (obj.id == false && obj.parentNode) { obj = obj.parentNode; }
+               return obj.id.substring(obj.id.indexOf('_')+1);
+       },
+
+       // dynamically manipulates the DOM to add the div needed for drag&drop at the bottom of the <body>-tag
+       addDragIcon: function() {
+               var code = '<div id="dragIcon" style="visibility: hidden;">&nbsp;</div>';
+               new Insertion.Bottom(document.getElementsByTagName('body')[0], code);
+       }
+}