1<?php
2/**
3 * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved.
4 *
5 * This source code is licensed under the GPL license found in the
6 * COPYING  file in the root directory of this source tree.
7 *
8 * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
9 * @author   ComboStrap <support@combostrap.com>
10 *
11 */
12
13namespace ComboStrap\TagAttribute;
14
15use ComboStrap\ExceptionBadArgument;
16use ComboStrap\ExceptionBadSyntax;
17use ComboStrap\ExceptionNotFound;
18use ComboStrap\LogUtility;
19use ComboStrap\PluginUtility;
20use ComboStrap\TagAttributes;
21
22/**
23 * Class Animation
24 * Manage the animation
25 * @package ComboStrap
26 */
27class Animation
28{
29
30    const ON_VIEW_ATTRIBUTE = "onview";
31    const ON_VIEW_SNIPPET_ID = "onview";
32    const ANIMATE_CLASS = "animate__animated";
33    const CANONICAL = "animation";
34
35    /**
36     * Based on https://wowjs.uk/
37     * @param TagAttributes $attributes
38     */
39    public static function processOnView(TagAttributes &$attributes)
40    {
41        if ($attributes->hasComponentAttribute(self::ON_VIEW_ATTRIBUTE)) {
42            $onView = $attributes->getValueAndRemove(self::ON_VIEW_ATTRIBUTE);
43
44            $animateClass = self::ANIMATE_CLASS;
45            $attributes->addClassName($animateClass);
46
47            $animationClass = "animate__" . $onView;
48            $attributes->addOutputAttributeValue("data-animated-class", $animationClass);
49
50            // TODO: Add attributes
51            //$delay = "animate__delay-2s";
52            //PluginUtility::addClass2Attributes($delay, $attributes);
53
54            $snippetManager = PluginUtility::getSnippetManager();
55
56            self::scrollMagicInit();
57
58            try {
59                $snippetManager
60                    ->attachRemoteCssStyleSheet(
61                        self::ON_VIEW_SNIPPET_ID,
62                        "https://cdn.jsdelivr.net/npm/animate.css@4.1.1/animate.min.css",
63                        "sha256-X7rrn44l1+AUO65h1LGALBbOc5C5bOstSYsNlv9MhT8="
64                    )
65                    ->setCritical(false);
66            } catch (ExceptionBadArgument|ExceptionBadSyntax|ExceptionNotFound $e) {
67                // should not happen
68                LogUtility::internalError("Error while trying to add the animate css stylesheet",self::CANONICAL,$e);
69            }
70
71        }
72
73    }
74
75    /**
76     * https://www.delac.io/wow/docs.html
77     * Offset: Define the distance between the bottom of browser viewport and the top of hidden box.
78     *         When the user scrolls and reach this distance the hidden box is revealed.
79     * Live  : Constantly check for new WOW elements on the page.
80     * @param $attributes
81     * @deprecated - wow permits only one trigger by animation
82     */
83    private static function wowInit(&$attributes)
84    {
85        $snippetManager = PluginUtility::getSnippetManager();
86        $wowClass = "wow";
87        $wowSnippetId = "wow";
88        PluginUtility::addClass2Attributes($wowClass, $attributes);
89        $snippetManager->attachCssInternalStyleSheet($wowSnippetId);
90
91
92        $animateClass = self::ANIMATE_CLASS;
93        $js = <<<EOF
94window.addEventListener("load", function(event) {
95    var wow = new WOW(
96      {
97        boxClass:     '$wowClass',      // animated element css class (default is wow)
98        animateClass: '$animateClass', // animation css class (default is animated)
99        offset:       0,          // distance to the element when triggering the animation (default is 0)
100        mobile:       true,       // trigger animations on mobile devices (default is true)
101        live:         false,       // act on asynchronously loaded content (default is true)
102        callback:     function(box) {
103          // the callback is fired every time an animation is started
104          // the argument that is passed in is the DOM node being animated
105        },
106        scrollContainer: null // optional scroll container selector, otherwise use window
107      }
108    );
109    wow.init();
110});
111EOF;
112        $snippetManager->attachJavascriptFromComponentId($wowSnippetId, $js);
113        $snippetManager->attachRemoteJavascriptLibrary(
114            $wowSnippetId,
115            "https://cdn.jsdelivr.net/npm/wowjs@1.1.3/dist/wow.min.js",
116            "sha256-gHiUEskgBO+3ccSDRM+c5+nEwTGp64R99KYPfITpnuo="
117        );
118    }
119
120    /**
121     * https://scrollmagic.io/docs/index.html
122     */
123    private static function scrollMagicInit()
124    {
125        $snippetManager = PluginUtility::getSnippetManager();
126
127        $scrollMagicSnippetId = "scroll-magic";
128        $snippetManager->attachJavascriptFromComponentId($scrollMagicSnippetId);
129        $snippetManager->attachRemoteJavascriptLibrary(
130            $scrollMagicSnippetId,
131            "https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/ScrollMagic.min.js",
132            "sha512-8E3KZoPoZCD+1dgfqhPbejQBnQfBXe8FuwL4z/c8sTrgeDMFEnoyTlH3obB4/fV+6Sg0a0XF+L/6xS4Xx1fUEg=="
133        );
134        $snippetManager->attachRemoteJavascriptLibrary(
135            $scrollMagicSnippetId,
136            "https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/plugins/debug.addIndicators.min.js",
137            "sha512-RvUydNGlqYJapy0t4AH8hDv/It+zKsv4wOQGb+iOnEfa6NnF2fzjXgRy+FDjSpMfC3sjokNUzsfYZaZ8QAwIxg=="
138        );
139    }
140
141}
142