Commit 9ceae125eed9d5a83efc00a4dfeb8ec1a2a7e288

Authored by Alexey Boroda
1 parent 013e4074

-Lazy load (now need to configure)

-Seo started
-Some other stuff
common/components/artboximage/ArtboxImageHelper.php
... ... @@ -18,7 +18,13 @@ class ArtboxImageHelper extends Object {
18 18 }
19 19 return self::$imageDriver;
20 20 }
21   -
  21 +
  22 + /**
  23 + * Returns the preset from config array
  24 + * @param $preset
  25 + *
  26 + * @return null
  27 + */
22 28 public function getPreset($preset) {
23 29  
24 30 if (empty(self::$presets)) {
... ... @@ -26,12 +32,39 @@ class ArtboxImageHelper extends Object {
26 32 }
27 33 return empty(self::$presets[$preset]) ? null : self::$presets[$preset];
28 34 }
29   -
  35 +
  36 + /**
  37 + * Gets html image tag with needed image
  38 + * @param $file
  39 + * @param $preset
  40 + * @param array $imgOptions
  41 + *
  42 + * @return string
  43 + */
30 44 public static function getImage($file, $preset, $imgOptions = []) {
31 45 $preset_alias = is_array($preset) ? array_keys($preset)[0] : null;
32 46 return Html::img(self::getImageSrc($file, $preset, $preset_alias), $imgOptions);
33 47 }
34   -
  48 +
  49 + public static function getLazyDiv($file, $preset, $options = [], $content = '') {
  50 + $preset_alias = is_array($preset) ? array_keys($preset)[0] : null;
  51 + if(!empty($options['class'])) {
  52 + $options['class'] = $options['class'] . ' lazy';
  53 + } else {
  54 + $options['class'] = 'lazy';
  55 + }
  56 + $options['data-src'] = self::getImageSrc($file, $preset, $preset_alias);
  57 + return Html::tag('div', $content, $options);
  58 + }
  59 +
  60 + /**
  61 + * Gets path to image with selected preset
  62 + * @param $file
  63 + * @param $preset
  64 + * @param null $preset_alias
  65 + *
  66 + * @return bool|mixed
  67 + */
35 68 public static function getImageSrc($file, $preset, $preset_alias = null) {
36 69 if (is_string($preset)) {
37 70 $preset_alias = $preset;
... ... @@ -47,19 +80,45 @@ class ArtboxImageHelper extends Object {
47 80 }
48 81 return self::getPresetUrl($filePath, $preset, $preset_alias);
49 82 }
50   -
  83 +
  84 + /**
  85 + * @param $model
  86 + * @param $modelField
  87 + * @param string $formField
  88 + * @param bool $multiple
  89 + *
  90 + * @return mixed
  91 + */
51 92 public static function fileinputWidget($model, $modelField, $formField = 'fileUpload', $multiple = false) {
52 93 return Yii::$app->artboximage->fileinputWidget($model, $modelField, $formField, $multiple);
53 94 }
54   -
  95 +
  96 + /**
  97 + * @param $url
  98 + *
  99 + * @return mixed
  100 + */
55 101 private static function getPathFromUrl($url) {
56 102 return substr_replace($url, self::getDriver()->rootPath, 0, strlen(self::getDriver()->rootUrl));
57 103 }
58   -
  104 +
  105 + /**
  106 + * @param $path
  107 + *
  108 + * @return mixed
  109 + */
59 110 private static function getUrlFromPath($path) {
60 111 return substr_replace($path, self::getDriver()->rootUrl, 0, strlen(self::getDriver()->rootPath));
61 112 }
62   -
  113 +
  114 + /**
  115 + * Gets path to image with preset
  116 + * @param $filePath
  117 + * @param $preset
  118 + * @param $preset_alias
  119 + *
  120 + * @return bool|mixed
  121 + */
63 122 private static function getPresetUrl($filePath, $preset, $preset_alias) {
64 123 $pathinfo = pathinfo($filePath);
65 124 $presetPath = $pathinfo['dirname'] .'/styles/'. strtolower($preset_alias);
... ... @@ -80,7 +139,15 @@ class ArtboxImageHelper extends Object {
80 139 }
81 140 return false;
82 141 }
83   -
  142 +
  143 + /**
  144 + * Create new image from existing one and with selected preset
  145 + * @param $filePath
  146 + * @param $preset
  147 + * @param $preset_alias
  148 + *
  149 + * @return string
  150 + */
84 151 private static function createPresetImage($filePath, $preset, $preset_alias)
85 152 {
86 153 $image = self::getDriver()->load($filePath);
... ...
common/modules/product/models/ProductVariant.php
... ... @@ -66,6 +66,7 @@
66 66 [
67 67 'product_id',
68 68 'product_unit_id',
  69 + 'sku',
69 70 ],
70 71 'required',
71 72 ],
... ...
common/widgets/Seo.php 0 → 100644
  1 +<?php
  2 +namespace common\widgets;
  3 +
  4 +use common\models\SeoDynamic;
  5 +use Yii;
  6 +use common\modules\product\models\Brand;
  7 +use common\modules\rubrication\models\TaxGroup;
  8 +use common\modules\rubrication\models\TaxOption;
  9 +use yii\base\Widget;
  10 +use yii\helpers\ArrayHelper;
  11 +use yii\helpers\Html;
  12 +use yii\helpers\Url;
  13 +use yii\web\HttpException;
  14 +
  15 +class Seo extends Widget
  16 +{
  17 + private $url;
  18 + public $row;
  19 + public $own_attr;
  20 + public $fields;
  21 + public $category_name;
  22 + public $description;
  23 + public $title;
  24 + public $meta;
  25 + public $seo_text;
  26 + public $h1;
  27 + public $key;
  28 + public $name;
  29 + public $project_name;
  30 + public static $optionsList;
  31 + protected static $check_url;
  32 + protected static $check_url_bool;
  33 +
  34 +
  35 + const SEO_TEXT = 'seo_text';
  36 + const DESCRIPTION = 'description';
  37 + const META = 'meta';
  38 + const H1 = 'h1';
  39 + const TITLE = 'title';
  40 +
  41 + public function init()
  42 + {
  43 + $this->url = \Yii::$app->request->url;
  44 + $this->project_name = \Yii::$app->name;
  45 + if(empty(self::$optionsList)){
  46 + self::$optionsList = ArrayHelper::getColumn(TaxGroup::find()->where(['is_filter' => 'TRUE'])->all(),'alias');
  47 + }
  48 +
  49 + parent::init();
  50 +
  51 + }
  52 +
  53 +
  54 + public function run()
  55 + {
  56 +
  57 + $seoData = $this->getViewData();
  58 + foreach ($seoData as $key => $value) {
  59 + $this->$key = $value;
  60 + }
  61 +
  62 +
  63 + switch ($this->row) {
  64 + case self::SEO_TEXT:
  65 +
  66 +
  67 + $filter = \Yii::$app->request->get('filters', []);
  68 + $sort = \Yii::$app->request->get('sort', []);
  69 + $paginate = \Yii::$app->request->get('page', []);
  70 +
  71 + if(empty($filter) && empty($sort) && empty($paginate) ){
  72 +
  73 + return $this->selectSeoData(self::SEO_TEXT);
  74 +
  75 + } else {
  76 +
  77 + $widgetData = static::findSeoByUrl($this->url);
  78 +
  79 + $result = '';
  80 +
  81 + if ($widgetData instanceof \common\models\Seo) {
  82 +
  83 + $result = $widgetData->{self::SEO_TEXT};
  84 +
  85 + } else {
  86 +
  87 + $widgetData = $this->findSeoByDynamic();
  88 +
  89 + if ($widgetData instanceof SeoDynamic) {
  90 +
  91 + $result = $widgetData->{self::SEO_TEXT};
  92 +
  93 + }
  94 +
  95 + }
  96 +
  97 + return $this->replaceData($result);
  98 + }
  99 +
  100 +
  101 + break;
  102 + case self::H1:
  103 +
  104 + $filter = \Yii::$app->request->get('filters', []);
  105 +
  106 +
  107 +
  108 + if ($this->checkFilter($filter)) {
  109 +
  110 + $array = $this->arrayBuilder($filter);
  111 + return $this->getNameString($array);
  112 +
  113 +
  114 + } else {
  115 + return $this->selectSeoData(self::H1);
  116 + }
  117 + break;
  118 + case self::TITLE:
  119 +
  120 + $filter = \Yii::$app->request->get('filters', []);
  121 +
  122 +
  123 +
  124 +
  125 + $title = $this->selectSeoData(self::TITLE);
  126 +
  127 +
  128 + if(!empty($filter) && isset($this->fields['meta-title']) && $title == $this->fields['meta-title'] || !empty($filter) && empty($title)) {
  129 + $array = $this->arrayBuilder($filter);
  130 +
  131 + $title_string = $this->getTitleString($array);
  132 +
  133 + if($title_string){
  134 + return $title_string;
  135 + }
  136 +
  137 + }
  138 +
  139 + if (!empty($title)) {
  140 + return $title;
  141 + } else {
  142 + return $this->project_name;
  143 + }
  144 +
  145 + break;
  146 + case self::DESCRIPTION:
  147 + $description = $this->selectSeoData(self::DESCRIPTION);
  148 +
  149 + if (!empty($description)) {
  150 +
  151 + $this->getView()->registerMetaTag([
  152 + 'name' => 'description',
  153 + 'content' => $description
  154 + ]);
  155 +
  156 + } else {
  157 +
  158 + $filter = \Yii::$app->request->get('filters', []);
  159 +
  160 + if(!empty($filter)){
  161 + $array = $this->arrayBuilder($filter);
  162 + $this->getView()->registerMetaTag([
  163 + 'name' => 'description',
  164 + 'content' => $this->getDescriptionString($array)
  165 + ]);
  166 + }
  167 +
  168 + }
  169 +
  170 + break;
  171 + case self::META:
  172 +
  173 + $meta = $this->selectSeoData(self::META);
  174 +
  175 + $filter = \Yii::$app->request->get('filters', []);
  176 + $sort = \Yii::$app->request->get('sort', []);
  177 + $paginate = \Yii::$app->request->get('page', []);
  178 +
  179 +
  180 +
  181 + if (!empty($meta)) {
  182 +
  183 + $this->getView()->registerMetaTag([
  184 + 'name' => 'robots',
  185 + 'content' => $meta
  186 + ]);
  187 +
  188 + } else if(!empty($filter['special'])){
  189 +
  190 + $this->getView()->registerMetaTag([
  191 + 'name' => 'robots',
  192 + 'content' => 'noindex,follow'
  193 + ]);
  194 +
  195 + } else if (
  196 + isset($filter['brands']) && count($filter['brands']) > 1
  197 + || isset($filter) && $this->checkFilter($filter)
  198 +
  199 + ) {
  200 + $this->getView()->registerMetaTag([
  201 + 'name' => 'robots',
  202 + 'content' => 'noindex,nofollow'
  203 + ]);
  204 +
  205 + } else if (
  206 + isset($filter['brands']) && count($filter['brands']) <= 1 && isset($filter) && count($filter, COUNT_RECURSIVE) >= 4
  207 + || isset($filter) && count($filter, COUNT_RECURSIVE) > 4
  208 + || !empty($sort) || !empty($paginate) || isset($filter['prices'])
  209 + ) {
  210 + $this->getView()->registerMetaTag([
  211 + 'name' => 'robots',
  212 + 'content' => 'noindex,nofollow'
  213 + ]);
  214 + } else {
  215 +
  216 + $this->getView()->registerMetaTag([
  217 + 'name' => 'robots',
  218 + 'content' => 'index,follow'
  219 + ]);
  220 + }
  221 +
  222 +
  223 +
  224 +
  225 + break;
  226 + }
  227 +
  228 +
  229 + }
  230 +
  231 + protected function replaceData($str)
  232 + {
  233 +
  234 + if (!empty($this->fields)) {
  235 + foreach ($this->fields as $field_name => $field_value) {
  236 + $str = str_replace('{' . $field_name . '}', $field_value, $str);
  237 + }
  238 + }
  239 + $str = str_replace('{project_name}', $this->project_name, $str);
  240 + return $str;
  241 + }
  242 +
  243 + protected static function findSeoByUrl($url)
  244 + {
  245 + if(empty(self::$check_url_bool)){
  246 + self::$check_url = \common\models\Seo::findOne(['url' => $url]);
  247 + self::$check_url_bool = true;
  248 + }
  249 + return self::$check_url;
  250 + }
  251 +
  252 + protected function findSeoByDynamic()
  253 + {
  254 +
  255 + if(!empty($this->key)){
  256 +
  257 + $query = SeoDynamic::find()->joinWith('seoCategory')->where(['controller' => \Yii::$app->controller->id, 'action' => \Yii::$app->controller->action->id, 'key' => $this->key]);
  258 + } else {
  259 +
  260 +
  261 + $query = SeoDynamic::find()->joinWith('seoCategory')->where(['controller' => \Yii::$app->controller->id, 'action' => \Yii::$app->controller->action->id]);
  262 + }
  263 +
  264 + return $query->one();
  265 + }
  266 +
  267 +
  268 + protected function findSeoByDynamicForFilters(){
  269 + return SeoDynamic::find()->joinWith('seoCategory')->where(['param' =>'filters'])->one();
  270 + }
  271 +
  272 +
  273 + protected function getViewData()
  274 + {
  275 + $params = $this->getView()->params;
  276 + if (isset($params['seo'])) {
  277 + return $params['seo'];
  278 + } else {
  279 + return [];
  280 + }
  281 + }
  282 +
  283 + protected function selectSeoData($param)
  284 + {
  285 + $result = '';
  286 +
  287 + $widgetData = static::findSeoByUrl($this->url);
  288 +
  289 + if ($widgetData instanceof \common\models\Seo) {
  290 +
  291 + $result = $widgetData->$param;
  292 +
  293 + } else if (!empty($this->$param)) {
  294 +
  295 + $result = $this->$param;
  296 +
  297 + } else {
  298 +
  299 + $widgetData = $this->findSeoByDynamic();
  300 +
  301 + if ($widgetData instanceof SeoDynamic) {
  302 +
  303 + $result = $widgetData->$param;
  304 +
  305 + }
  306 +
  307 + }
  308 +
  309 + return $this->replaceData($result);
  310 +
  311 + }
  312 +
  313 + public function getTitleString($array){
  314 + // "{Название раздела: Название блока фильтра | Фильтр 1 | Название блока фильтра: Фильтр 2 | Название блока фильтра: Фильтр 3} - купить в Киеве, Украине - интернет магазин Лінія Світла";
  315 + $row = '';
  316 + foreach($array as $name => $field){
  317 +
  318 + if($name == 'category' ){
  319 + $row = $field.' | '.$row;
  320 + } else {
  321 + $row .= $field['name'] .' '.$field['value'].' | ' ;
  322 + }
  323 +
  324 +
  325 +
  326 + }
  327 + $row = substr($row, 0,-2 );
  328 + $row .= " - купить в Киеве, Украине - интернет магазин Лінія Світла";
  329 + return $row;
  330 +// $template = SeoDynamic::find()->select('title')->where(['param' =>'filters'])->one();
  331 +// if($template instanceof SeoDynamic){
  332 +// foreach ($array as $field_name => $field_value) {
  333 +// $template->title = str_replace('{' . $field_name . '}', mb_strtolower($field_value), $template->title);
  334 +// }
  335 +// $template = preg_replace('/\{.[^\}]*\}\s/','',$template->title);
  336 +// return $template;
  337 +// }
  338 +//
  339 +// return false;
  340 +
  341 + }
  342 +
  343 +
  344 + public function getDescriptionString($array){
  345 + // "Лучшие цены на {Название раздела | Название блока фильтра: Фильтр 1 | Название блока фильтра: Фильтр 2 | Название блока фильтра: Фильтр 3}. Лінія Світла";
  346 + $row = 'Лучшие цены на ';
  347 + foreach($array as $name => $field){
  348 +
  349 + if($name == 'category' ){
  350 + $row = $field.' | '.$row;
  351 + } else {
  352 + $row .= $field['name'] .' '.$field['value'].' | ' ;
  353 + }
  354 +
  355 +
  356 +
  357 + }
  358 + $row = substr($row, 0,-2 );
  359 + $row .= ". Лінія Світла";
  360 + return $row;
  361 +
  362 + }
  363 +
  364 +
  365 + public function getNameString($array){
  366 + // "Лучшие цены на {Название раздела | Название блока фильтра: Фильтр 1 | Название блока фильтра: Фильтр 2 | Название блока фильтра: Фильтр 3}. Лінія Світла";
  367 + $row = '';
  368 + foreach($array as $name => $field){
  369 +
  370 + if($name == 'category' ){
  371 + $row = $field.' | '.$row;
  372 + } else {
  373 + $row .= $field['name'] .' '.$field['value'].' | ' ;
  374 + }
  375 +
  376 +
  377 +
  378 + }
  379 + $row = substr($row, 0,-2 );
  380 + return $row;
  381 +
  382 + }
  383 +
  384 + public function arrayBuilder($filter)
  385 + {
  386 +
  387 + $array = [
  388 + 'category' => $this->category_name
  389 + ];
  390 +
  391 +
  392 + if (isset($filter['brands']) && count($filter['brands']) == 1) {
  393 + $model = Brand::find()->where(['alias' => $filter['brands'][0]])->one();
  394 + if (!$model instanceof Brand) {
  395 +
  396 + \Yii::$app->response->redirect(['/site/error'], 404);
  397 + } else {
  398 + $array['brand']['name'] = 'Бренд';
  399 + $array['brand']['value'] = $model->name;
  400 + }
  401 +
  402 + }
  403 +
  404 +
  405 + $optionsList = ArrayHelper::map(TaxGroup::find()->where(['is_filter' => 'TRUE'])->all(), 'alias', 'name');
  406 +
  407 +
  408 + foreach ($optionsList as $optionList => $name) {
  409 +
  410 +
  411 + if (isset($filter[$optionList]) && count($filter[$optionList]) == 1) {
  412 +
  413 + $model = TaxOption::find()->where(['alias' => $filter[$optionList]])->one();
  414 + if (!$model instanceof TaxOption) {
  415 +
  416 + \Yii::$app->response->redirect(['site/error'], 404);
  417 + } else {
  418 + $array[$optionList]['value'] = $model->value;
  419 + $array[$optionList]['name'] = $name;
  420 + }
  421 +
  422 +
  423 + }
  424 +
  425 +
  426 + }
  427 +
  428 + return $array;
  429 +
  430 + }
  431 +
  432 + protected function checkFilter($filter){
  433 + foreach(self::$optionsList as $optionList){
  434 +
  435 + if(isset($filter[$optionList]) && count($filter[$optionList]) == 1){
  436 + return true;
  437 + }
  438 +
  439 + }
  440 + return false;
  441 + }
  442 +
  443 +
  444 +}
0 445 \ No newline at end of file
... ...
frontend/assets/AppAsset.php
... ... @@ -16,7 +16,7 @@ class AppAsset extends AssetBundle
16 16 'css/fonts.css',
17 17 ];
18 18 public $js = [
19   -// 'js/npm.js',
  19 + 'js/jquery.lazy.min.js',
20 20 'js/script.js',
21 21 ];
22 22 public $depends = [
... ...
frontend/views/catalog/_product_list.php
... ... @@ -21,9 +21,9 @@ use yii\widgets\ListView;
21 21 'product' => $model->alias,
22 22 'variant' => $model->variant->sku,
23 23 ])?>">
24   - <div class="picture" style="background-image:url('<?php
25   - echo ArtboxImageHelper::getImageSrc($model->getImageUrl(), 'product_list_item');
26   - ?>');"></div>
  24 + <?php
  25 + echo ArtboxImageHelper::getLazyDiv($model->getImageUrl(), 'product_list_item', ['class' => 'picture']);
  26 + ?>
