How to render content of parent documentNode in TYPO3 Neos? - typo3

I have a simple question. I have a custom content area on my page called "left". Its added to the NodeType "Page" as a childNode in the yaml file:
'TYPO3.Neos.NodeTypes:Page':
properties:
[...]
childNodes:
'left':
type: 'TYPO3.Neos:ContentCollection'
In my TypoScript I added it to the page.body.content part:
page.body.content {
main = PrimaryContent {
nodePath = 'main'
}
left = ContentCollection {
nodePath = 'left'
}
}
I can add content to this new content area and it shows up in the frontend. Everything works just fine. Now I want to check if the ContentCollection of the current documentNode is empty and if this is the case I want to render the ContentCollection of the 'left' nodePath of the parent documentNode.
In other words: Subpages should render content of their parents if they dont have content on their own withing the defined content area.
How do I achieve this?

left = ContentCollection {
#override.node = ${q(node).children('left').children().count() == 0 ? q(node).parent().get(0) : node}
nodePath = 'left'
}
Is untested but should work just fine.
Note that this only goes one level up. If you need to fallback to more levels this needs to be done a bit differently.

Related

How to make a custom content element containing header, bodytext, image from tt_content inline in TYPO3 / TCA overrides?

I want to get an array of custom content objects into my fluid template, so I can build an unordered List.
This is what I want to build:
unordered list of li elements containing image, header, bodytext
In my backend I build a custom element like this:
my custom content element with fields image, header, bodytext from tt_content
What I want to achieve is, that I have a container and in it I can have my custom content element. When expanding it, I can add header, image and bodytext. So that i basically get an array of custom content Elements that I can loop over in my fluid template.
It should look like this:
each entry should be my custom content element with image, header, bodytext when expanding.
Thanks a lot for help!
You can use the extension gridelements to create a container that can hold unlimited content elements and use its template to loop over the partial which creates your content element.
If you want to do it the TYPO3 way instead of using Grid Elements..
I see you already know how to make a custom content element. To make children within your content element you could make an extra SQL field xxx_foreign.
You need to make 2 content elements. The child you know how to make.
The TCA for the inline field of the parent and needed extra colPos in the backendLayout you can find here
Then you will need in typoscript a dataprocessor I will give an example in which the child contains assets (media). In that case you need a nested solution:
tt_content {
xxx_education_block < lib.xxxCustomContentElements
xxx_eheducation_block {
templateName = xxxEducationBlock
dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
10 {
if.isTrue.field = xxx_educations
table = tt_content
pidInList.field = pid
where = xxx_foreign=###uid### AND deleted=0 AND hidden=0
orderBy = sorting
markers {
uid.field = uid
}
as = xxxEducations
dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
10 {
if.isTrue.field = assets
references {
fieldName = assets
}
as = assets
}
}
}
}
}
}
To add this to the content wizard:
mod.wizards.newContentElement.wizardItems.blocks {
header = Xxx blokken
after = common
elements {
xxx_education_block {
iconIdentifier = content-bullets
title = XXX - Education intro block
description = Introblock xxx
tt_content_defValues {
CType = xxx_education_block
}
}
}
show := addToList(xxx_education_block)
}
If you do a debug in Fluid you should now be able to iterate over the children and the assets of the children.

How to set the zIndex layer order for geoJson layers?

