[!!!][TASK] Migrate non-ExtJS trees to jQuery 39/34239/7
authorBenjamin Mack <benni@typo3.org>
Sun, 16 Nov 2014 09:04:02 +0000 (10:04 +0100)
committerBenjamin Mack <benni@typo3.org>
Sat, 3 Jan 2015 13:46:35 +0000 (14:46 +0100)
Existing tree components that are
not using ExtJS are mainly within
the ElementBrowser and the FolderTree,
which is the navigation component inside filelist.

However, the "old" version of the original pagetree
still exists, and has support for IE5.5 as well, and
an option to filter for items within the pagetree (please
note: this feature was never added to the foldertree).

The old pagetree navigation component itself is now
deprecated (it can still be used in own modules). The
filter functionality is completely removed in the
old pagetree.

The necessary JavaScript code for drag+drop and
expand/collapse of the tree was migrated to RequireJS,
which avoids some more loading of scriptaculous
and prototype.

Releases: master
Resolves: #64059
Change-Id: If8de627d0284d77accdfe55cffe12c591f32df7a
Reviewed-on: http://review.typo3.org/34239
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
12 files changed:
typo3/alt_db_navframe.php
typo3/js/tree.js [deleted file]
typo3/sysext/backend/Classes/Controller/FileSystemNavigationFrameController.php
typo3/sysext/backend/Classes/Controller/PageTreeNavigationController.php
typo3/sysext/backend/Classes/Template/DocumentTemplate.php
typo3/sysext/backend/Resources/Private/Templates/alt_db_navframe.html
typo3/sysext/backend/Resources/Private/Templates/alt_file_navframe.html
typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js [new file with mode: 0644]
typo3/sysext/backend/Resources/Public/JavaScript/pagetreefiltermenu.js [deleted file]
typo3/sysext/core/Documentation/Changelog/master/Breaking-64059-Rewritten-JavaScript-Tree-Components.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Deprecation-64059-Pagetree-Navigation-Component.rst [new file with mode: 0644]
typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php

index f0c503c..ba0f2bf 100644 (file)
@@ -19,6 +19,7 @@
  */
 require_once 'init.php';
 
+\TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog('Usage of alt_db_navframe.php is deprecated since TYPO3 CMS 7, and will be removed in TYPO3 CMS 8');
 // Make instance if it is not an AJAX call
 if (!(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX)) {
        $pageTreeNavigationController = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\PageTreeNavigationController::class);
