1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7function wikiplugin_swiper_info() 8{ 9 return [ 10 'name' => tr('Swiper'), 11 'documentation' => 'PluginSwiper', 12 'description' => tr('Embed swiper in content, support file galleries, files id and custom content'), 13 'prefs' => ['wikiplugin_swiper'], 14 'body' => tr('Enter custom slides data separated by "|". Wiki Syntax / HTML supported in slide text, to include wiki page in slide text use pluginInclude.<code>title:Slide 1 title;text:HTML/Wiki Syntax Supported Slide 1 text;image:Slide Image URL;bgcolor:#colorcode;color: #color code for text | title:Slide 2 title;text:Slide 2 text;image:Slide Image URL;bgcolor:#colorcode</code> '), 15 'iconname' => 'tv', 16 'introduced' => 19, 17 'tags' => 'basic', 18 'params' => [ 19 'fgalId' => [ 20 'required' => false, 21 'name' => tr('File Gallery ID'), 22 'description' => tr('Enter file gallery id for slider'), 23 'since' => '19', 24 'separator' => ':', 25 'profile_reference' => 'file_gallery', 26 ], 27 'fileIds' => [ 28 'required' => false, 29 'name' => tr('File IDs'), 30 'description' => tr('List of IDs of images from the File Galleries separated by commas.'), 31 'filter' => 'striptags', 32 'default' => '', 33 ], 34 'effect' => [ 35 'required' => false, 36 'name' => tr('Transition Effect'), 37 'description' => tr('Tranisition effect. Could be "slide", "fade", "cube", "coverflow" or "flip"'), 38 'filter' => 'word', 39 'default' => 'slide', 40 'since' => '19.0', 41 'options' => [ 42 ['text' => 'Slide', 'value' => 'slide'], 43 ['text' => 'Fade', 'value' => 'fade'], 44 ['text' => 'Cube', 'value' => 'cube'], 45 ['text' => 'Coverflow', 'value' => 'coverflow'], 46 ['text' => 'Flip', 'value' => 'flip'], 47 ], 48 ], 49 'sliderPosition' => [ 50 'required' => false, 51 'name' => tr('Slider Placement on Page'), 52 'description' => tr('Placement of slider, above topbar, below topbar, above menus and content or inside content'), 53 'filter' => 'word', 54 'default' => '', 55 'since' => '19.0', 56 'options' => [ 57 ['text' => tr(''), 'value' => ''], 58 ['text' => tr('Inside Content'), 'value' => ''], 59 ['text' => tr('Above top bar / Top of page'), 'value' => 'abovetopbar'], 60 ['text' => tr('Above Content/Under top bar'), 'value' => 'undertopbar'] 61 ], 62 ], 63 'pagination' => [ 64 'required' => false, 65 'name' => tr('Pagination'), 66 'description' => tr('Slider pagination, default bullets'), 67 'filter' => 'word', 68 'default' => 'bullets', 69 'since' => '19.0', 70 'advanced' => true, 71 'options' => [ 72 ['text' => '', 'value' => ''], 73 ['text' => 'Off', 'value' => 'n'], 74 ['text' => tr('Bullets'), 'value' => 'bullets'], 75 ['text' => tr('Fraction'), 'value' => 'fraction'], 76 ['text' => tr('Progress bar'), 'value' => 'progressbar'], 77 ], 78 ], 79 'navigation' => [ 80 'required' => false, 81 'name' => tr('Navigation'), 82 'description' => tr('Display navigation arrows'), 83 'filter' => 'alpha', 84 'default' => 'y', 85 'since' => '19.0', 86 'options' => [ 87 ['text' => 'Yes', 'value' => 'y'], 88 ['text' => 'No ', 'value' => 'n'], 89 ], 90 ], 91 'background' => [ 92 'required' => false, 93 'name' => tr('Slider Background Color'), 94 'description' => tr('Slider background color, enter color code for example #000'), 95 'since' => '19.0' 96 ], 97 'parallaxBgImg' => [ 98 'required' => false, 99 'name' => tr('Slider Parallax Background Image'), 100 'description' => tr('Enter image url for parallax background behind swiper'), 101 'filter' => 'text', 102 'default' => '', 103 'advanced' => true, 104 'since' => '19.0' 105 ], 106 'width' => [ 107 'required' => false, 108 'name' => tr('Width'), 109 'description' => tr('Enter width of slider in px, default 100%'), 110 'filter' => 'word', 111 'default' => '100%', 112 'since' => '19.0' 113 ], 114 'height' => [ 115 'required' => false, 116 'name' => tr('Height'), 117 'description' => tr('Enter height of slider in px, default min height 100px, max height will adjust with content'), 118 'filter' => 'word', 119 'default' => '100px', 120 'since' => '19.0' 121 ], 122 'titleColor' => [ 123 'required' => false, 124 'name' => tr('Slide title color'), 125 'description' => tr('Enter text color code of slide title, for example #ccc'), 126 'filter' => 'text', 127 'default' => '', 128 'since' => '19.0' 129 ], 130 'titleSize' => [ 131 'required' => false, 132 'name' => tr('Title font size'), 133 'description' => tr('For example 42px, default 32 px'), 134 'filter' => 'word', 135 'default' => '32px', 136 'advanced' => true, 137 'since' => '19.0' 138 ], 139 'descriptionColor' => [ 140 'required' => false, 141 'name' => tr('Slide description color'), 142 'description' => tr('Enter text color code of slide description, for example #ccc'), 143 'filter' => 'text', 144 'default' => '', 145 'since' => '19.0' 146 ], 147 'descriptionSize' => [ 148 'required' => false, 149 'name' => tr('Description font size'), 150 'description' => tr('For example 24px, default 16 px'), 151 'filter' => 'word', 152 'default' => '16px', 153 'advanced' => true, 154 'since' => '19.0' 155 ], 156 'slideContentBg' => [ 157 'required' => false, 158 'name' => tr('Slide content background'), 159 'description' => tr('Enter a valid CSS color code, or an rgba value if opacity is desired; for example: #000 or rgba(00, 00, 00, 0.5).'), 160 'filter' => 'text', 161 'default' => '', 162 'since' => '19.0' 163 ], 164 'slideContentPostion' => [ 165 'required' => false, 166 'name' => tr('Slide content position'), 167 'description' => tr('Enter position for example top:20%;left:20% or bottom:20%;right:10%'), 168 'filter' => 'text', 169 'default' => 'top:20%;left:20%', 170 'since' => '19.0' 171 ], 172 'autoPlay' => [ 173 'required' => false, 174 'name' => tr('Auto Play'), 175 'description' => tr('Autoplay slider, on by default'), 176 'filter' => 'alpha', 177 'default' => 'y', 178 'since' => '19.0', 179 'advanced' => true, 180 'options' => [ 181 ['text' => 'Yes', 'value' => 'y'], 182 ['text' => 'No ', 'value' => 'n'], 183 ], 184 ], 185 'autoPlayDelay' => [ 186 'required' => false, 187 'name' => tr('Auto Play Delay'), 188 'description' => tr('Time interval to pause before moving to next slide in seconds.'), 189 'filter' => 'digits', 190 'default' => '5', 191 'since' => '19.0' 192 ], 193 'displayThumbnails' => [ 194 'required' => false, 195 'name' => tr('Display Thumbnails'), 196 'description' => tr('Show thumbnails under main slider'), 197 'filter' => 'alpha', 198 'default' => 'n', 199 'since' => '19.0', 200 'options' => [ 201 ['text' => 'No', 'value' => 'n'], 202 ['text' => 'Yes', 'value' => 'y'], 203 ], 204 ], 205 'speed' => [ 206 'required' => false, 207 'name' => tr('Speed'), 208 'description' => tr('Duration of transition between slides (in seconds)'), 209 'filter' => 'digits', 210 'default' => 300, 211 'advance'=>true, 212 'since' => '19.0' 213 ], 214 'autoHeight' => [ 215 'required' => false, 216 'name' => tr('Auto Height'), 217 'description' => tr('Set to true and slider wrapper will adopt its height to the height of the currently active slide'), 218 'filter' => 'alpha', 219 'default' => 'n', 220 'since' => '19.0', 221 'advanced' => true, 222 'options' => [ 223 ['text' => 'No', 'value' => 'n'], 224 ['text' => 'Yes', 'value' => 'y'], 225 ], 226 ], 227 //Slides grid 228 'spaceBetween' => [ 229 'required' => false, 230 'name' => tr('Space Between'), 231 'description' => tr('Distance between slides in px.'), 232 'filter' => 'digits', 233 'default' => 0, 234 'advanced' => true, 235 'since' => '19.0' 236 ], 237 'slidesPerView' => [ 238 'required' => false, 239 'name' => tr('Slides Per View'), 240 'description' => tr('Slides visible at the same time on slider\'s container. Coverflow transition works best with 3 slides per view'), 241 'filter' => 'digits', 242 'default' => 1, 243 'since' => '19.0' 244 ], 245 'slidesPerViewMobile' => [ 246 'required' => false, 247 'name' => tr('Slides Per View Mobile Screen'), 248 'description' => tr('Slides visible at the same time on small screens'), 249 'filter' => 'digits', 250 'default' => 0, 251 'advanced' => true, 252 'since' => '19.0' 253 ], 254 'slidesPerViewTab' => [ 255 'required' => false, 256 'name' => tr('Slides Per View Tablet'), 257 'description' => tr('Slides visible at the same time on low resolution tablets'), 258 'filter' => 'digits', 259 'default' => 0, 260 'advanced' => true, 261 'since' => '19.0' 262 ], 263 'slidesPerColumn' => [ 264 'required' => false, 265 'name' => tr('Slides Per Column'), 266 'description' => tr('Number of slides per column, for multirow layout'), 267 'filter' => 'digits', 268 'default' => 1, 269 'advanced'=>true, 270 'since' => '19.0' 271 ], 272 'slidesPerColumnFill' => [ 273 'required' => false, 274 'name' => tr('Slides Per Column Fill'), 275 'description' => tr('Could be \'column\' or \'row\'. Defines how slides should fill rows, by column or by row'), 276 'filter' => 'word', 277 'default' => 'column', 278 'since' => '19.0', 279 'advanced' => true, 280 'options' => [ 281 ['text' => 'Column', 'value' => 'column'], 282 ['text' => 'Row', 'value' => 'row'], 283 ], 284 ], 285 'centeredSlides' => [ 286 'required' => false, 287 'name' => tr('Centered Slides'), 288 'description' => tr('If true, then active slide will be centered, not always on the left side.'), 289 'filter' => 'alpha', 290 'default' => 'y', 291 'since' => '19.0', 292 'advanced' => true, 293 'options' => [ 294 ['text' => 'No', 'value' => 'n'], 295 ['text' => 'Yes', 'value' => 'y'], 296 ], 297 ], 298 'slidesOffsetBefore' => [ 299 'required' => false, 300 'name' => tr('Slides Offset Before'), 301 'description' => tr('Add (in px) additional slide offset in the beginning of the container (before all slides)'), 302 'filter' => 'digits', 303 'default' => 0, 304 'advanced' => true, 305 'since' => '19.0' 306 ], 307 'slidesOffsetAfter' => [ 308 'required' => false, 309 'name' => tr('Slides Offset After'), 310 'description' => tr('Add (in px) additional slide offset in the end of the container (after all slides)'), 311 'filter' => 'digits', 312 'default' => 0, 313 'advanced' => true, 314 'since' => '19.0' 315 ], 316 'slideToClickedSlide' => [ 317 'required' => false, 318 'name' => tr('Slide To Clicked Slide'), 319 'description' => tr('Set to true and click on any slide will produce transition to this slide.'), 320 'filter' => 'word', 321 'default' => 'n', 322 'since' => '19.0', 323 'advanced' => true, 324 'options' => [ 325 ['text' => 'No', 'value' => 'n'], 326 ['text' => 'Yes', 'value' => 'y'], 327 ], 328 ], 329 //freemode 330 'freeMode' => [ 331 'required' => false, 332 'name' => tr('Free Mode'), 333 'description' => tr('If true then slides will not have fixed positions.'), 334 'filter' => 'word', 335 'default' => 'n', 336 'since' => '19.0', 337 'advanced' => true, 338 'options' => [ 339 ['text' => 'No', 'value' => 'n'], 340 ['text' => 'Yes', 'value' => 'y'], 341 ], 342 ], 343 //Images 344 'preloadImages' => [ 345 'required' => false, 346 'name' => tr('Preload Images'), 347 'description' => tr('When enabled Swiper will force to load all images.'), 348 'filter' => 'word', 349 'default' => 'y', 350 'since' => '19.0', 351 'advanced' => true, 352 'options' => [ 353 ['text' => 'Yes', 'value' => 'y'], 354 ['text' => 'No', 'value' => 'n'], 355 ], 356 ], 357 'updateOnImagesReady' => [ 358 'required' => false, 359 'name' => tr('Update On Images Ready'), 360 'description' => tr('When enabled Swiper will be reinitialized after all inner images (<img> tags) are loaded. Required preloadimages: true.'), 361 'filter' => 'word', 362 'default' => 'y', 363 'since' => '19.0', 364 'advanced' => true, 365 'options' => [ 366 ['text' => 'Yes', 'value' => 'y'], 367 ['text' => 'No', 'value' => 'n'], 368 ], 369 ], 370 //Loop 371 'loop' => [ 372 'required' => false, 373 'name' => tr('Loop Slider'), 374 'description' => tr('Set to true to enable continuous loop mode (If you use it along with slidesperView: \'auto\' then you need to specify loopedslides parameter with amount of slides to loop (duplicate)).'), 375 'filter' => 'word', 376 'default' => 'n', 377 'since' => '19.0', 378 'options' => [ 379 ['text' => 'Yes', 'value' => 'y'], 380 ['text' => 'No', 'value' => 'n'], 381 ], 382 ], 383 ] 384 ]; 385} 386 387function wikiplugin_swiper($data, $params) 388{ 389 //checking for swiper existance 390 if(!file_exists("vendor_bundled/vendor/nolimits4web/swiper/dist/js/swiper.min.js")) { 391 Feedback::error(tr(' Please update composer to install required files')); 392 return; 393 } 394 if((! empty($params['fileIds']) && !$params['fileIds']) && !$params['fgalId'] && !$data) { 395 Feedback::error(tr('Paramaters missing: Please either select file gallery, give file ids or custom slide code in body.')); 396 return; 397 } 398 static $uid = 0; 399 $uid++; 400 $defaults = []; 401 $plugininfo = wikiplugin_swiper_info(); 402 foreach ($plugininfo['params'] as $key => $param) { 403 $defaults["$key"] = (! empty($param['default']) ? $param['default'] : ''); 404 //separating digits filter parameters 405 if(! empty($param['filter']) && $param['filter']=="digits") { 406 $swiperDigitsParams[]=$key; 407 } 408 } 409 $params = array_merge($defaults, $params); 410 if($params['autoPlay'] != 'n') { 411 $autoplayDelay=$params['autoPlayDelay']*1000; 412 $autoPlay='autoplay: { 413 delay: '.$autoplayDelay.', 414 },'; 415 } 416 else { 417 $autoPlay=''; 418 } 419 if($params['pagination'] != 'n') { 420 $pagination='pagination: { 421 el: \'.swiper-pagination\', 422 clickable: true, 423 type:"'.$params['pagination'].'" 424 },'; 425 $paginationDiv="<div class=\"swiper-pagination\"></div>"; 426 } 427 else { 428 $pagination=""; 429 $paginationDiv=""; 430 } 431 if($params['effect']=="fade"){ 432 $fadeEffectCSS="#swiper-container".$uid." .swiper-slide:not(.swiper-slide-active){opacity: 0 !important;}"; 433 } else { 434 $fadeEffectCSS = ''; 435 } 436 if($params['navigation'] != 'n') { 437 $navigation='navigation: { 438 nextEl: \'#swiper'.$uid.'-button-next\', 439 prevEl: \'#swiper'.$uid.'-button-prev\', 440 },'; 441 $navigationDiv='<div id="swiper'.$uid.'-button-prev" class="swiper-button-prev"></div><div class="swiper-button-next" id="swiper'.$uid.'-button-next"></div>'; 442 } 443 else { 444 $navigation=""; 445 $navigationDiv = ''; 446 } 447 $headerlib = TikiLib::lib('header'); 448 $headerlib->add_jsfile('vendor_bundled/vendor/nolimits4web/swiper/dist/js/swiper.min.js'); 449 $headerlib->add_cssfile('vendor_bundled/vendor/nolimits4web/swiper/dist/css/swiper.css'); 450 451 $slides = explode("|", ($data ? $data : "")); 452 $slidesHtml = ''; 453 //checking if gallery is choosen 454 $filegallib = TikiLib::lib('filegal'); 455 if ($params['fgalId']) { 456 $files = $filegallib->get_files(0, -1, '', '', $params['fgalId']); 457 } 458 if ($params['fileIds']) { 459 $params['fileIds'] = explode(',', $params['fileIds']); 460 foreach ($params['fileIds'] as $fileId) { 461 $file = $filegallib->get_file($fileId); 462 463 if (! is_null($file)) { 464 $files['data'][] = $file; 465 } 466 } 467 } 468 if (! empty($files['data'])) { 469 foreach ($files['data'] as $file) { 470 $slidesHtml .= '<div class="swiper-slide"><img src="tiki-download_file.php?fileId=' . $file['fileId'] . '&display'; 471 if (! empty($params['displaySize'])) { 472 if ($params['displaySize'] > 10) { 473 $slidesHtml .= '&max=' . $params['displaySize']; 474 } elseif ($params['displaySize'] <= 1) { 475 $slidesHtml .= '&scale=' . $params['displaySize']; 476 } 477 } 478 $slidesHtml .= '" alt="' . htmlentities($file['description']) . '" /></div>'; 479 } 480 } 481 foreach ($slides as $slide) { 482 if(trim($slide)) { 483 //processing slides 484 $slideArr=explode(";",$slide); 485 if(count($slideArr)>0) { 486 foreach($slideArr as $slideValue) { 487 $slideData=explode(":",$slideValue,2); 488 $slideArr[trim($slideData[0])]=trim($slideData[1]); 489 } 490 } 491 else { 492 $slideArr['text']=$slideArr[0]; //single attribute slide 493 } 494 (empty($slideArr['text']) || $slideArr['text']=='') ? $slideArr['text'] = '' : $slideArr['text']='<div>'.TikiLib::lib('parser')->parse_data($slideArr['text'], ['is_html' => true, 'parse_wiki' => true]).'</div>'; 495 if (empty($slideArr['color'])) { 496 $slideArr['color'] = ''; 497 } 498 if (empty($slideArr['bgcolor'])) { 499 $slideArr['bgcolor'] = ''; 500 } 501 if (empty($slideArr['title'])) { 502 $slideArr['title'] = ''; 503 } 504 $slidesHtml .= '<div data-swiper-parallax="-300" class="swiper-slide" style="color:'.$slideArr['color'].';background-color:'.$slideArr['bgcolor'].';background-image:url('.$slideArr['image'].')"><div class="slide-content'.$uid.'"><h1>' . $slideArr['title'] . '</h1>'.$slideArr['text'].'</div></div>'; 505 } 506 } 507 $swiperSettings = ''; 508 $swiperParams=array('effect','autoHeight','speed','spaceBetween','slidesPerView','slidesPerColumn','slidesPerColumnFill','centeredSlides','slidesOffsetBefore','slidesOffsetAfter','loop','preloadImages','slideToClickedSlide','freeMode','updateOnImagesReady'); 509 foreach($swiperParams as $swiperParam) { 510 $swiperSettings.=$swiperParam.":"; 511 if(!in_array($swiperParam,$swiperDigitsParams)) { 512 $swiperSettings.="'".$params[$swiperParam]."',"; 513 } 514 else { 515 $params[$swiperParam]==''?$swiperSettings.="0,":$swiperSettings.=$params[$swiperParam].","; 516 } 517 } 518 $breakpoints=''; 519 if($params['slidesPerViewMobile']>0 || $params['slidesPerViewTab']>0){ 520 $slidesPerView=$params['slidesPerView']==''?1:$params['slidesPerView']; 521 $slidesPerViewTab=$params['slidesPerViewTab']==''?$slidesPerView:$params['slidesPerViewTab']; //if not defined use default slides per view 522 $slidesPerViewMobile=$params['slidesPerViewMobile']==''?$slidesPerViewTab:$params['slidesPerViewMobile']; //if not defined use tablets slides per view 523 $breakpoints='breakpointsInverse: true, breakpoints: { 320: { slidesPerView: '.$slidesPerViewMobile.'},768: {slidesPerView: '.$slidesPerViewTab.'},1024: {slidesPerView: '.$slidesPerView.'}},'; 524 } 525 $swiperSettings=str_replace(array("'y'","'n'"),array("'true'","'false'"),$swiperSettings); 526 $headerlib->add_css('#swiper-container'.$uid.' {width: '.$params['width'].';background:'.$params['background'].';margin-bottom:20px;} #swiper-container'.$uid.' .swiper-slide {font-size:'.$params['descriptionSize'].';color:'.$params['descriptionColor'].';min-height:'.$params['height'].';text-align: center;width:100%;overflow:hidden;} .gallery-top {height: 80%;width: 100%;}.gallery-thumbs {height: 20%;box-sizing: border-box;padding: 10px 0;}.gallery-thumbs img {max-height:120px;height:120px;width:auto; margin-bottom:2%;cursor:pointer}.gallery-thumbs .swiper-slide {width: 25%; height: 100%;opacity: 0.4;}.gallery-thumbs .swiper-slide-active {opacity: 1;} #swiper-container'.$uid.' .swiper-slide h1{font-size:'.$params['titleSize'].';color:'.$params['titleColor'].'} .slide-content'.$uid.'{min-width:60%;position:absolute;'.$params['slideContentPostion'].';background:'.$params['slideContentBg'].';padding:1%;text-align:left} .parallax-bg { position: absolute;left: 0;top: 0;width: 130%;height: 100%;-webkit-background-size: cover;background-size: cover;background-position: center;} .swiper-slide img{max-width:100%}'.$fadeEffectCSS); 527 $thumbnails = ''; 528 $thumbclass = ''; 529 $swiperOpts = ''; 530 $thumbAfter = ''; 531 $thumbsSettings=''; 532 if($params['displayThumbnails']=="y") { 533 $thumbnails=' <div id="gallery-thumbs'.$uid.'" class="swiper-container gallery-thumbs"><div class="swiper-wrapper">'.$slidesHtml.'</div></div>' ; 534 $thumbclass='gallery-top'; 535 $swiperOpts='var galleryThumbs'.$uid.' = new Swiper("#gallery-thumbs'.$uid.'", {spaceBetween: 10, 536 slidesPerView: 3, 537 loopedSlides:1, 538 loop:true, 539 watchSlidesVisibility: true, 540 watchSlidesProgress: true, 541 slideToClickedSlide: true 542 });'; 543 $thumbsSettings=''; //' thumbs: {swiper: galleryThumbs'.$uid.'},'; 544 $thumbAfter='swiper'.$uid.'.controller.control = galleryThumbs'.$uid.';galleryThumbs'.$uid.'.controller.control =swiper'.$uid.';'; 545 } 546 $swiperOpts.='var swiper'.$uid.' = new Swiper("#swiper-container'.$uid.'",{ 547 '.$swiperSettings.' 548 init:false, 549 '.$thumbsSettings.' 550 '.$pagination.' 551 keyboard: { 552 enabled: true, 553 onlyInViewport: false, 554 }, 555 '.$breakpoints.' 556 '.$autoPlay.' 557 '.$navigation.' 558 559 });'.$thumbAfter; 560 if($params['sliderPosition']=='abovetopbar') { 561 $headerlib->add_css("#swiper-container".$uid."{visibility:hidden;}"); 562 $swiperOpts.='var container=$(".container").first();$("#swiper-container'.$uid.'").insertBefore( container );$("#gallery-thumbs'.$uid.'").insertAfter( "#swiper-container'.$uid.'" );'; 563 } 564 elseif($params['sliderPosition']=='undertopbar') { 565 $headerlib->add_css("#swiper-container".$uid."{visibility:hidden;}"); 566 $headerlib->add_js('$( document ).ready(function() { $("#swiper-container'.$uid.'").insertAfter( "#page-header" ); $("#gallery-thumbs'.$uid.'").insertAfter( "#swiper-container'.$uid.'" );})'); 567 } 568 //delaying initialization till window is fully loaded 569 $swiperOpts.='setTimeout( function(){ 570 $(window).trigger("resize") 571 }, 100); $(window).resize(function(){swiper'.$uid.'.init(); $("#swiper-container'.$uid.'").css("visibility","visible"); });'; 572 $headerlib->add_js( 573 '$( document ).ready(function() {'.$swiperOpts.';$("#swiper-container'.$uid.'").css("max-width",$("#swiper-container'.$uid.'").parent().width());})'); 574 $swiperCode='<div id="swiper-container'.$uid.'" class="swiper-container '.$thumbclass.'"> <div class="parallax-bg" style="background-image:url('.$params['parallaxBgImg'].')" data-swiper-parallax="-23%"></div> <div class="swiper-wrapper">'.$slidesHtml.'</div><!-- Add Pagination -->'.$paginationDiv.$navigationDiv.'</div>'.$thumbnails; 575 return $swiperCode; 576} 577