Typoscript append content in menu after sub-items - typo3

I want to create a popup menu with content elements of the items.
The structure in the backend is basically as follows:
Menu1
Submenu1.1
Submenu1.2
Submenu1.3
Menu2
Submenu2.1
Submenu2.2
Submenu2.3
Where Menu1 and Menu2 have content elements on the page.
I managed to access the content elements, however, the elements are rendered BEFORE the sub menu items. I need them after that.
What I get:
<div class="headeroverlay">
<div class="dropdown-overlay" id="overlay_4">
<!-- CONTENT ELEMENTS -->
<div class="contentimagesandtext">
<div class="item"><!-- Content Element 1 of Menu 1 --></div>
<div class="item"><!-- Content Element 2 of Menu 1 --></div>
</div>
<!-- SUB MENU -->
<div class="subnav-block">
<div class="subnav-link">Submenu1.1</div>
<div class="subnav-link">Submenu1.2</div>
<div class="subnav-link">Submenu1.3</div>
</div>
</div>
<div class="dropdown-overlay topdropdown" id="overlay_5">
<!-- same for Menu 2 -->
</div>
</div>
But I need content and submenu switched:
<div class="headeroverlay">
<div class="dropdown-overlay" id="overlay_4">
<!-- SUB MENU -->
<div class="subnav-block">
<div class="subnav-link">Submenu1.1</div>
<div class="subnav-link">Submenu1.2</div>
<div class="subnav-link">Submenu1.3</div>
</div>
<!-- CONTENT ELEMENTS -->
<div class="contentimagesandtext">
<div class="item"><!-- Content Element 1 of Menu 1 --></div>
<div class="item"><!-- Content Element 2 of Menu 1 --></div>
</div>
</div>
<div class="dropdown-overlay topdropdown" id="overlay_5">
<!-- same for Menu 2 -->
</div>
</div>
Here's my script so far:
lib.menuOverlay = HMENU
lib.menuOverlay{
1 = TMENU
1.expAll = 1
1.NO.doNotShowLink = 1
1.NO.wrapItemAndSub = <div class="dropdown-overlay topdropdown" id="overlay_{field:uid}">|</div>
1.NO.wrapItemAndSub.insertData = 1
# Append Content Elements to stdWrap2
1.NO.stdWrap2.append = CONTENT
1.NO.stdWrap2.append {
table = tt_content
select {
pidInList.stdWrap.data = field:uid
}
wrap = <div class="contentimagesandtext">|</div>
renderObj.stdWrap.wrap = <div class="item">|</div>
}
2 = TMENU
2.insertData = 1
2.wrap = <div class="subnav-block">|</div>
2.NO.wrapItemAndSub = <div class="subnav-link">|</div>
}
I tried adding the append to wrapItemAndSub. This will put the content elements after the submenus, but then I don't have a wrapper keeping them togehter.
Note that I need the Level-1 Page UID in the id tag of the wrapper
Question: How can I force the append to be AFTER the items, or alternatively, how can I add a wrapper around my wrapItemsAndSub, containing the parent UID?

you should care for your wraps.
you use stdWrap2 where you append your content. The append wraps the wrap-string of stdWrap2(which is empty), leaving the append the only value for stdWrap2.
now stdWrap2 has no marker where to split the wrap in before and after. So everything goes before the wrapped content. You need a split-marker in stdWrap2:
stdWrap2 = |
stdWrap2.append = ...
on the other side: you could use append as the only wrapping to get its value after the content.

Inspired by this answer, I managed to do what I need.
I append a COA to my first level menu, and put there the CONTENT and another HMENU with the sub-menu items, like this:
lib.menuOverlay = HMENU
lib.menuOverlay {
1 = TMENU
1.expAll = 1
1.NO.doNotShowLink = 1
1.NO.wrapItemAndSub = <div class="dropdown-overlay topdropdown" id="overlay_{field:uid}">|</div>
1.NO.wrapItemAndSub.insertData = 1
1.NO.stdWrap2.append = COA
1.NO.stdWrap2.append {
10 = HMENU
10 {
special = directory
special.value.data = field:uid
1 = TMENU
1.insertData = 1
1.wrap = <div class="subnav-block">|</div>
1.NO.wrapItemAndSub = <div class="subnav-link">|</div>
}
20 = CONTENT
20 {
table = tt_content
select {
pidInList.stdWrap.data = field:uid
}
wrap = <div class="contentimagesandtext">|</div>
renderObj.stdWrap.wrap = <div class="item">|</div>
}
}
}

Related