diff --git a/typo3/js/tree.js b/typo3/js/tree.js
deleted file mode 100644 (file)
index 392a5b0..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * javascript functions regarding the page & folder tree
- * relies on the javascript library "prototype"
- *
- * @author     Benjamin Mack
- */
-
-// new object-oriented drag and drop - code,
-// tested in IE 6, Firefox 2, Opera 9
-var DragDrop = {
-       dragID: null,
-
-       // options needed for doing the changes when dropping
-       table: null,    // can be "pages" or "folders"
-       backPath: null,
-
-
-       dragElement: function(event, elementID) {
-               Event.stop(event); // stop bubbling
-               this.dragID = this.getIdFromEvent(event);
-               if (!this.dragID) {
-                       return false;
-               }
-
-               if (!elementID) {
-                       elementID = this.dragID;
-               }
-               if (!$('dragIcon')) {
-                       this.addDragIcon();
-               }
-
-               $('dragIcon').innerHTML = $('dragIconID_'+elementID).innerHTML +
-                                                                 $('dragTitleID_'+elementID).firstChild.innerHTML;
-
-               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 parameters = 'dragDrop=' + this.table +
-                                       '&srcId=' + this.dragID +
-                                       '&dstId=' + dropID +
-                                       '&backPath=' + this.backPath;
-                       TYPO3.ClickMenu.fetch(parameters);
-               }
-               this.cancelDragEvent();
-               return false;
-       },
-
-
-       cancelDragEvent: function(event) {
-               this.dragID = null;
-               if ($('dragIcon') && $('dragIcon').style.visibility === 'visible') {
-                       $('dragIcon').style.visibility = 'hidden';
-               }
-
-               document.onmouseup = null;
-               document.onmousemove = null;
-       },
-
-       mouseMoveEvent: function(event) {
-               if (!event) {
-                       event = window.event;
-               }
-               $('dragIcon').style.left = (Event.pointerX(event) + 5) + 'px';
-               $('dragIcon').style.top  = (Event.pointerY(event) - 5) + 'px';
-               $('dragIcon').style.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>';
-               var insert = new Insertion.Bottom(document.getElementsByTagName('body')[0], code);
-       }
-};
-
-
-var Tree = {
-       ajaxID: 'SC_alt_db_navframe::expandCollapse',   // has to be either "SC_alt_db_navframe::expandCollapse" or "SC_alt_file_navframe::expandCollapse"
-       frameSetModule: null,
-       activateDragDrop: true,
-       highlightClass: 'active',
-       pageID: 0,
-
-       // reloads a part of the page tree (useful when "expand" / "collapse")
-       load: function(params, isExpand, obj, scopeData, scopeHash) {
-               var scope = '';
-
-               if (scopeData && scopeHash) {
-                       scope = '&scopeData=' + encodeURIComponent(scopeData) + '&scopeHash=' + encodeURIComponent(scopeHash);
-               }
-
-                       // fallback if AJAX is not possible (e.g. IE < 6)
-               if (typeof Ajax.getTransport() !== 'object') {
-                       window.location.href = TYPO3.settings.ajaxUrls[this.ajaxID] + '&PM=' + encodeURIComponent(params) + scope;
-                       return;
-               }
-
-               // immediately collapse the subtree and change the plus to a minus when collapsing
-               // without waiting for the response
-               if (!isExpand) {
-                       var ul = obj.parentNode.parentNode.getElementsByTagName('ul')[0];
-                       if (ul) {
-                               obj.parentNode.parentNode.removeChild(ul); // no remove() directly because of IE 5.5
-                       }
-                       var pm = Selector.findChildElements(obj.parentNode, ['.pm'])[0]; // Getting pm object by CSS selector (because document.getElementsByClassName() doesn't seem to work on Konqueror)
-                       if (pm) {
-                               pm.onclick = null;
-                               Element.cleanWhitespace(pm);
-                               pm.firstChild.src = pm.firstChild.src.replace('minus', 'plus');
-                       }
-               } else {
-                       obj.style.cursor = 'wait';
-               }
-               var call = new Ajax.Request(TYPO3.settings.ajaxUrls[this.ajaxID], {
-                       method: 'get',
-                       parameters: 'PM=' + encodeURIComponent(params) + scope,
-                       onComplete: function(xhr) {
-                               // the parent node needs to be overwritten, not the object
-                               $(obj.parentNode.parentNode).replace(xhr.responseText);
-                               TYPO3PageTreeFilter.filter();
-                               this.registerDragDropHandlers();
-                               this.reSelectActiveItem();
-                       }.bind(this),
-                       onT3Error: function(xhr) {
-                               // if this is not a valid ajax response, the whole page gets refreshed
-                               this.refresh();
-                       }.bind(this)
-               });
-       },
-
-       // does the complete page refresh (previously known as "_refresh_nav()")
-       refresh: function() {
-               var r = new Date();
-               // randNum is useful so pagetree does not get cached in browser cache when refreshing
-               var loc = window.location.href.replace(/&randNum=\d+|#.*/g, '');
-               var addSign = loc.indexOf('?') > 0 ? '&' : '?';
-               window.location = loc + addSign + 'randNum=' + r.getTime();
-       },
-
-       // 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 = Selector.findChildElements($('tree'), ['.'+className]); // using Selector because document.getElementsByClassName() doesn't seem to work on Konqueror
-               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() {
-               var obj = $(top.fsMod.navFrameHighlightedID[this.frameSetModule]);
-               if (obj) {
-                       Element.addClassName(obj, this.highlightClass);
-                       this.extractPageIdFromTreeItem(obj.id);
-               }
-       },
-
-       // 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;
-               this.extractPageIdFromTreeItem(highlightID);
-
-               // Remove all items that are already highlighted
-               var obj = $(top.fsMod.navFrameHighlightedID[frameSetModule]);
-               if (obj) {
-                       var classes = $w(this.highlightClass);
-                       for (var i = 0; i < classes.length; i++)
-                               Element.removeClassName(obj, classes[i]);
-               }
-
-               // Set the new item
-               top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID;
-               if ($(highlightID)) {
-                       Element.addClassName(highlightID, this.highlightClass);
-               }
-       },
-
-       //extract pageID from the given id (pagesxxx_y_z where xxx is the ID)
-       extractPageIdFromTreeItem: function(highlightID) {
-               if(highlightID) {
-                       this.pageID = highlightID.split('_')[0].substring(5);
-               }
-       }
-};
-
-
-
-
-/**
- *
- * @author     Ingo Renner <ingo@typo3.org>
- **/
-var PageTreeFilter = Class.create({
-       field: 'treeFilter',
-       resetfield: 'treeFilterReset',
-
-       /**
-        * constructor with event listener
-        */
-       initialize: function() {
-                       // event listener
-               Event.observe(document, 'dom:loaded', function(){
-                       Event.observe(this.field, "keyup", this.filter.bindAsEventListener(this));
-                       Event.observe(this.resetfield, "click", this.resetSearchField.bindAsEventListener(this) );
-               }.bind(this));
-       },
-
-       /**
-        * Filters the tree by setting a class on items not matching search input string
-        * tested in FF2, S3, IE6, IE7
-        */
-       filter: function() {
-               var searchString = $F(this.field).toLowerCase();
-
-               var pages = $$('#treeRoot .dragTitle a');
-               pages.each(function(el) {
-                       if (el.innerHTML.toLowerCase().include(searchString)) {
-                               el.up().removeClassName('not-found');
-                       } else {
-                               el.up().addClassName('not-found');
-                       }
-               });
-               this.toggleReset();
-
-       },
-
-       /**
-        * toggles the visibility of the reset button
-        */
-       toggleReset: function() {
-               var searchFieldContent = $F(this.field);
-               var resetButton = $(this.resetfield);
-
-               if (searchFieldContent != '' && resetButton.getStyle('visibility') == 'hidden') {
-                       resetButton.setStyle({ visibility: 'visible'} );
-               } else if (searchFieldContent == '' && resetButton.getStyle('visibility') == 'visible') {
-                       resetButton.setStyle( {visibility: 'hidden'} );
-               }
-       },
-
-       /**
-        * resets the search field
-        */
-       resetSearchField: function() {
-               if ($(this.resetfield).getStyle('visibility') == 'visible') {
-                       $(this.field).value = '';
-                       this.filter('');
-               }
-       }
-});
-
-
-// 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.)
-// please use the function in the "Tree" object for future implementations
-function refresh_nav() {
-       window.setTimeout('Tree.refresh();',0);
-}
index 500d154..240b2eb 100644 (file)
@@ -122,15 +122,23 @@ class FileSystemNavigationFrameController {
                $this->doc->backPath = $GLOBALS['BACK_PATH'];
                $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/alt_file_navframe.html');
                $this->doc->showFlashMessages = FALSE;
-               // Adding javascript code for AJAX (prototype), drag&drop and the filetree as well as the click menu code
-               $this->doc->getDragDropCode('folders');
+               // Adding javascript code for drag&drop and the filetree as well as the click menu code
+               $dragDropCode = '
+                       Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
+                       Tree.registerDragDropHandlers()';
+               if ($this->doHighlight) {
+                       $hlClass = $GLOBALS['BE_USER']->workspace === 0 ? 'active' : 'active active-ws wsver' . $GLOBALS['BE_USER']->workspace;
+                       $dragDropCode .= '
+                       Tree.highlightClass = "' . $hlClass . '";
+                       Tree.highlightActiveItem("", top.fsMod.navFrameHighlightedID["file"]);
+                       ';
+               }
+               // Adding javascript for drag & drop activation and highlighting
+               $this->doc->getDragDropCode('folders', $dragDropCode);
                $this->doc->getContextMenuCode();
+
                // Setting JavaScript for menu.
                $this->doc->JScode .= $this->doc->wrapScriptTags(($this->currentSubScript ? 'top.currentSubScript=unescape("' . rawurlencode($this->currentSubScript) . '");' : '') . '
-
-               // setting prefs for foldertree
-               Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
-
                // Function, loading the list frame from navigation tree:
                function jumpTo(id, linkObj, highlightID, bank) {
                        var theUrl = top.TS.PATH_typo3 + top.currentSubScript ;
@@ -159,19 +167,12 @@ class FileSystemNavigationFrameController {
                $tree = $this->foldertree->getBrowsableTree();
                // Outputting page tree:
                $this->content .= $tree;
-               // Adding javascript for drag & drop activation and highlighting
-               $this->content .= $this->doc->wrapScriptTags('
-                       ' . ($this->doHighlight ? 'Tree.highlightActiveItem("", top.fsMod.navFrameHighlightedID["file"]);' : '') . '
-                       Tree.registerDragDropHandlers();');
                // Setting up the buttons and markers for docheader
                $docHeaderButtons = $this->getButtons();
                $markers = array(
-                       'IMG_RESET' => '<img' . IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/close_gray.gif', ' width="16" height="16"') . ' id="treeFilterReset" alt="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.resetFilter') . '" ' . 'title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.resetFilter') . '" />',
                        'CONTENT' => $this->content
                );
                $subparts = array();
-               // Possible filter/search like in page tree
-               $subparts['###SECOND_ROW###'] = '';
                // Build the <body> for the module
                $this->content = $this->doc->startPage('TYPO3 Folder Tree');
                $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers, $subparts);
index e81c55e..beb4851 100644 (file)
@@ -20,6 +20,8 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Main script class for the page tree navigation frame
+ * This is the class for rendering the "page tree" navigation frame without ExtJS, used prior to TYPO3 CMS 4.5.
+ * This functionality is deprecated since TYPO3 CMS 7, and will be removed with TYPO3 CMS 8
  *
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
@@ -78,16 +80,10 @@ class PageTreeNavigationController {
        public $template;
 
        /**
-        * Depends on userTS-setting
-        *
-        * @var bool
-        */
-       public $hasFilterBox;
-
-       /**
         * Constructor
         */
        public function __construct() {
+               GeneralUtility::deprecationLog('PageTreeNavigationController is deprecated in favor of new pagetrees');
                $GLOBALS['SOBE'] = $this;
                $GLOBALS['BACK_PATH'] = '';
 
@@ -106,8 +102,6 @@ class PageTreeNavigationController {
                $this->cMR = (bool)GeneralUtility::_GP('cMR');
                $this->currentSubScript = GeneralUtility::_GP('currentSubScript');
                $this->setTempDBmount = GeneralUtility::_GP('setTempDBmount');
-               // look for User setting
-               $this->hasFilterBox = !$GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.hideFilter');
                // Create page tree object:
                $this->pagetree = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\View\PageTreeView::class);
                $this->pagetree->ext_IconMode = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.disableIconLinkToContextmenu');
@@ -137,30 +131,30 @@ class PageTreeNavigationController {
        public function initPage() {
                // Setting highlight mode:
                $this->doHighlight = !$GLOBALS['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) {
-                       $hlClass = $GLOBALS['BE_USER']->workspace === 0 ? 'active' : 'active active-ws wsver' . $GLOBALS['BE_USER']->workspace;
-               }
                // Create template object:
                $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
                $this->doc->backPath = $GLOBALS['BACK_PATH'];
                $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/alt_db_navframe.html');
                $this->doc->showFlashMessages = FALSE;
                // Get HTML-Template
-               // Adding javascript code for AJAX (prototype), drag&drop and the pagetree as well as the click menu code
-               $this->doc->getDragDropCode('pages');
+
+               // Adding javascript for drag & drop activation and highlighting
+               $dragDropCode = 'Tree.registerDragDropHandlers();';
+
+               // If highlighting is active, define the CSS class for the active item depending on the workspace
+               if ($this->doHighlight) {
+                       $hlClass = $GLOBALS['BE_USER']->workspace === 0 ? 'active' : 'active active-ws wsver' . $GLOBALS['BE_USER']->workspace;
+                       $dragDropCode .= '
+                               Tree.highlightClass = "' . $hlClass . '";
+                               Tree.highlightActiveItem("",top.fsMod.navFrameHighlightedID["web"]);';
+               }
+               // Adding javascript code for drag&drop and the pagetree as well as the click menu code
+               $this->doc->getDragDropCode('pages', $dragDropCode);
                $this->doc->getContextMenuCode();
                /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
                $pageRenderer = $this->doc->getPageRenderer();
-               $pageRenderer->loadScriptaculous('effects');
                $pageRenderer->loadExtJS();
-               if ($this->hasFilterBox) {
-                       $pageRenderer->addJsFile('sysext/backend/Resources/Public/JavaScript/pagetreefiltermenu.js');
-               }
                $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 ;
@@ -176,7 +170,7 @@ class PageTreeNavigationController {
                        if (linkObj) { linkObj.blur(); }
                        return false;
                }
-               ' . ($this->cMR ? 'jumpTo(top.fsMod.recentIds[\'web\'],\'\');' : '') . ($this->hasFilterBox ? 'var TYPO3PageTreeFilter = new PageTreeFilter();' : '') . '
+               ' . ($this->cMR ? 'jumpTo(top.fsMod.recentIds[\'web\'],\'\');' : '') . '
 
                ');
                $this->doc->bodyTagId = 'typo3-pagetree';
@@ -200,25 +194,13 @@ class PageTreeNavigationController {
                }
                // Outputting page tree:
                $this->content .= '<div id="PageTreeDiv">' . $tree . '</div>';
-               // Adding javascript for drag & drop activation and highlighting
-               $this->content .= $this->doc->wrapScriptTags('
-                       ' . ($this->doHighlight ? 'Tree.highlightActiveItem("",top.fsMod.navFrameHighlightedID["web"]);' : '') . '
-                       Tree.registerDragDropHandlers();');
                // Setting up the buttons and markers for docheader
                $docHeaderButtons = $this->getButtons();
                $markers = array(
-                       'IMG_RESET' => IconUtility::getSpriteIcon('actions-document-close', array(
-                               'id' => 'treeFilterReset',
-                               'alt' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.resetFilter'),
-                               'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.resetFilter')
-                       )),
                        'WORKSPACEINFO' => $this->getWorkspaceInfo(),
                        'CONTENT' => $this->content
                );
                $subparts = array();
-               if (!$this->hasFilterBox) {
-                       $subparts['###SECOND_ROW###'] = '';
-               }
                // Build the <body> for the module
                $this->content = $this->doc->startPage('TYPO3 Page Tree');
                $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers, $subparts);
@@ -244,8 +226,7 @@ class PageTreeNavigationController {
                $buttons = array(
                        'csh' => '',
                        'new_page' => '',
-                       'refresh' => '',
-                       'filter' => ''
+                       'refresh' => ''
                );
                // New Page
                $onclickNewPageWizard = 'top.content.list_frame.location.href=top.TS.PATH_typo3+\'db_new.php?pagesOnly=1&amp;id=\'+Tree.pageID;';
@@ -254,10 +235,6 @@ class PageTreeNavigationController {
                $buttons['refresh'] = '<a href="' . htmlspecialchars(GeneralUtility::getIndpEnv('REQUEST_URI')) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.refresh', TRUE) . '">' . IconUtility::getSpriteIcon('actions-system-refresh') . '</a>';
                // CSH
                $buttons['csh'] = str_replace('typo3-csh-inline', 'typo3-csh-inline show-right', BackendUtility::cshItem('xMOD_csh_corebe', 'pagetree'));
-               // Filter
-               if ($this->hasFilterBox) {
-                       $buttons['filter'] = '<a href="#" id="tree-toolbar-filter-item">' . IconUtility::getSpriteIcon('actions-system-tree-search-open', array('title' => $GLOBALS['LANG']->sL('LLL:EXT:cms/layout/locallang.xlf:labels.filter', TRUE))) . '</a>';
-               }
                return $buttons;
        }
 
index e1c8d40..5748824 100644 (file)
@@ -1484,21 +1484,18 @@ function jumpToUrl(URL) {
        }
 
        /**
-        * Includes the necessary javascript file (tree.js) for use on pages which have the
-        * drag and drop functionality (usually pages and folder display trees)
+        * Includes the necessary javascript file for use on pages which have the
+        * drag and drop functionality (legacy folder tree)
         *
         * @param string $table indicator of which table the drag and drop function should work on (pages or folders)
+        * @param string $additionalJavaScriptCode adds more code to the additional javascript code
         * @return void
         */
-       public function getDragDropCode($table) {
-               $this->getContextMenuCode();
-               $this->pageRenderer->loadPrototype();
-               $this->loadJavascriptLib('js/tree.js');
-               // Setting prefs for drag & drop
-               $this->JScodeArray['dragdrop'] = '
-                       DragDrop.backPath  = "' . GeneralUtility::shortMD5('|' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']) . '";
-                       DragDrop.table     = "' . $table . '";
-               ';
+       public function getDragDropCode($table, $additionalJavaScriptCode = '') {
+               $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree', 'function() {
+                       DragDrop.table = "' . $table . '";
+                       ' . $additionalJavaScriptCode . '
+               }');
        }
 
        /**
index 62f3526..a740dda 100644 (file)
@@ -7,15 +7,6 @@
                        <div class="left">###BUTTONLIST_LEFT###</div>
                        <div class="right">###BUTTONLIST_RIGHT###</div>
                </div>
-
-               <!-- ###SECOND_ROW### -->
-               <div id="treeFilterBox">
-                       <div id="searchBubble">
-                               <input type="text" value="" name="treeFilter" id="treeFilter" />
-                               ###IMG_RESET###
-                       </div>
-               </div>
-               <!-- ###SECOND_ROW### -->
        </div>
 
        <div id="typo3-docbody">
@@ -34,7 +25,7 @@
 <!-- ###BUTTON_GROUP_WRAP### -->
 
 <!-- ###BUTTON_GROUPS_LEFT### -->
-<!-- ###BUTTON_GROUP4### -->###NEW_PAGE######FILTER###<!-- ###BUTTON_GROUP4### -->
+<!-- ###BUTTON_GROUP4### -->###NEW_PAGE###<!-- ###BUTTON_GROUP4### -->
 <!-- ###BUTTON_GROUPS_LEFT### -->
 
 <!-- ###BUTTON_GROUPS_RIGHT### -->
index fb81590..a2bc3b6 100644 (file)
@@ -7,15 +7,6 @@
                        <div class="left">###BUTTONLIST_LEFT###</div>
                        <div class="right">###BUTTONLIST_RIGHT###</div>
                </div>
-
-               <!-- ###SECOND_ROW### -->
-               <div id="treeFilterBox">
-                       <div id="searchBubble">
-                               <input type="text" value="" name="treeFilter" id="treeFilter" />
-                               ###IMG_RESET###
-                       </div>
-               </div>
-               <!-- ###SECOND_ROW### -->
        </div>
 
        <div id="typo3-docbody">
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js
new file mode 100644 (file)
index 0000000..8be8800
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * JavaScript RequireJS module in use for legacy trees, used
+ * in FolderTree, Element Browser PageTree and
+ * Element Browser FolderTree
+ * note that this should not be used (thus, declared as anonymous
+ * UMD module)
+ */
+var Tree, DragDrop;
+define(['jquery'], function($) {
+
+       DragDrop = {
+               dragID: null,
+               table: null     // can be "pages" or "folders", needed for doing the changes when dropping
+       };
+
+       DragDrop.dragElement = function(event, $element) {
+               event.preventDefault();
+               var $container = $element.parent().parent();
+               var elementID = $container.prop('id');
+               elementID = elementID.substring(elementID.indexOf('_') + 1);
+               DragDrop.dragID = DragDrop.getIdFromEvent(event);
+
+               if (!DragDrop.dragID) {
+                       return false;
+               }
+
+               if (!elementID) {
+                       elementID = DragDrop.dragID;
+               }
+
+               if ($('#dragIcon').length === 0) {
+                       $('body').append('<div id="dragIcon" style="display: none;">&nbsp;</div>');
+               }
+
+               $('#dragIcon').html($container.find('.dragIcon').html() + $container.find('.dragTitle').children(':first').text());
+
+               document.onmouseup = function(event) {
+                       DragDrop.cancelDragEvent(event);
+               };
+
+               document.onmousemove = function(event) {
+                       DragDrop.mouseMoveEvent(event);
+               };
+       };
+
+       DragDrop.dropElement = function(event) {
+               var dropID = DragDrop.getIdFromEvent(event);
+               if ((DragDrop.dragID) && (DragDrop.dragID !== dropID)) {
+                       var parameters = 'dragDrop=' + DragDrop.table +
+                                       '&srcId=' + DragDrop.dragID +
+                                       '&dstId=' + dropID;
+                       TYPO3.ClickMenu.fetch(parameters);
+               }
+               DragDrop.cancelDragEvent();
+               return false;
+       };
+
+       DragDrop.cancelDragEvent = function(event) {
+               DragDrop.dragID = null;
+               if ($('#dragIcon').length && $('#dragIcon').is(':visible')) {
+                       $('#dragIcon').hide();
+               }
+
+               document.onmouseup = null;
+               document.onmousemove = null;
+       };
+
+       DragDrop.mouseMoveEvent = function(event) {
+               if (!event) {
+                       event = window.event;
+               }
+               $('#dragIcon').css({
+                       left: (event.x + 5) + 'px',
+                       top: (event.y - 5) + 'px'
+               }).show();
+       };
+
+       DragDrop.getIdFromEvent = function(event) {
+               var obj = event.currentTarget;
+               while (obj.id == false && obj.parentNode) {
+                       obj = obj.parentNode;
+               }
+               return obj.id.substring(obj.id.indexOf('_') + 1);
+       };
+
+       Tree = {
+               ajaxID: 'SC_alt_db_navframe::expandCollapse',   // has to be either "SC_alt_db_navframe::expandCollapse" or "SC_alt_file_navframe::expandCollapse"
+               frameSetModule: null,
+               activateDragDrop: true,
+               highlightClass: 'active',
+               pageID: 0,
+
+               // reloads a part of the page tree (useful when "expand" / "collapse")
+               load: function(params, isExpand, obj, scopeData, scopeHash) {
+                       var $obj = $(obj);
+                       var $parentNode = $(obj).parent().parent();
+
+                       // immediately collapse the subtree and change the plus to a minus when collapsing
+                       // without waiting for the response
+                       if (!isExpand) {
+                               $parentNode.find('ul:first').remove();
+                               var $pm = $obj.parent().find('.pm:first');
+                               if ($pm.length) {
+                                       $pm.get().onclick = null;
+                                       var src = $pm.children(':first').prop('src');
+                                       src = src.replace(/minus/, 'plus');
+                                       $pm.children('first').prop('src', src);
+                               }
+                       } else {
+                               $obj.css({cursor: 'wait'});
+                       }
+                       $.ajax({
+                               url: TYPO3.settings.ajaxUrls[this.ajaxID],
+                               data: {
+                                       PM: encodeURIComponent(params),
+                                       scopeData: encodeURIComponent(scopeData),
+                                       scopeHash: encodeURIComponent(scopeHash)
+                               }
+                       }).done(function(data) {
+                               // the parent node needs to be overwritten, not the object
+                               $parentNode.replaceWith(data);
+                               Tree.reSelectActiveItem();
+                       });
+               },
+
+               // does the complete page refresh (previously known as "_refresh_nav()")
+               refresh: function() {
+                       var r = new Date();
+                       // randNum is useful so pagetree does not get cached in browser cache when refreshing
+                       var loc = window.location.href.replace(/&randNum=\d+|#.*/g, '');
+                       var addSign = loc.indexOf('?') > 0 ? '&' : '?';
+                       window.location = loc + addSign + 'randNum=' + r.getTime();
+               },
+
+               // attaches the events to the elements needed for the drag and drop (for the titles and the icons)
+               registerDragDropHandlers: function() {
+                       if (!Tree.activateDragDrop) {
+                               return;
+                       }
+
+                       $('.tree').on('mousedown', '.dragTitle, .dragIcon', function(evt) {
+                               DragDrop.dragElement(evt, $(this));
+                       }).on('mouseup', '.dragTitle, .dragIcon', function(evt) {
+                               DragDrop.dropElement(evt, $(this));
+                       });
+               },
+
+               // selects the activated item again, in case it collapsed and got expanded again
+               reSelectActiveItem: function() {
+                       var $activeItem = $('#' + top.fsMod.navFrameHighlightedID[this.frameSetModule]);
+                       if ($activeItem.length) {
+                               $activeItem.addClass(Tree.highlightClass);
+                               Tree.extractPageIdFromTreeItem($activeItem.prop('id'));
+                       }
+               },
+
+               // 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) {
+                       Tree.frameSetModule = frameSetModule;
+                       Tree.extractPageIdFromTreeItem(highlightID);
+
+                       // Remove all items that are already highlighted
+                       var $obj = $('#' + top.fsMod.navFrameHighlightedID[frameSetModule]);
+                       if ($obj.length) {
+                               $obj.removeClass(Tree.highlightClass);
+                       }
+
+                       // Set the new item
+                       top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID;
+                       $('#' + highlightID).addClass(Tree.highlightClass);
+               },
+
+               //extract pageID from the given id (pagesxxx_y_z where xxx is the ID)
+               extractPageIdFromTreeItem: function(highlightID) {
+                       if (highlightID) {
+                               Tree.pageID = highlightID.split('_')[0].substring(5);
+                       }
+               }
+       };
+
+       return function() {
+               return Tree;
+       }();
+});
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/pagetreefiltermenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/pagetreefiltermenu.js
deleted file mode 100644 (file)
index 6119e3c..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * class to handle the pagetree filter menu
- */
-var PagetreeFilterMenu = Class.create({
-
-       /**
-        * registers for resize event listener and executes on DOM ready
-        */
-       initialize: function() {
-               Ext.onReady(function() {
-                       Ext.get('tree-toolbar-filter-item').on('click', this.toggleMenu);
-               }, this);
-       },
-
-       /**
-        * toggles the visibility of the filter
-        */
-       toggleMenu: function(event) {
-               var toolbarItem = Ext.get('tree-toolbar-filter-item');
-               var treeFilterBox = Ext.get('treeFilterBox');
-               var treeFilterItem = Ext.get('treeFilter');
-               var treeFilterReset = Ext.get('treeFilterReset');
-
-               toolbarItem.blur();
-
-               if (toolbarItem.hasClass('active')) {
-                       treeFilterBox.fadeOut();
-                       TYPO3PageTreeFilter.resetSearchField();
-               } else {
-                       treeFilterBox.fadeIn();
-                       treeFilterItem.focus();
-               }
-
-               toolbarItem.toggleClass('active');
-
-       }
-});
-
-var TYPO3BackendFilterMenu = new PagetreeFilterMenu();
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-64059-Rewritten-JavaScript-Tree-Components.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-64059-Rewritten-JavaScript-Tree-Components.rst
new file mode 100644 (file)
index 0000000..8da8e78
--- /dev/null
@@ -0,0 +1,36 @@
+=======================================================
+Breaking: #64059 - Rewritten Javascript Tree Components
+=======================================================
+
+Description
+===========
+
+In the process of refactoring prototype/scriptaculous code and migrate to an AMD module, the tree component and its
+drag&drop parts are migrated to a RequireJS / jQuery module.
+
+The page tree filter functionality of the prototype tree, which is not used in the TYPO3 core, was removed from the
+tree component.
+
+The file typo3/js/tree.js was removed, the replacement code, based on jQuery is located under
+EXT:backend/Resources/Public/JavaScript/LegacyTree.js.
+
+
+Impact
+======
+
+Any usages in third party extensions that include js/tree.js will fail, as the tree component was removed. Any
+extension using the filter part of the tree.js component will not work.
+
+
+Affected installations
+======================
+
+Any installation with its own backend module using the tree component from the core.
+
+
+Migration
+=========
+
+Rewrite any needed logic for filtering, and include the RequireJS module like in e.g.
+FileSystemNavigationFrameController.php, to use the tree component. If the old code is needed, the tree.js file
+and prototype need to be included as part of the extension, not from the core.
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-64059-Pagetree-Navigation-Component.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-64059-Pagetree-Navigation-Component.rst
new file mode 100644 (file)
index 0000000..fbb791c
--- /dev/null
@@ -0,0 +1,29 @@
+==========================================================
+Deprecation: #64059 - Non-ExtJS Page Tree Navigation Frame
+==========================================================
+
+Description
+===========
+
+The non-ExtJS page tree navigation frame which was used in the core until TYPO3 CMS 4.5, is still available and can be
+included within a module, if the module is registering a navFrameScript in ext_tables.php:
+
+:php:`'navFrameScript' => 'alt_db_navframe.php'`
+
+
+Impact
+======
+
+Usage of the PHP class, and the entry script typo3/alt_db_navframe.php is deprecated.
+
+
+Affected installations
+======================
+
+All installations with extensions using modules with the non-ExtJS page tree navigation frame.
+
+
+Migration
+=========
+
+Use the ExtJS navigationComponentID instead within the module registration.
index 1eebf52..78fe3c3 100644 (file)
@@ -345,10 +345,8 @@ class ElementBrowser {
                $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
                $this->doc->bodyTagId = 'typo3-browse-links-php';
                $this->doc->backPath = $GLOBALS['BACK_PATH'];
-               // Load the Prototype library and the tree
-               $this->doc->getPageRenderer()->loadPrototype();
-               $this->doc->loadJavascriptLib('js/tree.js');
                $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/BrowseLinks');
+               $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree');
        }
 
        /**
@@ -1222,9 +1220,9 @@ class ElementBrowser {
                        $files = $this->expandFolder($selectedFolder, $allowedExtensions);
                }
                // Create folder tree:
-               $this->doc->JScode .= $this->doc->wrapScriptTags('
-                               Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
-                       ');
+               $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree', 'function(Tree) {
+                       Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
+               }');
                $content .= '
                                <!--
                                        Wrapper table for folder tree / file/folder list:
@@ -1426,10 +1424,7 @@ class ElementBrowser {
         */
        public function main_file() {
                // include JS files and set prefs for foldertree
-               $this->doc->getDragDropCode('folders');
-               $this->doc->JScode .= $this->doc->wrapScriptTags('
-                       Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
-               ');
+               $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "SC_alt_file_navframe::expandCollapse"');
                // Starting content:
                $content = $this->doc->startPage('TBE file selector');
                // Init variable:
@@ -1559,11 +1554,8 @@ class ElementBrowser {
         */
        public function main_folder() {
                // include JS files
-               $this->doc->getDragDropCode('folders');
                // Setting prefs for foldertree
-               $this->doc->JScode .= $this->doc->wrapScriptTags('
-                       Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
-               ');
+               $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";');
                // Starting content:
                $content = $this->doc->startPage('TBE folder selector');
                // Init variable: