xref: /template/strap/ComboStrap/CarrouselTag.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeaunamespace ComboStrap;
4*04fd306cSNickeau
5*04fd306cSNickeau
6*04fd306cSNickeauuse syntax_plugin_combo_fragment;
7*04fd306cSNickeau
8*04fd306cSNickeau/**
9*04fd306cSNickeau * Carrousel
10*04fd306cSNickeau *
11*04fd306cSNickeau * We loved
12*04fd306cSNickeau * https://github.com/OwlCarousel2/OwlCarousel2
13*04fd306cSNickeau * but it's deprecated and
14*04fd306cSNickeau * send us to
15*04fd306cSNickeau * https://github.com/ganlanyuan/tiny-slider
16*04fd306cSNickeau * But it used as gutter the padding not the margin (http://ganlanyuan.github.io/tiny-slider/demo/#gutter_wrapper)
17*04fd306cSNickeau * Then we found
18*04fd306cSNickeau * https://glidejs.com/
19*04fd306cSNickeau *
20*04fd306cSNickeau * If we need another,
21*04fd306cSNickeau * * https://swiperjs.com/ - <a href="https://themes.getbootstrap.com/preview/?theme_id=5348">purpose template</a>
22*04fd306cSNickeau * * https://github.com/ganlanyuan/tiny-slider - https://themes.getbootstrap.com/preview/?theme_id=92520 - blogzine
23*04fd306cSNickeau *
24*04fd306cSNickeau *
25*04fd306cSNickeau */
26*04fd306cSNickeauclass CarrouselTag
27*04fd306cSNickeau{
28*04fd306cSNickeau    public const ELEMENT_WIDTH_ATTRIBUTE = "element-width";
29*04fd306cSNickeau    /**
30*04fd306cSNickeau     * To center the image inside a link in a carrousel
31*04fd306cSNickeau     */
32*04fd306cSNickeau    public const MEDIA_CENTER_LINK_CLASS = "justify-content-center align-items-center d-flex";
33*04fd306cSNickeau    public const CONTROL_ATTRIBUTE = "control";
34*04fd306cSNickeau    public const CANONICAL = CarrouselTag::TAG;
35*04fd306cSNickeau    public const ELEMENTS_MIN_ATTRIBUTE = "elements-min";
36*04fd306cSNickeau    public const ELEMENTS_MIN_DEFAULT = 3;
37*04fd306cSNickeau    public const GLIDE_SLIDE_CLASS = "glide__slide";
38*04fd306cSNickeau    public const TAG = 'carrousel';
39*04fd306cSNickeau
40*04fd306cSNickeau
41*04fd306cSNickeau    /**
42*04fd306cSNickeau     * Glide copy the HTML element and lozad does not see element that are not visible
43*04fd306cSNickeau     * The element non-visible are not processed by lozad
44*04fd306cSNickeau     * We set lazy loading to HTML loading attribute
45*04fd306cSNickeau     */
46*04fd306cSNickeau    public static function setLazyLoadToHtmlOnImageTagUntilTheEndOfTheStack(CallStack $callStack)
47*04fd306cSNickeau    {
48*04fd306cSNickeau        while ($actualCall = $callStack->next()) {
49*04fd306cSNickeau            if ($actualCall->getState() === DOKU_LEXER_SPECIAL && in_array($actualCall->getTagName(), Call::IMAGE_TAGS)) {
50*04fd306cSNickeau                $actualCall->addAttribute(
51*04fd306cSNickeau                    LazyLoad::LAZY_LOAD_METHOD,
52*04fd306cSNickeau                    LazyLoad::LAZY_LOAD_METHOD_HTML_VALUE
53*04fd306cSNickeau                );
54*04fd306cSNickeau            }
55*04fd306cSNickeau        }
56*04fd306cSNickeau    }
57*04fd306cSNickeau
58*04fd306cSNickeau    public static function handleEnter(\Doku_Handler $handler): array
59*04fd306cSNickeau    {
60*04fd306cSNickeau        $callStack = CallStack::createFromHandler($handler);
61*04fd306cSNickeau        $parent = $callStack->moveToParent();
62*04fd306cSNickeau        $context = null;
63*04fd306cSNickeau        if ($parent !== false) {
64*04fd306cSNickeau            $context = $parent->getTagName();
65*04fd306cSNickeau        }
66*04fd306cSNickeau        return array(PluginUtility::CONTEXT => $context);
67*04fd306cSNickeau    }
68*04fd306cSNickeau
69*04fd306cSNickeau    public static function handleExit(\Doku_Handler $handler): array
70*04fd306cSNickeau    {
71*04fd306cSNickeau        $callStack = CallStack::createFromHandler($handler);
72*04fd306cSNickeau        $openingCall = $callStack->moveToPreviousCorrespondingOpeningCall();
73*04fd306cSNickeau        $actualCall = $callStack->moveToFirstChildTag();
74*04fd306cSNickeau        if ($actualCall !== false) {
75*04fd306cSNickeau            if ($actualCall->getTagName() === FragmentTag::FRAGMENT_TAG) {
76*04fd306cSNickeau                $templateEndCall = $callStack->moveToNextCorrespondingExitTag();
77*04fd306cSNickeau                $templateCallStackInstructions = $templateEndCall->getPluginData(FragmentTag::CALLSTACK);
78*04fd306cSNickeau                if ($templateCallStackInstructions !== null) {
79*04fd306cSNickeau                    $templateCallStack = CallStack::createFromInstructions($templateCallStackInstructions);
80*04fd306cSNickeau                    // Lazy load
81*04fd306cSNickeau                    $templateCallStack->moveToStart();
82*04fd306cSNickeau                    CarrouselTag::setLazyLoadToHtmlOnImageTagUntilTheEndOfTheStack($templateCallStack);
83*04fd306cSNickeau                    $templateEndCall->setPluginData(FragmentTag::CALLSTACK, $templateCallStack->getStack());
84*04fd306cSNickeau                }
85*04fd306cSNickeau            } else {
86*04fd306cSNickeau                // Lazy load
87*04fd306cSNickeau                $callStack->moveToEnd();
88*04fd306cSNickeau                $callStack->moveToPreviousCorrespondingOpeningCall();
89*04fd306cSNickeau                CarrouselTag::setLazyLoadToHtmlOnImageTagUntilTheEndOfTheStack($callStack);
90*04fd306cSNickeau            }
91*04fd306cSNickeau        }
92*04fd306cSNickeau        return array(PluginUtility::ATTRIBUTES => $openingCall->getAttributes());
93*04fd306cSNickeau    }
94*04fd306cSNickeau
95*04fd306cSNickeau    public static function renderEnterXhtml(TagAttributes $tagAttributes, array $data): string
96*04fd306cSNickeau    {
97*04fd306cSNickeau        /**
98*04fd306cSNickeau         * Control
99*04fd306cSNickeau         */
100*04fd306cSNickeau        $control = $tagAttributes->getValueAndRemoveIfPresent(CarrouselTag::CONTROL_ATTRIBUTE);
101*04fd306cSNickeau        if ($control !== null) {
102*04fd306cSNickeau            $tagAttributes->addOutputAttributeValue("data-" . CarrouselTag::CONTROL_ATTRIBUTE, $control);
103*04fd306cSNickeau        }
104*04fd306cSNickeau
105*04fd306cSNickeau        /**
106*04fd306cSNickeau         * Element Min
107*04fd306cSNickeau         */
108*04fd306cSNickeau        $elementsMin = $tagAttributes->getValueAndRemoveIfPresent(CarrouselTag::ELEMENTS_MIN_ATTRIBUTE, CarrouselTag::ELEMENTS_MIN_DEFAULT);
109*04fd306cSNickeau        $tagAttributes->addOutputAttributeValue("data-" . CarrouselTag::ELEMENTS_MIN_ATTRIBUTE, $elementsMin);
110*04fd306cSNickeau
111*04fd306cSNickeau        /**
112*04fd306cSNickeau         * Minimal Width
113*04fd306cSNickeau         */
114*04fd306cSNickeau        $slideMinimalWidth = $tagAttributes->getValueAndRemoveIfPresent(CarrouselTag::ELEMENT_WIDTH_ATTRIBUTE);
115*04fd306cSNickeau        if ($slideMinimalWidth !== null) {
116*04fd306cSNickeau            try {
117*04fd306cSNickeau                $slideMinimalWidth = ConditionalLength::createFromString($slideMinimalWidth)->toPixelNumber();
118*04fd306cSNickeau                $tagAttributes->addOutputAttributeValue("data-" . CarrouselTag::ELEMENT_WIDTH_ATTRIBUTE, $slideMinimalWidth);
119*04fd306cSNickeau            } catch (ExceptionCompile $e) {
120*04fd306cSNickeau                LogUtility::msg("The minimal width value ($slideMinimalWidth) is not a valid value. Error: {$e->getMessage()}");
121*04fd306cSNickeau            }
122*04fd306cSNickeau        }
123*04fd306cSNickeau
124*04fd306cSNickeau
125*04fd306cSNickeau        /**
126*04fd306cSNickeau         * Snippets
127*04fd306cSNickeau         */
128*04fd306cSNickeau        $snippetSystem = ExecutionContext::getActualOrCreateFromEnv()
129*04fd306cSNickeau            ->getSnippetSystem();
130*04fd306cSNickeau
131*04fd306cSNickeau
132*04fd306cSNickeau        $snippetId = CarrouselTag::TAG;
133*04fd306cSNickeau
134*04fd306cSNickeau        // Theme customized from the below official theme
135*04fd306cSNickeau        // https://cdn.jsdelivr.net/npm/@glidejs/glide@3.5.2/dist/css/glide.theme.css
136*04fd306cSNickeau        $snippetSystem->attachCssInternalStyleSheet($snippetId)->setCritical(false);
137*04fd306cSNickeau
138*04fd306cSNickeau        /**
139*04fd306cSNickeau         * The dependency first
140*04fd306cSNickeau         */
141*04fd306cSNickeau        $snippetSystem->attachJavascriptFromComponentId("combo-loader");
142*04fd306cSNickeau        $snippetSystem->attachJavascriptFromComponentId($snippetId);
143*04fd306cSNickeau
144*04fd306cSNickeau        /**
145*04fd306cSNickeau         * Return
146*04fd306cSNickeau         */
147*04fd306cSNickeau        return $tagAttributes->toHtmlEnterTag("div");
148*04fd306cSNickeau    }
149*04fd306cSNickeau
150*04fd306cSNickeau    public static function renderExitXhtml(): string
151*04fd306cSNickeau    {
152*04fd306cSNickeau        return '</div>';
153*04fd306cSNickeau    }
154*04fd306cSNickeau}
155*04fd306cSNickeau
156