├── Configuration ├── Settings.yaml └── NodeTypes.yaml ├── Resources └── Private │ ├── Fusion │ ├── Library │ │ └── NodeTypes │ │ │ ├── MultiColumn.ts2 │ │ │ ├── MultiColumnItem.ts2 │ │ │ ├── NavTabPanel.ts2 │ │ │ ├── Jumbotron.ts2 │ │ │ ├── ResponsiveImage.ts2 │ │ │ ├── Menu.ts2 │ │ │ ├── MediaList.ts2 │ │ │ ├── PanelGroup.ts2 │ │ │ ├── Media.ts2 │ │ │ ├── Panel.ts2 │ │ │ ├── Carousel.ts2 │ │ │ ├── YouTube.ts2 │ │ │ ├── Button.ts2 │ │ │ └── NavTab.ts2 │ └── Root.fusion │ └── Templates │ ├── NodeTypes │ ├── PanelGroup.html │ ├── MediaList.html │ ├── ResponsiveImage.html │ ├── Button.html │ ├── Jumbotron.html │ ├── NavTab.html │ ├── Partials │ │ ├── NavTabNavigation.html │ │ └── ResponsiveImage.html │ ├── YouTube.html │ ├── Carousel.html │ ├── Panel.html │ ├── Media.html │ └── Menu.html │ └── TypoScriptObjects │ ├── NavTabPanel.html │ └── CarouselItem.html ├── .gitignore ├── README.md ├── Changelog.txt └── composer.json /Configuration/Settings.yaml: -------------------------------------------------------------------------------- 1 | 2 | Neos: 3 | Neos: 4 | nodeTypes: 5 | groups: 6 | bootstrap: 7 | position: 300 8 | label: Bootstrap 9 | fusion: 10 | autoInclude: 11 | Weissheiten.Neos.Bootstrap: true 12 | -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/MultiColumn.ts2: -------------------------------------------------------------------------------- 1 | # Code originates from the TYPO3 Neos Demo Package 2 | # Section was added to allow for schema support 3 | prototype(Neos.NodeTypes:MultiColumn) { 4 | attributes.class = 'row' 5 | columns.iterationName = 'multiColumnIteration' 6 | } -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/MultiColumnItem.ts2: -------------------------------------------------------------------------------- 1 | # Code originates from the TYPO3 Neos Demo Package 2 | # Section was added to allow for schema support 3 | prototype(Neos.NodeTypes:MultiColumnItem) { 4 | attributes.class = ${'col-sm-' + String.split(q(node).parent().property('layout'), '-')[multiColumnIteration.index]} 5 | } -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/NavTabPanel.ts2: -------------------------------------------------------------------------------- 1 | prototype(Weissheiten.Neos.Bootstrap:NavTabPanel) < prototype(Neos.Neos:Content){ 2 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/NavTabPanel.html' 3 | sectionName = 'navTabPanel' 4 | 5 | tablabel = ${q(node).property('tablabel')} 6 | } -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/Jumbotron.ts2: -------------------------------------------------------------------------------- 1 | prototype(Weissheiten.Neos.Bootstrap:Jumbotron) < prototype(Neos.Neos:Content){ 2 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/Jumbotron.html' 3 | sectionName = 'jumbotron' 4 | 5 | jumbotronItems = Neos.Neos:ContentCollection{ 6 | nodePath = 'jumbotronItems' 7 | } 8 | } -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/PanelGroup.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
8 | 9 |
10 |
-------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/MediaList.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
8 | 9 |
10 |
11 | 12 | -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/ResponsiveImage.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | f:format.raw()}> 8 | 9 | 10 | -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/Button.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/ResponsiveImage.ts2: -------------------------------------------------------------------------------- 1 | prototype(Weissheiten.Neos.Bootstrap:ResponsiveImage) < prototype(Neos.NodeTypes:Image){ 2 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/ResponsiveImage.html' 3 | sectionName = 'responsiveImage' 4 | imageStyle = ${q(node).property('imageStyle')} 5 | 6 | imageStyle = ${q(node).is('[responsive=true]') ? q(node).property('imageStyle') + ' img-responsive' : q(node).property('imageStyle')} 7 | } -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/Jumbotron.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 |
13 | 14 | -------------------------------------------------------------------------------- /Resources/Private/Templates/TypoScriptObjects/NavTabPanel.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
f:format.raw()}> 8 | 9 | 10 | 11 |
12 |
-------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/NavTab.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 |
14 |
-------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/Menu.ts2: -------------------------------------------------------------------------------- 1 | // alter the prototype of menu to apply the changes to each menu used 2 | prototype(Weissheiten.Neos.Bootstrap:Menu) < prototype(Neos.Neos:Menu){ 3 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/Menu.html' 4 | sectionName = 'menu' 5 | 6 | navAttributes = Neos.Fusion:Attributes 7 | navAttributes{ 8 | class = 'navbar navbar-default navbar-fixed-top' 9 | } 10 | 11 | site = ${site} 12 | attributes{ 13 | class = 'nav navbar-nav' 14 | } 15 | } -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/MediaList.ts2: -------------------------------------------------------------------------------- 1 | prototype(Weissheiten.Neos.Bootstrap:MediaList) < prototype(Neos.Neos:Content){ 2 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/MediaList.html' 3 | sectionName = 'mediaList' 4 | 5 | prototype(Weissheiten.Neos.Bootstrap:Media){ 6 | tagName = 'li' 7 | } 8 | 9 | mediaListItems = Neos.Neos:ContentCollection { 10 | nodePath = 'mediaListItems' 11 | tagName = 'ul' 12 | attributes.class = "media-list" 13 | // overwrite the prototype for Media and include those as list items 14 | } 15 | } -------------------------------------------------------------------------------- /Resources/Private/Fusion/Root.fusion: -------------------------------------------------------------------------------- 1 | include: Library/NodeTypes/Carousel.ts2 2 | include: Library/NodeTypes/Jumbotron.ts2 3 | include: Library/NodeTypes/Media.ts2 4 | include: Library/NodeTypes/MediaList.ts2 5 | include: Library/NodeTypes/Menu.ts2 6 | include: Library/NodeTypes/MultiColumn.ts2 7 | include: Library/NodeTypes/MultiColumnItem.ts2 8 | include: Library/NodeTypes/NavTab.ts2 9 | include: Library/NodeTypes/NavTabPanel.ts2 10 | include: Library/NodeTypes/Panel.ts2 11 | include: Library/NodeTypes/PanelGroup.ts2 12 | include: Library/NodeTypes/YouTube.ts2 13 | include: Library/NodeTypes/Button.ts2 14 | include: Library/NodeTypes/ResponsiveImage.ts2 -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/Partials/NavTabNavigation.html: -------------------------------------------------------------------------------- 1 | {namespace neos=Neos\Neos\ViewHelpers} 2 | {namespace ts=Neos\Fusion\ViewHelpers} 3 | 4 | 5 | f:format.raw()}> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | f:format.raw()} {f:if(condition:tabIterator.isFirst, then: 'class="active"')}> 14 | {item.node.properties.tablabel} 15 | 16 | 17 | -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/YouTube.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | f:format.raw()}> 7 | 8 | 9 | f:format.raw()} class="embed-responsive-item" width="{width}" height="{height}"> 10 | 11 | 12 |