27 27 <div class="title_1"><?php echo $model->name; ?></div>
28 28 <div class="title_2"><?php echo $model->variant->sku; ?></div>
29 29 </a>
... ...
frontend/views/category/collection.php
... ... @@ -53,9 +53,7 @@ $this-&gt;params[&#39;breadcrumbs&#39;][] = $this-&gt;title;
53 53 'product' => $product->alias,
54 54 'variant' => $product->variant->sku,
55 55 ]); ?>" alt="nabuco">
56   - <div class="label"><span><?php echo $product->name; ?></span><?php
57   - echo $product->variant->sku;
58   - ?></div>
  56 + <div class="label"><span><?php echo $product->name; ?></span></div>
59 57 <?php echo ArtboxImageHelper::getImage($product->getImageUrl(), 'collections_thumb');?>
60 58 </a>
61 59 <?php } ?>
... ...
frontend/views/category/index.php
... ... @@ -9,6 +9,7 @@ use yii\widgets\ListView;
9 9 * @var ActiveDataProvider $dataProvider
10 10 * @var View $this
11 11 */
  12 + $this->params[ 'seo' ][ 'title' ] = !empty($category->meta_title) ? $category->meta_title : $category->name;
12 13 $this->title = $category->name;
13 14 $this->params[ 'breadcrumbs' ][] = $this->title;
14 15  
... ...
frontend/views/layouts/main.php
... ... @@ -9,6 +9,7 @@
9 9  
10 10 use common\models\Page;
11 11 use common\modules\product\models\Category;
  12 + use common\widgets\Seo;