I would like to have certain layers to be always on top of others, no matter in which order they are added to the map.
I am aware of bringToFront(), but it does not meet my requirements. I would like to set the zIndex dynamically based on properties.
Leaflet has the method setZIndex(), but this apparently does not work for geoJson layers:
https://jsfiddle.net/jw2srhwn/
Any ideas?
Cannot be done for vector geometries.
zIndex is a property of HTMLElements, and vector geometries (lines and polygons) are rendered as SVG elements, or programatically as <canvas> draw calls. Those two methods have no concept of zIndex, so the only thing that works is pushing elements to the top (or bottom) of the SVG group or <canvas> draw sequence.
Also, remind that L.GeoJSON is just a specific type of L.LayerGroup, in your case containing instances of L.Polygon. Furthermore, if you read Leaflet's documentation about the setZIndex() method on L.LayerGroup:
Calls setZIndex on every layer contained in this group, passing the z-index.
So, do L.Polygons have a setZIndex() method? No. So calling that in their containing group does nothing. It will have an effect on any L.GridLayers contained in that group, though.
Coming back to your problem:
I would like to have certain layers to be always on top of others, no matter in which order they are added to the map.
Looks like the thing you're looking for is map panes. Do read the map panes tutorial.
This is one of the reason for the implementation of user defined "panes" in Leaflet 1.0 (compared to versions 0.x).
Create panes: var myPane = map.createPane("myPaneName")
If necessary, set the class / z-index of the pane element: myPane.style.zIndex = 450 (refer to z-index values of built-in panes)
When creating your layers, specify their target pane option: L.rectangle(corners, { pane: "myPaneName" })
When building through the L.geoJSON factory, you can loop through your features with the onEachFeature option to clone your layers with specified target pane.
Demo: https://jsfiddle.net/3v7hd2vx/90/
For peoples who are searching about Z-Index
All path layers (so all except for markers) have no z-index because svg layers have a fix order. The first element is painted first. So the last element is painted on top.
#IvanSanchez described good why zIndex not working.
You can control the order with layer.bringToBack() or layer.bringToFront().
With that code you have more options to control the order of the layers.
L.Path.include({
getZIndex: function() {
var node = this._path;
var index = 0;
while ( (node = node.previousElementSibling) ) {
index++;
}
return index;
},
setZIndex: function(idx) {
var obj1 = this._path;
var parent = obj1.parentNode;
if(parent.childNodes.length < idx){
idx = parent.childNodes.length-1;
}
var obj2 = parent.childNodes[idx];
if(obj2 === undefined || obj2 === null){
return;
}
var next2 = obj2.nextSibling;
if (next2 === obj1) {
parent.insertBefore(obj1, obj2);
} else {
parent.insertBefore(obj2, obj1);
if (next2) {
parent.insertBefore(obj1, next2);
} else {
parent.appendChild(obj1);
}
}
},
oneUp: function(){
this.setZIndex(this.getZIndex()+1)
},
oneDown: function(){
this.setZIndex(this.getZIndex()-1)
}
});
Then you can call
polygon.oneUp()
polygon.oneDown()
polygon.setZIndex(2)
polygon.getZIndex()
And now layergroup.setZIndex(2) are working

Customizing fullpage.js to skip section(s) dynamically

The question is simple but i'm not able to make a script by myself for what i need...
I am actually using a script ( fullpage.js ) who toggle some classes into a container ( in my case switching from fp-viewing-1 to fp-viewing-x ) when you scroll down/up between sections.
I need to make a script that listen from this container and toggle a new class into a div ONLY when a class ( in my case fp-viewing-3 ) is added to this container ( from the fullpage.js script of course ).
Any way to make it?
I need to make a script that listen from this container
That's not the way to go for it.
If you want to use the status class, then just create a new class based on the previous ones as explained in this fullpage.js tutorial.
Create a conditional CSS class that will only get applied when its parent class matches your requirement.
Something like this, for example, would only apply the red color to element with myClass when you are in section 1 slide 0.
.fp-viewing-1-0 .myClass{
color: red;
}
Having:
<div id="fullpage">
<div class="section"></div>
<div class="section myClass"></div>
<div class="section"></div>
<div>
If for some other reason (use of plugins etc) you really need to add the class dynamically, then go for fullpage.js callbacks onLeave or afterLoad:
$('#fullpage').fullpage({
onLeave: function(index, nextIndex, direction){
var destination = $('.section').eq(nextIndex - 1);
destination.find('.my-element').addClass('myClass');
}
});
This is the solution to my problem.
Fullpage works as intended except for section 2.
Section 2 will be usable only scrolling down, the script ignore it when scrolling up.
$(document).ready(function() {
$('#application').fullpage({
onLeave: function(index, nextIndex, direction){
var destinationToIgnore = $('.fp-section').hasClass('ignore');
if(destinationToIgnore && direction =='up'){
var destination = nextIndex = 1
$.fn.fullpage.moveTo(destination);
}
},
afterLoad: function(anchorLink, index){
var loadedSection = $(this);
if(index !== 1){
$('.section-intro').removeClass('ignore');
}
if(index == 3){
$('.section-intro').addClass('ignore');
}
}
});
});

