Completed
Pull Request — master (#2040)
by Basil
02:29
created

LazyLoad::generateAspectRation()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 3
nc 4
nop 0
1
<?php
2
3
namespace luya\lazyload;
4
5
use luya\base\Widget;
6
use yii\base\InvalidConfigException;
7
use yii\helpers\Html;
8
use luya\web\View;
9
10
/**
11
 * Image Lazy Loader.
12
 *
13
 * ```php
14
 * <?= LazyLoad::widget(['src' => 'http://www.zephir.ch/img/zephir-logo.png']); ?>
15
 * ```
16
 *
17
 * In order to read more visit the [[concept-lazyload.md]] guide section.
18
 *
19
 * @author Basil Suter <[email protected]>
20
 * @author Marc Stampfli <[email protected]>
21
 * @author Alex Schmid <[email protected]>
22
 * @since 1.0.0
23
 */
24
class LazyLoad extends Widget
25
{
26
    const JS_ASSET_KEY = 'lazyload.js.register';
27
28
    const CSS_ASSET_KEY = 'lazyload.css.register';
29
    const CSS_ASSET_KEY_PLACEHOLDER = 'lazyload.placeholder.css.register';
30
31
    /**
32
     * @var string The path to the image you want to lazy load.
33
     */
34
    public $src;
35
36
    /**
37
     * @var string Path for the placeholder image that will be base64 encoded.
38
     * @since 1.0.14
39
     */
40
    public $placeholderSrc;
41
42
    /**
43
     * @var boolean Inline the placeholder source as base64 encoded string
44
     * @since 1.0.14
45
     */
46
    public $placeholderAsBase64 = false;
47
48
    /**
49
     * @var integer The width of the image, this information should be provided in order to display a placeholder.
50
     */
51
    public $width;
52
53
    /**
54
     * @var integer The height of the image, this information should be provided in order to display a placeholder.
55
     */
56
    public $height;
57
58
    /**
59
     * @var boolean Define whether a full image tag should be return or only the attributes. This can be applied when using the lazy loader in background images.
60
     */
61
    public $attributesOnly = false;
62
63
    /**
64
     * @var string Additional classes for the lazy load image.
65
     */
66
    public $extraClass;
67
68
    /**
69
     * @var array Options array for the html tag. This array can be used to pass e.g. a `title` or `alt` tag.
70
     * @since 1.6.0
71
     */
72
    public $options = [];
73
74
    /**
75
     * @var array Legacy support for older Browsers (Adds the IntersectionOberserver Polyfill, default: true)
76
     * @since 1.6.0
77
     */
78
    public $legacySupport = true;
79
80
    /**
81
     * @var array Optionally disable the automatic init of the lazyload function so you can override the JS options
82
     * @since 1.6.0
83
     */
84
    public $initJs = true;
85
86
    /**
87
     * @var string The default classes which will be registered.
88
     * @since 1.6.1
89
     */
90
    public $defaultCss = '.lazyimage-wrapper {
91
        display: block;
92
        width: 100%;
93
        position: relative;
94
        overflow: hidden;
95
    }
96
    .lazyimage {
97
        position: absolute;
98
        top: 50%;
99
        left: 50%;
100
        bottom: 0;
101
        right: 0;
102
        opacity: 0;
103
        height: 100%;
104
        width: 100%;
105
        -webkit-transition: .5s ease-in-out opacity;
106
        transition: .5s ease-in-out opacity;
107
        -webkit-transform: translate(-50%,-50%);
108
        transform: translate(-50%,-50%);
109
        -o-object-fit: cover;
110
        object-fit: cover;
111
        -o-object-position: center center;
112
        object-position: center center;
113
        z-index: 20;
114
    }
115
    .lazyimage.loaded {
116
        opacity: 1;
117
    }
118
    .lazyimage-placeholder {
119
        display: block;
120
        width: 100%;
121
        height: auto;
122
        background-color: #f0f0f0;
123
    }
124
    .nojs .lazyimage,
125
    .nojs .lazyimage-placeholder,
126
    .no-js .lazyimage,
127
    .no-js .lazyimage-placeholder {
128
        display: none;
129
    }';
130
131
    /**
132
     * @inheritdoc
133
     */
134
    public function init()
135
    {
136
        parent::init();
137
138
        if ($this->src === null) {
139
            throw new InvalidConfigException("The parameter src is required by the lazyload widget.");
140
        }
141
142
        // register the asset file
143
        if ($this->legacySupport) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->legacySupport of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
144
            IntersectionObserverPolyfillAsset::register($this->view);
145
        }
146
        LazyLoadAsset::register($this->view);
147
148
        if ($this->initJs) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->initJs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
149
            // register js and css code with keys in order to ensure the registration is done only once
150
            $this->view->registerJs("$.lazyLoad();", View::POS_READY, self::JS_ASSET_KEY);
151
        }
152
153
        $this->view->registerCss($this->defaultCss, [], self::CSS_ASSET_KEY);
154
    }
155
    
156
    /**
157
     * Returns the aspect ration based on height or width.
158
     * 
159
     * If no width or height is provided, the default value 56.25 will be returned.
160
     *
161
     * @return float A dot seperated ratio value
162
     * @since 1.6.1
163
     */
164
    protected function generateAspectRation()
165
    {
166
        return ($this->height && $this->width) ? str_replace(',', '.', ($this->height / $this->width) * 100) : 56.25;
167
    }
168
169
    /**
170
     * @inheritdoc
171
     */
172
    public function run()
173
    {
174
        if ($this->placeholderSrc && $this->placeholderAsBase64) {
175
            $this->placeholderSrc = 'data:image/jpg;base64,' . base64_encode(file_get_contents($this->placeholderSrc));
176
        }
177
178
        if ($this->attributesOnly && !$this->placeholderSrc) {
179
            return "class=\"js-lazyimage {$this->extraClass}\" data-src=\"$this->src\" data-width=\"$this->width\" data-height=\"$this->height\" data-as-background=\"1\"";
180
        }
181
182
        $tag = '<div class="lazyimage-wrapper ' . $this->extraClass . '">';
183
        $tag .= Html::tag('img', '', array_merge($this->options, ['class' => 'js-lazyimage lazyimage', 'data-src' => $this->src, 'data-width' => $this->width, 'data-height' => $this->height]));
184
        if ($this->placeholderSrc) {
185
            $tag .= Html::tag('img', '', ['class' => 'lazyimage-placeholder', 'src' => $this->placeholderSrc]);
186
        } else {
187
            $tag .= '<div class="lazyimage-placeholder"><div style="display: block; height: 0px; padding-bottom: ' . $this->generateAspectRation() . '%;"></div><div class="loader"></div></div>';
188
        }
189
        $tag .= '<noscript><img class="lazyimage loaded ' . $this->extraClass . '" src="'.$this->src.'" /></noscript>';
190
        $tag .= '</div>';
191
192
        return $tag;
193
    }
194
}
195