Please specify video ID

13 |
14 |
15 | 16 |
-------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/PanelGroup.ts2: -------------------------------------------------------------------------------- 1 | prototype(Weissheiten.Neos.Bootstrap:PanelGroup) < prototype(Neos.Neos:Content){ 2 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/PanelGroup.html' 3 | sectionName = 'panelGroup' 4 | 5 | panelGroupItems = Neos.Neos:ContentCollection { 6 | nodePath = 'panelGroupItems' 7 | tagName = 'div' 8 | attributes{ 9 | class = "panel-group" 10 | id = ${q(node).property('_name')} 11 | } 12 | # overwrite the prototype to have a possible collapse option in the link inside the panel add a data parent 13 | prototype(Weissheiten.Neos.Bootstrap:Panel){ 14 | panelHeaderAttributes.data-parent = ${'#' + q(node).parents('[instanceof Weissheiten.Neos.Bootstrap:PanelGroup]').property('_name')} 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/Media.ts2: -------------------------------------------------------------------------------- 1 | prototype(Weissheiten.Neos.Bootstrap:Media) < prototype(Neos.Neos:Content){ 2 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/Media.html' 3 | sectionName = 'media' 4 | // Media can be used as standalone or in a list - define tag here to allow overwriting in a media list 5 | tagName = 'div' 6 | 7 | mediaAlignment = ${q(node).is('[alignment="right"]') ? 'media-right' : 'media-left'} 8 | 9 | mediaHeader = ${q(node).property('mediaHeader')} 10 | mediaText = ${q(node).property('mediaText')} 11 | 12 | image = ${q(node).property('image')} 13 | alternativeText = ${q(node).property('alternativeText')} 14 | title = ${q(node).property('title')} 15 | 16 | link = ${q(node).is('[link=""]') ? '#' : q(node).property('link')} 17 | 18 | maximumWidth = 100 19 | maximumHeight = 100 20 | } -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/Panel.ts2: -------------------------------------------------------------------------------- 1 | prototype(Weissheiten.Neos.Bootstrap:Panel) < prototype(Neos.Neos:Content){ 2 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/Panel.html' 3 | sectionName = 'panel' 4 | headerIncluded = ${q(node).property('headerIncluded')} 5 | footerIncluded = ${q(node).property('footerIncluded')} 6 | panelStyle = ${q(node).property('panelStyle')} 7 | collapsable = ${q(node).property('collapsable')} 8 | 9 | panelItems = Neos.Neos:ContentCollection{ 10 | nodePath = 'panelItems' 11 | } 12 | panelHeader = Neos.NodeTypes:Headline{ 13 | @override.node = ${q(node).children('panelHeader').get(0)} 14 | } 15 | panelHeaderAttributes = Neos.Fusion:Attributes{ 16 | data-toggle = 'collapse' 17 | href = ${'#' + node.name} 18 | } 19 | 20 | panelFooter = Neos.NodeTypes:Text{ 21 | @override.node = ${q(node).children('panelFooter').get(0)} 22 | } 23 | } -------------------------------------------------------------------------------- /Resources/Private/Templates/TypoScriptObjects/CarouselItem.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | f:format.raw()}> 8 | 9 | 10 | 11 | 12 | 13 | Dummy image 14 | 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 2 | 3 | *.iml 4 | 5 | ## Directory-based project format: 6 | .idea/ 7 | # if you remove the above rule, at least ignore the following: 8 | 9 | # User-specific stuff: 10 | # .idea/workspace.xml 11 | # .idea/tasks.xml 12 | # .idea/dictionaries 13 | # .idea/shelf 14 | 15 | # Sensitive or high-churn files: 16 | # .idea/dataSources.ids 17 | # .idea/dataSources.xml 18 | # .idea/sqlDataSources.xml 19 | # .idea/dynamic.xml 20 | # .idea/uiDesigner.xml 21 | 22 | # Gradle: 23 | # .idea/gradle.xml 24 | # .idea/libraries 25 | 26 | # Mongo Explorer plugin: 27 | # .idea/mongoSettings.xml 28 | 29 | ## File-based project format: 30 | *.ipr 31 | *.iws 32 | 33 | ## Plugin-specific files: 34 | 35 | # IntelliJ 36 | /out/ 37 | 38 | # mpeltonen/sbt-idea plugin 39 | .idea_modules/ 40 | 41 | # JIRA plugin 42 | atlassian-ide-plugin.xml 43 | 44 | # Crashlytics plugin (for Android Studio and IntelliJ) 45 | com_crashlytics_export_strings.xml 46 | crashlytics.properties 47 | crashlytics-build.properties 48 | fabric.properties -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/Carousel.ts2: -------------------------------------------------------------------------------- 1 | # Code originates from the TYPO3 Neos Demo Package 2 | # Section was added to allow for schema support 3 | ## 4 | # "Carousel" element 5 | # 6 | prototype(Weissheiten.Neos.Bootstrap:Carousel) { 7 | sectionName = 'carousel' 8 | carouselItems = Neos.Neos:ContentCollection { 9 | nodePath = 'carouselItems' 10 | content.iterationName = 'carouselItemsIteration' 11 | attributes.class = 'carousel-inner' 12 | } 13 | 14 | carouselItemArray = ${q(node).children('carouselItems').children('[instanceof Neos.NodeTypes:Image]')} 15 | 16 | // Enhance image prototype for the carousel 17 | prototype(Neos.NodeTypes:Image) { 18 | // Render images in the carousel with a special template. 19 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/TypoScriptObjects/CarouselItem.html' 20 | sectionName = 'carouselItem' 21 | attributes.class = ${'item' + (carouselItemsIteration.isFirst ? ' active' : '')} 22 | 23 | // We want to use the item iterator in the template so we have to store it in ts. 24 | iteration = ${carouselItemsIteration} 25 | } 26 | } -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/Carousel.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | f:format.raw()}> 6 | 25 | 26 | -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/YouTube.ts2: -------------------------------------------------------------------------------- 1 | // under development until NEOS 1.2 when @IF for optional attributes is added - see Button.ts2 comment 2 | 3 | # based on the "YouTube" element of the NeosDemoTypo3Org package - added responsiveness support 4 | prototype(Weissheiten.Neos.Bootstrap:YouTube) < prototype(Neos.Neos:Content) { 5 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/YouTube.html' 6 | sectionName = 'YouTube' 7 | aspectRatio = ${q(node).property('aspectRatio')} 8 | video = ${q(node).property('video')} 9 | /* 10 | class="embed-responsive-item" 11 | width="{width}" height="{height}" frameborder="0" allowfullscreen> 12 | */ 13 | attributes.class > 14 | attributes = Neos.Fusion:Attributes{ 15 | src = ${'http://www.youtube.com/embed/' + q(node).property('video') + '?wmode=transparent'} 16 | frameborder = '0' 17 | allowfullscreen = 'allowfullscreen' 18 | } 19 | 20 | divattributes = Neos.Fusion:Attributes{ 21 | class = ${q(node).is('[aspectRatio=unresponsive]') ? 'video' : ' video embed-responsive embed-responsive-' + q(node).property('aspectRatio')} 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Neos CMS Twitter Bootstrap Plugin 2 | 3 | The Weissheiten Bootstrap package should allow its users to get an easy introduction to Neos CMS with the popular bootstrap template. Starting from the great TYPO3.NeosDemoTypo3Org Site package the amount of available content elements has been significantly extended and at some places altered. 4 | A big thank you to the awesome Neos CMS core team that gave me insight needed to create many of these new nodes. 5 | 6 | ## Installation 7 | 8 | The Weissheiten.Neos.Bootstrap is listed on packagist now (https://packagist.org/packages/weissheiten/neos-bootstrap) - therefore you don't have to include the package in your "repositories" entry any more. 9 | 10 | Just add the following line to your require section: 11 | 12 | ``` 13 | "weissheiten/neos-bootstrap": "2.*" 14 | ``` 15 | 16 | And the run this command to fetch the plugin: 17 | 18 | ``` 19 | composer update 20 | ``` 21 | 22 | ## Including Bootstrap 23 | 24 | The Weissheiten Bootstrap package does NOT use the TYPO3.Twitter.Bootstrap package at the moment. 25 | So you have to include either that package or Bootstrap yourself in your main templates. 26 | 27 | ## Author 28 | 29 | * email: florian.weiss@weissheiten.at 30 | * url: http://www.weissheiten.at 31 | * twitter: @WeissheitenWien 32 | 33 | ## Contributors 34 | 35 | Thank you for contributing 36 | * Egobude (zeroboh@gmail.com) 37 | -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/Partials/ResponsiveImage.html: -------------------------------------------------------------------------------- 1 | {namespace neos=Neos\Neos\ViewHelpers} 2 | {namespace media=Neos\Media\ViewHelpers} 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Dummy image 21 | 22 | 23 | 24 | 25 | 26 |
27 | {neos:contentElement.editable(property: 'caption', node: node)} 28 |
29 |
30 | -------------------------------------------------------------------------------- /Changelog.txt: -------------------------------------------------------------------------------- 1 | ###################################### 2 | # Bootstrap Package 2.1 for Neos 2.0 # 3 | ###################################### 4 | 5 | Changes 6 | ------- 7 | *) removed BreadCrumb -> Neos 2.0 core covers this well with: prototype(TYPO3.Neos:BreadcrumbMenu) 8 | *) minor adjustments from 2.0 9 | *) fixes for composer file to let versions be handled by tags instead of listing them in composer.json 10 | 11 | ################################ 12 | # Bootstrap Package 1.2 stable # 13 | ################################ 14 | 15 | BREAKING CHANGES 16 | ----------------- 17 | *) "Menu" and "Breadcrumbmenu" have been moved to a new namespace to avoid interference with the basic implementations that come with the core 18 | Please change the use of 19 | (TYPO3.Neos:Menu) to (Weissheiten.Neos.Bootstrap:Menu) 20 | and 21 | (TYPO3.Neos:BreadcrumbMenu) to (Weissheiten.Neos.Bootstrap:BreadcrumbMenu) 22 | accordingly. 23 | 24 | Changes 25 | -------- 26 | *) New NodeType: NavTab (see http://getbootstrap.com/javascript/#tabs for details) 27 | -) currently it is not possible to make a different tab than the first one the automatically selected one when loading the page containing the NavTab 28 | 29 | *) Made use of the new possibility of restricting childnodes in ContentCollections in the following nodes: 30 | -) PanelGroup 31 | -) Carousel 32 | -) NavTab 33 | 34 | Notes 35 | ------ 36 | *) Button Node is still present but not implemented with interactive functionality yet 37 | *) In case you don't see all NodeTypes when adding new content please scroll down in the "add" dialog to see all elements -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/Panel.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | f:format.raw()}> 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |
22 | 23 | 24 | 25 |
26 | 27 | 28 |
29 | 30 | 31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 | 43 |
44 |
45 | 46 | -------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/Button.ts2: -------------------------------------------------------------------------------- 1 | // This is an attempt to streamline optional attributes via prototyping 2 | // TYPO3 NEOS 1.2 will include an @IF statement to handle this problem (Neos Page.ts2 in master for reference) 3 | 4 | // base attributesRenderer that contains all attributes that are shared for all cases 5 | prototype(Weissheiten.Neos.Bootstrap:attributesRenderer) < prototype(Neos.Fusion:Attributes){ 6 | class = ${'btn ' + q(node).property('buttonStyle') + (q(node).is('[buttonSize=btn-std]') ? '' : ' ' + q(node).property('buttonSize'))} 7 | } 8 | 9 | prototype(Weissheiten.Neos.Bootstrap:attributesCase){ 10 | // by default the condition will be true - this should be overwritten by the user 11 | condition = ${true} 12 | // path of the object to render 13 | renderPath = 'renderer' 14 | renderer = Weissheiten.Neos.Bootstrap:attributesRenderer 15 | } 16 | 17 | prototype(Weissheiten.Neos.Bootstrap:Button) < prototype(Neos.Neos:Content){ 18 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/Button.html' 19 | sectionName = 'buttonSection' 20 | 21 | // "attributes >" will not delete the subproperties (.class) - line below must be used to get it to work properly 22 | attributes.class > 23 | 24 | attributes = Neos.Fusion:Case { 25 | collapseTargetAvailable { 26 | condition = ${q(node).property('collapseTarget')!=''} 27 | renderPath = 'renderer' 28 | 29 | renderer = Weissheiten.Neos.Bootstrap:attributesRenderer{ 30 | collapseTarget = ${'#' + q(node).property('collapseTarget')} 31 | data-toggle = 'collapse' 32 | } 33 | } 34 | default{ 35 | condition = ${true} 36 | renderPath = 'renderer' 37 | renderer = Weissheiten.Neos.Bootstrap:attributesRenderer 38 | } 39 | } 40 | 41 | buttonText = ${q(node).property('buttonText')} 42 | } 43 | -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/Media.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 14 | <{tagName} class="media"> 15 | 31 |
32 |

33 | 34 |
35 | 36 |
37 | 38 | -------------------------------------------------------------------------------- /Resources/Private/Templates/NodeTypes/Menu.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | f:format.raw()} role="navigation"> 12 |
13 | 25 | 26 | 31 |
32 | 33 |
34 | 35 | 36 | 37 | 38 | f:format.raw()}> 39 | {item.label} 40 | 41 |
    42 | 43 |