Typoscript Menu with different 2nd level depending on 1st level

I am trying to build a menu with typoscript, in which the 2nd level differs depending on the 1st level menu items - this is what I've tried so far, but it doesn't work as wanted:
lib.mainnav = HMENU
lib.mainnav {
wrap = <ul id="nv-main">|<li class="responav"><i class="fas fa-bars"></i></li></ul>
1 = TMENU
1 {
expAll = 1
NO = 1
NO.wrapItemAndSub = <li>|</li>
NO.stdWrap.htmlSpecialChars = 1
CUR = 1
CUR.wrapItemAndSub = <li class="current">|</li>
CUR.stdWrap.htmlSpecialChars = 1
}
# von 1 (TMENU) kopieren
2 < .1
2 {
expAll = 1
wrap = <div class="nv-main-sub-bg"><div class="nv-main-sub-wrapper clearfix">|</div></div>
wrap.override = <div class="nv-main-sub-bg"><div class="nv-main-sub-wrapper indented clearfix">|</div></div>
wrap.override.if {
value = 6
equals.data = page:uid
}
stdWrap.cObject = COA
stdWrap.cObject {
20 = HMENU
20 {
special = directory
special.value.data = field:pid
1 = TMENU
1 {
wrap = <div class="nv-main-col-sub"><ul>|</ul></div>
NO = 1
NO.allWrap = <li>|</li>
NO.stdWrap.htmlSpecialChars = 1
NO.after.cObject = COA
NO.after.cObject {
wrap = <div class="nv-main-info-wrapper"><div class="nv-main-col-info">|</div></div>
# Text aus dem Feld subtitle oder title der Seiteneigenschaften auslesen
10 = TEXT
10 {
value.field = subtitle // title
stdWrap.wrap = <p>|</p>
}
# Bild aus Reiter Resourcen der Seiteneigenschaften auslesen (nur bei Page-UID 4)
20 = FILES
20 {
if.value.field = pid
if.equals = 4
references {
table = pages
# Seiten-ID
uid.dataWrap= {field:uid}
fieldName = media
}
renderObj = IMAGE
renderObj {
file.width = 290c
file.height = 200c
file.import.data = file:current:uid
file.crop.data = file:current:crop
file.treatIdAsReference = 1
altText.data = file:current:title
##params = class="img-responsive"
wrap = |
}
}
# Text aus dem Feld "abstract" auslesen (nur bei Page-UID 6)
30 = TEXT
30 {
if.equals.field = pid
if.value = 6
value.field = abstract
stdWrap.wrap = <p class="b-sub">|</p>
}
}
CUR < .NO
CUR.allWrap = <li class="current">|</li>
}
}
}
}
}
This will create a 2-level-menu, where the 2nd level is a combination of the menu items each with a text info and a picture which already works. What I want is a different 2nd-level menu depending on the selected 1st level item. For this I need to change the wrapping and replace the image by additional text.
Can you please give me a hint? Thank you very much for your help!
Michael
EDIT:
Typo3 V. 8.7.16
Page Tree:
Item 1
-- Subitem 1 **with text and picture**
-- Subitem 2 **with text and picture**
-- Subitem 3 **with text and picture**
-- ...
-- Subitem XX **with text and picture**
Item 2
-- Subitem 1 **with text and picture**
-- Subitem 2 **with text and picture**
-- Subitem 3 **with text and picture**
-- ...
-- Subitem XX **with text and picture**
Item 3
-- Subitem 1 **only with text** (headline and copytext)
-- Subitem 2 **only with text** (headline and copytext)
-- Subitem 3 **only with text** (headline and copytext)
-- ...
-- Subitem XX **only with text** (headline and copytext)
Item 4
-- Subitem 1 ...
-- ...
Item 5
-- Subitem 1 ...
-- ...
HTML-structure:
<ul id="nv-main">
<li>
Item 1
<div class="nv-main-sub-bg">
<div class="nv-main-sub-wrapper clearfix">
<div class="nv-main-col-sub">
<ul>
<li>
Subitem 1 ** with text and picture **
<div class="nv-main-info-wrapper">
<div class="nv-main-col-info">
<p>XXX</p> <!— from title/subtitle —>
<img src=„XXX“ border="0"> <!— from Resources —>
</div>
</div>
</li>
<li> … </li>
<li> … </li>
<li> … </li>
…
</ul>
</div>
</div>
</div>
</li>
<li> … </li>
<li>
Item 3
<div class="nv-main-sub-bg">
<div class="nv-main-sub-wrapper **indented** clearfix">
<div class="nv-main-col-sub">
<ul>
<li>
Subitem 1 ** only with text **
<div class="nv-main-info-wrapper">
<div class="nv-main-col-info">
<p class="b-head">XXX</p> <!— from title/subtitle —>
<p class="b-sub">XXX</p> <!— from abstract —>
</div>
</div>
</li>
<li> … </li>
<li> … </li>
<li> … </li>
…
</ul>
</div>
</div>
</div>
</li>
<li> … </li>
<li> … </li>
</ul>
One solution would be to render all information for the second level and decide by CSS which parts will be shown (depending on a matching class set on the first level by a property of the level one page)
The other way would be (as Joey mentioned): build your .after object depending on the pid of the current page. either you have a list of pages, which have the special rendering 'only with text' or (more complicated) you use the pid to access a property of the level one page which indicates this special rendering.
The easy solution with a list of page uids could be:
2.after.cObject = CASE
2.after.cObject {
key.field = pid
default = COA
default {
// rendering of **with text and picture**
}
// uid of level1 page
123 = COA
123 {
// rendering of **only with text**
}
// alternative level1 page with this rendering:
234 < .123
}
If your option **only with text** means the same as **with text and picture** just without the picture you can modify your existing code (which seems very complictaed using the HMENU with special=directory) to blank the the picture:
NO.after.cObject.20.if {
isInList.field = pid
// store pages uids in constant like: 1,2,34,50,87
value = {$specialPagesUidsList}
negate = 1
}
I recently had a similar problem.
Second and third level navigation had to be the depending to the chosen item of the first level.
Do you need to have the second leven nested into the active item?
<ul class="first-level">
<li>item 1</li>
<li>item 2
<ul class="second-level">
<li>item 3</li>
</li>
</ul>
or could you handle a structure like this?
<ul class="first-level">
<li>item 1</li>
<li>item 2</li>
</ul>
<ul class="second-level">
<li>item 3</li>
</ul>
Usually dealing with the "position" within a menu is a job for option split, but this would need a completely rewritten second level, since it had to be put to the "after" part of the first level items.
But since the behaviour of a submenu is actually determined by the parent page it belongs to and not just by the position this parent page has got within the first level of the menu, you should go for a specific PID value instead of the position.
You can use "if" or a "cObject" CASE for that purpose, so that the second level can be changed based on the pid value of its items.

