TYPO3: Slider mit gridelements

gridelementsBisher 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:

  1. Es muss keine separate Extension installiert werden
  2. 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
  3. Es können alle beliebigen Inhalte im Slider angezeigt werden, also z.B. auch Formulare, Plugins, Text mit Bild usw.
  4. 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:

gridelements slider

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:

slider demo

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.

Autor:
Geändert: Dienstag, 1. Dezember 2015 16:58 Uhr
Erstellt: Sonntag, 21. Juli 2013 16:32 Uhr
Tags: , , , , , , , , ,
Themengebiet: Web Entwicklung, TYPO3

Trackback: Trackback-URL LoadingZu Favoriten hinzufügen

13 Kommentare

  1. 1

    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.

  2. 2

    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.

  3. 3

    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

  4. 4

    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.

  5. 5

    hi, ne tolle Anleitung. Aber ich traus mich gar nicht sagen.. – Wie binde ich denn den Anythingslider optimal ins Template ein?

  6. 6

    Hi Alex,
    dafür gibt es viele Möglichkeiten. Am besten per TypoScript: page.includeJS
    Gruß Sven

  7. 7

    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
    }
    }

  8. 8

    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 :)

  9. 9

    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
    }

  10. 10

    Der JS-Code verwendet implizite globale Variablen. Ein Antipattern dass es unbedingt zu vermeiden gilt.

  11. 11

    @wefgwfgv: Danke für den Hinweis, ich habe es korrigiert.

  12. 12

    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.

  13. 13

    @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.

Kommentar abgeben