Sections

Sections Plugin

Das Plugin ist kein klassisches Plugin, welches man auf einer Seite plazieren kann, sondern es steuert nur Resourcen und Typoscript bei. Dadurch ist aber eine bessere Strukturierung und Wiederverwendbarkeit gegeben.

Im Prinzip ist es eine Art Sitemap für die aktuelle Seite, ich habe damit ein OnePage Layout realisiert.

Meine Sections Plugin bestehen aus

  • Mehreren Elementen vom Typ Section
  • Jede Section sollte einen je ein SectionHeader enthalten an erster Stelle
  • Ein Container vom Typ Sections der die Elemente vom Typ Section beinhaltet
  • Einem SectionMenu das alle SectionHeader anzeigt als Navigation
Erstellt: 03/2014| Geändert: 10/2015

Plugin anlegen

Zum Anlegen folgendes:

./flow kickstart:package RSYS.Plugin.Sections

Dann habe ich das Manifest composer.json editiert

{
    "name": "rsys/plugin-sections",
    "description": "Sections plugin for TYPO3 Neos",
    "type":"typo3-flow-plugin",
    "license": "GPL-3.0+",
    "authors": [
    {
        "name": "Erwin Knoll",
        "email": "typo3coding@rootsystem.de"
    }
    ],
    "require": {
        "typo3/flow":"*",
        "typo3/neos":"*"
    },
    "autoload": {
        "psr-0": {
            "RSYS\\Plugin\\Sections": "Classes"
        }
    }
}

Erstellt: 03/2014| Geändert: 10/2015

NodeTypes

NodeTypes

Dann anlegen von Configuration/NodeTypes.yaml:

         
##
# A custom "Menu" NodeType for Sections
#
'RSYS.Plugin.Sections:SectionMenu':
  superTypes: ['TYPO3.Neos:Content']
  ui:
    label: 'Section menu'
    icon: 'icon-file-text'
    inspector:
      groups:
        general:
          label: 'Eigenschaften'
          position: 1   
  properties: 
    title:
      type: string
      ui:
        label: 'Title'
        inspector:
          group: 'general'
    height:
      type: integer
      defaultValue: '200'  
      ui:
        label: 'Height'
        inspector:
          group: 'general'         
    backgroundImage:
      type: TYPO3\Media\Domain\Model\ImageVariant
      ui:
        label: 'Image'
        reloadIfChanged: TRUE
        inspector:
          group: 'general'


##
# Section
#
'RSYS.Plugin.Sections:Section':
  superTypes: ['TYPO3.Neos:ContentCollection']
  ui:
    label: 'Section'
    inspector:
      groups:
        document:
          label: 'Section'
          position: 1
 
  properties:
    caption:
      type: string
      ui:
        label: 'Caption'
        reloadIfChanged: TRUE
        inspector:
          group: 'document'
         
##
# Section Collection

'RSYS.Plugin.Sections:Sections':
  superTypes: ['TYPO3.Neos.NodeTypes:Column']
  ui:
    label: 'Sections'
    inspector:
      groups:
        document:
          label: 'Document'
          position: 1
  properties:
    title:
      type: string
      ui:
        label: 'Title'
        reloadIfChanged: TRUE
        inspector:
          group: 'document'
  childNodes:
    column0:
      type: 'RSYS.Plugin.Sections:Section'     
    column1:
      type: 'RSYS.Plugin.Sections:Section'
    column2:
      type: 'RSYS.Plugin.Sections:Section'
    column3:
      type: 'RSYS.Plugin.Sections:Section'

