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