12 13 use frontend\assets\AppAsset;
13 14 use yii\helpers\Html;
14 15 use yii\helpers\Url;
... ... @@ -54,7 +55,17 @@
54 55 <meta http-equiv="X-UA-Compatible" content="IE=edge">
55 56 <meta name="viewport" content="width=device-width, initial-scale=1">
56 57 <?= Html::csrfMetaTags(); ?>
57   - <title><?= Html::encode($this->title); ?></title>
  58 + <title><?php echo Seo::widget([
  59 + 'row' => Seo::TITLE,
  60 + ]); ?></title>
  61 + <?php
  62 + echo Seo::widget([
  63 + 'row' => Seo::DESCRIPTION,
  64 + ]);
  65 + echo Seo::widget([
  66 + 'row' => Seo::META,
  67 + ]);
  68 + ?>
58 69 <?php $this->head(); ?>
59 70 </head>
60 71 <body>
... ...
frontend/web/js/jquery.lazy.min.js 0 → 100644
  1 +/*! jQuery & Zepto Lazy v1.7.3 - http://jquery.eisbehr.de/lazy - MIT&GPL-2.0 license - Copyright 2012-2016 Daniel 'Eisbehr' Kern */
  2 +!function(t,e){"use strict";function r(r,a,i,l,u){function c(){L=t.devicePixelRatio>1,f(i),a.delay>=0&&setTimeout(function(){s(!0)},a.delay),(a.delay<0||a.combined)&&(l.e=v(a.throttle,function(t){"resize"===t.type&&(w=B=-1),s(t.all)}),l.a=function(t){f(t),i.push.apply(i,t)},l.g=function(){return i=n(i).filter(function(){return!n(this).data(a.loadedName)})},s(),n(a.appendScroll).on("scroll."+u+" resize."+u,l.e))}function f(t){var i=a.defaultImage,o=a.placeholder,l=a.imageBase,u=a.srcsetAttribute,c=a.loaderAttribute,f=a._f||{};t=n(t).filter(function(){var t=n(this),r=b(this);return!t.data(a.handledName)&&(t.attr(a.attribute)||t.attr(u)||t.attr(c)||f[r]!==e)}).data("plugin_"+a.name,r);for(var s=0,d=t.length;s<d;s++){var A=n(t[s]),m=b(t[s]),h=A.attr(a.imageBaseAttribute)||l;m==N&&h&&A.attr(u)&&A.attr(u,g(A.attr(u),h)),f[m]===e||A.attr(c)||A.attr(c,f[m]),m==N&&i&&!A.attr(E)?A.attr(E,i):m==N||!o||A.css(O)&&"none"!=A.css(O)||A.css(O,"url('"+o+"')")}}function s(t){if(!i.length)return void(a.autoDestroy&&r.destroy());for(var e=!1,o=a.imageBase||"",l=a.srcsetAttribute,u=a.handledName,c=0;c<i.length;c++)if(t||A(i[c])){var f=n(i[c]),s=b(i[c]),m=f.attr(a.attribute),h=f.attr(a.imageBaseAttribute)||o,g=f.attr(a.loaderAttribute);f.data(u)||a.visibleOnly&&!f.is(":visible")||!((m||f.attr(l))&&(s==N&&(h+m!=f.attr(E)||f.attr(l)!=f.attr(F))||s!=N&&h+m!=f.css(O))||g)||(e=!0,f.data(u,!0),d(f,s,h,g))}e&&(i=n(i).filter(function(){return!n(this).data(u)}))}function d(t,e,r,i){++z;var o=function(){y("onError",t),p(),o=n.noop};y("beforeLoad",t);var l=a.attribute,u=a.srcsetAttribute,c=a.sizesAttribute,f=a.retinaAttribute,s=a.removeAttribute,d=a.loadedName,A=t.attr(f);if(i){var m=function(){s&&t.removeAttr(a.loaderAttribute),t.data(d,!0),y(T,t),setTimeout(p,1),m=n.noop};t.off(I).one(I,o).one(D,m),y(i,t,function(e){e?(t.off(D),m()):(t.off(I),o())})||t.trigger(I)}else{var h=n(new Image);h.one(I,o).one(D,function(){t.hide(),e==N?t.attr(C,h.attr(C)).attr(F,h.attr(F)).attr(E,h.attr(E)):t.css(O,"url('"+h.attr(E)+"')"),t[a.effect](a.effectTime),s&&(t.removeAttr(l+" "+u+" "+f+" "+a.imageBaseAttribute),c!==C&&t.removeAttr(c)),t.data(d,!0),y(T,t),h.remove(),p()});var b=(L&&A?A:t.attr(l))||"";h.attr(C,t.attr(c)).attr(F,t.attr(u)).attr(E,b?r+b:null),h.complete&&h.load()}}function A(t){var e=t.getBoundingClientRect(),r=a.scrollDirection,n=a.threshold,i=h()+n>e.top&&-n<e.bottom,o=m()+n>e.left&&-n<e.right;return"vertical"==r?i:"horizontal"==r?o:i&&o}function m(){return w>=0?w:w=n(t).width()}function h(){return B>=0?B:B=n(t).height()}function b(t){return t.tagName.toLowerCase()}function g(t,e){if(e){var r=t.split(",");t="";for(var a=0,n=r.length;a<n;a++)t+=e+r[a].trim()+(a!==n-1?",":"")}return t}function v(t,e){var n,i=0;return function(o,l){function u(){i=+new Date,e.call(r,o)}var c=+new Date-i;n&&clearTimeout(n),c>t||!a.enableThrottle||l?u():n=setTimeout(u,t-c)}}function p(){--z,i.length||z||y("onFinishedAll")}function y(t,e,n){return!!(t=a[t])&&(t.apply(r,[].slice.call(arguments,1)),!0)}var z=0,w=-1,B=-1,L=!1,T="afterLoad",D="load",I="error",N="img",E="src",F="srcset",C="sizes",O="background-image";"event"==a.bind||o?c():n(t).on(D+"."+u,c)}function a(a,o){var l=this,u=n.extend({},l.config,o),c={},f=u.name+"-"+ ++i;return l.config=function(t,r){return r===e?u[t]:(u[t]=r,l)},l.addItems=function(t){return c.a&&c.a("string"===n.type(t)?n(t):t),l},l.getItems=function(){return c.g?c.g():{}},l.update=function(t){return c.e&&c.e({},!t),l},l.loadAll=function(){return c.e&&c.e({all:!0},!0),l},l.destroy=function(){return n(u.appendScroll).off("."+f,c.e),n(t).off("."+f),c={},e},r(l,u,a,c,f),u.chainable?a:l}var n=t.jQuery||t.Zepto,i=0,o=!1;n.fn.Lazy=n.fn.lazy=function(t){return new a(this,t)},n.Lazy=n.lazy=function(t,r,i){if(n.isFunction(r)&&(i=r,r=[]),n.isFunction(i)){t=n.isArray(t)?t:[t],r=n.isArray(r)?r:[r];for(var o=a.prototype.config,l=o._f||(o._f={}),u=0,c=t.length;u<c;u++)(o[t[u]]===e||n.isFunction(o[t[u]]))&&(o[t[u]]=i);for(var f=0,s=r.length;f<s;f++)l[r[f]]=t[0]}},a.prototype.config={name:"lazy",chainable:!0,autoDestroy:!0,bind:"load",threshold:500,visibleOnly:!1,appendScroll:t,scrollDirection:"both",imageBase:null,defaultImage:"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",placeholder:null,delay:-1,combined:!1,attribute:"data-src",srcsetAttribute:"data-srcset",sizesAttribute:"data-sizes",retinaAttribute:"data-retina",loaderAttribute:"data-loader",imageBaseAttribute:"data-imagebase",removeAttribute:!0,handledName:"handled",loadedName:"loaded",effect:"show",effectTime:0,enableThrottle:!0,throttle:250,beforeLoad:e,afterLoad:e,onError:e,onFinishedAll:e},n(t).on("load",function(){o=!0})}(window);
0 3 \ No newline at end of file
... ...
frontend/web/js/script.js
1 1 $(document).ready(
2 2 function()
3 3 {
  4 + $('.lazy').Lazy({
  5 + effect: 'fadeIn'
  6 + });
  7 +
4 8 $(".active").click(
5 9 function()
6 10 {
... ...