How to have Frontend Layout determine columns and backend layout?

Is there a way to have the Frontend layout determine the Backend layout, template file and columns?
At the moment I have the following code that allows you to set the Backend layout and it uses the appropriate template file. But this gets very messy when there are different column positions for each layout.
page.10 = FLUIDTEMPLATE
page.10 {
#format = html
file= fileadmin/templates/example/partials/example_home.html
partialRootPath = fileadmin/templates/example/partials/
layoutRootPath = fileadmin/templates/example/layouts/
variables {
# Assign the Columns
main < styles.content.get
main.select.where = colPos = 0
news < styles.content.get
news.select.where = colPos = 1
}
}
}
# Assign the Template files with the Fluid Backend-Template
page.10.file.stdWrap.cObject = CASE
page.10.file.stdWrap.cObject {
key.data = levelfield:-1, backend_layout_next_level, slide
key.override.field = backend_layout
# Set the default Template
default = TEXT
default.value = fileadmin/templates/example/partials/example_home.html
# Set a second Template
23 = TEXT
23.value = fileadmin/templates/example/partials/example_internal.html
}
Not messy at all, here's a real world example:
page.10 = FLUIDTEMPLATE
page.10 {
file.stdWrap.cObject = CASE
file.stdWrap.cObject {
key.data = pagelayout
default = TEXT
default.value = {$customPagesTemplatePath}/Standard.html
1 = TEXT
1.value = {$customPagesTemplatePath}/Home.html
2 = TEXT
2.value = {$customPagesTemplatePath}/Landing.html
10 = TEXT
10.value = {$customPagesTemplatePath}/NewsDetail.html
11 = TEXT
11.value = {$customPagesTemplatePath}/LandingMini.html
12 = TEXT
12.value = {$customPagesTemplatePath}/FullWidth.html
}
layoutRootPath = {$customPagesLayoutPath}
partialRootPath = {$customPagesPartialPath}
}
Think about it like this:
As you say, forget about frontend layout. That's legacy; be layout serves for BE and FE.
If a page was a city, the colPos would be the street. Or rather, imagine the Backend is a map you're drawing, and the frontend is a LEGO City you build according tho that map :-)) If it's OK, I'll stick with that metaphor.
ColPos is a determined part of a page where a record lives. If you can, take a look at the tt_content table in the database: you'll see that colPos is just a column with a number. So in the city "Page 1", there's a street called "colPos 7", and it contains some records (those would be houses). With the be_layout wizard in TYPO3 you'll create an administrative map of that city: how the editor should see these streets.
In the FLUIDTEMPLATE you call depending on the selected be_layout, you will create the city itself; the rendered frontend.
Here's another real world example for such a fluid template (Home.html):
<f:render partial="Mobilenav" />
<f:render partial="Header"/>
<div class="row">
<f:cObject typoscriptObjectPath="lib.home-teaser" />
</div>
<aside>
<div class="row">
<div class="columns">
<div class="row">
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<f:cObject typoscriptObjectPath="lib.home-something" />
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<f:cObject typoscriptObjectPath="lib.home-somethingelse" />
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<div class="fp-teaser-box">
<f:cObject typoscriptObjectPath="lib.home-news-plugin-title" />
<div class="fp-teaser-hr"></div>
<div class="fp-teaser-content">
<f:cObject typoscriptObjectPath="lib.home-news" />
</div>
</div>
</div>
</div>
<div class="fp-teaser-outer small-48 medium-24 large-12 columns">
<div class="fp-teaser-box-wrapper">
<div class="fp-teaser-box">
<f:cObject typoscriptObjectPath="lib.home-blog-plugin-title" />
<div class="fp-teaser-hr"></div>
<div class="fp-teaser-content">
<f:cObject typoscriptObjectPath="lib.home-blog" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</aside>
<f:render partial="Footer"/>
... well, but where's the correlation with the colPos?
Nowhere yet! I (while being positive that there are other approaches) do this in TypoScript:
lib.home-something < styles.content.get
lib.home-something {
select.where = colPos = 7
}
So by this we prepare content for the fluid template: get all content of that page's column 7 (using the extension fluid_styled_content) and put it into a "lib" content object.
That's then inserted into the page via the f:cObject viewhelper:
<f:cObject typoscriptObjectPath="lib.home-something" />
Like this, all houses in 7th street are put into the city in exactly this location – and thus rendered in your page.
Programmatically,
$backendLayout=$GLOBALS['TSFE']->cObj->getData('pageLayout');
If None was selected in the backend [-1], it will output 'none'.
If nothing was selected it will output 'default'. Otherwise it will output the correct backend layout prefixed with your extension, taking into account subpage layouts up the page ancestry chain.