44 |
45 | 46 |
47 |
-------------------------------------------------------------------------------- /Resources/Private/Fusion/Library/NodeTypes/NavTab.ts2: -------------------------------------------------------------------------------- 1 | prototype(Weissheiten.Neos.Bootstrap:NavTab) < prototype(Neos.Neos:Content){ 2 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/NavTab.html' 3 | sectionName = 'navTab' 4 | 5 | // Build the menu for the NavTab 6 | navTabNavigation = Neos.Neos:Menu{ 7 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/NodeTypes/Partials/NavTabNavigation.html' 8 | sectionName = 'navTabNavigation' 9 | 10 | // start from the current level 11 | entryLevel = 1 12 | // only use nodes from the current level 13 | maximumLevels = 0 14 | 15 | // item collection consists of all children of type NavTabPanel 16 | itemCollection = ${q(node).children('navTabPanels').children('[instanceof Weissheiten.Neos.Bootstrap:NavTabPanel]').get()} 17 | 18 | // set the filter (practically redundant) 19 | filter = 'Weissheiten.Neos.Bootstrap:NavTabPanel' 20 | 21 | // add the attributes for the menu itself 22 | attributes{ 23 | class = 'nav nav-tabs' 24 | role = 'tablist' 25 | } 26 | 27 | // add the "presentation" role to all tabs (aka menu entries) no matter what state they are in (due to this being anchors we will only have the "normal" state 28 | active.attributes = Neos.Fusion:Attributes { 29 | class > 30 | role = 'presentation' 31 | } 32 | current.attributes = Neos.Fusion:Attributes { 33 | class > 34 | role = 'presentation' 35 | } 36 | normal.attributes = Neos.Fusion:Attributes { 37 | class > 38 | role = 'presentation' 39 | } 40 | site = ${site} 41 | } 42 | 43 | // set navTabPanels to a content collection with the according nodePath - we can do this because the nodetype restriction in nodetypes.yaml ensures 44 | // that there will never be anything else but objects of type 'Weissheiten.Neos.Bootstrap:NavTabPanel' in here 45 | navTabPanels = Neos.Neos:ContentCollection{ 46 | nodePath = 'navTabPanels' 47 | iterationName = 'navTabItemsIteration' 48 | attributes.class = 'tab-content' 49 | } 50 | 51 | // adapt the prototype for NavTabPanels rendered inside a NavTab 52 | prototype(Weissheiten.Neos.Bootstrap:NavTabPanel) { 53 | // Render images in the carousel with a special template. 54 | templatePath = 'resource://Weissheiten.Neos.Bootstrap/Private/Templates/TypoScriptObjects/NavTabPanel.html' 55 | sectionName = 'navTabPanel' 56 | attributes{ 57 | class = ${'tab-pane' + (navTabItemsIteration.isFirst ? ' active' : '')} 58 | role = 'tabpanel' 59 | id = ${node.identifier} 60 | } 61 | // We want to use the item iterator in the template so we have to store it in ts. 62 | iteration = ${navTabItemsIteration} 63 | 64 | // assign the Content of the navTabPanel for rendering 65 | navTabPanelContent = Neos.Neos:ContentCollection{ 66 | nodePath = 'navTabPanelContent' 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weissheiten/neos-bootstrap", 3 | "type": "neos-package", 4 | "keywords": [ 5 | "bootstrap", 6 | "neos" 7 | ], 8 | "description": "Neos CMS Bootstrap Plugin, providing a variety of NodeTypes for out-of-the-box use", 9 | "license": "GPL-3.0+", 10 | "authors": [ 11 | { 12 | "name": "Florian Weiss", 13 | "email": "office@weissheiten.at", 14 | "homepage": "http://www.weissheiten.at", 15 | "role": "Developer" 16 | } 17 | ], 18 | "require": { 19 | "neos/neos": "~4.0", 20 | "neos/nodetypes": "~4.0" 21 | }, 22 | "autoload": { 23 | "psr-0": { 24 | "Weissheiten\\Neos\\Bootstrap": "Classes" 25 | } 26 | }, 27 | "extra": { 28 | "applied-flow-migrations": [ 29 | "TYPO3.FLOW3-201201261636", 30 | "TYPO3.Fluid-201205031303", 31 | "TYPO3.FLOW3-201205292145", 32 | "TYPO3.FLOW3-201206271128", 33 | "TYPO3.FLOW3-201209201112", 34 | "TYPO3.Flow-201209251426", 35 | "TYPO3.Flow-201211151101", 36 | "TYPO3.Flow-201212051340", 37 | "TYPO3.TypoScript-130516234520", 38 | "TYPO3.TypoScript-130516235550", 39 | "TYPO3.TYPO3CR-130523180140", 40 | "TYPO3.Neos.NodeTypes-201309111655", 41 | "TYPO3.Flow-201310031523", 42 | "TYPO3.Flow-201405111147", 43 | "TYPO3.Neos-201407061038", 44 | "TYPO3.Neos-201409071922", 45 | "TYPO3.TYPO3CR-140911160326", 46 | "TYPO3.Neos-201410010000", 47 | "TYPO3.TYPO3CR-141101082142", 48 | "TYPO3.Neos-20141113115300", 49 | "TYPO3.Fluid-20141113120800", 50 | "TYPO3.Flow-20141113121400", 51 | "TYPO3.Fluid-20141121091700", 52 | "TYPO3.Neos-20141218134700", 53 | "TYPO3.Fluid-20150214130800", 54 | "TYPO3.Neos-20150303231600", 55 | "TYPO3.TYPO3CR-20150510103823", 56 | "TYPO3.Flow-20151113161300", 57 | "TYPO3.Form-20160601101500", 58 | "TYPO3.Flow-20161115140400", 59 | "TYPO3.Flow-20161115140430", 60 | "Neos.Flow-20161124204700", 61 | "Neos.Flow-20161124204701", 62 | "Neos.Twitter.Bootstrap-20161124204912", 63 | "Neos.Form-20161124205254", 64 | "Neos.Flow-20161124224015", 65 | "Neos.Party-20161124225257", 66 | "Neos.Eel-20161124230101", 67 | "Neos.Kickstart-20161124230102", 68 | "Neos.Setup-20161124230842", 69 | "Neos.Imagine-20161124231742", 70 | "Neos.Media-20161124233100", 71 | "Neos.NodeTypes-20161125002300", 72 | "Neos.SiteKickstarter-20161125002311", 73 | "Neos.Neos-20161125002322", 74 | "Neos.ContentRepository-20161125012000", 75 | "Neos.Fusion-20161125013710", 76 | "Neos.Setup-20161125014759", 77 | "Neos.SiteKickstarter-20161125095901", 78 | "Neos.Fusion-20161125104701", 79 | "Neos.NodeTypes-20161125104800", 80 | "Neos.Neos-20161125104802", 81 | "Neos.Kickstarter-20161125110814", 82 | "Neos.Neos-20161125122412", 83 | "Neos.Flow-20161125124112", 84 | "TYPO3.FluidAdaptor-20161130112935", 85 | "Neos.Fusion-20161201202543", 86 | "Neos.Neos-20161201222211", 87 | "Neos.Fusion-20161202215034", 88 | "Neos.Fusion-20161219092345", 89 | "Neos.ContentRepository-20161219093512", 90 | "Neos.Media-20161219094126", 91 | "Neos.Neos-20161219094403", 92 | "Neos.Neos-20161219122512", 93 | "Neos.Fusion-20161219130100", 94 | "Neos.Neos-20161220163741", 95 | "Neos.Neos-20170115114620", 96 | "Neos.Fusion-20170120013047", 97 | "Neos.Flow-20170125103800", 98 | "Neos.Seo-20170127154600", 99 | "Neos.Flow-20170127183102", 100 | "Neos.SwiftMailer-20161130105617", 101 | "Neos.Fusion-20180211175500", 102 | "Neos.Fusion-20180211184832", 103 | "Neos.Flow-20180415105700" 104 | ] 105 | } 106 | } -------------------------------------------------------------------------------- /Configuration/NodeTypes.yaml: -------------------------------------------------------------------------------- 1 | 2 | 'Weissheiten.Neos.Bootstrap:Jumbotron': 3 | superTypes: 4 | 'Neos.Neos:Content': true 5 | ui: 6 | label: Jumbotron 7 | icon: icon-sign-blank 8 | group: bootstrap 9 | inlineEditable: true 10 | childNodes: 11 | jumbotronItems: 12 | type: 'Neos.Neos:ContentCollection' 13 | 'Weissheiten.Neos.Bootstrap:PanelGroup': 14 | superTypes: 15 | 'Neos.Neos:Content': true 16 | ui: 17 | label: 'Panel Group' 18 | icon: icon-list 19 | group: bootstrap 20 | inlineEditable: true 21 | childNodes: 22 | panelGroupItems: 23 | constraints: 24 | nodeTypes: 25 | '*': false 26 | 'Weissheiten.Neos.Bootstrap:Panel': true 27 | type: 'Neos.Neos:ContentCollection' 28 | 'Weissheiten.Neos.Bootstrap:Panel': 29 | superTypes: 30 | 'Neos.Neos:Content': true 31 | ui: 32 | label: Panel 33 | icon: icon-check-empty 34 | group: bootstrap 35 | inlineEditable: true 36 | inspector: 37 | groups: 38 | layout: 39 | label: Layout 40 | position: 10 41 | properties: 42 | headerIncluded: 43 | type: boolean 44 | defaultValue: false 45 | ui: 46 | reloadIfChanged: true 47 | label: Header 48 | inspector: 49 | group: layout 50 | footerIncluded: 51 | type: boolean 52 | defaultValue: false 53 | ui: 54 | reloadIfChanged: true 55 | label: Footer 56 | inspector: 57 | group: layout 58 | panelStyle: 59 | type: string 60 | defaultValue: panel-default 61 | ui: 62 | reloadIfChanged: true 63 | label: 'Panel style' 64 | inspector: 65 | group: layout 66 | editor: Neos.Neos/Inspector/Editors/SelectBoxEditor 67 | editorOptions: 68 | values: 69 | panel-default: 70 | label: Standard 71 | panel-primary: 72 | label: Primary 73 | panel-success: 74 | label: Success 75 | panel-info: 76 | label: Info 77 | panel-warning: 78 | label: Warning 79 | panel-danger: 80 | label: Danger 81 | collapsable: 82 | type: string 83 | defaultValue: uncollapsable 84 | ui: 85 | reloadIfChanged: true 86 | label: Collapsable 87 | inspector: 88 | group: layout 89 | editor: Neos.Neos/Inspector/Editors/SelectBoxEditor 90 | editorOptions: 91 | values: 92 | uncollapsable: 93 | label: 'Not collapsable' 94 | 'collapse in': 95 | label: 'Collapsable show' 96 | collapse: 97 | label: 'Collapsable hidden' 98 | childNodes: 99 | panelHeader: 100 | type: 'Neos.NodeTypes:Headline' 101 | panelFooter: 102 | type: 'Neos.NodeTypes:Text' 103 | panelItems: 104 | type: 'Neos.Neos:ContentCollection' 105 | 'Weissheiten.Neos.Bootstrap:MediaList': 106 | superTypes: 107 | 'Neos.Neos:Content': true 108 | ui: 109 | label: 'Media List' 110 | icon: icon-list 111 | group: bootstrap 112 | inlineEditable: true 113 | childNodes: 114 | mediaListItems: 115 | constraints: 116 | nodeTypes: 117 | '*': false 118 | 'Weissheiten.Neos.Bootstrap:Media': true 119 | type: 'Neos.Neos:ContentCollection' 120 | 'Weissheiten.Neos.Bootstrap:Media': 121 | superTypes: 122 | 'Neos.Neos:Content': true 123 | 'Neos.NodeTypes:ImageMixin': true 124 | 'Neos.NodeTypes:LinkMixin': true 125 | 'Neos.NodeTypes:ImageAlignmentMixin': true 126 | ui: 127 | label: Media 128 | icon: icon-picture 129 | group: bootstrap 130 | inlineEditable: true 131 | inspector: 132 | groups: 133 | media: 134 | label: Media 135 | position: 11 136 | properties: 137 | mediaHeader: 138 | type: string 139 | defaultValue: 'Media header' 140 | mediaText: 141 | type: string 142 | defaultValue: 'Media text' 143 | link: 144 | ui: 145 | inspector: 146 | group: image 147 | 'Weissheiten.Neos.Bootstrap:YouTube': 148 | superTypes: 149 | 'Neos.Neos:Content': true 150 | ui: 151 | label: YouTube 152 | icon: icon-youtube 153 | group: bootstrap 154 | inspector: 155 | groups: 156 | video: 157 | label: Video 158 | position: 50 159 | properties: 160 | video: 161 | type: string 162 | defaultValue: '' 163 | ui: 164 | label: 'YouTube video ID' 165 | reloadIfChanged: true 166 | inspector: 167 | group: video 168 | aspectRatio: 169 | type: string 170 | defaultValue: 16by9 171 | ui: 172 | reloadIfChanged: true 173 | label: Layout 174 | inspector: 175 | group: video 176 | editor: Neos.Neos/Inspector/Editors/SelectBoxEditor 177 | editorOptions: 178 | values: 179 | 16by9: 180 | label: '16:9' 181 | 4by3: 182 | label: '4:3' 183 | unresponsive: 184 | label: unresponsive 185 | width: 186 | type: integer 187 | defaultValue: 400 188 | ui: 189 | label: 'Width (ignored when responsive)' 190 | reloadIfChanged: true 191 | inspector: 192 | group: video 193 | height: 194 | type: integer 195 | defaultValue: 300 196 | ui: 197 | label: 'Height (ignored when responsive)' 198 | reloadIfChanged: true 199 | inspector: 200 | group: video 201 | 'Weissheiten.Neos.Bootstrap:Button': 202 | superTypes: 203 | 'Neos.Neos:Content': true 204 | ui: 205 | label: Button 206 | icon: icon-minus-sign-alt 207 | group: bootstrap 208 | inlineEditable: true 209 | inspector: 210 | groups: 211 | layout: 212 | label: Layout 213 | position: 11 214 | trigger: 215 | label: 'Trigger & Events' 216 | position: 12 217 | properties: 218 | buttonText: 219 | type: string 220 | defaultValue: Text 221 | buttonStyle: 222 | type: string 223 | defaultValue: btn-default 224 | ui: 225 | reloadIfChanged: true 226 | label: Style 227 | inspector: 228 | group: layout 229 | editor: Neos.Neos/Inspector/Editors/SelectBoxEditor 230 | editorOptions: 231 | values: 232 | btn-default: 233 | label: Standard 234 | btn-primary: 235 | label: Primary 236 | btn-success: 237 | label: Success 238 | btn-info: 239 | label: Info 240 | btn-warning: 241 | label: Warning 242 | btn-danger: 243 | label: Link 244 | buttonSize: 245 | type: string 246 | defaultValue: btn-std 247 | ui: 248 | reloadIfChanged: true 249 | label: Size 250 | inspector: 251 | group: layout 252 | editor: Neos.Neos/Inspector/Editors/SelectBoxEditor 253 | editorOptions: 254 | values: 255 | btn-xs: 256 | label: 'Extra small' 257 | btn-sm: 258 | label: Small 259 | btn-std: 260 | label: Standard 261 | btn-lg: 262 | label: Large 263 | collapseTarget: 264 | type: string 265 | defaultValue: '' 266 | ui: 267 | label: 'Collapse Target ID' 268 | reloadIfChanged: true 269 | inspector: 270 | group: trigger 271 | 'Weissheiten.Neos.Bootstrap:ResponsiveImage': 272 | superTypes: 273 | 'Neos.NodeTypes:Image': true 274 | ui: 275 | label: 'Bootstrap Image' 276 | icon: icon-picture 277 | group: bootstrap 278 | inlineEditable: true 279 | properties: 280 | imageStyle: 281 | type: string 282 | defaultValue: '' 283 | ui: 284 | reloadIfChanged: true 285 | label: Style 286 | inspector: 287 | group: image 288 | editor: Neos.Neos/Inspector/Editors/SelectBoxEditor 289 | editorOptions: 290 | values: 291 | '': 292 | label: Standard 293 | img-rounded: 294 | label: Rounded 295 | img-circle: 296 | label: Circle 297 | img-thumbnail: 298 | label: Thumbnail 299 | responsive: 300 | type: boolean 301 | defaultValue: true 302 | ui: 303 | reloadIfChanged: true 304 | label: Responsive 305 | inspector: 306 | group: image 307 | 'Weissheiten.Neos.Bootstrap:NavTab': 308 | superTypes: 309 | 'Neos.Neos:Content': true 310 | ui: 311 | label: 'Togglable tab' 312 | icon: icon-table 313 | group: bootstrap 314 | inlineEditable: true 315 | inspector: 316 | groups: 317 | layout: 318 | label: Layout 319 | position: 11 320 | childNodes: 321 | navTabPanels: 322 | constraints: 323 | nodeTypes: 324 | '*': false 325 | 'Weissheiten.Neos.Bootstrap:NavTabPanel': true 326 | type: 'Neos.Neos:ContentCollection' 327 | 'Weissheiten.Neos.Bootstrap:NavTabPanel': 328 | superTypes: 329 | 'Neos.Neos:Content': true 330 | ui: 331 | label: 'Tab Panel' 332 | icon: icon-table 333 | group: bootstrap 334 | inlineEditable: true 335 | inspector: 336 | groups: 337 | layout: 338 | label: Layout 339 | position: 11 340 | properties: 341 | tablabel: 342 | type: string 343 | defaultValue: 'Tab label' 344 | ui: 345 | label: 'Tab label' 346 | reloadIfChanged: true 347 | inspector: 348 | group: layout 349 | childNodes: 350 | navTabPanelContent: 351 | type: 'Neos.Neos:ContentCollection' 352 | 'Neos.NodeTypes:TwoColumn': 353 | properties: 354 | layout: 355 | defaultValue: 6-6 356 | ui: 357 | inspector: 358 | editorOptions: 359 | values: 360 | 50-50: null 361 | 75-25: null 362 | 25-75: null 363 | 66-33: null 364 | 33-66: null 365 | 6-6: 366 | label: '50% / 50%' 367 | 8-4: 368 | label: '66% / 33%' 369 | 4-8: 370 | label: '33% / 66%' 371 | 'Neos.NodeTypes:ThreeColumn': 372 | properties: 373 | layout: 374 | defaultValue: 4-4-4 375 | ui: 376 | inspector: 377 | editorOptions: 378 | values: 379 | 33-33-33: null 380 | 50-25-25: null 381 | 25-50-25: null 382 | 25-25-50: null 383 | 4-4-4: 384 | label: '33% / 33% / 33%' 385 | 6-3-3: 386 | label: '50% / 25% / 33%' 387 | 3-6-3: 388 | label: '25% / 50% / 25%' 389 | 3-3-6: 390 | label: '25% / 25% / 50%' 391 | 'Neos.NodeTypes:FourColumn': 392 | properties: 393 | layout: 394 | defaultValue: 3-3-3-3 395 | ui: 396 | inspector: 397 | editorOptions: 398 | values: 399 | 25-25-25-25: null 400 | 3-3-3-3: 401 | label: '25% / 25% / 25% / 25%' 402 | 'Weissheiten.Neos.Bootstrap:Carousel': 403 | superTypes: 404 | 'Neos.Neos:Content': true 405 | childNodes: 406 | carouselItems: 407 | constraints: 408 | nodeTypes: 409 | '*': false 410 | 'Neos.NodeTypes:Image': true 411 | type: 'Neos.Neos:ContentCollection' 412 | ui: 413 | label: Carousel 414 | group: bootstrap 415 | icon: icon-picture 416 | inlineEditable: true 417 | --------------------------------------------------------------------------------