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