TYPO3 - Custom page types not showing in menu

in my TYPO3 7.5 project I have created some custom page types by registering them in ext_tables.php as described further here
I can select those page types in the backend, no errors, all good. Also checking for a certain page-type via statements in the frontend works fine.
Now I want to create a menu of those (sub-)page trees. The TypoScript solution looks like this and works fine:
lib.tourTeasers = HMENU
lib.tourTeasers {
special = directory
wrap = <section class="row">|</section>
1 = TMENU
1 {
wrap = <div class="col-sm-12">|</div>
expAll = 1
NO {
doNotLinkIt = 1
linkWrap = <h2 style="text-align:right">Kategorie: |</h2>
}
}
2 = TMENU
2{
expAll = 1
NO{
doNotLinkIt = 1
linkWrap = <h3>Tourtyp: |</h3>
}
}
3 = TMENU
3{
NO{
doNotLinkIt = 1
linkWrap = <h4>|</h4>
after.cObject = COA
after.cObject {
stdWrap.dataWrap = <div class="row teaser">|</div>
10 = FILES
10 {
references {
table = pages
fieldName = media
}
renderObj=IMAGE
renderObj{
file{
width=300c
height=150c
#maxW=257c
#maxH=150c
import.data= file:current:publicUrl
}
altText.data = file:current:title
#altText.field=abstract
#titleText.field=nav_title
#stdWrap.dataWrap = |</a>
stdWrap.dataWrap(
<a href="index.php?id={field:uid}" title="Tour {field:title} ansehen">
<div class="col-sm-4 teaser__image">|</div>
</a>
)
params = class="img-responsive"
}
}
30 = TEXT
30.field = abstract // bodytext
30.crop = 250
30.wrap = <div class="col-sm-8 teaser__description"><p>|</p>
40 = TEXT
40.value = Ansehen
40.typolink.parameter.field = uid
40.typolink.ATagParams = class="btn"
40.wrap = <div class="button teaser__cta">|</div></div>
}
}
}
}
My problem is:
If I use the very Fluid Viewhelper that is intended to render exacly the same
<v:page.menu.directory pages="{page_uid}" as="tours" expandAll="true">
<f:for each="{tours}" as="tour">
<div class="row">
<div class="col-sm-3">
<v:page.resources.fal table="pages" field="media" uid="{tour.uid}" as="images">
<f:for each="{images}" as="image">
<f:image src="{image.url}" alt="{image.alternative} {image.name}" title="{image.title}" class="img-responsive"/>
</f:for>
</v:page.resources.fal>
</div>
<div class="col-sm-9">
<h3>{tour.title}</h3>
{tour.abstract}
</div>
</div>
</f:for>
</v:page.menu.directory>
{page_uid} being the parent page, nothing is displayed.
If I change some of the sub-pages' doktype back to "default" they are displayed in the rendered menu.
any idea as to why this is? Am i missing a certain argument in the viewhelper? i also tried to set the allowed doktypes in the viewhelper but that doesn't change anything.
thanks for the reponses, indeed it had to do with the doktype, is I didn't include the "new" ones for both the parent pages AND their sub-pages. Works now, solved. Fluid really rocks