Set default value for image width in TYPO3 Neos

I would like to set a default value for an image width in TYPO3 Neos.
Right now an editor may insert any image and the »width« value will be equal to the original size by default.
Example
First question:
I would like to set a default of 400 pixel instead. But the width field is no distinct node property, but an attribute of »image«. How do I set default values for attributes in Neos?
Second question:
What would I need to do, to completely hide the pixel based value field and offer an selection instead? Like „Option 1: Small teaser (150px), Option 2: Regular content image (400px), Option 3: Large image (980px)“.
Should I somehow remove the »width« attribute and add a new property node? Or may I change the type of the attribute somehow?
you can extend and configure default NodeType (TYPO3.Neos.NodeTypes:ImageMixin) for ImageEditor in Neos CMS.
Follow this steps:
Step 1:
Create new configuration file NodeTypes.Mixins.yaml in your sitepackage (for example: /Packages/Sites/YourSitePackageName/Configuration/NodeTypes.ImageMixin.yaml)
Step 2:
Copy default configuration for ImageMixin from Neos CMS Core (/Packages/Application/TYPO3.Neos.NodeTypes/Configuration/NodeTypes.Mixin.yaml) and remove properties which you doesn't like to extend/configure/override (for example: alternativeText and title). At the end you must have similar code:
`# Image mixin
'TYPO3.Neos.NodeTypes:ImageMixin':
abstract: TRUE
ui:
inspector:
groups:
image:
label: i18n
position: 5
properties:
image:
type: TYPO3\Media\Domain\Model\ImageInterface
ui:
label: i18n
reloadIfChanged: TRUE
inspector:
group: 'image'
position: 50`
Step 3: If you like to hide pixel base value fields (width, height) and crop button, you must add following editor options to image property:
position: 50
editorOptions:
features:
crop: FALSE --> hides crop button
resize: FALSE --> hides pixel based value fields
You can read more about this in Neos Documentation.
Step 4: For selection of predefined image sizes we add custom property imageSize (you can use other name) with following configuration:
imageSize:
type: string
ui:
label: 'Select Image Size'
reloadIfChanged: TRUE
inspector:
group: 'image'
position: 60
editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor'
editorOptions:
values:
small:
label: 'Small teaser (150x150)'
regular:
label: 'Regular content image (400x270)'
large:
label: 'Large image (980x500)'
allowEmpty: TRUE
This configuration add an select field with custom image sizes.
Step 5: Now we need to override default Image NodeType in TypoScript. Add following code to your Root.ts (/Packages/Sites/YourSitePackageName/Resources/Private/TypoScript/Root.ts2) (maybe you use other typoscript file).
prototype(TYPO3.Neos.NodeTypes:Image) {
// overwrite template for images
templatePath = 'resource://Vendor.YouSitePackageName/Private/Templates/NodeTypes/Image.html'
// define maximumWidth for images
maximumWidth = TYPO3.TypoScript:Case {
smallCondition {
condition = ${q(node).property('imageSize') == 'small'}
renderer = 150
}
regularCondition {
condition = ${q(node).property('imageSize') == 'regular'}
renderer = 400
}
largeCondition {
condition = ${q(node).property('imageSize') == 'large'}
renderer = 980
}
fallback {
condition = ${q(node).property('imageSize') == ''}
renderer = 400
}
}
// define maximumHeight for images
maximumHeight = TYPO3.TypoScript:Case {
smallCondition {
condition = ${q(node).property('imageSize') == 'small'}
renderer = 150
}
regularCondition {
condition = ${q(node).property('imageSize') == 'regular'}
renderer = 270
}
largeCondition {
condition = ${q(node).property('imageSize') == 'large'}
renderer = 500
}
fallback {
condition = ${q(node).property('imageSize') == ''}
renderer = 270
}
}
allowCropping = true
}
TYPO3.TypoScript:Case works like switch-function in PHP. We use this function for maximumWidth and maximumHeight. After create an condition for every option. In this condition we check which image size is selected and then write custom pixel value for width and height. With fallback condition you can define default value if image size is empty or was not selected.
The final solution may look as follows:
Example: Select Image Size
I hope this solution was helpful.

