[TASK] Rework folder trees based on CSS only 01/41001/5
authorThomas Schlumberger <thomas@b13.de>
Wed, 8 Jul 2015 15:09:33 +0000 (17:09 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Thu, 9 Jul 2015 18:08:13 +0000 (20:08 +0200)
Renders all folder and page trees in the same HTML
manner.

These are located in:
- Link Wizards
- RTE popups
- Select / Group Field Selector Popups (e.g. Insert Record)

Next steps:
- Rework the impexp tree
- Rework the Move Tree and the New Element Position Maps
- Add highlighting
- Simplify the calls to each method and remove
"old" parameters to methods, rename the methods
to make them speaking.

Releases: master
Resolves: #68018
Change-Id: I675368039f2065dcd9e4bb2555da4495f84eb87b
Reviewed-on: http://review.typo3.org/41001
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php
typo3/sysext/backend/Classes/Tree/View/ElementBrowserFolderTreeView.php
typo3/sysext/backend/Classes/Tree/View/ElementBrowserPageTreeView.php
typo3/sysext/backend/Classes/Tree/View/FolderTreeView.php
typo3/sysext/impexp/Classes/LocalPageTree.php
typo3/sysext/rtehtmlarea/Classes/PageTree.php
typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_tree.less
typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css

index 7904437..69a6628 100644 (file)
@@ -381,9 +381,8 @@ abstract class AbstractTreeView {
                        $this->ids = $curIds;
                        // Set PM icon for root of mount:
                        $cmd = $this->bank . '_' . ($isOpen ? '0_' : '1_') . $uid . '_' . $this->treeName;
-                       $icon = IconUtility::getSpriteIcon('treeline-' . ($isOpen ? 'minus' : 'plus') . 'only');
 
-                       $firstHtml = $this->PM_ATagWrap($icon, $cmd);
+                       $firstHtml = $this->PM_ATagWrap('', $cmd, '', $isOpen);
                        // Preparing rootRec for the mount
                        if ($uid) {
                                $rootRec = $this->getRecord($uid);
@@ -397,15 +396,13 @@ abstract class AbstractTreeView {
                                // In case it was swapped inside getRecord due to workspaces.
                                $uid = $rootRec['uid'];
                                // Add the root of the mount to ->tree
-                               $this->tree[] = array('HTML' => $firstHtml, 'row' => $rootRec, 'bank' => $this->bank);
+                               $this->tree[] = array('HTML' => $firstHtml, 'row' => $rootRec, 'hasSub' => $isOpen, 'bank' => $this->bank);
                                // If the mount is expanded, go down:
                                if ($isOpen) {
-                                       // Set depth:
-                                       $depthD = IconUtility::getSpriteIcon('treeline-blank');
                                        if ($this->addSelfId) {
                                                $this->ids[] = $uid;
                                        }
-                                       $this->getTree($uid, 999, $depthD, '', $rootRec['_SUBCSSCLASS']);
+                                       $this->getTree($uid, 999, '', '', $rootRec['_SUBCSSCLASS']);
                                }
                                // Add tree:
                                $treeArr = array_merge($treeArr, $this->tree);
@@ -426,27 +423,40 @@ abstract class AbstractTreeView {
                        $treeArr = $this->tree;
                }
                $out = '';
-               // put a table around it with IDs to access the rows from JS
-               // not a problem if you don't need it
-               // In XHTML there is no "name" attribute of <td> elements -
-               // but Mozilla will not be able to highlight rows if the name
-               // attribute is NOT there.
-               $out .= '
-
-                       <!--
-                         TYPO3 tree structure.
-                       -->
-                       <table cellpadding="0" cellspacing="0" border="0" id="typo3-tree">';
-               foreach ($treeArr as $k => $v) {
-                       $idAttr = htmlspecialchars($this->domIdPrefix . $this->getId($v['row']) . '_' . $v['bank']);
-                       $out .= '
-                               <tr>
-                                       <td id="' . $idAttr . '"' . ($v['row']['_CSSCLASS'] ? ' class="' . $v['row']['_CSSCLASS'] . '"' : '') . '>' . $v['HTML'] . $this->wrapTitle($this->getTitleStr($v['row'], $titleLen), $v['row'], $v['bank']) . '</td>
-                               </tr>
-                       ';
+               $closeDepth = array();
+               foreach ($treeArr as $treeItem) {
+                       $classAttr = $treeItem['row']['_CSSCLASS'];
+                       if ($treeItem['isFirst']) {
+                               $out .= '<ul class="list-tree">';
+                       }
+
+                       // Add CSS classes to the list item
+                       if ($treeItem['hasSub']) {
+                               $classAttr .= ' list-tree-control-open';
+                       }
+
+                       $idAttr = htmlspecialchars($this->domIdPrefix . $this->getId($treeItem['row']) . '_' . $treeItem['bank']);
+                       $out .= '<li id="' . $idAttr . '"' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '') . '><span class="list-tree-group">' . $treeItem['HTML'] . $this->wrapTitle($this->getTitleStr($treeItem['row'], $titleLen), $treeItem['row'], $treeItem['bank']) . '</span>';
+
+                       if (!$treeItem['hasSub']) {
+                               $out .= '</li>';
+                       }
+
+                       // We have to remember if this is the last one
+                       // on level X so the last child on level X+1 closes the <ul>-tag
+                       if ($treeItem['isLast']) {
+                               $closeDepth[$treeItem['invertedDepth']] = 1;
+                       }
+                       // If this is the last one and does not have subitems, we need to close
+                       // the tree as long as the upper levels have last items too
+                       if ($treeItem['isLast'] && !$treeItem['hasSub']) {
+                               for ($i = $treeItem['invertedDepth']; $closeDepth[$i] == 1; $i++) {
+                                       $closeDepth[$i] = 0;
+                                       $out .= '</ul></li>';
+                               }
+                       }
                }
-               $out .= '
-                       </table>';
+               $out = '<ul class="list-tree" id="treeRoot">' . $out . '</ul>';
                return $out;
        }
 
@@ -462,21 +472,19 @@ abstract class AbstractTreeView {
         * @param int $a The current entry number
         * @param int $c The total number of entries. If equal to $a, a "bottom" element is returned.
         * @param int $nextCount The number of sub-elements to the current element.
-        * @param bool $exp The element was expanded to render subelements if this flag is set.
+        * @param bool $isOpen The element was expanded to render subelements if this flag is set.
         * @return string Image tag with the plus/minus icon.
         * @access private
         * @see \TYPO3\CMS\Backend\Tree\View\PageTreeView::PMicon()
         */
-       public function PMicon($row, $a, $c, $nextCount, $exp) {
-               $PM = $nextCount ? ($exp ? 'minus' : 'plus') : 'join';
-               $BTM = $a == $c ? 'bottom' : '';
-               $icon = IconUtility::getSpriteIcon('treeline-' . $PM . $BTM);
+       public function PMicon($row, $a, $c, $nextCount, $isOpen) {
                if ($nextCount) {
-                       $cmd = $this->bank . '_' . ($exp ? '0_' : '1_') . $row['uid'] . '_' . $this->treeName;
+                       $cmd = $this->bank . '_' . ($isOpen ? '0_' : '1_') . $row['uid'] . '_' . $this->treeName;
                        $bMark = $this->bank . '_' . $row['uid'];
-                       $icon = $this->PM_ATagWrap($icon, $cmd, $bMark);
+                       return $this->PM_ATagWrap('', $cmd, $bMark, $isOpen);
+               } else {
+                       return '';
                }
-               return $icon;
        }
 
        /**
@@ -485,17 +493,18 @@ abstract class AbstractTreeView {
         * @param string $icon HTML string to wrap, probably an image tag.
         * @param string $cmd Command for 'PM' get var
         * @param bool $bMark If set, the link will have a anchor point (=$bMark) and a name attribute (=$bMark)
+        * @param bool $isOpen
         * @return string Link-wrapped input string
         * @access private
         */
-       public function PM_ATagWrap($icon, $cmd, $bMark = '') {
+       public function PM_ATagWrap($icon, $cmd, $bMark = '', $isOpen = FALSE) {
                if ($this->thisScript) {
                        if ($bMark) {
                                $anchor = '#' . $bMark;
                                $name = ' name="' . $bMark . '"';
                        }
                        $aUrl = $this->getThisScript() . 'PM=' . $cmd . $anchor;
-                       return '<a href="' . htmlspecialchars($aUrl) . '"' . $name . '>' . $icon . '</a>';
+                       return '<a class="list-tree-control ' . ($isOpen ? 'list-tree-control-open' : 'list-tree-control-closed') . ' href="' . htmlspecialchars($aUrl) . '"' . $name . '><i class="fa"></i></a>';
                } else {
                        return $icon;
                }
@@ -731,7 +740,6 @@ abstract class AbstractTreeView {
                        end($this->tree);
                        // Get the key for this space
                        $treeKey = key($this->tree);
-                       $LN = $a == $c ? 'blank' : 'line';
                        // If records should be accumulated, do so
                        if ($this->setRecs) {
                                $this->recs[$row['uid']] = $row;
@@ -742,34 +750,35 @@ abstract class AbstractTreeView {
                        $this->orig_ids_hierarchy[$depth][] = $row['_ORIG_uid'] ?: $row['uid'];
 
                        // Make a recursive call to the next level
-                       $HTML_depthData = $depthData . IconUtility::getSpriteIcon('treeline-' . $LN);
-                       if ($depth > 1 && $this->expandNext($newID) && !$row['php_tree_stop']) {
-                               $nextCount = $this->getTree($newID, $depth - 1, $this->makeHTML ? $HTML_depthData : '', $blankLineCode . ',' . $LN, $row['_SUBCSSCLASS']);
+                       $hasSub = $this->expandNext($newID) && !$row['php_tree_stop'];
+                       if ($depth > 1 && $hasSub) {
+                               $nextCount = $this->getTree($newID, $depth - 1, '', '', $row['_SUBCSSCLASS']);
                                if (!empty($this->buffer_idH)) {
                                        $idH[$row['uid']]['subrow'] = $this->buffer_idH;
                                }
                                // Set "did expand" flag
-                               $exp = 1;
+                               $isOpen = 1;
                        } else {
                                $nextCount = $this->getCount($newID);
                                // Clear "did expand" flag
-                               $exp = 0;
+                               $isOpen = 0;
                        }
                        // Set HTML-icons, if any:
                        if ($this->makeHTML) {
-                               $HTML = $depthData . $this->PMicon($row, $a, $c, $nextCount, $exp);
-                               $HTML .= $this->wrapStop($this->getIcon($row), $row);
+                               $HTML = $this->PMicon($row, $a, $c, $nextCount, $isOpen) . $this->wrapStop($this->getIcon($row), $row);
                        }
                        // Finally, add the row/HTML content to the ->tree array in the reserved key.
                        $this->tree[$treeKey] = array(
                                'row' => $row,
                                'HTML' => $HTML,
-                               'HTML_depthData' => $this->makeHTML == 2 ? $HTML_depthData : '',
                                'invertedDepth' => $depth,
-                               'blankLineCode' => $blankLineCode,
-                               'bank' => $this->bank
+                               'bank' => $this->bank,
+                               'hasSub' => $nextCount && $hasSub,
+                               'isFirst' => $a === 1,
+                               'isLast' => $a === $c,
                        );
                }
+
                $this->getDataFree($res);
                $this->buffer_idH = $idH;
                return $c;
@@ -842,8 +851,7 @@ abstract class AbstractTreeView {
                        }
                        return $parentId;
                } else {
-                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(implode(',', $this->fieldArray), $this->table, $this->parentField . '=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($parentId, $this->table) . BackendUtility::deleteClause($this->table) . BackendUtility::versioningPlaceholderClause($this->table) . $this->clause, '', $this->orderByFields);
-                       return $res;
+                       return $GLOBALS['TYPO3_DB']->exec_SELECTquery(implode(',', $this->fieldArray), $this->table, $this->parentField . '=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($parentId, $this->table) . BackendUtility::deleteClause($this->table) . BackendUtility::versioningPlaceholderClause($this->table) . $this->clause, '', $this->orderByFields);
                }
        }
 
@@ -859,8 +867,7 @@ abstract class AbstractTreeView {
                if (is_array($this->data)) {
                        return count($this->dataLookup[$res][$this->subLevelID]);
                } else {
-                       $c = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
-                       return $c;
+                       return $GLOBALS['TYPO3_DB']->sql_num_rows($res);
                }
        }
 
index 5c517f8..8f4bfc1 100644 (file)
@@ -83,7 +83,7 @@ class ElementBrowserFolderTreeView extends FolderTreeView {
         * @return string Link-wrapped input string
         * @access private
         */
-       public function PM_ATagWrap($icon, $cmd, $bMark = '') {
+       public function PM_ATagWrap($icon, $cmd, $bMark = '', $isOpen = FALSE) {
                $name = $anchor = '';
                if ($bMark) {
                        $anchor = '#' . $bMark;
index d44721d..edbbc74 100644 (file)
@@ -68,32 +68,49 @@ class ElementBrowserPageTreeView extends BrowseTreeView {
                        $treeArr = $this->tree;
                }
                $out = '';
-               $c = 0;
-               foreach ($treeArr as $k => $v) {
-                       $c++;
-                       $bgColorClass = ($c + 1) % 2 ? 'bgColor' : 'bgColor-10';
-                       if ($GLOBALS['SOBE']->browser->curUrlInfo['act'] == 'page' && $GLOBALS['SOBE']->browser->curUrlInfo['pageid'] == $v['row']['uid'] && $GLOBALS['SOBE']->browser->curUrlInfo['pageid']) {
-                               $arrCol = '<td><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_right.gif', 'width="5" height="9"') . ' class="c-blinkArrowR" alt="" /></td>';
-                               $bgColorClass = 'bgColor4';
+               // We need to count the opened <ul>'s every time we dig into another level,
+               // so we know how many we have to close when all children are done rendering
+               $closeDepth = array();
+               foreach ($treeArr as $treeItem) {
+                       $classAttr = $treeItem['row']['_CSSCLASS'];
+                       if ($treeItem['isFirst']) {
+                               $out .= '<ul class="list-tree">';
+                       }
+
+                       // Add CSS classes to the list item
+                       if ($treeItem['hasSub']) {
+                               $classAttr .= ' list-tree-control-open';
+                       }
+
+                       if ($GLOBALS['SOBE']->browser->curUrlInfo['act'] == 'page' && $GLOBALS['SOBE']->browser->curUrlInfo['pageid'] == $treeItem['row']['uid'] && $GLOBALS['SOBE']->browser->curUrlInfo['pageid']) {
+                               $arrCol = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_right.gif', 'width="5" height="9"') . ' class="c-blinkArrowR pull-right" alt="" />';
                        } else {
-                               $arrCol = '<td></td>';
+                               $arrCol = '';
                        }
-                       $aOnClick = 'return jumpToUrl(' . \TYPO3\CMS\Core\Utility\GeneralUtility::quoteJSvalue($this->getThisScript() . 'act=' . $GLOBALS['SOBE']->browser->act . '&mode=' . $GLOBALS['SOBE']->browser->mode . '&expandPage=' . $v['row']['uid']) . ');';
-                       $cEbullet = $this->ext_isLinkable($v['row']['doktype'], $v['row']['uid']) ? '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '"><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/arrowbullet.gif', 'width="18" height="16"') . ' alt="" /></a>' : '';
-                       $out .= '
-                               <tr class="' . $bgColorClass . '">
-                                       <td nowrap="nowrap"' . ($v['row']['_CSSCLASS'] ? ' class="' . $v['row']['_CSSCLASS'] . '"' : '') . '>' . $v['HTML'] . $this->wrapTitle($this->getTitleStr($v['row'], $titleLen), $v['row'], $this->ext_pArrPages) . '</td>' . $arrCol . '<td>' . $cEbullet . '</td>
-                               </tr>';
-               }
-               $out = '
+                       $aOnClick = 'return jumpToUrl(' . \TYPO3\CMS\Core\Utility\GeneralUtility::quoteJSvalue($this->getThisScript() . 'act=' . $GLOBALS['SOBE']->browser->act . '&mode=' . $GLOBALS['SOBE']->browser->mode . '&expandPage=' . $treeItem['row']['uid']) . ');';
+                       $cEbullet = $this->ext_isLinkable($treeItem['row']['doktype'], $treeItem['row']['uid']) ? '<a href="#" class="pull-right" onclick="' . htmlspecialchars($aOnClick) . '"><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/arrowbullet.gif', 'width="18" height="16"') . ' alt="" /></a>' : '';
+                       $out .= '<li' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '') . '><span class="list-tree-group">' . $treeItem['HTML'] . $this->wrapTitle($this->getTitleStr($treeItem['row'], $titleLen), $treeItem['row'], $this->ext_pArrPages) . $cEbullet . $arrCol . '</span>';
 
+                       if (!$treeItem['hasSub']) {
+                               $out .= '</li>';
+                       }
 
-                       <!--
-                               Navigation Page Tree:
-                       -->
-                       <table border="0" cellpadding="0" cellspacing="0" id="typo3-tree">
-                               ' . $out . '
-                       </table>';
+                       // We have to remember if this is the last one
+                       // on level X so the last child on level X+1 closes the <ul>-tag
+                       if ($treeItem['isLast']) {
+                               $closeDepth[$treeItem['invertedDepth']] = 1;
+                       }
+                       // If this is the last one and does not have subitems, we need to close
+                       // the tree as long as the upper levels have last items too
+                       if ($treeItem['isLast'] && !$treeItem['hasSub']) {
+                               for ($i = $treeItem['invertedDepth']; $closeDepth[$i] == 1; $i++) {
+                                       $closeDepth[$i] = 0;
+                                       $out .= '</ul></li>';
+                               }
+                       }
+
+               }
+               $out = '<ul class="list-tree" id="treeRoot">' . $out . '</ul>';
                return $out;
        }
 
@@ -116,16 +133,17 @@ class ElementBrowserPageTreeView extends BrowseTreeView {
         * @param string $icon HTML string to wrap, probably an image tag.
         * @param string $cmd Command for 'PM' get var
         * @param bool $bMark If set, the link will have a anchor point (=$bMark) and a name attribute (=$bMark)
+        * @param bool $isOpen
         * @return string Link-wrapped input string
         */
-       public function PM_ATagWrap($icon, $cmd, $bMark = '') {
+       public function PM_ATagWrap($icon, $cmd, $bMark = '', $isOpen = FALSE) {
                $name = '';
                if ($bMark) {
                        $anchor = '#' . $bMark;
                        $name = ' name=' . $bMark;
                }
                $aOnClick = 'return jumpToUrl(' . \TYPO3\CMS\Core\Utility\GeneralUtility::quoteJSvalue($this->getThisScript() . 'PM=' . $cmd) . ',' . \TYPO3\CMS\Core\Utility\GeneralUtility::quoteJSvalue($anchor) . ');';
-               return '<a href="#"' . htmlspecialchars($name) . ' onclick="' . htmlspecialchars($aOnClick) . '">' . $icon . '</a>';
+               return '<a class="list-tree-control ' . ($isOpen ? 'list-tree-control-open' : 'list-tree-control-closed') . '" href="#"' . htmlspecialchars($name) . ' onclick="' . htmlspecialchars($aOnClick) . '"><i class="fa"></i></a>';
        }
 
        /**
index 8f22411..a5d7fba 100644 (file)
@@ -99,9 +99,7 @@ class FolderTreeView extends AbstractTreeView {
         * @see \TYPO3\CMS\Backend\Tree\View\PageTreeView::PMicon()
         */
        public function PMicon(\TYPO3\CMS\Core\Resource\Folder $folderObject, $subFolderCounter, $totalSubFolders, $nextCount, $isExpanded) {
-               $PM = $nextCount ? ($isExpanded ? 'minus' : 'plus') : 'join';
-               $BTM = $subFolderCounter == $totalSubFolders ? 'bottom' : '';
-               $icon = '<img' . IconUtility::skinImg($this->backPath, ('gfx/ol/' . $PM . $BTM . '.gif'), 'width="18" height="16"') . ' alt="" />';
+               $icon = '';
                if ($nextCount) {
                        $cmd = $this->generateExpandCollapseParameter($this->bank, !$isExpanded, $folderObject);
                        $icon = $this->PMiconATagWrap($icon, $cmd, !$isExpanded);
@@ -137,7 +135,7 @@ class FolderTreeView extends AbstractTreeView {
                        $scopeData = serialize($this->scope);
                        $scopeHash = GeneralUtility::hmac($scopeData);
                        $js = htmlspecialchars('Tree.load(' . GeneralUtility::quoteJSvalue($cmd) . ', ' . (int)$isExpand . ', this, ' . GeneralUtility::quoteJSvalue($scopeData) . ', ' . GeneralUtility::quoteJSvalue($scopeHash) . ');');
-                       return '<a class="pm" onclick="' . $js . '">' . $icon . '</a>';
+                       return '<a class="list-tree-control' . (!$isExpand ? ' list-tree-control-open' : ' list-tree-control-closed') . '" onclick="' . $js . '"><i class="fa"></i></a>';
                } else {
                        return $icon;
                }
@@ -245,11 +243,6 @@ class FolderTreeView extends AbstractTreeView {
                        $this->getBrowseableTreeForStorage($storageObject);
                        // Add tree:
                        $treeItems = array_merge($treeItems, $this->tree);
-                       // if this is an AJAX call, don't run through all mounts, only
-                       // show the expansion of the current one, not the rest of the mounts
-                       if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
-
-                       }
                }
                return $this->printTree($treeItems);
        }
@@ -294,18 +287,14 @@ class FolderTreeView extends AbstractTreeView {
                        // Set PM icon:
                        $cmd = $this->generateExpandCollapseParameter($this->bank, !$isOpen, $rootLevelFolder);
                        if (!$storageObject->isBrowsable() || $this->getNumberOfSubfolders($rootLevelFolder) === 0) {
-                               $rootIcon = 'blank';
-                       } elseif (!$isOpen) {
-                               $rootIcon = 'plusonly';
+                               $firstHtml = '';
                        } else {
-                               $rootIcon = 'minusonly';
-                       }
-                       $icon = '<img' . IconUtility::skinImg($this->backPath, ('gfx/ol/' . $rootIcon . '.gif')) . ' alt="" />';
-                       // Only link icon if storage is browseable
-                       if (in_array($rootIcon, array('minusonly', 'plusonly'))) {
-                               $firstHtml = $this->PM_ATagWrap($icon, $cmd);
-                       } else {
-                               $firstHtml = $icon;
+                               // Only show and link icon if storage is browseable
+                               $link = '';
+                               if ($this->thisScript) {
+                                       $link = ' href="' . htmlspecialchars($this->getThisScript() . 'PM=' . $cmd) . '"';
+                               }
+                               $firstHtml = '<a class="list-tree-control list-tree-control-' . ($isOpen ? 'open' : 'closed') . '"' . $link . '><i class="fa"></i></a>';
                        }
                        // Mark a storage which is not online, as offline
                        // maybe someday there will be a special icon for this
@@ -443,7 +432,7 @@ class FolderTreeView extends AbstractTreeView {
 
                $out = '
                        <!-- TYPO3 folder tree structure. -->
-                       <ul class="tree" id="treeRoot">
+                       <ul id="treeRoot" class="list-tree">
                ';
                // Evaluate AJAX request
                if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
@@ -471,21 +460,16 @@ class FolderTreeView extends AbstractTreeView {
                        // If this item is the start of a new level,
                        // then a new level <ul> is needed, but not in ajax mode
                        if ($treeItem['isFirst'] && !$doCollapse && !($doExpand && $isExpandedFolderIdentifier)) {
-                               $itemHTML = '<ul>
-';
+                               $itemHTML = '<ul class="list-tree">';
                        }
                        // Add CSS classes to the list item
                        if ($treeItem['hasSub']) {
-                               $classAttr .= ' expanded';
-                       }
-                       if ($treeItem['isLast']) {
-                               $classAttr .= ' last';
+                               $classAttr .= ' list-tree-control-open';
                        }
                        $itemHTML .= '
-                               <li id="' . $idAttr . '" ' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '') . '><div class="treeLinkItem">' . $treeItem['HTML'] . $this->wrapTitle($this->getTitleStr($treeItem['row'], $titleLength), $folderObject, $treeItem['bank']) . '</div>';
+                               <li id="' . $idAttr . '" ' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '') . '><span class="list-tree-group">' . $treeItem['HTML'] . $this->wrapTitle($this->getTitleStr($treeItem['row'], $titleLength), $folderObject, $treeItem['bank']) . '</span>';
                        if (!$treeItem['hasSub']) {
-                               $itemHTML .= '</li>
-';
+                               $itemHTML .= '</li>';
                        }
                        // We have to remember if this is the last one
                        // on level X so the last child on level X+1 closes the <ul>-tag
@@ -497,8 +481,7 @@ class FolderTreeView extends AbstractTreeView {
                        if ($treeItem['isLast'] && !$treeItem['hasSub'] && !$doCollapse && !($doExpand && $isExpandedFolderIdentifier)) {
                                for ($i = $treeItem['invertedDepth']; $closeDepth[$i] == 1; $i++) {
                                        $closeDepth[$i] = 0;
-                                       $itemHTML .= '</ul></li>
-';
+                                       $itemHTML .= '</ul></li>';
                                }
                        }
                        // Ajax request: collapse
index aa66022..0ad7080 100644 (file)
@@ -46,9 +46,10 @@ class LocalPageTree extends \TYPO3\CMS\Backend\Tree\View\BrowseTreeView {
         * @param string $icon Icon HTML
         * @param mixed $cmd (See parent class)
         * @param mixed $bMark (See parent class)
+        * @param bool $isOpen
         * @return string Icon HTML
         */
-       public function PM_ATagWrap($icon, $cmd, $bMark = '') {
+       public function PM_ATagWrap($icon, $cmd, $bMark = '', $isOpen = '') {
                return $icon;
        }
 
index 9dc9ed6..894a6f4 100644 (file)
@@ -45,32 +45,47 @@ class PageTree extends \TYPO3\CMS\Backend\Tree\View\ElementBrowserPageTreeView {
                        $treeArr = $this->tree;
                }
                $out = '';
-               $c = 0;
-               foreach ($treeArr as $k => $v) {
-                       $c++;
-                       $bgColorClass = ($c + 1) % 2 ? 'bgColor' : 'bgColor-10';
-                       if ($GLOBALS['SOBE']->browser->curUrlInfo['act'] == 'page' && $GLOBALS['SOBE']->browser->curUrlInfo['pageid'] == $v['row']['uid'] && $GLOBALS['SOBE']->browser->curUrlInfo['pageid']) {
-                               $arrCol = '<td><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_right.gif', 'width="5" height="9"') . ' class="c-blinkArrowR" alt="" /></td>';
-                               $bgColorClass = 'bgColor4';
+               $closeDepth = array();
+               foreach ($treeArr as $treeItem) {
+
+                       $classAttr = $treeItem['row']['_CSSCLASS'];
+                       if ($treeItem['isFirst']) {
+                               $out .= '<ul class="list-tree">';
+                       }
+
+                       // Add CSS classes to the list item
+                       if ($treeItem['hasSub']) {
+                               $classAttr .= ' list-tree-control-open';
+                       }
+
+                       if ($GLOBALS['SOBE']->browser->curUrlInfo['act'] == 'page' && $GLOBALS['SOBE']->browser->curUrlInfo['pageid'] == $treeItem['row']['uid'] && $GLOBALS['SOBE']->browser->curUrlInfo['pageid']) {
+                               $arrCol = '<img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/blinkarrow_right.gif', 'width="5" height="9"') . ' class="c-blinkArrowR pull-right" alt="" />';
                        } else {
-                               $arrCol = '<td></td>';
+                               $arrCol = '';
                        }
-                       $aOnClick = 'return jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . 'act=' . $GLOBALS['SOBE']->browser->act . '&editorNo=' . $GLOBALS['SOBE']->browser->editorNo . '&contentTypo3Language=' . $GLOBALS['SOBE']->browser->contentTypo3Language . '&mode=' . $GLOBALS['SOBE']->browser->mode . '&expandPage=' . $v['row']['uid']) . ');';
-                       $cEbullet = $this->ext_isLinkable($v['row']['doktype'], $v['row']['uid']) ? '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '"><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/arrowbullet.gif', 'width="18" height="16"') . ' alt="" /></a>' : '';
-                       $out .= '
-                               <tr class="' . $bgColorClass . '">
-                                       <td nowrap="nowrap"' . ($v['row']['_CSSCLASS'] ? ' class="' . $v['row']['_CSSCLASS'] . '"' : '') . '>' . $v['HTML'] . $this->wrapTitle($this->getTitleStr($v['row'], $titleLen), $v['row'], $this->ext_pArrPages) . '</td>' . $arrCol . '<td>' . $cEbullet . '</td>
-                               </tr>';
-               }
-               $out = '
+                       $aOnClick = 'return jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . 'act=' . $GLOBALS['SOBE']->browser->act . '&editorNo=' . $GLOBALS['SOBE']->browser->editorNo . '&contentTypo3Language=' . $GLOBALS['SOBE']->browser->contentTypo3Language . '&mode=' . $GLOBALS['SOBE']->browser->mode . '&expandPage=' . $treeItem['row']['uid']) . ');';
+                       $cEbullet = $this->ext_isLinkable($treeItem['row']['doktype'], $treeItem['row']['uid']) ? '<a href="#" class="pull-right" onclick="' . htmlspecialchars($aOnClick) . '"><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/arrowbullet.gif', 'width="18" height="16"') . ' alt="" /></a>' : '';
+                       $out .= '<li' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '') . '><span class="list-tree-group">' . $treeItem['HTML'] . $this->wrapTitle($this->getTitleStr($treeItem['row'], $titleLen), $treeItem['row'], $this->ext_pArrPages) . $cEbullet . $arrCol . '</span>';
 
+                       if (!$treeItem['hasSub']) {
+                               $out .= '</li>';
+                       }
 
-                       <!--
-                               Navigation Page Tree:
-                       -->
-                       <table border="0" cellpadding="0" cellspacing="0" id="typo3-tree">
-                               ' . $out . '
-                       </table>';
+                       // We have to remember if this is the last one
+                       // on level X so the last child on level X+1 closes the <ul>-tag
+                       if ($treeItem['isLast']) {
+                               $closeDepth[$treeItem['invertedDepth']] = 1;
+                       }
+                       // If this is the last one and does not have subitems, we need to close
+                       // the tree as long as the upper levels have last items too
+                       if ($treeItem['isLast'] && !$treeItem['hasSub']) {
+                               for ($i = $treeItem['invertedDepth']; $closeDepth[$i] == 1; $i++) {
+                                       $closeDepth[$i] = 0;
+                                       $out .= '</ul></li>';
+                               }
+                       }
+               }
+               $out = '<ul class="list-tree" id="treeRoot">' . $out . '</ul>';
                return $out;
        }
 
index 681a673..60a9189 100644 (file)
@@ -132,6 +132,29 @@ body#typo3-alt-db-navframe-php div.c-notice {
        width: 95%;
 }
 
+/** CSS-based tree for Foldertree */
+ul#treeRoot {
+       li:last-child:before {
+               background-color: #ececec;
+       }
+
+       &:before {
+               border: 0;
+       }
+
+       > li:before {
+               border: 0;
+       }
+
+       > li {
+               border-left: 0;
+       }
+}
+
+// change background color for folder nav frame
+body#ext-backend-Modules-FileSystemNavigationFrame-index-php ul#treeRoot li:last-child:before {
+       background-color: #f5f5f5;
+}
 //
 // Configuration trees, used in Admin Tools => Configuration
 //
@@ -157,10 +180,12 @@ body#ext-backend-Modules-FileSystemNavigationFrame-index-php {
        padding: 0;
 }
 
-body#typo3-pagetree #typo3-inner-docbody,
-body#ext-backend-Modules-FileSystemNavigationFrame-index-php #typo3-inner-docbody {
+body#typo3-pagetree #typo3-inner-docbody {
        padding: 0 0 10px 0;
 }
+body#ext-backend-Modules-FileSystemNavigationFrame-index-php #typo3-inner-docbody {
+       padding: 10px 0;
+}
 
 ul.tree {
        line-height: 12px;
@@ -300,8 +325,7 @@ ul.tree div.treeLinkItem span.dragIcon {
        visibility: hidden;
 }
 
-#typo3-pagetree #typo3-docheader img,
-#ext-backend-Modules-FileSystemNavigationFrame-index-php #typo3-docheader img {
+#typo3-pagetree #typo3-docheader img {
        margin: 2px;
 }
 
index f9b83fe..4bd4579 100644 (file)
@@ -10865,6 +10865,22 @@ body#typo3-alt-db-navframe-php div.c-notice {
   padding: 5px 5px 5px 5px;
   width: 95%;
 }
+/** CSS-based tree for Foldertree */
+ul#treeRoot li:last-child:before {
+  background-color: #ececec;
+}
+ul#treeRoot:before {
+  border: 0;
+}
+ul#treeRoot > li:before {
+  border: 0;
+}
+ul#treeRoot > li {
+  border-left: 0;
+}
+body#ext-backend-Modules-FileSystemNavigationFrame-index-php ul#treeRoot li:last-child:before {
+  background-color: #f5f5f5;
+}
 table.t3-tree-config {
   background: #ececec;
   background-image: linear-gradient(center top, #ffffff 0px, #ececec 100px);
@@ -10879,10 +10895,12 @@ body#ext-backend-Modules-FileSystemNavigationFrame-index-php {
   margin: 0;
   padding: 0;
 }
-body#typo3-pagetree #typo3-inner-docbody,
-body#ext-backend-Modules-FileSystemNavigationFrame-index-php #typo3-inner-docbody {
+body#typo3-pagetree #typo3-inner-docbody {
   padding: 0 0 10px 0;
 }
+body#ext-backend-Modules-FileSystemNavigationFrame-index-php #typo3-inner-docbody {
+  padding: 10px 0;
+}
 ul.tree {
   line-height: 12px;
   list-style: none;
@@ -10987,8 +11005,7 @@ ul.tree div.treeLinkItem span.dragIcon {
   cursor: pointer;
   visibility: hidden;
 }
-#typo3-pagetree #typo3-docheader img,
-#ext-backend-Modules-FileSystemNavigationFrame-index-php #typo3-docheader img {
+#typo3-pagetree #typo3-docheader img {
   margin: 2px;
 }
 .t3-icon-treeline {