Get current pagetitle in Typo3 in Hmenu

I want to get the pagetitle of the current page I'm on in Typo3. I want to wrap a div - Box for a Hmenu. That works, but I also want the Title in the div to be the title of the current page. My typoscript looks like this
temp.pagetitle = TEXT
temp.pagetitle.field=title
page=PAGE
page.typeNum = 0
page.10.marks.LEFT_MENU = HMENU
page.10.marks.LEFT_MENU {
special = directory
special.value = {$pwcms.linkesMenu.rootSeitenID}
excludeUidList = {$pwcms.linkesMenu.nichtSichtbareSeiten}
stdWrap.preCObject < temp.pagetitle
stdWrap.wrap = <div class="bigBox shadow"> <div class="csc-header csc-header-n1">
<h1 class="csc-firstHeader">temp.pagetitle</h1></div>| </div>
stdWrap.wrap.insertData = 1
If I save these settings and reload the page, the caption in my div Box just says "temp.pagetitle"
I guess it should be some kind of this way:
page = PAGE
page.typeNum = 0
page.10.marks.LEFT_MENU = HMENU
page.10.marks.LEFT_MENU {
special = directory
special.value = {$pwcms.linkesMenu.rootSeitenID}
excludeUidList = {$pwcms.linkesMenu.nichtSichtbareSeiten}
stdWrap.preCObject = TEXT
stdWrap.preCObject.data = page : file
stdWrap.preCObject.wrap = <div class="bigBox shadow"> <div class="csc-header csc-header-n1">
<h1 class="csc-firstHeader"> | </h1> </div> </div>
}

TYPO3 TMENU each special.value wrap

I dont come forth. I want to wrap each given PID in its own unique wrap.
Here my code:
menutab.list = HMENU
menutab.list.special = directory
menutab.list.special.value = 7,8,9,10,11,12,13
menutab.list.1 = TMENU
menutab.list.1.wrap = <div>|</div>
...
So thats working fine. I get every submenu of given PIDs but now i'm searching for something like that:
menutab.list.special.value.wrap = <div id="current PID!"> | </div>
I hope someone understand my issue.
Big thanks!!
It depends which field you would like to display, but basically any field from the page record can be displayed into the output.
menutab.list = HMENU
menutab.list {
special = directory
special.value = 7,8,9,10,11,12,13
1 = TMENU
1 {
# stdWrap2 wraps the whole item, including the link
NO.stdWrap2.dataWrap = <div id="p{field:uid}">|</div>
}
}
This will give the following output:
<div id="p26">Test 0</div>
<div id="p27">Test 1</div>
<div id="p30">Test 2</div>
<div id="p31">Test 3</div>
<div id="p35">Test 4</div>
<div id="p36">Test 5</div>
<div id="p37">Test 6</div>
For more options, please take a look at the TSref and the stdWrap functions.
TSref
http://typo3.org/documentation/document-library/references/doc_core_tsref/4.4.0/view/toc/0/
stdWrap
http://typo3.org/documentation/document-library/references/doc_core_tsref/4.4.0/view/1/5/#id2618234
I think the easiest is to do something like that, not sure of the syntax... :
menutab.list.1 = HMENU
menutab.list.1 {
special = directory
special.value = 7
1 = TMENU
1.wrap = <div id="7"> | </div>
}
menutab.list.2 < menutab.list.1
menutab.list.2.special.value = 8
menutab.list.2.1.wrap = <div id="8"> | </div>
...
Not the best solution, but can work