##
# Section Header
#
'RSYS.Plugin.Sections:SectionHeader':
  superTypes: ['TYPO3.Neos:Content']
  ui:
    label: 'Section Header'
    icon: 'icon-file-text'
    inspector:
      groups:
        general:
          label: 'Eigenschaften'
          position: 1
  properties:
    title:
      type: string
      defaultValue: '<h1>Enter headline here</h1>'
      ui:
        inlineEditable: TRUE
        aloha:
          'format':
            'sub': TRUE
            'sup': TRUE
            'p': TRUE
            'h1': TRUE
            'h2': TRUE
            'h3': TRUE
            'removeFormat': TRUE
          'link':
            'a': TRUE
    name:
      type: string
      defaultValue: 'name'  
      ui:
        label: 'Name'
        inspector:
          group: 'general'
    height:
      type: integer
      defaultValue: 287
      ui:
        label: 'Height'
        inspector:
          group: 'general'
    texttop:
      type: string     
      defaultValue: 'margin-0' 
      ui:
        label: 'Text Top'
        reloadIfChanged: TRUE
        inspector:
          group: 'general'
          editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor'
          editorOptions:
            placeholder: 'Default'
            values:
              'margin-0':
                label: 'Keiner'
              'margin-1':
                label: 'Abstand 1' 
              'margin-2':
                label: 'Abstand 2' 
              'margin-3':
                label: 'Abstand 3' 
              'margin-4':
                label: 'Abstand 4'
              'margin-5':
                label: 'Abstand 5'
    imagetop:
      type: integer     
      defaultValue: -280
      ui:
        label: 'Image Top'
        reloadIfChanged: TRUE
        inspector:
          group: 'general'           
    backgroundImage:
      type: TYPO3\Media\Domain\Model\ImageVariant
      ui:
        label: 'Image'
        reloadIfChanged: TRUE
        inspector:
          group: 'general'         

Typoscript

Resources/Private/TypoScripts/Library/Root.ts2

include: resource://RSYS.Plugin.Sections/Private/TypoScripts/Library/NodeTypes.ts2

Resources/Private/TypoScripts/Library/NodeTypes.ts2

#
# A Section is a Content Collection
#

prototype(RSYS.Plugin.Sections:Section) < prototype(TYPO3.Neos.NodeTypes:MultiColumnItem) {
        templatePath = 'resource://RSYS.Plugin.Sections/Private/Templates/NodeTypes/Section.html'
        sectiontitle = ${q(node).property('sectiontitle')}
        caption = ${q(node).property('caption')}
        attributes = TYPO3.TypoScript:Attributes {
            class = 'section'
        }
}

#
# A Section Header will be schown in the SectionMenu
#
prototype(RSYS.Plugin.Sections:SectionHeader) < prototype(TYPO3.Neos:Content) {
        templatePath = 'resource://RSYS.Plugin.Sections/Private/Templates/NodeTypes/SectionHeader.html'       
        height = ${q(node).property('height')}
        imageleft = ${q(node).property('imageleft')}
        imagetop = ${q(node).property('imagetop')}
        textleft = ${q(node).property('textleft')}
        backgroundImage  = TYPO3.TypoScript.TypoScriptObjects:ValueImplementation {
                @class = 'TYPO3\\TypoScript\\TypoScriptObjects\\ValueImplementation'
                value = ${q(node).property('backgroundImage')}
        }
}


#
# Sections is the container for serveral Section elements
#
prototype(RSYS.Plugin.Sections:Sections) < prototype(TYPO3.Neos.NodeTypes:MultiColumn) {
        templatePath = 'resource://RSYS.Plugin.Sections/Private/Templates/NodeTypes/Sections.html'
        caption = ${q(node).property('caption')}
        title = ${q(node).property('title')}
        attributes = TYPO3.TypoScript:Attributes {
            class = 'fullwidth-container'
        }
        columns = RSYS.Plugin.Sections:Section {
            collection = ${q(node).children('[instanceof RSYS.Plugin.Sections:Section]')}
            itemRenderer = RSYS.Plugin.Sections:Section
            itemName = 'node'
        }
}


#
# SectionMenu ist the navigation/menu
#
prototype(RSYS.Plugin.Sections:SectionMenu) < prototype(TYPO3.Neos:Content) {
    attributes.class = 'section-menu'
    height = ${q(node).property('height')}   
    items = ${q(node).parent().children('[instanceof RSYS.Plugin.Sections:Sections]').children('[instanceof RSYS.Plugin.Sections:Section]').children('[instanceof RSYS.Plugin.Sections:SectionHeader]')}
   
}

Fluid Templates

Templates/NodeTypes/Section.html

{namespace ts=TYPO3\TypoScript\ViewHelpers}
<div{attributes -> f:format.raw()}>
    <ts:render path="columnContent" />
</div>

Templates/NodeTypes/SectionHeader.html

{namespace neos=TYPO3\Neos\ViewHelpers}
{namespace media=TYPO3\Media\ViewHelpers}

<f:if condition="{backgroundImage}">
<f:then>       
    <div  class="section-header" style="background: url(/_Resources/Static/Packages/RSYS.DefaultSite/Images/bg-seil.png) 0px {imagetop}px  repeat-x;">
</f:then>
<f:else>
    <div  class="section-header">   