ExtJS4: Add field to form panel but not want it to be rendered by panel

I have a static html form layout where i add extjs form fields using the "renderTo" config. In order to have form validation and simple submit methods i want to add the fields to a form panel. As the layout is managed by the html frame i don't want the form to be rendered by the panel (panel has html frame as contentEl and this should be used as is).
In extjs3 i could achieve this by adding the field not to the panel but to the BasicForm (formpanel.getForm().add(...)) but in extjs4 this method seems to be gone.
How can i do this using extjs4?
Thanks in advance.
Since you already have a Panel that uses the contentEl to render HTML into its body, I recommend to stick with this approach:
Replace the panel with an Ext.form.Panel instance - the configuration, particularly the contentEl config - can remain unchanged.
The code provided here will override a standard Ext class (Ext.layout.Layout) and introduce support for a 'renderItemTo' config property on child items of any Ext container or panel instance (including Ext.form.Panel).
The value of the config property should be the ID of an already rendered DOM node, e.g. a DIV element that is part of the HTML fragment used in as the contentEl of the parent container's body.
Ext.require(['Ext.layout.Layout'], function() {
Ext.override(Ext.layout.Layout, {
renderItem: function (item, target, position) {
if(item.renderItemTo) {
// render 'renderItemTo' components into the specified DOM element
item.render(item.renderItemTo, 1);
// don't allow container layout to seize the component
item.layoutManagedHeight = 2;
item.layoutManagedWidth = 2;
} else {
// just use standard Ext code for non-renderItemTo components
this.callOverridden(arguments);
}
},
isValidParent: function(item, target, position) {
// signal Ext that we are OK with were our 'renderItemTo' component is right now
// otherwise it would get moved during the layout process
return item.renderItemTo ? true : this.callOverridden(arguments);
}
});
});
Usage:
var panel = Ext.create('Ext.form.Panel', {
contentEl: 'form', // the DOM element ID that holds the HTML fragment for the body
title: 'My FormPanel with special FX',
items: [
{
xtype: 'textfield',
renderItemTo: 'text1', // the ID of a DOM element inside the HTML fragment
fieldLabel: 'Label 1',
},
{
xtype: 'textfield',
renderItemTo: 'text2', // the ID of a DOM element inside the HTML fragment
fieldLabel: 'Label 2'
}
]
});
I uploaded a working example to JSFiddle (note: resize the window if you experience a render problem - this is related to JSFiddle, not my override).
After digging through the layout system of ExtJS 4.1 i implemented a custom layout which moves the items after rendering to the desired position in the fixed markup. The result is the same as for the ExtJS 4.0.7 version from this thread. It seams to work for the ExtJS standard fields. I have some problems with my custom fields though.
Ext.define('Ext.ux.layout.Fixed', {
extend: 'Ext.layout.container.Auto',
alias: 'layout.uxfixed',
afterRenderItem: function(item) {
// move items with renderToFixedMarkup to desired position
if (item.renderToFixedMarkup) {
var target = Ext.getDom(item.renderToFixedMarkup);
this.moveItem(item, target);
}
},
isValidParent: function(item, target, position) {
// items with renderToFixedMarkup property are always positioned correctly
return (item.renderToFixedMarkup) ? true : this.callOverridden(arguments);
}
});
It can be used by setting "layout: 'uxfixed'" on the panel and the "renderToFixedMarkup" config on the items.