1<?php 2 3 4namespace ComboStrap; 5 6 7use dokuwiki\Extension\SyntaxPlugin; 8use syntax_plugin_combo_button; 9use syntax_plugin_combo_link; 10 11class Dimension 12{ 13 /** 14 * The element that have an width and height 15 */ 16 const NATURAL_SIZING_ELEMENT = [SvgImageLink::CANONICAL, RasterImageLink::CANONICAL]; 17 18 const DESIGN_LAYOUT_CONSTRAINED = "constrained"; // fix value 19 const DESIGN_LAYOUT_FLUID = "fluid"; // adapt 20 21 /** 22 * On the width, if set, the design is fluid and will adapt to all screen 23 * with a min-width 24 */ 25 const WIDTH_LAYOUT_DEFAULT = self::DESIGN_LAYOUT_FLUID; 26 /** 27 * On height, if set, the design is constrained and overflow 28 */ 29 const HEIGHT_LAYOUT_DEFAULT = self::DESIGN_LAYOUT_CONSTRAINED; 30 const SCROLL = "scroll"; 31 const HEIGHT_KEY = 'height'; 32 const WIDTH_KEY = 'width'; 33 34 35 /** 36 * @param TagAttributes $attributes 37 */ 38 public static function processWidthAndHeight(&$attributes) 39 { 40 $widthName = self::WIDTH_KEY; 41 if ($attributes->hasComponentAttribute($widthName)) { 42 43 $widthValue = trim($attributes->getValueAndRemove($widthName)); 44 45 if ($widthValue == "0") { 46 47 /** 48 * For an image, the dimension are restricted by height 49 */ 50 if ($attributes->hasComponentAttribute(self::HEIGHT_KEY)) { 51 $attributes->addStyleDeclaration("width", "auto"); 52 } 53 54 } else { 55 56 57 if ($widthValue == "fit") { 58 $widthValue = "fit-content"; 59 } else { 60 /** Numeric value */ 61 $widthValue = TagAttributes::toQualifiedCssValue($widthValue); 62 } 63 64 65 /** 66 * For an image 67 */ 68 if (in_array($attributes->getLogicalTag(), self::NATURAL_SIZING_ELEMENT)) { 69 70 /** 71 * If the image is not ask as static resource (ie HTTP request) 72 * but added in HTML 73 * (ie {@link \action_plugin_combo_svg}) 74 */ 75 $requestedMime = $attributes->getMime(); 76 if ($requestedMime == TagAttributes::TEXT_HTML_MIME) { 77 $attributes->addStyleDeclaration('max-width', $widthValue); 78 $attributes->addStyleDeclaration('width', "100%"); 79 } 80 81 } else { 82 83 /** 84 * For a block 85 */ 86 $attributes->addStyleDeclaration('max-width', $widthValue); 87 88 } 89 } 90 91 } 92 93 $heightName = self::HEIGHT_KEY; 94 if ($attributes->hasComponentAttribute($heightName)) { 95 $heightValue = trim($attributes->getValueAndRemove($heightName)); 96 if ($heightValue !== "") { 97 $heightValue = TagAttributes::toQualifiedCssValue($heightValue); 98 99 if (in_array($attributes->getLogicalTag(), self::NATURAL_SIZING_ELEMENT)) { 100 101 /** 102 * A element with a natural height is responsive, we set only the max-height 103 * 104 * By default, the image has a `height: auto` due to the img-fluid class 105 * Making its height responsive 106 */ 107 $attributes->addStyleDeclaration("max-height", $heightValue); 108 109 } else { 110 111 /** 112 * HTML Block 113 * 114 * Without the height value, a block display will collapse 115 */ 116 if (self::HEIGHT_LAYOUT_DEFAULT == self::DESIGN_LAYOUT_CONSTRAINED) { 117 118 /** 119 * The box is constrained in height 120 * By default, a box is not constrained 121 */ 122 $attributes->addStyleDeclaration("height", $heightValue); 123 124 $scrollMechanism = $attributes->getValueAndRemoveIfPresent("scroll"); 125 if ($scrollMechanism != null) { 126 $scrollMechanism = trim(strtolower($scrollMechanism)); 127 } 128 switch ($scrollMechanism) { 129 case "toggle": 130 // https://jsfiddle.net/gerardnico/h0g6xw58/ 131 $attributes->addStyleDeclaration("overflow-y", "hidden"); 132 $attributes->addStyleDeclaration("position", "relative"); 133 $attributes->addStyleDeclaration("display", "block"); 134 // The block should collapse to this height 135 $attributes->addStyleDeclaration("min-height", $heightValue); 136 if ($attributes->hasComponentAttribute("id")) { 137 $id = $attributes->getValue("id"); 138 } else { 139 $id = $attributes->generateAndSetId(); 140 } 141 /** 142 * Css of the button and other standard attribute 143 */ 144 PluginUtility::getSnippetManager()->attachCssSnippetForBar("height-toggle"); 145 /** 146 * Set the color dynamically to the color of the parent 147 */ 148 PluginUtility::getSnippetManager()->attachJavascriptSnippetForBar("height-toggle"); 149 /** 150 * The height when there is not the show class 151 * is the original height 152 */ 153 $css = <<<EOF 154#$id:not(.show){ 155 height: $heightValue; 156 transition: height .35s ease; 157} 158EOF; 159 PluginUtility::getSnippetManager()->attachCssSnippetForBar("height-toggle-show", $css); 160 $bootstrapDataNameSpace = Bootstrap::getDataNamespace(); 161 $button = <<<EOF 162<button class="height-toggle-combo" data$bootstrapDataNameSpace-toggle="collapse" data$bootstrapDataNameSpace-target="#$id" aria-expanded="false"></button> 163EOF; 164 165 $attributes->addHtmlAfterEnterTag($button); 166 167 break; 168 case "lift"; 169 default: 170 $attributes->addStyleDeclaration("overflow", "auto"); 171 break; 172 173 } 174 175 176 } else { 177 178 /** 179 * if fluid 180 * min-height and not height to not constraint the box 181 */ 182 $attributes->addStyleDeclaration("min-height", $heightValue); 183 184 } 185 } 186 } 187 188 } 189 } 190 191 /** 192 * 193 * Toggle with a click on the collpased element 194 * if there is no control element such as button or link inside 195 * 196 * This function is used at the {@link DOKU_LEXER_EXIT} state of a {@link SyntaxPlugin::handle()} 197 * 198 * @param CallStack $callStack 199 */ 200 public static function addScrollToggleOnClickIfNoControl(CallStack $callStack) 201 { 202 $callStack->moveToEnd(); 203 $openingCall = $callStack->moveToPreviousCorrespondingOpeningCall(); 204 $scrollAttribute = $openingCall->getAttribute(Dimension::SCROLL); 205 if ($scrollAttribute != null && $scrollAttribute == "toggle") { 206 207 $controlFound = false; 208 while ($actualCall = $callStack->next()) { 209 if (in_array($actualCall->getTagName(), 210 [syntax_plugin_combo_button::TAG, syntax_plugin_combo_link::TAG, "internallink", "externallink"])) { 211 $controlFound = true; 212 break; 213 } 214 } 215 if (!$controlFound) { 216 $toggleOnClickId = "height-toggle-onclick"; 217 PluginUtility::getSnippetManager()->attachJavascriptSnippetForBar($toggleOnClickId); 218 $openingCall->addClassName("{$toggleOnClickId}-combo"); 219 $openingCall->addCssStyle("cursor", "pointer"); 220 } 221 222 } 223 } 224} 225