</f:else>
</f:if>

    <f:if condition="{backgroundImage}">
    <f:then>           
        <div id="{neos:contentElement.editable(property: 'name') -> f:format.stripTags()}" class="container" style="background: url({media:uri.image(image:backgroundImage)}) 0px {imagetop}px no-repeat;  ">
    </f:then>
    <f:else>
        <div id="{neos:contentElement.editable(property: 'name') -> f:format.stripTags()}" class="container">
    </f:else>
    </f:if>
        <div class="row">
            <div><a href="#top" class="linktotop pull-right"><img src="/_Resources/Static/Packages/RSYS.DefaultSite/Images/linktotop.png" alt="Zum Seitenanfang" title="Zum Seitenanfang" /></a></div>
        </div>
        <div class="row">
            <div class="col-sm-4 "  style="height: {height}px;">
            </div>
            <div class="col-sm-8 section-header-text {texttop}">
               

                {neos:contentElement.editable(property: 'title')}
            </div>
        </div>
       
    </div>
       
</div>

Templates/NodeTypes/Sections.html

{namespace ts=TYPO3\TypoScript\ViewHelpers}
<div{attributes -> f:format.raw()}>
    <ts:render path="columns" />
</div>

Templates/NodeTypes/SectionMenu.html

{namespace neos=TYPO3\Neos\ViewHelpers}
{namespace media=TYPO3\Media\ViewHelpers}


<div class="section-menu">
    <f:if condition="{backgroundImage}">
        <f:then>           
            <div class="container"  style="background: url({media:uri.image(image:backgroundImage)}) 0px -280px no-repeat;">
        </f:then>
        <f:else>
            <div class="container">
        </f:else>
    </f:if>
   
        <div class="col-sm-4 "  style="height: {height}px;" >
             
        </div>
        <div class="col-sm-8">
            <ul class="" >       
                <f:for each="{items}" as="item">
                    <li class="{item.state} ">
                        <div class="section-menu-item {item.properties.name -> f:format.stripTags()}"> <a href="#{item.properties.name -> f:format.stripTags()}">{item.properties.title -> f:format.stripTags()}</a></div>
                       
                    </li>
                </f:for>
            </ul>
        </div>
    </div>
</div>

Integration

Im Root.ts2 einfügen:

include: resource://RSYS.Plugin.Sections/Private/TypoScripts/Library/Root.ts2

Inhalte dann wie folgt anlegen:

- SectionMenu
- Sections
  - Section
    - Section Header
    - Content 1
    - Content 2
    - ...
  - Section
    - Section Header
    - Content 1
    - Content 2
    - ...

Erstellt: 03/2014| Geändert: 10/2015

Typoscript

 Typoscript

Resources/Private/TypoScripts/Library/Root.ts2

include: resource://RSYS.Plugin.Sections/Private/TypoScripts/Library/NodeTypes.ts2

Resources/Private/TypoScripts/Library/NodeTypes.ts2

#
# A Section is a Content Collection
#

prototype(RSYS.Plugin.Sections:Section) < prototype(TYPO3.Neos.NodeTypes:MultiColumnItem) {
        templatePath = 'resource://RSYS.Plugin.Sections/Private/Templates/NodeTypes/Section.html'
        sectiontitle = ${q(node).property('sectiontitle')}
        caption = ${q(node).property('caption')}
        attributes = TYPO3.TypoScript:Attributes {
            class = 'section'
        }
}

#
# A Section Header will be schown in the SectionMenu
#
prototype(RSYS.Plugin.Sections:SectionHeader) < prototype(TYPO3.Neos:Content) {
        templatePath = 'resource://RSYS.Plugin.Sections/Private/Templates/NodeTypes/SectionHeader.html'       
        height = ${q(node).property('height')}
        imageleft = ${q(node).property('imageleft')}
        imagetop = ${q(node).property('imagetop')}
        textleft = ${q(node).property('textleft')}
        backgroundImage  = TYPO3.TypoScript.TypoScriptObjects:ValueImplementation {
                @class = 'TYPO3\\TypoScript\\TypoScriptObjects\\ValueImplementation'
                value = ${q(node).property('backgroundImage')}
        }
}


