Bisher war meine bevorzugte Extension für einen Slider in TYPO3 die Erweiterung jfmulticontents, diese hat aber paar Dinge, die mir nicht so gefallen, unter anderem gibt es mit Ext. gridelements einen kleinen Konflikt bzgl. dem Feld „Spalte“ (colPos). Daher habe ich mich daran gemacht, einen Slider mit der Erweiterung gridelements umzusetzen.
Vorteile des Sliders mit gridelements:
- Es muss keine separate Extension installiert werden
- Es kann jede beliebige JavaScript-Library und dazu passenden Slider-Plugins eingesetzt werden, mit den Slider-Optionen die man benötigt und den Effekten, die einem gefallen
- Es können alle beliebigen Inhalte im Slider angezeigt werden, also z.B. auch Formulare, Plugins, Text mit Bild usw.
- Der Slider ist direkt über das Raster-Element konfigurierbar
Zuerst einmal muss man ein einspaltiges Raster-Element für gridelements anlegen. Wie man das genau macht, möchte ich an dieser Stelle nicht näher erläutern, dafür gibt es ausreichend Dokumentation. In Feld „Raster-Konfiguration“ kommt diese Backend-Layout-Konfiguration:
backend_layout { colCount = 1 rowCount = 1 rows { 1 { columns { 1 { name = Slider-Elemente colPos = 1 } } } } } |
Mit dieser Konfiguration werden die Inhalte aus der ersten (und einzigen) Spalte des Raster-Elements eingelesen und im Frontend ausgegeben.In Feld „Seiteninhalts-Konfiguration“ kommt die FlexForm-Konfiguration für die Slider-Optionen. Als Slider setze ich AnythingSlider ein, daher stehen hier die Optionen für dieses jQuery Plugin:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <T3DataStructure> <meta> <langDisable>1</langDisable> </meta> <sheets> <sDEF> <ROOT> <TCEforms> <sheetTitle>Allgemein</sheetTitle> </TCEforms> <type>array</type> <el type="array"> <mode type="array"> <TCEforms type="array"> <label>Modus</label> <config type="array"> <type>select</type> <items type="array"> <numIndex index="0" type="array"> <numIndex index="0">Horizontal </numIndex> <numIndex index="1">h </numIndex> </numIndex> <numIndex index="1" type="array"> <numIndex index="0">Vertikal </numIndex> <numIndex index="1">v </numIndex> </numIndex> <numIndex index="2" type="array"> <numIndex index="0">Fade </numIndex> <numIndex index="1">f </numIndex> </numIndex> </items> </config> </TCEforms> </mode> <showMultiple type="array"> <TCEforms type="array"> <label>Anzahl sichtbare Slider-Elemente (2 bis 6, die Höhe MUSS manuell gesetzt werden) </label> <config type="array"> <type>input</type> <size>1</size> <max>1</max> <eval>int</eval> <range> <lower>2</lower> <upper>6</upper> </range> </config> </TCEforms> </showMultiple> <height type="array"> <TCEforms type="array"> <label>Höhe des Sliders</label> <config type="array"> <type>input</type> <size>4</size> <max>4</max> <eval>int</eval> </config> </TCEforms> </height> <infiniteSlides type="array"> <TCEforms type="array"> <label>Unendliches Sliden (nach dem letzten Element im Slider geht es übergangslos zum ersten weiter, ansonsten erfolgt ein Sprung zurück zum ersten) </label> <config type="array"> <type>check</type> <default>1</default> </config> </TCEforms> </infiniteSlides> <animationTime type="array"> <TCEforms type="array"> <label>Animationsdauer (Millisekunden) </label> <config type="array"> <type>input</type> <size>5</size> <max>5</max> <eval>int</eval> </config> </TCEforms> </animationTime> </el> </ROOT> </sDEF> <navigation> <ROOT> <TCEforms> <sheetTitle>Navigation</sheetTitle> </TCEforms> <type>array</type> <el type="array"> <buildArrows type="array"> <TCEforms type="array"> <label>Pfeile anzeigen</label> <config type="array"> <type>check</type> <default>1</default> </config> <onChange>reload</onChange> </TCEforms> </buildArrows> <toggleArrows type="array"> <TCEforms type="array"> <label>Pfeile einblenden bei Mouseover </label> <config type="array"> <type>check</type> <default>0</default> </config> <displayCond>FIELD:buildArrows:REQ:true</displayCond> </TCEforms> </toggleArrows> <buildNavigation type="array"> <TCEforms type="array"> <label>Navigation anzeigen</label> <config type="array"> <type>check</type> <default>0</default> </config> <onChange>reload</onChange> </TCEforms> </buildNavigation> <toggleControls type="array"> <TCEforms type="array"> <label>Navigation einblenden bei Mouseover </label> <config type="array"> <type>check</type> <default>0</default> </config> <displayCond>FIELD:buildNavigation:REQ:true</displayCond> </TCEforms> </toggleControls> </el> </ROOT> </navigation> <slideshow> <ROOT> <TCEforms> <sheetTitle>Slideshow</sheetTitle> </TCEforms> <type>array</type> <el type="array"> <autoPlay type="array"> <TCEforms type="array"> <label>Slideshow (automatisches Sliden) </label> <config type="array"> <type>check</type> <default>0</default> </config> </TCEforms> </autoPlay> <buildStartStop type="array"> <TCEforms type="array"> <label>Start-Stop-Button anzeigen</label> <config type="array"> <type>check</type> <default>0</default> </config> </TCEforms> </buildStartStop> <autoPlayDelayed type="array"> <TCEforms type="array"> <label>Zeitverzögerung bis Start (Millisekunden) </label> <config type="array"> <type>input</type> <size>5</size> <max>5</max> <eval>int</eval> </config> </TCEforms> </autoPlayDelayed> <delay type="array"> <TCEforms type="array"> <label>Zeitverzögerung bis zum nächsten Sliden (Millisekunden) </label> <config type="array"> <type>input</type> <size>5</size> <max>5</max> <eval>int</eval> </config> </TCEforms> </delay> <pauseOnHover type="array"> <TCEforms type="array"> <label>Pausieren bei Mouseover</label> <config type="array"> <type>check</type> <default>1</default> </config> </TCEforms> </pauseOnHover> </el> </ROOT> </slideshow> </sheets> </T3DataStructure> |
AnythingSlider hat noch weitere Optionen, die erachte ich aber als nicht so wichtig, dass dem Redakteur diese zur Verfügung stehen müssten.Wenn man TYPO3 Version 6.1 oder höher einsetzt, kann man die Bedingung, zu denen ein Feld angezeigt wird, noch etwas verfeinern, indem man ODER- oder UND-Bedingungen definiert, z.B. für das Feld „toggleControls“, das bestimmt, ob die Navigation und der Start-Stop-Button erst beim Mouseover über den Slider eingeblendet wird:
<displayCond> <OR> <numIndex>FIELD:buildNavigation:REQ:true</numIndex> <numIndex>FIELD:buildStartStop:REQ:true</numIndex> </OR> </displayCond> |
Nun steht im TYPO3 Backend das Raster-Element „Slider“ zur Verfügung, in das man, wie gewohnt, alle verfügbaren Inhaltselemente einfügen kann:
Als nächstes muss man die HTML-Ausgabe dieses Raster-Elementes konfigurieren:
TS Setup
tt_content.gridelements_pi1 { 20.10.setup { 1 < lib.gridelements.defaultGridSetup 1 { columns { default.renderObj.wrap = <li>|</li> } wrap.stdWrap.cObject = COA wrap.stdWrap.cObject { wrap = <div class="anythingSliderOuter">|</div> 10 = COA 10 { 10 = COA 10 { wrap = <div class="options">{|}</div> // General settings 110 = TEXT 110.wrap = "mode":"|", 110.field = flexform_mode 120 = TEXT 120.wrap = "showMultiple":|, 120.field = flexform_showMultiple 120.if.value = 1 120.if.isGreaterThan.field = flexform_showMultiple 130 = TEXT 130.value = "infiniteSlides":false, 130.if.isFalse.field = flexform_infiniteSlides 140 = TEXT 140.wrap = "animationTime":|, 140.field = flexform_animationTime 140.if.isTrue.field = flexform_animationTime // Navigation options 210 = TEXT 210.value = "buildArrows":false, 210.if.isFalse.field = flexform_buildArrows 220 = TEXT 220.value = "toggleArrows":true, 220.if.isTrue.field = flexform_toggleArrows 230 = TEXT 230.value = "buildNavigation":false, 230.if.isFalse.field = flexform_buildNavigation 240 = TEXT 240.value = "toggleControls":true, 240.if.isTrue.field = flexform_toggleControls 250 = TEXT 250.value = "buildStartStop":false, 250.if.isFalse.field = flexform_buildStartStop // Slideshow options 310 = TEXT 310.wrap = "autoPlay":true, 310.if.isTrue.field = flexform_autoPlay 320 = TEXT 320.wrap = "autoPlayDelayed":|, 320.field = flexform_autoPlayDelayed 320.if.isTrue.field = flexform_autoPlayDelayed 330 = TEXT 330.wrap = "delay":|, 330.field = flexform_delay 330.if.isTrue.field = flexform_delay 340 = TEXT 340.value = "pauseOnHover":false, 340.if.isFalse.field = flexform_pauseOnHover // Other options 9980 = TEXT 9980.wrap = "height":|, 9980.field = flexform_height 9980.if.isTrue.field = flexform_height 9990 = TEXT 9990.value = "expand":true } 20 = TEXT 20.value = <ul class="anythingSliderContents">|</ul> } } } } } |
Die daraus resultierende HTML-Ausgabe sieht wie folgt aus:
<div class="anythingSliderOuter"> <div class="options">{"mode":"h","buildArrows":false,"delay":1000,"expand":true}</div> <ul class="anythingSliderContents"> <li>...</li> <li>...</li> </ul> </div> |
Man sieht hier, dass die Inhaltselemente in einer unsortierten Liste ausgegeben werden und die Slider-Optionen über ein DIV übermittelt werden. Dieses DIV sollte man natürlich über CSS ausblenden.Nun muss man nur noch die Optionen im JavaScript einlesen und an das Slider-Plugin übergeben. Da AnythingSlider Probleme hat, die Höhe der Slider-Inhalte korrekt zu bestimmen, wird hier noch dem Slider die Höhe des höchsten Slider-Elementes zugewiesen, falls der Redakteur die Höhe nicht selbst bestimmt hat:
$('ul.anythingSliderContents').each(function(){ var anythingSliderContents = $(this); var anythingSliderContainer = anythingSliderContents.closest('.anythingSliderOuter'); var options = anythingSliderContainer.find('.options').text(); if(options) { options = $.parseJSON(options); } else { options = []; } anythingSliderContainer.css('width', '100%'); if(options.height) { anythingSliderContainer.css('height', options.height); } else { // determine height anythingSliderContainer.css('height', 0); anythingSliderContents.children('li').each(function(){ if($(this).height() > anythingSliderContainer.height()){ anythingSliderContainer.css('height', $(this).height()); } }); } // determine height again when screen size changed /*$(this).bind('slideshow_resized', function(event, slider){ // only, if height isn't set to fixed value if(!slider.options.height) { anythingSliderContainer.css('height', slider.$el.closest('.anythingSlider').css('height')); } });*/ anythingSliderContents.anythingSlider(options); }); |
Wenn man alles richtig gemacht hat, hat man einen schönen Slider:
Viel Erfolg bei der Implementierung deines Sliders! Über Optimierungsvorschläge bin ich sehr dankbar, so gefällt mir z.B. die Übermittlung der Slider-Optionen über ein DIV nicht wirklich. Gerne verlinke ich hier auch deinen Slider, den du mit gridelements umgesetzt hast.
Interessanter Beitrag, ich ziehe auch eventuell so eine Lösung in Erwägung. Allerdings kommt mir das Herzstück, die Gridelements Config, etwas zu kurz.
Ich würde schon gern wissen, wie genau Gridelements es schafft das ein Element nach dem anderen durchgerendert wird.
Hallo Panade,
ich denke, zu diesem Punkt solltest du die Dokumentation der gridelements Extension lesen. Dieser Artikel ist nur eine Anleitung, wie man einen Slider einrichtet, wenn ich näher auf die verwendete Software (wie gridelements, AnythingSlider, jQuery) eingehe, wird dieser zu umfangreich.
Hallo Sven, hast du denn die nähere Erläuterung irgendwo im Netz abgelegt und für User zugänglich gemacht? Denn mich würde die genauere Ausführung auch sehr interessieren. Viele Grüße
Hallo Prajit,
zu der gridelements Konfiguration habe ich keine näheren Erläuterungen, ich meinte zu Panade, er soll das in der gridelements Dokumentation lesen. Die Doku scheint gerade nicht im TER verfügbar zu sein, aber im doc Verzeichnis der Extension findest du sie.
Meine gridelements Konfiguration ist ja rudimentär, viel passiert da ja nicht. Ich habe unter die Konfiguration nun geschrieben, was dort passiert.
hi, ne tolle Anleitung. Aber ich traus mich gar nicht sagen.. – Wie binde ich denn den Anythingslider optimal ins Template ein?
Hi Alex,
dafür gibt es viele Möglichkeiten. Am besten per TypoScript: page.includeJS
Gruß Sven
ok. habs geschafft. Es war ein ganz anderes Problem bei mir.
Wie schaff ich es jetzt, ich habe die Bilder in colPos 101, die Bilder zu croppen? Es wäre doch schön, wenn das Bild z. B. eine height=240c hat. Das ist mein TS:
temp.tt_content.image < tt_content.image
tt_content.image = CASE
tt_content.image {
key.field=colPos
101
101.20.1.file.height >
101.20.1.file {
width = 698c
height = 240c
}
}
Ich kann dir leider aus dem Stehgreif keine Lösung anbieten. Eine Suche nach „gridelements typoscript image“ ergab unter anderem diesen Treffer: http://blog.teamgeist-medien.de/2013/11/typo3-maxw-fuer-bilder-in-verschiedenen-gridelement-spalten.html
Vielleicht kannst du davon deine benötigten Einstellungen ableiten.
Noch schöner wäre es dann natürlich, wenn die Höhe nicht in TypoScript festgelegt wird, sondern der Wert, den der Redakteur in den Slider-Einstellungen einträgt, ausgelesen wird.
Wenn du die Lösung hast, her damit :)
Hi,
ich habs anhand eines content layouts gelöst – musst halt jedes Bild im Slider mit dem layout eins belegen..
tt_content.image.20.1.file.width{
override.if.value.field = layout
override.if.equals = 1
override = 966
}
tt_content.image.20.1.file.height{
override.if.value.field = layout
override.if.equals = 1
override = 350c
}
Der JS-Code verwendet implizite globale Variablen. Ein Antipattern dass es unbedingt zu vermeiden gilt.
@wefgwfgv: Danke für den Hinweis, ich habe es korrigiert.
Zur Übergabe der options: Man kann das auch so wrappen:
…wrap = <script type=“text/javascript“>var options = {|};<script>
Dann hast du options gleich als Variable im Javascript.
@Stefan Padberg: Danke für deinen Kommentar. Ich fürchte aber, dann funktioniert es nicht mehr, wenn mehrere Slider auf einer Seite sind, die „options“-Variable des zweiten Sliders überschreibt die erste.