#
# Sections is the container for serveral Section elements
#
prototype(RSYS.Plugin.Sections:Sections) < prototype(TYPO3.Neos.NodeTypes:MultiColumn) {
        templatePath = 'resource://RSYS.Plugin.Sections/Private/Templates/NodeTypes/Sections.html'
        caption = ${q(node).property('caption')}
        title = ${q(node).property('title')}
        attributes = TYPO3.TypoScript:Attributes {
            class = 'fullwidth-container'
        }
        columns = RSYS.Plugin.Sections:Section {
            collection = ${q(node).children('[instanceof RSYS.Plugin.Sections:Section]')}
            itemRenderer = RSYS.Plugin.Sections:Section
            itemName = 'node'
        }
}


#
# SectionMenu ist the navigation/menu
#
prototype(RSYS.Plugin.Sections:SectionMenu) < prototype(TYPO3.Neos:Content) {
    attributes.class = 'section-menu'
    height = ${q(node).property('height')}   
    items = ${q(node).parent().children('[instanceof RSYS.Plugin.Sections:Sections]').children('[instanceof RSYS.Plugin.Sections:Section]').children('[instanceof RSYS.Plugin.Sections:SectionHeader]')}
   
}

Erstellt: 03/2014| Geändert: 10/2015

Fluid Templates

Fluid Templates

Templates/NodeTypes/Section.html

{namespace ts=TYPO3\TypoScript\ViewHelpers}
<div{attributes -> f:format.raw()}>
    <ts:render path="columnContent" />
</div>

Templates/NodeTypes/SectionHeader.html

{namespace neos=TYPO3\Neos\ViewHelpers}
{namespace media=TYPO3\Media\ViewHelpers}

<f:if condition="{backgroundImage}">
<f:then>        
    <div  class="section-header" style="background: url(/_Resources/Static/Packages/RSYS.DefaultSite/Images/bg-seil.png) 0px {imagetop}px  repeat-x;">
</f:then>
<f:else>
    <div  class="section-header">    
</f:else>
</f:if>

    <f:if condition="{backgroundImage}">
    <f:then>            
        <div id="{neos:contentElement.editable(property: 'name') -> f:format.stripTags()}" class="container" style="background: url({media:uri.image(image:backgroundImage)}) 0px {imagetop}px no-repeat;  ">
    </f:then>
    <f:else>
        <div id="{neos:contentElement.editable(property: 'name') -> f:format.stripTags()}" class="container">
    </f:else>
    </f:if>
        <div class="row">
            <div><a href="#top" class="linktotop pull-right"><img src="/_Resources/Static/Packages/RSYS.DefaultSite/Images/linktotop.png" alt="Zum Seitenanfang" title="Zum Seitenanfang" /></a></div>
        </div>
        <div class="row">
            <div class="col-sm-4 "  style="height: {height}px;">
            </div>
            <div class="col-sm-8 section-header-text {texttop}">
               

                {neos:contentElement.editable(property: 'title')}
            </div>
        </div>
       
    </div>
       
</div>

Templates/NodeTypes/Sections.html

{namespace ts=TYPO3\TypoScript\ViewHelpers}
<div{attributes -> f:format.raw()}>
    <ts:render path="columns" />
</div>

Templates/NodeTypes/SectionMenu.html

{namespace neos=TYPO3\Neos\ViewHelpers}
{namespace media=TYPO3\Media\ViewHelpers}


<div class="section-menu">
    <f:if condition="{backgroundImage}">
        <f:then>            
            <div class="container"  style="background: url({media:uri.image(image:backgroundImage)}) 0px -280px no-repeat;">
        </f:then>
        <f:else>
            <div class="container">
        </f:else>
    </f:if>
   
        <div class="col-sm-4 "  style="height: {height}px;" >
             
        </div>
        <div class="col-sm-8">
            <ul class="" >        
                <f:for each="{items}" as="item">
                    <li class="{item.state} ">
                        <div class="section-menu-item {item.properties.name -> f:format.stripTags()}"> <a href="#{item.properties.name -> f:format.stripTags()}">{item.properties.title -> f:format.stripTags()}</a></div>
                       
                    </li>
                </f:for>
            </ul>
        </div>
    </div>
</div>

Erstellt: 03/2014| Geändert: 10/2015

Integration

Integration

Im Root.ts2 einfügen:

include: resource://RSYS.Plugin.Sections/Private/TypoScripts/Library/Root.ts2

Inhalte dann wie folgt anlegen:

- SectionMenu
- Sections
  - Section
    - Section Header
    - Content 1
    - Content 2
    - ...
  - Section
    - Section Header
    - Content 1
    - Content 2
    - ...

Erstellt: 03/2014| Geändert: 10/2015