This commit is contained in:
2024-05-20 15:37:46 +03:00
commit 00b7dbd0b7
10404 changed files with 3285853 additions and 0 deletions

View File

@ -0,0 +1,154 @@
<?php
namespace Nextend\SmartSlider3\Renderable;
use Nextend\Framework\Font\FontParser;
use Nextend\Framework\Font\FontRenderer;
use Nextend\Framework\Style\StyleParser;
use Nextend\Framework\Style\StyleRenderer;
use Nextend\SmartSlider3\Slider\FeatureManager;
abstract class AbstractRenderable {
public $isAdmin = false;
public $less = array();
public $css = array();
public $cssDevice = array(
'all' => array(),
'desktoplandscape' => array(),
'desktopportrait' => array(),
'tabletlandscape' => array(),
'tabletportrait' => array(),
'mobilelandscape' => array(),
'mobileportrait' => array(),
);
public $elementId = '';
public $fontSize = 16;
protected $images = array();
private $fontCache = array();
private $styleCache = array();
public $initCallbacks = array();
public $addedScriptResources = array();
/**
* @var FeatureManager
*/
public $features;
public function addLess($file, $context) {
$this->less[$file] = $context;
}
public function addCSS($css) {
$this->css[] = $css;
}
public function addDeviceCSS($device, $css) {
$this->cssDevice[$device][] = $css;
}
public function getSelector() {
return 'div#' . $this->elementId . ' ';
}
private function _addFontCache($font, $mode, $pre, $fontSize) {
$cacheKey = md5($font . $mode . $pre . $fontSize);
if (!isset($this->fontCache[$cacheKey])) {
$fontData = FontRenderer::render($font, $mode, $pre, $fontSize);
if ($fontData) {
$this->addCSS($fontData[1]);
$this->fontCache[$cacheKey] = $fontData[0];
} else {
$this->fontCache[$cacheKey] = '';
}
}
return $this->fontCache[$cacheKey];
}
public function addFont($font, $mode, $pre = null) {
$font = FontParser::parse($font);
if ($this->isAdmin) {
$fontData = FontRenderer::render($font, $mode, $pre == null ? $this->getSelector() : $pre, $this->fontSize);
if ($fontData) {
$this->addCSS($fontData[1]);
return $fontData[0];
}
return '';
}
return $this->_addFontCache($font, $mode, $pre == null ? $this->getSelector() : $pre, $this->fontSize);
}
private function _addStyleCache($style, $mode, $pre) {
$cacheKey = md5($style . $mode . $pre);
if (!isset($this->styleCache[$cacheKey])) {
$styleData = StyleRenderer::render($style, $mode, $pre);
if ($styleData) {
$this->addCSS($styleData[1]);
$this->styleCache[$cacheKey] = $styleData[0];
} else {
$this->styleCache[$cacheKey] = '';
}
}
return $this->styleCache[$cacheKey];
}
public function addStyle($style, $mode, $pre = null) {
$style = StyleParser::parse($style);
if ($this->isAdmin) {
$styleData = StyleRenderer::render($style, $mode, $pre == null ? $this->getSelector() : $pre);
if ($styleData) {
$this->addCSS($styleData[1]);
return $styleData[0];
}
return '';
}
return $this->_addStyleCache($style, $mode, $pre == null ? $this->getSelector() : $pre);
}
public function addScript($script, $name = false) {
if ($name !== false) {
$this->addedScriptResources[] = $name;
}
$this->initCallbacks[] = $script;
}
public function isScriptAdded($name) {
return in_array($name, $this->addedScriptResources);
}
public function addImage($imageUrl) {
$this->images[] = $imageUrl;
}
public function getImages() {
return $this->images;
}
public abstract function render();
}

View File

@ -0,0 +1,106 @@
<?php
namespace Nextend\SmartSlider3\Renderable;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\Component\ComponentCol;
use Nextend\SmartSlider3\Renderable\Component\ComponentContent;
use Nextend\SmartSlider3\Renderable\Component\ComponentLayer;
use Nextend\SmartSlider3\Renderable\Component\ComponentRow;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
abstract class AbstractRenderableOwner {
public $underEdit = false;
/**
* @var AbstractRenderable
*/
protected $renderable;
/** @var string Used for generators when multiple slides might contain the same unique class */
public $unique = '';
/**
* @return AbstractRenderable
*/
public function getRenderable() {
return $this->renderable;
}
public abstract function getElementID();
public function isComponentVisible($generatorVisibleVariable) {
return true;
}
public function fill($value) {
return $value;
}
public function fillLayers(&$layers) {
for ($i = 0; $i < count($layers); $i++) {
if (isset($layers[$i]['type'])) {
switch ($layers[$i]['type']) {
case 'slide':
$this->fillLayers($layers[$i]['layers']);
break;
case 'content':
ComponentContent::getFilled($this, $layers[$i]);
break;
case 'row':
ComponentRow::getFilled($this, $layers[$i]);
break;
case 'col':
ComponentCol::getFilled($this, $layers[$i]);
break;
case 'group':
$this->fillLayers($layers[$i]['layers']);
break;
default:
ComponentLayer::getFilled($this, $layers[$i]);
}
} else {
ComponentLayer::getFilled($this, $layers[$i]);
}
}
}
public function isLazyLoadingEnabled() {
return false;
}
/**
* @param AbstractItemFrontend $item
* @param $src
* @param array $attributes
*
* @return string
*/
public function renderImage($item, $src, $attributes = array(), $pictureAttributes = array()) {
return Html::image($src, $attributes);
}
public abstract function addScript($script, $name = false);
public abstract function isScriptAdded($name);
public abstract function addLess($file, $context);
public abstract function addCSS($css);
public abstract function addDeviceCSS($device, $css);
public abstract function addFont($font, $mode, $pre = null);
public abstract function addStyle($style, $mode, $pre = null);
public abstract function addImage($imageUrl);
public abstract function isAdmin();
public abstract function getAvailableDevices();
}

View File

@ -0,0 +1,891 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Component;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Parser\Color;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\BackupSlider\ExportSlider;
use Nextend\SmartSlider3\BackupSlider\ImportSlider;
use Nextend\SmartSlider3\Renderable\AbstractRenderableOwner;
use Nextend\SmartSlider3\Renderable\ComponentContainer;
use Nextend\SmartSlider3\Renderable\Placement\AbstractPlacement;
use Nextend\SmartSlider3\Renderable\Placement\PlacementAbsolute;
use Nextend\SmartSlider3\Renderable\Placement\PlacementDefault;
use Nextend\SmartSlider3\Renderable\Placement\PlacementNormal;
use Nextend\SmartSlider3\Slider\Slide;
abstract class AbstractComponent {
public static $isAdmin = false;
/**
* @var Slide
*/
protected $owner;
/**
* @var Style
*/
public $style;
protected $type = '';
protected $name = '';
/**
* @var AbstractComponent|bool
*/
protected $group;
/**
* @var AbstractPlacement
*/
protected $placement;
/**
* @var ComponentContainer
*/
protected $container = false;
protected $fontSizeModifier = 100;
protected $attributes = array(
'class' => 'n2-ss-layer n2-ow',
'style' => ''
);
public $data;
protected $localStyle = array();
protected $localRawStyles = array();
protected $hasBackground = false;
/**
* AbstractBuilderComponent constructor.
*
* @param int $index
* @param AbstractRenderableOwner $owner
* @param AbstractComponent|bool $group
* @param $data
*/
public function __construct($index, $owner, $group, $data) {
$this->owner = $owner;
$this->group = $group;
$this->style = new Style($this);
$this->data = new Data($data);
$this->fontSizeModifier = $this->data->get('desktopportraitfontsize', 100);
if (!is_numeric($this->fontSizeModifier)) {
$this->fontSizeModifier = 100;
}
switch ($this->getPlacement()) {
case 'normal':
$this->placement = new PlacementNormal($this, $index);
break;
case 'default':
$this->placement = new PlacementDefault($this, $index);
break;
case 'absolute':
default:
$this->placement = new PlacementAbsolute($this, $index);
break;
}
}
public function getPlacement() {
if ($this->data->has('pm')) {
return $this->data->get('pm');
}
if ($this->group->getType() == 'slide') {
return 'absolute';
}
return 'normal';
}
/**
* @return Slide
*/
public function getOwner() {
return $this->owner;
}
public function isRenderAllowed() {
$generatorVisible = $this->data->get('generatorvisible', '');
if ($this->owner->isComponentVisible($generatorVisible) && !self::$isAdmin) {
$filled = $this->owner->fill($generatorVisible);
if (empty($filled)) {
return false;
}
}
return true;
}
public abstract function render($isAdmin);
protected function renderContainer($isAdmin) {
if ($this->container) {
return $this->container->render($isAdmin);
}
return '';
}
protected function admin() {
$this->createProperty('id', '');
$this->createProperty('uniqueclass', '');
$this->createProperty('zindex', 2);
$this->createProperty('class', '');
$this->createProperty('name', $this->name);
$this->createProperty('namesynced', 1);
$this->createProperty('status');
$this->createProperty('generatorvisible', '');
$this->placement->adminAttributes($this->attributes);
}
public function spacingToPxValue($value) {
$values = explode('|*|', $value);
unset($values[4]);
return array_map('intval', $values) + array(
0,
0,
0,
0
);
}
protected function prepareHTML() {
$this->attributes['data-sstype'] = $this->type;
$id = $this->data->get('id', '');
if (!empty($id)) {
$this->attributes['id'] = $id;
}
$class = $this->data->get('class', '');
if (!empty($class)) {
$this->attributes['class'] .= ' ' . $this->getOwner()
->fill($class);
}
$uniqueClass = $this->data->get('uniqueclass', '');
if (!empty($uniqueClass)) {
$this->addUniqueClass($uniqueClass . $this->owner->unique);
}
$zIndex = intval($this->data->get('zindex', 2));
if ($zIndex != 2) {
$this->attributes['style'] .= 'z-index:' . $zIndex . ';';
}
}
protected function addUniqueClass($class) {
$this->attributes['class'] .= ' ' . $class;
}
protected function runPlugins() {
$this->pluginRotation();
$this->pluginShowOn();
$this->pluginFontSize();
$this->pluginParallax();
}
protected function renderPlugins($html) {
return $this->pluginCrop($html);
}
private function pluginRotation() {
$rotation = $this->data->get('rotation', 0);
if ($rotation) {
$this->createProperty('rotation', 0);
$this->attributes['style'] .= 'transform:rotate(' . $rotation . 'deg);';
}
}
private function pluginCrop($html) {
$cropStyle = $this->data->get('crop', 'visible');
if (self::$isAdmin) {
if ($cropStyle == 'auto') {
$cropStyle = 'hidden';
}
} else {
if ($cropStyle == 'auto') {
$this->attributes['class'] .= ' n2_container_scrollable';
}
}
if ($cropStyle == 'mask') {
$cropStyle = 'hidden';
$html = Html::tag('div', array('class' => 'n2-ss-layer-mask n2-ss-layer-wrapper'), $html);
$this->attributes['data-animatableselector'] = '.n2-ss-layer-mask';
}
if (!empty($cropStyle) && $cropStyle != 'visible') {
$this->attributes['style'] .= 'overflow:' . $cropStyle . ';';
}
if (self::$isAdmin) {
$crop = $this->data->get('crop', 'visible');
if (empty($crop)) {
$crop = 'visible';
}
$this->attributes['data-crop'] = $crop;
}
return $html;
}
/**
* Transform V1 animations to V2
*
* @param $data
*
* @return array
*/
private function pluginAnimationsConvertV1ToV2($data) {
if (empty($data)) {
return array();
}
if (isset($data['in'])) {
if (!isset($data['basic'])) {
$data['basic'] = array(
'in' => array()
);
} else if (!isset($data['basic']['in'])) {
$data['basic']['in'] = array();
}
$this->pluginAnimationsConvertV1ToV2RemoveName($data['in']);
if (isset($data['in'][0]['delay']) && isset($data['repeatable']) && $data['repeatable'] == 1) {
if ($data['in'][0]['delay'] > 0) {
$data['startDelay'] = $data['in'][0]['delay'];
}
unset($data['in'][0]['delay']);
}
$data['basic']['in']['keyFrames'] = $data['in'];
unset($data['in']);
}
if (isset($data['specialZeroIn'])) {
if (isset($data['basic']['in'])) {
$data['basic']['in']['specialZero'] = $data['specialZeroIn'];
}
unset($data['specialZeroIn']);
}
if (isset($data['transformOriginIn'])) {
if (isset($data['basic']['in'])) {
$data['basic']['in']['transformOrigin'] = $data['transformOriginIn'];
}
unset($data['transformOriginIn']);
}
if (isset($data['loop'])) {
if (!isset($data['basic'])) {
$data['basic'] = array(
'loop' => array()
);
} else if (!isset($data['basic']['loop'])) {
$data['basic']['loop'] = array();
}
$this->pluginAnimationsConvertV1ToV2RemoveName($data['loop']);
$data['basic']['loop']['keyFrames'] = $data['loop'];
unset($data['loop']);
}
if (isset($data['repeatCount'])) {
if (isset($data['basic']['loop'])) {
$data['basic']['loop']['repeatCount'] = $data['repeatCount'];
}
unset($data['repeatCount']);
}
if (isset($data['repeatStartDelay'])) {
if (isset($data['basic']['loop'])) {
$data['basic']['loop']['repeatStartDelay'] = $data['repeatStartDelay'];
}
unset($data['repeatStartDelay']);
}
if (isset($data['transformOriginLoop'])) {
if (isset($data['basic']['loop'])) {
$data['basic']['loop']['transformOrigin'] = $data['transformOriginLoop'];
}
unset($data['transformOriginLoop']);
}
if (isset($data['out'])) {
if (!isset($data['basic'])) {
$data['basic'] = array(
'out' => array()
);
} else if (!isset($data['basic']['out'])) {
$data['basic']['out'] = array();
}
$this->pluginAnimationsConvertV1ToV2RemoveName($data['out']);
$data['basic']['out']['keyFrames'] = $data['out'];
unset($data['out']);
}
if (isset($data['transformOriginOut'])) {
if (isset($data['basic']['out'])) {
$data['basic']['out']['transformOrigin'] = $data['transformOriginOut'];
}
unset($data['transformOriginOut']);
}
if (!isset($data['instantOut']) || $data['instantOut'] == '1') {
if (empty($data['outPlayEvent']) && $this->owner->getSlider()->params->get('layer-animation-play-mode') === 'forced') {
$data['outPlayEvent'] = 'InstantOut';
}
}
if (isset($data['instantOut'])) {
unset($data['instantOut']);
}
return $data;
}
private function pluginAnimationsConvertV1ToV2RemoveName(&$keyFrames) {
for ($i = 0; $i < count($keyFrames); $i++) {
if (isset($keyFrames[$i]['name'])) {
unset($keyFrames[$i]['name']);
}
}
}
private function pluginAnimations() {
}
private static function fixAnimationArray(&$array, $key) {
if (isset($array[$key]) && is_array($array[$key])) {
for ($i = 0; $i < count($array[$key]); $i++) {
$array[$key][$i] = (object)$array[$key][$i];
}
}
}
private function pluginAnimationGetEventAttributes() {
if (!self::$isAdmin) {
$elementID = $this->owner->getElementID();
$click = $this->data->get('click');
if (!empty($click)) {
$this->attributes['data-click'] = $this->pluginAnimationParseEventCode($click, $elementID);
}
$mouseenter = $this->data->get('mouseenter');
if (!empty($mouseenter)) {
$this->attributes['data-mouseenter'] = $this->pluginAnimationParseEventCode($mouseenter, $elementID);
}
$mouseleave = $this->data->get('mouseleave');
if (!empty($mouseleave)) {
$this->attributes['data-mouseleave'] = $this->pluginAnimationParseEventCode($mouseleave, $elementID);
}
$play = $this->data->get('play');
if (!empty($play)) {
$this->attributes['data-play'] = $this->pluginAnimationParseEventCode($play, $elementID);
}
$pause = $this->data->get('pause');
if (!empty($pause)) {
$this->attributes['data-pause'] = $this->pluginAnimationParseEventCode($pause, $elementID);
}
$stop = $this->data->get('stop');
if (!empty($stop)) {
$this->attributes['data-stop'] = $this->pluginAnimationParseEventCode($stop, $elementID);
}
} else {
$click = $this->data->get('click');
if (!empty($click)) {
$this->attributes['data-click'] = $click;
}
$mouseenter = $this->data->get('mouseenter');
if (!empty($mouseenter)) {
$this->attributes['data-mouseenter'] = $mouseenter;
}
$mouseleave = $this->data->get('mouseleave');
if (!empty($mouseleave)) {
$this->attributes['data-mouseleave'] = $mouseleave;
}
$play = $this->data->get('play');
if (!empty($play)) {
$this->attributes['data-play'] = $play;
}
$pause = $this->data->get('pause');
if (!empty($pause)) {
$this->attributes['data-pause'] = $pause;
}
$stop = $this->data->get('stop');
if (!empty($stop)) {
$this->attributes['data-stop'] = $stop;
}
}
}
private function pluginAnimationParseEventCode($code, $elementId) {
if (preg_match('/^[a-zA-Z0-9_\-,]+$/', $code)) {
if (is_numeric($code)) {
$code = "window['" . $elementId . "'].changeTo(" . ($code - 1) . ");";
} else if ($code == 'next') {
$code = "window['" . $elementId . "'].next();";
} else if ($code == 'previous') {
$code = "window['" . $elementId . "'].previous();";
} else {
$code = "n2ss.trigger(e.currentTarget, '" . $code . "');";
}
}
return $code;
}
private function pluginShowOn() {
if (self::$isAdmin) {
$this->createDeviceProperty('', 1);
}
$devices = $this->owner->getAvailableDevices();
foreach ($devices as $device) {
if (!$this->isShown($device)) {
$this->attributes['data-hide' . $device] = 1;
$this->style->addOnly($device, '', 'display:none');
}
}
}
public function isShown($device) {
return intval($this->data->get($device, 1)) === 1;
}
protected function pluginFontSize() {
if (self::$isAdmin) {
$this->createDeviceProperty('fontsize', 100);
}
$devices = $this->owner->getAvailableDevices();
$desktopFontSize = $this->data->get('desktopportraitfontsize');
foreach ($devices as $device) {
$fontSize = $this->data->get($device . 'fontsize');
if ($fontSize !== '') {
if ($device === 'desktopportrait') {
if ($fontSize != 100) {
$this->style->add($device, '', '--ssfont-scale:' . $fontSize / 100 . '');
}
} else if ($fontSize != $desktopFontSize) {
$this->style->add($device, '', '--ssfont-scale:' . $fontSize / 100 . '');
}
}
}
}
public function pluginParallax() {
$parallax = intval($this->data->get('parallax', 0));
if (self::$isAdmin) {
$this->attributes['data-parallax'] = $parallax;
} else if ($parallax >= 1) {
/**
* FlatSome theme use data-parallax and we are conflicting with it.
*
* @see SSDEV-2769
*/
$this->attributes['data-ssparallax'] = $parallax;
}
}
public function createProperty($name, $default = null) {
$this->attributes['data-' . $name] = $this->data->get($name, $default);
}
public function createColorProperty($name, $allowVariable, $default = null) {
$value = $this->data->get($name, $default);
if (!$allowVariable || ($value !== NULL && substr($value, 0, 1) != '{')) {
$l = strlen($value);
if (($l != 6 && $l != 8) || !preg_match('/^[0-9A-Fa-f]+$/', $value)) {
$value = $default;
}
}
$this->attributes['data-' . $name] = $value;
}
public function createDeviceProperty($name, $default = null) {
$device = 'desktopportrait';
$this->attributes['data-' . $device . $name] = $this->data->get($device . $name, $default);
$devices = array(
'desktoplandscape',
'tabletportrait',
'tabletlandscape',
'mobileportrait',
'mobilelandscape'
);
foreach ($devices as $device) {
$this->attributes['data-' . $device . $name] = $this->data->get($device . $name, null);
}
}
protected function renderBackground() {
$backgroundStyle = '';
$image = $this->owner->fill($this->data->get('bgimage', ''));
if ($image != '') {
$x = intval($this->data->get('bgimagex', 50));
$y = intval($this->data->get('bgimagey', 50));
$backgroundStyle .= '--n2bgimage:URL("' . esc_url(ResourceTranslator::toUrl($image)) . '");';
$backgroundStyle .= 'background-position:50% 50%,' . $x . '% ' . $y . '%;';
$this->hasBackground = true;
$optimizedData = $this->owner->optimizeImageWebP($image);
if (isset($optimizedData['normal'])) {
$this->owner->addImage($optimizedData['normal']['src']);
$this->localRawStyles[] = '.n2webp @rule-inner{--n2bgimage: URL(' . $optimizedData['normal']['src'] . ')}';
}
if (isset($optimizedData['medium'])) {
$this->owner->addImage($optimizedData['medium']['src']);
$this->localRawStyles[] = '@media (max-width: ' . $optimizedData['medium']['width'] . 'px) {.n2webp @rule-inner{--n2bgimage: URL(' . $optimizedData['medium']['src'] . ')}}';
}
if (isset($optimizedData['small'])) {
$this->owner->addImage($optimizedData['small']['src']);
$this->localRawStyles[] = '@media (max-width: ' . $optimizedData['small']['width'] . 'px) {.n2webp @rule-inner{--n2bgimage: URL(' . $optimizedData['small']['src'] . ')}}';
}
}
$color = $this->owner->fill($this->data->get('bgcolor', '00000000'));
if (empty($color)) {
$color = '00000000';
}
$gradient = $this->data->get('bgcolorgradient', 'off');
$colorEnd = $this->owner->fill($this->data->get('bgcolorgradientend', '00000000'));
if (empty($colorEnd)) {
$colorEnd = '00000000';
}
$this->addLocalStyle('normal', 'background', $this->getBackgroundCSS($color, $gradient, $colorEnd, $backgroundStyle) . $backgroundStyle);
$colorHover = $this->owner->fill($this->data->get('bgcolor-hover'));
$gradientHover = $this->data->get('bgcolorgradient-hover');
$colorEndHover = $this->owner->fill($this->data->get('bgcolorgradientend-hover'));
$isHoverDifferent = false;
if (!empty($colorHover) && $colorHover != $color) {
$isHoverDifferent = true;
}
if (!empty($gradientHover) && $gradientHover != $gradient) {
$isHoverDifferent = true;
}
if (!empty($colorEndHover) && $colorEndHover != $colorEnd) {
$isHoverDifferent = true;
}
if ($isHoverDifferent) {
if (empty($colorHover)) $colorHover = $color;
if (empty($gradientHover)) $gradientHover = $gradient;
if (empty($colorEndHover)) $colorEndHover = $colorEnd;
$this->addLocalStyle('hover', 'background', $this->getBackgroundCSS($colorHover, $gradientHover, $colorEndHover, $backgroundStyle, true));
}
}
protected function getBackgroundCSS($color, $gradient, $colorend, $backgroundStyle, $isHover = false) {
if (Color::hex2alpha($color) != 0 || ($gradient != 'off' && Color::hex2alpha($colorend) != 0) || $isHover) {
$this->hasBackground = true;
switch ($gradient) {
case 'horizontal':
return '--n2bggradient:linear-gradient(to right, ' . Color::colorToRGBA($color) . ' 0%,' . Color::colorToRGBA($colorend) . ' 100%);';
case 'vertical':
return '--n2bggradient:linear-gradient(to bottom, ' . Color::colorToRGBA($color) . ' 0%,' . Color::colorToRGBA($colorend) . ' 100%);';
case 'diagonal1':
return '--n2bggradient:linear-gradient(45deg, ' . Color::colorToRGBA($color) . ' 0%,' . Color::colorToRGBA($colorend) . ' 100%);';
case 'diagonal2':
return '--n2bggradient:linear-gradient(135deg, ' . Color::colorToRGBA($color) . ' 0%,' . Color::colorToRGBA($colorend) . ' 100%);';
case 'off':
default:
if (!empty($backgroundStyle)) {
return "--n2bggradient:linear-gradient(" . Color::colorToRGBA($color) . ", " . Color::colorToRGBA($color) . ");";
} else {
return "background-color:" . Color::colorToRGBA($color) . ';';
}
break;
}
}
return '';
}
/**
* @param AbstractRenderableOwner $slide
* @param array $layer
*/
public static function getFilled($slide, &$layer) {
if (!empty($layer['uniqueclass'])) {
$layer['uniqueclass'] .= $slide->unique;
}
if (!empty($layer['class'])) {
$layer['class'] = $slide->fill($layer['class']);
}
}
/**
* @param ExportSlider $export
* @param array $layer
*/
public static function prepareExport($export, $layer) {
}
/**
* @param ImportSlider $import
* @param array $layer
*/
public static function prepareImport($import, &$layer) {
}
/**
* @param array $layer
*/
public static function prepareSample(&$layer) {
}
public function getAttribute($key) {
if (isset($this->attributes[$key])) {
return $this->attributes[$key];
}
return null;
}
public function setAttribute($key, $value) {
$this->attributes[$key] = $value;
}
protected function addLocalStyle($group, $name, $style) {
if (!empty($style)) {
for ($i = 0; $i < count($this->localStyle); $i++) {
if ($this->localStyle[$i]['group'] == $group) {
$this->localStyle[$i]['css'][$name] = $style;
break;
}
}
}
}
protected function serveLocalStyle() {
$uniqueClassSelector = $this->getUniqueClassSelector();
$css = '';
for ($i = 0; $i < count($this->localStyle); $i++) {
$style = '';
foreach ($this->localStyle[$i]['css'] as $_css) {
$style .= $_css;
}
if (!empty($style)) {
$css .= '@rule' . $this->localStyle[$i]['selector'] . '{' . $style . '}';
}
}
if (!empty($css)) {
$this->getOwner()
->addCSS(str_replace('@rule', $uniqueClassSelector, $css));
}
if (!empty($this->localRawStyles)) {
foreach ($this->localRawStyles as $localRawStyle) {
$this->getOwner()
->addCSS(str_replace('@rule', $uniqueClassSelector, $localRawStyle));
}
}
foreach ($this->style->styles as $device => $styles) {
foreach ($styles as $selector => $stylesData) {
$this->getOwner()
->addDeviceCSS($device, $uniqueClassSelector . $selector . '{' . implode(';', $stylesData) . '}');
}
}
}
public function getUniqueClassSelector() {
$uniqueClass = $this->data->get('uniqueclass', '');
if (empty($uniqueClass)) {
$uniqueClass = self::generateUniqueIdentifier('n-uc-');
$this->data->set('uniqueclass', $uniqueClass);
}
$uniqueClass .= $this->owner->unique;
return 'div#' . $this->owner->getElementID() . ' .' . $uniqueClass;
}
protected static function generateUniqueIdentifier($prefix = 'n', $length = 12) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[mt_rand(0, $charactersLength - 1)];
}
return $prefix . $randomString;
}
public static function translateUniqueIdentifier($layers, $isAction = true) {
$idTranslation = array();
self::translateUniqueIdentifierID($idTranslation, $layers);
self::translateUniqueIdentifierParentID($idTranslation, $layers);
if ($isAction) {
self::translateUniqueIdentifierClass($layers);
}
return $layers;
}
private static function translateUniqueIdentifierID(&$idTranslation, &$layers) {
if (is_array($layers)) {
for ($i = 0; $i < count($layers); $i++) {
if (!empty($layers[$i]['id'])) {
$newId = self::generateUniqueIdentifier();
$idTranslation[$layers[$i]['id']] = $newId;
$layers[$i]['id'] = $newId;
}
if (isset($layers[$i]['type'])) {
switch ($layers[$i]['type']) {
case 'row':
self::translateUniqueIdentifierID($idTranslation, $layers[$i]['cols']);
break;
case 'col':
case 'content':
self::translateUniqueIdentifierID($idTranslation, $layers[$i]['layers']);
break;
}
}
}
}
}
private static function translateUniqueIdentifierParentID(&$idTranslation, &$layers) {
if (is_array($layers)) {
for ($i = 0; $i < count($layers); $i++) {
if (!empty($layers[$i]['parentid'])) {
if (isset($idTranslation[$layers[$i]['parentid']])) {
$layers[$i]['parentid'] = $idTranslation[$layers[$i]['parentid']];
} else {
$layers[$i]['parentid'] = '';
}
}
if (isset($layers[$i]['type'])) {
switch ($layers[$i]['type']) {
case 'row':
self::translateUniqueIdentifierParentID($idTranslation, $layers[$i]['cols']);
break;
case 'col':
case 'content':
self::translateUniqueIdentifierParentID($idTranslation, $layers[$i]['layers']);
break;
}
}
}
}
}
private static function translateUniqueIdentifierClass(&$layers) {
if (is_array($layers)) {
for ($i = 0; $i < count($layers); $i++) {
if (!empty($layers[$i]['uniqueclass'])) {
$layers[$i]['uniqueclass'] = self::generateUniqueIdentifier('n-uc-');
}
if (isset($layers[$i]['type'])) {
switch ($layers[$i]['type']) {
case 'row':
self::translateUniqueIdentifierClass($layers[$i]['cols']);
break;
case 'col':
case 'content':
self::translateUniqueIdentifierClass($layers[$i]['layers']);
break;
}
}
}
}
}
/**
* @return string
*/
public function getType() {
return $this->type;
}
public static function innerAlignToStyle($innerAlign) {
if ($innerAlign == 'left') {
return 'text-align:left;--ssselfalign:var(--ss-fs);';
} else if ($innerAlign == 'center') {
return 'text-align:center;--ssselfalign:center;';
} else if ($innerAlign == 'right') {
return 'text-align:right;--ssselfalign:var(--ss-fe);';
} else if ($innerAlign == '') {
return '';
}
return 'text-align:inherit;--ssselfalign:inherit;';
}
public static function selfAlignToStyle($innerAlign) {
if ($innerAlign == 'left') {
return 'align-self:var(--ss-fs);';
} else if ($innerAlign == 'center') {
return 'align-self:center;';
} else if ($innerAlign == 'right') {
return 'align-self:var(--ss-fe);';
} else if ($innerAlign == '') {
return '';
}
return 'align-self:var(--ssselfalign);';
}
}

View File

@ -0,0 +1,429 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Component;
use Nextend\Framework\Parser\Color;
use Nextend\Framework\Parser\Common;
use Nextend\Framework\Parser\Link;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Application\Model\ModelSlides;
use Nextend\SmartSlider3\BackupSlider\ExportSlider;
use Nextend\SmartSlider3\Renderable\AbstractRenderableOwner;
use Nextend\SmartSlider3\Renderable\ComponentContainer;
class ComponentCol extends AbstractComponent {
protected $type = 'col';
protected $colAttributes = array(
'class' => 'n2-ss-layer-col n2-ss-layer-with-background n2-ss-layer-content',
'style' => ''
);
protected $localStyle = array(
array(
"group" => "normal",
"selector" => '-inner',
"css" => array()
),
array(
"group" => "hover",
"selector" => '-inner:HOVER',
"css" => array()
),
);
protected $width;
public function __construct($index, $owner, $group, $data) {
parent::__construct($index, $owner, $group, $data);
$this->container = new ComponentContainer($owner, $this, $data['layers']);
$this->data->un_set('layers');
$this->upgradeData();
$this->attributes['style'] = '';
$devices = $this->owner->getAvailableDevices();
$desktopportraitInnerAlign = $this->data->get('desktopportraitinneralign', 'inherit');
$desktopPortraitMaxWidth = intval($this->data->get('desktopportraitmaxwidth'));
foreach ($devices as $device) {
if ($this->data->has($device . 'padding')) {
$padding = $this->data->get($device . 'padding');
if (!empty($padding)) {
$paddingValues = $this->spacingToPxValue($padding);
$this->style->add($device, '-inner', 'padding:' . implode('px ', $paddingValues) . 'px');
}
}
if ($this->data->has($device . 'maxwidth')) {
$maxWidth = intval($this->data->get($device . 'maxwidth'));
if ($maxWidth > 0) {
$this->style->add($device, '', 'max-width: ' . $maxWidth . 'px');
} else if ($device != 'desktopportrait' && $maxWidth != $desktopPortraitMaxWidth) {
$this->style->add($device, '', 'max-width: none');
}
}
$innerAlign = $this->data->get($device . 'inneralign', '');
if ($device == 'desktopportrait') {
if ($desktopportraitInnerAlign != 'inherit') {
$this->style->add($device, '-inner', AbstractComponent::innerAlignToStyle($innerAlign));
}
} else if ($desktopportraitInnerAlign != $innerAlign) {
$this->style->add($device, '-inner', AbstractComponent::innerAlignToStyle($innerAlign));
}
$verticalAlign = $this->data->get($device . 'verticalalign');
if (!empty($verticalAlign)) {
$this->style->add($device, '-inner', 'justify-content:' . $verticalAlign);
}
if ($this->data->has($device . 'order')) {
$order = intval($this->data->get($device . 'order'));
if ($order > 0) {
$this->style->add($device, '', 'order: ' . $order);
}
}
}
$this->renderBackground();
$borderRadius = intval($this->data->get('borderradius', '0'));
$this->addLocalStyle('normal', 'borderradius', $this->getBorderRadiusCSS($borderRadius));
$borderRadiusHover = intval($this->data->get('borderradius-hover'));
if (!empty($borderRadiusHover) && $borderRadiusHover != $borderRadius) {
$this->addLocalStyle('hover', 'borderradius', $this->getBorderRadiusCSS($borderRadiusHover));
}
$boxShadow = $this->data->get('boxshadow', '0|*|0|*|0|*|0|*|00000080');
$this->addLocalStyle('normal', 'boxshadow', $this->getBoxShadowCSS($boxShadow));
$boxShadowHover = $this->data->get('boxshadow-hover');
if (!empty($boxShadowHover) && $boxShadowHover != $boxShadow) {
$this->addLocalStyle('hover', 'boxshadow', $this->getBoxShadowCSS($boxShadowHover));
}
$borderWidth = $this->data->get('borderwidth', '1|*|1|*|1|*|1');
$borderStyle = $this->data->get('borderstyle', 'none');
$borderColor = $this->data->get('bordercolor', 'ffffffff');
if ($borderStyle != 'none') {
$this->addLocalStyle('normal', 'border', $this->getBorderCSS($borderWidth, $borderStyle, $borderColor));
}
$borderWidthHover = $this->data->get('borderwidth-hover');
$borderStyleHover = $this->data->get('borderstyle-hover');
$borderColorHover = $this->data->get('bordercolor-hover');
$isHoverDifferent = false;
if (!empty($borderWidthHover) || $borderWidthHover != $borderWidth) {
$isHoverDifferent = true;
}
if (!empty($borderStyleHover) || $borderStyleHover != $borderStyle) {
$isHoverDifferent = true;
}
if (!empty($borderColorHover) || $borderColorHover != $borderColor) {
$isHoverDifferent = true;
}
if ($isHoverDifferent) {
if (empty($borderWidthHover)) $borderWidthHover = $borderWidth;
if (empty($borderStyleHover)) $borderStyleHover = $borderStyle;
if (empty($borderColorHover)) $borderColorHover = $borderColor;
$this->addLocalStyle('hover', 'border', $this->getBorderCSS($borderWidthHover, $borderStyleHover, $borderColorHover));
}
$this->placement->attributes($this->attributes);
$width = explode('/', $this->data->get('colwidth', 1));
if (count($width) == 2) {
if ($width[0] == 0 || $width[1] == 0) {
$width[0] = 1;
$width[1] = 2;
$this->data->set('colwidth', '1/2');
}
$width = floor($width[0] / $width[1] * 1000) / 10;
} else {
$width = 100;
}
$this->width = $width;
if (!AbstractComponent::$isAdmin) {
$this->makeLink();
}
}
public function setWidth($device) {
$this->style->add($device, '', 'width:' . $this->width . '%');
}
public function setWidthAuto($device) {
$this->style->add($device, '', 'width:auto');
}
public function setWrapAfterWidth($device, $width, $gutter) {
$this->style->add($device, '', 'width:calc(' . $width . '% - ' . $gutter . 'px)');
}
protected function upgradeData() {
if ($this->data->has('verticalalign')) {
/**
* Upgrade data to device specific
*/
$this->data->set('desktopportraitverticalalign', $this->data->get('verticalalign'));
$this->data->un_set('verticalalign');
}
}
public function getPlacement() {
return 'default';
}
private function getBorderRadiusCSS($borderRadius) {
if ($borderRadius > 0) {
return 'border-radius:' . $borderRadius . 'px;';
}
return '';
}
private function getBoxShadowCSS($boxShadow) {
$boxShadowArray = explode('|*|', $boxShadow);
if (count($boxShadowArray) == 5 && ($boxShadowArray[0] != 0 || $boxShadowArray[1] != 0 || $boxShadowArray[2] != 0 || $boxShadowArray[3] != 0) && Color::hex2alpha($boxShadowArray[4]) != 0) {
return 'box-shadow:' . $boxShadowArray[0] . 'px ' . $boxShadowArray[1] . 'px ' . $boxShadowArray[2] . 'px ' . $boxShadowArray[3] . 'px ' . Color::colorToRGBA($boxShadowArray[4]) . ';';
}
return '';
}
private function getBorderCSS($width, $style, $color) {
if ($style != 'none') {
$values = explode('|*|', $width);
$unit = 'px';
$values[4] = '';
$css = 'border-width:' . implode($unit . ' ', $values) . ';';
$css .= 'border-style:' . $style . ';';
$css .= 'border-color:' . Color::colorToRGBA($color) . ';';
return $css;
}
return '';
}
private function makeLink() {
$linkV1 = $this->data->get('link', '');
if (!empty($linkV1)) {
list($link, $target) = array_pad((array)Common::parse($linkV1), 2, '');
$this->data->un_set('link');
$this->data->set('href', $link);
$this->data->set('href-target', $target);
}
$link = $this->data->get('href');
if (($link != '#' && !empty($link))) {
$target = $this->data->get('href-target');
$link = Link::parse($this->owner->fill($link), $this->attributes);
$this->attributes['data-href'] = $link;
$this->attributes['tabindex'] = 0;
$this->attributes['role'] = 'button';
$ariaLabel = $this->data->get('aria-label');
if (!empty($ariaLabel)) {
$this->attributes['aria-label'] = $this->owner->fill($ariaLabel);
}
if (!isset($this->attributes['onclick']) && !isset($this->attributes['data-n2-lightbox'])) {
if (!empty($target) && $target != '_self') {
$this->attributes['data-target'] = $target;
}
$this->attributes['data-n2click'] = "url";
}
$this->attributes['data-force-pointer'] = "";
}
}
public function render($isAdmin) {
if ($this->isRenderAllowed()) {
$this->runPlugins();
$this->serveLocalStyle();
if ($isAdmin) {
$this->admin();
}
$this->prepareHTML();
$html = Html::tag('div', $this->colAttributes, parent::renderContainer($isAdmin));
$html = $this->renderPlugins($html);
return Html::tag('div', $this->attributes, $html);
}
return '';
}
protected function addUniqueClass($class) {
$this->attributes['class'] .= ' ' . $class;
$this->colAttributes['class'] .= ' ' . $class . '-inner';
}
protected function admin() {
$linkV1 = $this->data->get('link', '');
if (!empty($linkV1)) {
list($link, $target) = array_pad((array)Common::parse($linkV1), 2, '');
$this->data->un_set('link');
$this->data->set('href', $link);
$this->data->set('href-target', $target);
}
$this->createProperty('href', '');
$this->createProperty('href-target', '_self');
$this->createProperty('aria-label', '');
$this->createProperty('colwidth');
$this->createProperty('bgimage', '');
$this->createProperty('bgimagex', 50);
$this->createProperty('bgimagey', 50);
$this->createColorProperty('bgcolor', true, '00000000');
$this->createProperty('bgcolorgradient', 'off');
$this->createColorProperty('bgcolorgradientend', true, '00000000');
$this->createColorProperty('bgcolor-hover', true);
$this->createProperty('bgcolorgradient-hover');
$this->createColorProperty('bgcolorgradientend-hover', true);
$this->createProperty('borderradius', '0');
$this->createProperty('borderradius-hover');
$this->createProperty('boxshadow', '0|*|0|*|0|*|0|*|00000080');
$this->createProperty('boxshadow-hover');
$this->createProperty('borderwidth', '1|*|1|*|1|*|1');
$this->createProperty('borderstyle', 'none');
$this->createProperty('bordercolor', 'FFFFFFFF');
$this->createProperty('borderwidth-hover');
$this->createProperty('borderstyle-hover');
$this->createProperty('bordercolor-hover');
$this->createProperty('opened', 1);
$this->createDeviceProperty('maxwidth', '0');
$this->createDeviceProperty('padding', '10|*|10|*|10|*|10');
$this->createDeviceProperty('verticalalign', 'flex-start');
$this->createDeviceProperty('inneralign', 'inherit');
$this->createDeviceProperty('order');
parent::admin();
}
/**
* @param ExportSlider $export
* @param array $layer
*/
public static function prepareExport($export, $layer) {
if (!empty($layer['bgimage'])) {
$export->addImage($layer['bgimage']);
}
$export->prepareLayer($layer['layers']);
}
public static function prepareImport($import, &$layer) {
if (!empty($layer['bgimage'])) {
$layer['bgimage'] = $import->fixImage($layer['bgimage']);
}
$import->prepareLayers($layer['layers']);
}
public static function prepareSample(&$layer) {
if (!empty($layer['bgimage'])) {
$layer['bgimage'] = ResourceTranslator::toUrl($layer['bgimage']);
}
ModelSlides::prepareSample($layer['layers']);
}
/**
* @param AbstractRenderableOwner $slide
* @param array $layer
*/
public static function getFilled($slide, &$layer) {
AbstractComponent::getFilled($slide, $layer);
$fields = array(
'bgimage',
'href'
);
foreach ($fields as $field) {
if (!empty($layer[$field])) {
$layer[$field] = $slide->fill($layer[$field]);
}
}
$slide->fillLayers($layer['layers']);
}
public function getOrder($device) {
$order = intval($this->data->get($device . 'order'));
if ($order > 0) {
return $order;
}
return 10;
}
public function getWidth() {
return $this->width;
}
public static $compareOrderDevice;
/**
* @param ComponentCol $column1
* @param ComponentCol $column2
*
* @return int
*/
public static function compareOrder($column1, $column2) {
$order1 = $column1->getOrder(self::$compareOrderDevice);
$order2 = $column2->getOrder(self::$compareOrderDevice);
if ($order1 == $order2) {
return 0;
}
return ($order1 < $order2) ? -1 : 1;
}
}

View File

@ -0,0 +1,220 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Component;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Application\Model\ModelSlides;
use Nextend\SmartSlider3\BackupSlider\ExportSlider;
use Nextend\SmartSlider3\Renderable\AbstractRenderableOwner;
use Nextend\SmartSlider3\Renderable\ComponentContainer;
class ComponentContent extends AbstractComponent {
protected $type = 'content';
protected $name = 'Content';
protected $colAttributes = array(
'class' => 'n2-ss-section-main-content n2-ss-layer-with-background n2-ss-layer-content n2-ow',
'style' => ''
);
protected $localStyle = array(
array(
"group" => "normal",
"selector" => '-inner',
"css" => array()
),
array(
"group" => "hover",
"selector" => '-inner:HOVER',
"css" => array()
),
);
public function getPlacement() {
return 'default';
}
public function __construct($index, $owner, $group, $data) {
parent::__construct($index, $owner, $group, $data);
$this->container = new ComponentContainer($owner, $this, $data['layers']);
$this->data->un_set('layers');
$this->upgradeData();
$this->attributes['style'] = '';
$devices = $this->owner->getAvailableDevices();
$desktopPortraitSelfAlign = $this->data->get('desktopportraitselfalign', 'inherit');
$desktopportraitInnerAlign = $this->data->get('desktopportraitinneralign', 'inherit');
foreach ($devices as $device) {
$padding = $this->data->get($device . 'padding');
if (!empty($padding)) {
$paddingValues = $this->spacingToPxValue($padding);
$this->style->add($device, '-inner', 'padding:' . implode('px ', $paddingValues) . 'px');
}
$maxWidth = intval($this->data->get($device . 'maxwidth', 0));
if ($maxWidth > 0) {
$this->style->add($device, '', 'max-width: ' . $maxWidth . 'px');
}
$innerAlign = $this->data->get($device . 'inneralign', '');
if ($device == 'desktopportrait') {
if ($desktopportraitInnerAlign != 'inherit') {
$this->style->add($device, '-inner', AbstractComponent::innerAlignToStyle($innerAlign));
}
} else if ($desktopportraitInnerAlign != $innerAlign) {
$this->style->add($device, '-inner', AbstractComponent::innerAlignToStyle($innerAlign));
}
$selfAlign = $this->data->get($device . 'selfalign', '');
if ($device == 'desktopportrait') {
if ($desktopPortraitSelfAlign != 'inherit') {
$this->style->add($device, '', AbstractComponent::selfAlignToStyle($selfAlign));
}
} else if ($desktopPortraitSelfAlign != $selfAlign) {
$this->style->add($device, '', AbstractComponent::selfAlignToStyle($selfAlign));
}
$verticalAlign = $this->data->get($device . 'verticalalign');
if (!empty($verticalAlign)) {
$this->style->add($device, '-inner', 'justify-content:' . $verticalAlign);
}
}
$this->renderBackground();
$this->placement->attributes($this->attributes);
}
protected function upgradeData() {
if ($this->data->has('verticalalign')) {
/**
* Upgrade data to device specific
*/
$this->data->set('desktopportraitverticalalign', $this->data->get('verticalalign'));
$this->data->un_set('verticalalign');
}
}
public function render($isAdmin) {
if ($this->isRenderAllowed()) {
if ($isAdmin || $this->hasBackground || count($this->container->getLayers())) {
$this->runPlugins();
$this->serveLocalStyle();
if ($isAdmin) {
$this->admin();
}
$this->prepareHTML();
$this->attributes['data-hasbackground'] = $this->hasBackground ? '1' : '0';
$html = Html::tag('div', $this->colAttributes, parent::renderContainer($isAdmin));
$html = $this->renderPlugins($html);
return Html::tag('div', $this->attributes, $html);
}
}
return '';
}
protected function addUniqueClass($class) {
$this->attributes['class'] .= ' ' . $class;
$this->colAttributes['class'] .= ' ' . $class . '-inner';
}
protected function admin() {
$this->createDeviceProperty('verticalalign', 'center');
$this->createDeviceProperty('inneralign', 'inherit');
$this->createDeviceProperty('selfalign', 'center');
$this->createDeviceProperty('maxwidth', '0');
$this->createDeviceProperty('padding', '10|*|10|*|10|*|10');
$this->createProperty('bgimage', '');
$this->createProperty('bgimagex', 50);
$this->createProperty('bgimagey', 50);
$this->createColorProperty('bgcolor', true, '00000000');
$this->createProperty('bgcolorgradient', 'off');
$this->createColorProperty('bgcolorgradientend', true, '00000000');
$this->createColorProperty('bgcolor-hover', true);
$this->createProperty('bgcolorgradient-hover');
$this->createColorProperty('bgcolorgradientend-hover', true);
$this->createProperty('opened', 1);
$this->createProperty('id', '');
$this->createProperty('uniqueclass', '');
$this->createProperty('class', '');
$this->createProperty('status');
$this->createProperty('generatorvisible', '');
$this->placement->adminAttributes($this->attributes);
}
/**
* @param ExportSlider $export
* @param array $layer
*/
public static function prepareExport($export, $layer) {
if (!empty($layer['bgimage'])) {
$export->addImage($layer['bgimage']);
}
$export->prepareLayer($layer['layers']);
}
public static function prepareImport($import, &$layer) {
if (!empty($layer['bgimage'])) {
$layer['bgimage'] = $import->fixImage($layer['bgimage']);
}
$import->prepareLayers($layer['layers']);
}
public static function prepareSample(&$layer) {
if (!empty($layer['bgimage'])) {
$layer['bgimage'] = ResourceTranslator::toUrl($layer['bgimage']);
}
ModelSlides::prepareSample($layer['layers']);
}
/**
* @param AbstractRenderableOwner $slide
* @param array $layer
*/
public static function getFilled($slide, &$layer) {
AbstractComponent::getFilled($slide, $layer);
if (!empty($layer['bgimage'])) {
$layer['bgimage'] = $slide->fill($layer['bgimage']);
}
$slide->fillLayers($layer['layers']);
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Component;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\AbstractRenderableOwner;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
use Nextend\SmartSlider3\Renderable\Item\ItemFactory;
class ComponentLayer extends AbstractComponent {
protected $type = 'layer';
/** @var AbstractItemFrontend */
private $item;
public function __construct($index, $owner, $group, $data) {
parent::__construct($index, $owner, $group, $data);
$this->attributes['style'] = '';
$item = $this->data->get('item');
if (empty($item)) {
$items = $this->data->get('items');
$item = $items[0];
}
$this->item = ItemFactory::create($this, $item);
$this->placement->attributes($this->attributes);
}
public function render($isAdmin) {
if ($this->isRenderAllowed()) {
$this->runPlugins();
$this->serveLocalStyle();
$this->prepareHTML();
if ($isAdmin) {
$renderedItem = $this->item->renderAdmin();
} else {
$renderedItem = $this->item->render();
}
if ($renderedItem === false) {
return '';
}
if ($this->item->needHeight()) {
$this->attributes['class'] .= ' n2-ss-layer--need-height';
}
if ($this->item->isAuto()) {
$this->attributes['class'] .= ' n2-ss-layer--auto';
}
$html = $this->renderPlugins($renderedItem);
if ($isAdmin) {
$this->admin();
}
return Html::tag('div', $this->attributes, $html);
}
return '';
}
/**
* @param AbstractRenderableOwner $slide
* @param array $layer
*/
public static function getFilled($slide, &$layer) {
AbstractComponent::getFilled($slide, $layer);
if (empty($layer['item'])) {
$layer['item'] = $layer['items'][0];
unset($layer['items']);
}
ItemFactory::getFilled($slide, $layer['item']);
}
public static function prepareExport($export, $layer) {
if (empty($layer['item'])) {
$layer['item'] = $layer['items'][0];
unset($layer['items']);
}
ItemFactory::prepareExport($export, $layer['item']);
}
public static function prepareImport($import, &$layer) {
if (empty($layer['item'])) {
$layer['item'] = $layer['items'][0];
unset($layer['items']);
}
$layer['item'] = ItemFactory::prepareImport($import, $layer['item']);
}
public static function prepareSample(&$layer) {
if (empty($layer['item'])) {
$layer['item'] = $layer['items'][0];
unset($layer['items']);
}
$layer['item'] = ItemFactory::prepareSample($layer['item']);
}
}

View File

@ -0,0 +1,445 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Component;
use Nextend\Framework\Parser\Color;
use Nextend\Framework\Parser\Common;
use Nextend\Framework\Parser\Link;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Application\Model\ModelSlides;
use Nextend\SmartSlider3\BackupSlider\ExportSlider;
use Nextend\SmartSlider3\Renderable\AbstractRenderableOwner;
use Nextend\SmartSlider3\Renderable\ComponentContainer;
class ComponentRow extends AbstractComponent {
protected $type = 'row';
protected $rowAttributes = array(
'class' => 'n2-ss-layer-row n2-ss-layer-with-background',
'style' => ''
);
protected $rowAttributesInner = array(
'class' => 'n2-ss-layer-row-inner '
);
protected $localStyle = array(
array(
"group" => "normal",
"selector" => '-inner',
"css" => array()
),
array(
"group" => "hover",
"selector" => '-inner:HOVER',
"css" => array()
),
);
protected $html = '';
public function __construct($index, $owner, $group, $data) {
parent::__construct($index, $owner, $group, $data);
$this->container = new ComponentContainer($owner, $this, $data['cols']);
$this->data->un_set('cols');
$this->data->un_set('inneralign');
$fullWidth = $this->data->get('fullwidth', 1);
if ($fullWidth) {
$this->attributes['class'] .= ' n2-ss-layer--block';
} else {
$this->attributes['class'] .= ' n2-ss-layer--auto';
}
$devices = $this->owner->getAvailableDevices();
$desktopportraitInnerAlign = $this->data->get('desktopportraitinneralign', 'inherit');
$desktopportraitGutter = $this->getGutter('desktopportrait');
if (empty($desktopportraitGutter)) {
$desktopportraitGutter = 0;
}
$desktopportraitWrapAfter = $this->data->get('desktopportraitwrapafter', 0);
if (empty($desktopportraitWrapAfter)) {
$desktopportraitWrapAfter = 0;
}
foreach ($devices as $device) {
$padding = $this->data->get($device . 'padding');
if (!empty($padding)) {
$paddingValues = $this->spacingToPxValue($padding);
$this->style->add($device, '-inner', 'padding:' . implode('px ', $paddingValues) . 'px');
}
$innerAlign = $this->data->get($device . 'inneralign', '');
if ($device == 'desktopportrait') {
if ($desktopportraitInnerAlign != 'inherit') {
$this->style->add($device, '-inner', AbstractComponent::innerAlignToStyle($innerAlign));
}
} else if ($desktopportraitInnerAlign != $innerAlign) {
$this->style->add($device, '-inner', AbstractComponent::innerAlignToStyle($innerAlign));
}
$gutter = $this->getGutter($device);
$wrapAfter = $this->data->get($device . 'wrapafter', '');
if ($wrapAfter === '') {
$wrapAfter = $desktopportraitWrapAfter; // inherit desktop value
}
if ($gutter !== null) {
$sideGutter = $gutter / 2;
/**
* +1 to fix Safari line break
*
* @see https://bugs.webkit.org/show_bug.cgi?id=225962
* @see SSDEV-2980
*/
$this->style->add($device, '-inner > .n2-ss-layer-row-inner', 'width:calc(100% + ' . ($gutter + 1) . 'px);margin:-' . $sideGutter . 'px');
$this->style->add($device, '-inner > .n2-ss-layer-row-inner > .n2-ss-layer[data-sstype="col"]', 'margin:' . $sideGutter . 'px');
} else {
$gutter = $desktopportraitGutter;
}
$columns = $this->getSortedColumns($device);
$columnsCount = count($columns);
if ($wrapAfter > 0 || !$fullWidth) {
$this->style->add($device, '-inner > .n2-ss-layer-row-inner', 'flex-wrap:wrap;');
if ($fullWidth && $wrapAfter <= $columnsCount) {
$rows = array_fill(0, ceil($columnsCount / $wrapAfter), 0);
for ($i = 0; $i < $columnsCount; $i++) {
$rowIndex = floor($i / $wrapAfter);
$rows[$rowIndex] += $columns[$i]->getWidth();
}
for ($i = 0; $i < $columnsCount; $i++) {
$rowIndex = floor($i / $wrapAfter);
$columns[$i]->setWrapAfterWidth($device, floor($columns[$i]->getWidth() / $rows[$rowIndex] * 100), $gutter);
}
} else {
foreach ($columns as $column) {
$column->setWidthAuto($device);
}
}
} else {
$this->style->add($device, '-inner > .n2-ss-layer-row-inner', 'flex-wrap:nowrap;');
if ($fullWidth) {
foreach ($columns as $column) {
$column->setWidth($device);
}
} else {
foreach ($columns as $column) {
$column->setWidthAuto($device);
}
}
}
}
$this->renderBackground();
$this->attributes['class'] .= ' n2-ss-has-self-align';
$stretch = $this->data->get('stretch', 0);
if ($stretch) {
$this->attributes['class'] .= ' n2-ss-stretch-layer';
}
$borderWidth = $this->data->get('borderwidth', '1|*|1|*|1|*|1');
$borderStyle = $this->data->get('borderstyle', 'none');
$borderColor = $this->data->get('bordercolor', 'ffffffff');
if ($borderStyle != 'none') {
$this->addLocalStyle('normal', 'border', $this->getBorderCSS($borderWidth, $borderStyle, $borderColor));
}
$borderWidthHover = $this->data->get('borderwidth-hover');
$borderStyleHover = $this->data->get('borderstyle-hover');
$borderColorHover = $this->data->get('bordercolor-hover');
$isHoverDifferent = false;
if (!empty($borderWidthHover) || $borderWidthHover != $borderWidth) {
$isHoverDifferent = true;
}
if (!empty($borderStyleHover) || $borderStyleHover != $borderStyle) {
$isHoverDifferent = true;
}
if (!empty($borderColorHover) || $borderColorHover != $borderColor) {
$isHoverDifferent = true;
}
if ($isHoverDifferent) {
if (empty($borderWidthHover)) $borderWidthHover = $borderWidth;
if (empty($borderStyleHover)) $borderStyleHover = $borderStyle;
if (empty($borderColorHover)) $borderColorHover = $borderColor;
$this->addLocalStyle('hover', 'border', $this->getBorderCSS($borderWidthHover, $borderStyleHover, $borderColorHover));
}
$borderRadius = intval($this->data->get('borderradius', 0));
$this->addLocalStyle('normal', 'borderradius', $this->getBorderRadiusCSS($borderRadius));
$borderRadiusHover = intval($this->data->get('borderradius-hover'));
if (!empty($borderRadiusHover) && $borderRadiusHover != $borderRadius) {
$this->addLocalStyle('hover', 'borderradius', $this->getBorderRadiusCSS($borderRadiusHover));
}
$boxShadow = $this->data->get('boxshadow', '0|*|0|*|0|*|0|*|00000080');
$this->addLocalStyle('normal', 'boxshadow', $this->getBoxShadowCSS($boxShadow));
$boxShadowHover = $this->data->get('boxshadow-hover');
if (!empty($boxShadowHover) && $boxShadowHover != $boxShadow) {
$this->addLocalStyle('hover', 'boxshadow', $this->getBoxShadowCSS($boxShadowHover));
}
$this->placement->attributes($this->attributes);
if (!AbstractComponent::$isAdmin) {
$this->makeLink();
}
}
public function getGutter($device) {
return $this->data->get($device . 'gutter', null);
}
public function render($isAdmin) {
if ($this->isRenderAllowed()) {
$this->runPlugins();
$this->serveLocalStyle();
if ($isAdmin) {
$this->admin();
}
$this->prepareHTML();
$html = Html::tag('div', $this->rowAttributes, Html::tag('div', $this->rowAttributesInner, parent::renderContainer($isAdmin)));
$html = $this->renderPlugins($html);
return Html::tag('div', $this->attributes, $html);
}
return '';
}
/**
* @return ComponentCol[]
*/
protected function getColumns() {
$layers = $this->container->getLayers();
$columns = array();
for ($i = 0; $i < count($layers); $i++) {
if ($layers[$i] instanceof ComponentCol) {
$columns[] = $layers[$i];
}
}
return $columns;
}
protected function getSortedColumns($device) {
$columns = $this->getColumns();
for ($i = count($columns) - 1; $i >= 0; $i--) {
if (!$columns[$i]->isShown($device)) {
array_splice($columns, $i, 1);
}
}
ComponentCol::$compareOrderDevice = $device;
usort($columns, array(
ComponentCol::class,
'compareOrder'
));
return $columns;
}
protected function addUniqueClass($class) {
$this->attributes['class'] .= ' ' . $class;
$this->rowAttributes['class'] .= ' ' . $class . '-inner';
}
private function makeLink() {
$linkV1 = $this->data->get('link', '');
if (!empty($linkV1)) {
list($link, $target) = array_pad((array)Common::parse($linkV1), 2, '');
$this->data->un_set('link');
$this->data->set('href', $link);
$this->data->set('href-target', $target);
}
$link = $this->data->get('href');
if (($link != '#' && !empty($link))) {
$target = $this->data->get('href-target');
$link = Link::parse($this->owner->fill($link), $this->attributes);
$this->attributes['data-href'] = $link;
$this->attributes['tabindex'] = 0;
$this->attributes['role'] = 'button';
$ariaLabel = $this->data->get('aria-label');
if (!empty($ariaLabel)) {
$this->attributes['aria-label'] = $this->owner->fill($ariaLabel);
}
if (!isset($this->attributes['onclick']) && !isset($this->attributes['data-n2-lightbox'])) {
if (!empty($target) && $target != '_self') {
$this->attributes['data-target'] = $target;
}
$this->attributes['data-n2click'] = "url";
}
$this->attributes['data-force-pointer'] = "";
}
}
protected function admin() {
$linkV1 = $this->data->get('link', '');
if (!empty($linkV1)) {
list($link, $target) = array_pad((array)Common::parse($linkV1), 2, '');
$this->data->un_set('link');
$this->data->set('href', $link);
$this->data->set('href-target', $target);
}
$this->createProperty('href', '');
$this->createProperty('href-target', '_self');
$this->createProperty('aria-label', '');
$this->createProperty('bgimage', '');
$this->createProperty('bgimagex', 50);
$this->createProperty('bgimagey', 50);
$this->createColorProperty('bgcolor', true, '00000000');
$this->createProperty('bgcolorgradient', 'off');
$this->createColorProperty('bgcolorgradientend', true, '00000000');
$this->createColorProperty('bgcolor-hover', true);
$this->createProperty('bgcolorgradient-hover');
$this->createColorProperty('bgcolorgradientend-hover', true);
$this->createProperty('borderwidth', '1|*|1|*|1|*|1');
$this->createProperty('borderstyle', 'none');
$this->createProperty('bordercolor', 'FFFFFFFF');
$this->createProperty('borderwidth-hover');
$this->createProperty('borderstyle-hover');
$this->createProperty('bordercolor-hover');
$this->createProperty('borderradius', 0);
$this->createProperty('borderradius-hover');
$this->createProperty('boxshadow', '0|*|0|*|0|*|0|*|00000080');
$this->createProperty('boxshadow-hover');
$this->createProperty('fullwidth', '1');
$this->createProperty('stretch', '0');
$this->createProperty('opened', 1);
$this->createDeviceProperty('padding', '10|*|10|*|10|*|10');
$this->createDeviceProperty('gutter', 20);
$this->createDeviceProperty('wrapafter', 0);
$this->createDeviceProperty('inneralign', 'inherit');
parent::admin();
}
/**
* @param ExportSlider $export
* @param array $layer
*/
public static function prepareExport($export, $layer) {
if (!empty($layer['bgimage'])) {
$export->addImage($layer['bgimage']);
}
$export->prepareLayer($layer['cols']);
}
public static function prepareImport($import, &$layer) {
if (!empty($layer['bgimage'])) {
$layer['bgimage'] = $import->fixImage($layer['bgimage']);
}
$import->prepareLayers($layer['cols']);
}
public static function prepareSample(&$layer) {
if (!empty($layer['bgimage'])) {
$layer['bgimage'] = ResourceTranslator::toUrl($layer['bgimage']);
}
ModelSlides::prepareSample($layer['cols']);
}
/**
* @param AbstractRenderableOwner $slide
* @param array $layer
*/
public static function getFilled($slide, &$layer) {
AbstractComponent::getFilled($slide, $layer);
$fields = array(
'bgimage',
'href'
);
foreach ($fields as $field) {
if (!empty($layer[$field])) {
$layer[$field] = $slide->fill($layer[$field]);
}
}
$slide->fillLayers($layer['cols']);
}
private function getBorderCSS($width, $style, $color) {
if ($style != 'none') {
$values = explode('|*|', $width);
$unit = 'px';
$values[4] = '';
$css = 'border-width:' . implode($unit . ' ', $values) . ';';
$css .= 'border-style:' . $style . ';';
$css .= 'border-color:' . Color::colorToRGBA($color) . ';';
return $css;
}
return '';
}
private function getBorderRadiusCSS($borderRadius) {
if ($borderRadius > 0) {
return 'border-radius:' . $borderRadius . 'px;';
}
return '';
}
private function getBoxShadowCSS($boxShadow) {
$boxShadowArray = explode('|*|', $boxShadow);
if (count($boxShadowArray) == 5 && ($boxShadowArray[0] != 0 || $boxShadowArray[1] != 0 || $boxShadowArray[2] != 0 || $boxShadowArray[3] != 0) && Color::hex2alpha($boxShadowArray[4]) != 0) {
return 'box-shadow:' . $boxShadowArray[0] . 'px ' . $boxShadowArray[1] . 'px ' . $boxShadowArray[2] . 'px ' . $boxShadowArray[3] . 'px ' . Color::colorToRGBA($boxShadowArray[4]) . ';';
}
return '';
}
}

View File

@ -0,0 +1,151 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Component;
use Nextend\Framework\Parser\Common;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\ComponentContainer;
use Nextend\SmartSlider3\Slider\Slide;
use Nextend\SmartSlider3\Slider\SliderType\SliderTypeFactory;
class ComponentSlide extends AbstractComponent {
protected $type = 'slide';
/**
* @var Slide
*/
protected $owner;
/**
* ComponentSlide constructor.
*
* @param Slide $owner
* @param $data
*/
public function __construct($owner, $data) {
if (!$owner->underEdit) {
$data['layers'] = AbstractComponent::translateUniqueIdentifier($data['layers'], false);
}
parent::__construct(0, $owner, false, $data);
$this->container = new ComponentContainer($owner, $this, $data['layers']);
$this->data->un_set('layers');
$this->container->addContentLayer($owner, $this);
$this->upgradeData();
$devices = $this->owner->getAvailableDevices();
foreach ($devices as $device) {
$padding = $this->data->get($device . 'padding');
if (!empty($padding)) {
$this->style->add($device, '', 'padding:' . implode('px ', explode('|*|', $padding)) . 'px');
}
}
}
protected function upgradeData() {
if ($this->data->get('background-type') == '') {
$this->data->set('background-type', 'color');
if ($this->data->get('backgroundVideoMp4')) {
$this->data->set('background-type', 'video');
} else if ($this->data->get('backgroundImage')) {
$this->data->set('background-type', 'image');
}
}
$linkV1 = $this->data->getIfEmpty('link', '');
if (!empty($linkV1)) {
list($link, $target) = array_pad((array)Common::parse($linkV1), 2, '');
$this->data->un_set('link');
$this->data->set('href', $link);
$this->data->set('href-target', $target);
}
}
public function getPlacement() {
return 'default';
}
protected function admin() {
/**
* Hide on properties
*/
$this->createDeviceProperty('', 1);
$this->createProperty('title', '');
$this->createProperty('publish_up', '0000-00-00 00:00:00');
$this->createProperty('publish_down', '0000-00-00 00:00:00');
$this->createProperty('published', 1);
$this->createProperty('description', '');
$this->createProperty('thumbnail', '');
$this->createProperty('thumbnailAlt', '');
$this->createProperty('thumbnailType', 'default');
$this->createProperty('static-slide', 0);
$this->createProperty('slide-duration', 0);
$this->createProperty('ligthboxImage', '');
$this->createProperty('record-slides', 0);
SliderTypeFactory::getType($this->owner->getSlider()->data->get('type'))
->createAdmin()
->registerSlideAdminProperties($this);
$this->createProperty('href', '');
$this->createProperty('href-target', '');
$this->createProperty('aria-label', '');
$this->createProperty('background-type', 'color');
$this->createProperty('backgroundColor', 'ffffff00');
$this->createProperty('backgroundGradient', 'off');
$this->createProperty('backgroundColorEnd', 'ffffff00');
$this->createProperty('backgroundColorOverlay', 0);
$this->createProperty('backgroundImage', '');
$this->createProperty('backgroundFocusX', 50);
$this->createProperty('backgroundFocusY', 50);
$this->createProperty('backgroundImageOpacity', 100);
$this->createProperty('backgroundImageBlur', 0);
$this->createProperty('backgroundAlt', '');
$this->createProperty('backgroundTitle', '');
$this->createProperty('backgroundMode', 'default');
$this->createProperty('backgroundBlurFit', 7);
$this->createProperty('backgroundVideoMp4', '');
$this->createProperty('backgroundVideoOpacity', 100);
$this->createProperty('backgroundVideoLoop', 1);
$this->createProperty('backgroundVideoReset', 1);
$this->createProperty('backgroundVideoMode', 'fill');
$this->createDeviceProperty('padding', '10|*|10|*|10|*|10');
}
public function render($isAdmin) {
$this->attributes['data-sstype'] = $this->type;
$this->placement->attributes($this->attributes);
$this->serveLocalStyle();
if ($isAdmin) {
$this->admin();
}
$uniqueClass = $this->data->get('uniqueclass', '');
if (!empty($uniqueClass)) {
$this->addUniqueClass($uniqueClass . $this->owner->unique);
}
return Html::tag('div', $this->attributes, parent::renderContainer($isAdmin));
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Component;
class Style {
public $styles = array(
'all' => array(),
'desktoplandscape' => array(),
'tabletlandscape' => array(),
'tabletportrait' => array(),
'mobilelandscape' => array(),
'mobileportrait' => array(),
);
/**
* @var AbstractComponent
*/
protected $component;
/**
* Style constructor.
*
* @param AbstractComponent $component
*/
public function __construct($component) {
$this->component = $component;
}
public function add($device, $selector, $css) {
if (!empty($css)) {
if ($device == 'desktopportrait') {
$device = 'all';
}
$this->addOnly($device, $selector, $css);
}
}
public function addOnly($device, $selector, $css) {
if (!empty($css)) {
if (!isset($this->styles[$device][$selector])) {
$this->styles[$device][$selector] = array();
}
$this->styles[$device][$selector][] = $css;
}
}
}

View File

@ -0,0 +1,136 @@
<?php
namespace Nextend\SmartSlider3\Renderable;
use Exception;
use Nextend\Framework\Notification\Notification;
use Nextend\SmartSlider3\Renderable\Component\AbstractComponent;
use Nextend\SmartSlider3\Renderable\Component\ComponentCol;
use Nextend\SmartSlider3\Renderable\Component\ComponentContent;
use Nextend\SmartSlider3\Renderable\Component\ComponentLayer;
use Nextend\SmartSlider3\Renderable\Component\ComponentRow;
use Nextend\SmartSlider3\Slider\Slide;
class ComponentContainer {
/** @var AbstractComponent[] */
protected $layers = array();
protected $index = 0;
/** @var Slide */
protected $slide;
/** @var AbstractComponent */
protected $component;
/**
*
* @param Slide $slide
* @param AbstractComponent $component
* @param array $componentsData
*/
public function __construct($slide, $component, $componentsData) {
$this->slide = $slide;
$this->component = $component;
if (is_array($componentsData)) {
if ($component->getType() == 'slide') {
$componentsData = array_reverse($componentsData);
}
foreach ($componentsData as $componentData) {
$this->addComponent($componentData);
}
}
}
private function addComponent($componentData) {
$this->index++;
if (!isset($componentData['type'])) {
$componentData['type'] = 'layer';
}
switch ($componentData['type']) {
case 'content':
$this->layers[] = new ComponentContent($this->index, $this->slide, $this->component, $componentData);
break;
case 'row':
$this->layers[] = new ComponentRow($this->index, $this->slide, $this->component, $componentData);
break;
case 'col':
$this->layers[] = new ComponentCol($this->index, $this->slide, $this->component, $componentData);
break;
case 'layer':
try {
if (empty($componentData['item'])) {
if (empty($componentData['items'])) {
$this->index--;
break;
}
$componentData['item'] = $componentData['items'][0];
}
$layer = new ComponentLayer($this->index, $this->slide, $this->component, $componentData);
$this->layers[] = $layer;
} catch (Exception $e) {
$this->index--;
Notification::error($e->getMessage());
}
break;
case 'group':
$componentData['layers'] = array_reverse($componentData['layers']);
foreach ($componentData['layers'] as $subComponentData) {
$this->addComponent($subComponentData);
}
break;
}
}
public function addContentLayer($slide, $component) {
$content = false;
$layerCount = count($this->layers);
for ($i = 0; $i < $layerCount; $i++) {
if ($this->layers[$i] instanceof ComponentContent) {
$content = $this->layers[$i];
break;
}
}
if ($content === false) {
array_unshift($this->layers, new ComponentContent($layerCount + 1, $slide, $component, array(
'bgimage' => '',
'bgimagex' => 50,
'bgimagey' => 50,
'bgcolor' => '00000000',
'bgcolorgradient' => 'off',
'verticalalign' => 'center',
'desktopportraitinneralign' => 'inherit',
'desktopportraitpadding' => '10|*|10|*|10|*|10|*|px',
'layers' => array()
), 'absolute'));
}
return $content;
}
/**
* @return AbstractComponent[]
*/
public function getLayers() {
return $this->layers;
}
public function render($isAdmin) {
$html = '';
foreach ($this->layers as $layer) {
$html .= $layer->render($isAdmin);
}
return $html;
}
}

View File

@ -0,0 +1,230 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Font\FontParser;
use Nextend\Framework\Form\ContainerInterface;
use Nextend\Framework\Model\Section;
use Nextend\Framework\Pattern\GetAssetsPathTrait;
use Nextend\Framework\Pattern\OrderableTrait;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\Framework\Style\StyleParser;
use Nextend\SmartSlider3\BackupSlider\ExportSlider;
use Nextend\SmartSlider3\BackupSlider\ImportSlider;
use Nextend\SmartSlider3\Renderable\AbstractRenderableOwner;
use Nextend\SmartSlider3\Slider\Admin\AdminSlider;
abstract class AbstractItem {
use GetAssetsPathTrait, OrderableTrait;
protected $layerProperties = array();
protected $fonts = array();
protected $styles = array();
/**
* AbstractItem constructor.
*
* @param ItemFactory $factory
*/
public function __construct($factory) {
$this->initDefault();
$factory->addItem($this);
}
private function initDefault() {
foreach ($this->fonts as &$fontData) {
$this->loadDefaultFont($fontData['defaultName'], $fontData['value']);
}
foreach ($this->styles as &$styleData) {
$this->loadDefaultStyle($styleData['defaultName'], $styleData['value']);
}
}
protected function loadDefaultFont($name, &$value) {
$res = Section::get('smartslider', 'default', $name);
if (is_array($res)) {
$value = $res['value'];
}
$value = FontParser::parse($value);
}
protected function loadDefaultStyle($name, &$value) {
$res = Section::get('smartslider', 'default', $name);
if (is_array($res)) {
$value = $res['value'];
}
$value = StyleParser::parse($value);
}
/**
* @param $id
* @param $itemData
* @param $layer
*
* @return AbstractItemFrontend
*/
public abstract function createFrontend($id, $itemData, $layer);
/**
* @return string
*/
public abstract function getTitle();
/**
* @return string
*/
public abstract function getIcon();
/**
* @return string
*/
public function getGroup() {
return n2_x('Basic', 'Layer group');
}
public function getLayerProperties() {
return $this->layerProperties;
}
public function isLegacy() {
return false;
}
public function getValues() {
$values = array();
foreach ($this->fonts as $name => $fontData) {
$values[$name] = $fontData['value'];
}
foreach ($this->styles as $name => $styleData) {
$values[$name] = $styleData['value'];
}
return $values;
}
/**
* @param $slide AbstractRenderableOwner
* @param $data Data
*
* @return Data
*/
public function getFilled($slide, $data) {
$this->upgradeData($data);
return $data;
}
/**
* @param Data $data
*/
public function upgradeData($data) {
}
/**
* Fix linked fonts/styles for the editor
*
* @param Data $data
*/
public function adminNormalizeFontsStyles($data) {
foreach ($this->fonts as $name => $fontData) {
$data->set($name, FontParser::parse($data->get($name)));
}
foreach ($this->styles as $name => $styleData) {
$data->set($name, StyleParser::parse($data->get($name)));
}
}
/**
* @param ExportSlider $export
* @param Data $data
*/
public function prepareExport($export, $data) {
$this->upgradeData($data);
}
/**
* @param ImportSlider $import
* @param Data $data
*
* @return Data
*/
public function prepareImport($import, $data) {
$this->upgradeData($data);
return $data;
}
/**
* @param Data $data
*
* @return Data
*/
public function prepareSample($data) {
$this->upgradeData($data);
return $data;
}
public function fixImage($image) {
return ResourceTranslator::toUrl($image);
}
public function fixLightbox($url) {
preg_match('/^([a-zA-Z]+)\[(.*)](.*)/', $url, $matches);
if (!empty($matches) && $matches[1] == 'lightbox') {
$images = explode(',', $matches[2]);
$newImages = array();
foreach ($images as $image) {
$newImages[] = ResourceTranslator::toUrl($image);
}
$url = 'lightbox[' . implode(',', $newImages) . ']' . $matches[3];
}
return $url;
}
/**
* @param AdminSlider $renderable
*/
public function loadResources($renderable) {
}
/**
* @return string
*/
public abstract function getType();
protected function isBuiltIn() {
return false;
}
/**
* @param ContainerInterface $container
*/
public abstract function renderFields($container);
/**
* @param ContainerInterface $container
*/
public function globalDefaultItemFontAndStyle($container) {
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Parser\Link;
use Nextend\Framework\Pattern\GetAssetsPathTrait;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\Component\ComponentLayer;
abstract class AbstractItemFrontend {
use GetAssetsPathTrait;
/** @var AbstractItem */
protected $item;
protected $id;
/** @var ComponentLayer */
protected $layer;
/** @var Data */
public $data;
protected $isEditor = false;
/**
*
* @param AbstractItem $item
* @param string $id
* @param array $itemData
* @param ComponentLayer $layer
*/
public function __construct($item, $id, $itemData, $layer) {
$this->item = $item;
$this->id = $id;
$this->data = new Data($itemData);
$this->layer = $layer;
$this->fillDefault($item->getValues());
}
private function fillDefault($defaults) {
$this->item->upgradeData($this->data);
$this->data->fillDefault($defaults);
}
public abstract function render();
public function renderAdmin() {
$this->isEditor = true;
/**
* Fix linked fonts/styles for the editor
*/
$this->item->adminNormalizeFontsStyles($this->data);
$rendered = $this->renderAdminTemplate();
$json = $this->data->toJson();
return Html::tag("div", array(
"class" => "n2-ss-item n2-ss-item-" . $this->item->getType(),
"data-item" => $this->item->getType(),
"data-itemvalues" => $json
), $rendered);
}
protected abstract function renderAdminTemplate();
public function needHeight() {
return false;
}
public function isAuto() {
return false;
}
protected function hasLink() {
$link = $this->data->get('href', '#');
if (($link != '#' && !empty($link))) {
return true;
}
return false;
}
protected function getLink($content, $attributes = array(), $renderEmpty = false) {
$link = $this->data->get('href', '#');
$target = $this->data->get('href-target', '#');
$rel = $this->data->get('href-rel', '#');
$class = $this->data->get('href-class', '');
if (($link != '#' && !empty($link)) || $renderEmpty === true) {
$link = Link::parse($this->layer->getOwner()
->fill($link), $attributes, $this->isEditor);
if (!empty($target) && $target != '_self') {
$attributes['target'] = $target;
}
if (!empty($rel)) {
$attributes['rel'] = $rel;
}
if (!empty($class)) {
$attributes['class'] = $class;
}
return Html::link($content, $link, $attributes);
}
return $content;
}
}

View File

@ -0,0 +1,172 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Button;
use Nextend\Framework\Form\Container\ContainerTable;
use Nextend\Framework\Form\Element\Font;
use Nextend\Framework\Form\Element\Hidden\HiddenFont;
use Nextend\Framework\Form\Element\Hidden\HiddenStyle;
use Nextend\Framework\Form\Element\Icon;
use Nextend\Framework\Form\Element\OnOff;
use Nextend\Framework\Form\Element\Select;
use Nextend\Framework\Form\Element\Select\LinkTarget;
use Nextend\Framework\Form\Element\Style;
use Nextend\Framework\Form\Element\Text;
use Nextend\Framework\Form\Element\Text\NumberSlider;
use Nextend\Framework\Form\Element\Text\Url;
use Nextend\Framework\Form\Fieldset;
use Nextend\Framework\Parser\Common;
use Nextend\SmartSlider3\Renderable\Item\AbstractItem;
class ItemButton extends AbstractItem {
protected $ordering = 4;
protected $fonts = array(
'font' => array(
'defaultName' => 'item-button-font',
'value' => '{"data":[{"color":"ffffffff","size":"14||px","align":"center"}, {"extra":""}]}'
)
);
protected $styles = array(
'style' => array(
'defaultName' => 'item-button-style',
'value' => '{"data":[{"backgroundcolor":"5cba3cff","padding":"10|*|30|*|10|*|30|*|px"}, {"extra":""}]}'
)
);
protected function isBuiltIn() {
return true;
}
public function getType() {
return 'button';
}
public function getTitle() {
return n2_('Button');
}
public function getIcon() {
return 'ssi_32 ssi_32--button';
}
public function createFrontend($id, $itemData, $layer) {
return new ItemButtonFrontend($this, $id, $itemData, $layer);
}
public function globalDefaultItemFontAndStyle($container) {
$table = new ContainerTable($container, $this->getType(), $this->getTitle());
$row1 = $table->createRow($this->getType() . '-1');
new Font($row1, 'item-button-font', false, $this->fonts['font']['value'], array(
'mode' => 'link'
));
new Style($row1, 'item-button-style', false, $this->styles['style']['value'], array(
'mode' => 'button'
));
}
public function getValues() {
return parent::getValues() + array(
'content' => n2_x('MORE', 'Button layer default text'),
'nowrap' => 1,
'fullwidth' => 0,
'href' => '#',
'href-target' => '_self',
'href-rel' => '',
'class' => '',
'icon' => '',
'iconsize' => '100',
'iconspacing' => '30',
'iconplacement' => 'left',
);
}
public function upgradeData($data) {
$linkV1 = $data->get('link', '');
if (!empty($linkV1)) {
list($link, $target, $rel) = array_pad((array)Common::parse($linkV1), 3, '');
$data->un_set('link');
$data->set('href', $link);
$data->set('href-target', $target);
$data->set('href-rel', $rel);
}
}
public function getFilled($slide, $data) {
$data = parent::getFilled($slide, $data);
$data->set('content', $slide->fill($data->get('content', '')));
$data->set('href', $slide->fill($data->get('href', '#|*|')));
return $data;
}
public function prepareExport($export, $data) {
parent::prepareExport($export, $data);
$export->addVisual($data->get('font'));
$export->addVisual($data->get('style'));
$export->addLightbox($data->get('href'));
}
public function prepareImport($import, $data) {
$data = parent::prepareImport($import, $data);
$data->set('font', $import->fixSection($data->get('font')));
$data->set('style', $import->fixSection($data->get('style')));
$data->set('href', $import->fixLightbox($data->get('href')));
return $data;
}
public function loadResources($renderable) {
parent::loadResources($renderable);
$renderable->addLess(self::getAssetsPath() . "/button.n2less", array(
"sliderid" => $renderable->elementId
));
}
public function renderFields($container) {
$settings = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-button', n2_('General'));
new Text($settings, 'content', n2_('Label'), n2_('Button'), array(
'style' => 'width:302px;'
));
new HiddenFont($settings, 'font', false, '', array(
'mode' => 'link'
));
new HiddenStyle($settings, 'style', false, '', array(
'mode' => 'button'
));
new OnOff($settings, 'fullwidth', n2_('Full width'), 1);
new OnOff($settings, 'nowrap', n2_('No wrap'), 1, array(
'tipLabel' => n2_('No wrap'),
'tipDescription' => n2_('Prevents the text from breaking into more lines')
));
$link = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-button-link', n2_('Link'));
new Url($link, 'href', n2_('Link'), '', array(
'relatedFields' => array(
'item_buttonhref-target',
'item_buttonhref-rel'
),
'width' => 248
));
new LinkTarget($link, 'href-target', n2_('Target window'));
new Text($link, 'href-rel', n2_('Rel'), '', array(
'style' => 'width:195px;',
'tipLabel' => n2_('Rel'),
'tipDescription' => sprintf(n2_('Enter the %1$s rel attribute %2$s that represents the relationship between the current document and the linked document. Multiple rel attributes can be separated with space. E.g. nofollow noopener noreferrer'), '<a href="https://www.w3schools.com/TAGS/att_a_rel.asp" target="_blank">', '</a>')
));
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Button;
use Nextend\Framework\Icon\Icon;
use Nextend\Framework\Sanitize;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\AbstractRenderableOwner;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
class ItemButtonFrontend extends AbstractItemFrontend {
public function render() {
return $this->getHtml();
}
public function renderAdminTemplate() {
return $this->getHtml();
}
private function getHtml() {
$owner = $this->layer->getOwner();
$this->loadResources($owner);
$font = $owner->addFont($this->data->get('font'), 'link');
$html = Html::openTag("div", array(
"class" => "n2-ss-button-container n2-ss-item-content n2-ow " . $font . ($this->data->get('nowrap', 1) ? ' n2-ss-nowrap' : '') . ($this->isAuto() ? ' n2-ss-button-container--non-full-width' : '')
));
$content = '<div>' . Sanitize::filter_allowed_html($owner->fill($this->data->get("content"))) . '</div>';
$attrs = array();
$style = $owner->addStyle($this->data->get('style'), 'heading');
$html .= $this->getLink('<div>' . $content . '</div>', $attrs + array(
"class" => "{$style} n2-ow " . $owner->fill($this->data->get('class', ''))
), true);
$html .= Html::closeTag("div");
return $html;
}
/**
* @param AbstractRenderableOwner $owner
*/
public function loadResources($owner) {
$owner->addLess(self::getAssetsPath() . "/button.n2less", array(
"sliderid" => $owner->getElementID()
));
}
public function isAuto() {
return !$this->data->get('fullwidth', 0);
}
}

View File

@ -0,0 +1,193 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Heading;
use Nextend\Framework\Form\Container\ContainerTable;
use Nextend\Framework\Form\Element\Font;
use Nextend\Framework\Form\Element\Hidden\HiddenFont;
use Nextend\Framework\Form\Element\Hidden\HiddenStyle;
use Nextend\Framework\Form\Element\MixedField;
use Nextend\Framework\Form\Element\OnOff;
use Nextend\Framework\Form\Element\Select;
use Nextend\Framework\Form\Element\Select\LinkTarget;
use Nextend\Framework\Form\Element\Style;
use Nextend\Framework\Form\Element\Text;
use Nextend\Framework\Form\Element\Text\Number;
use Nextend\Framework\Form\Element\Text\NumberAutoComplete;
use Nextend\Framework\Form\Element\Text\Url;
use Nextend\Framework\Form\Element\Textarea;
use Nextend\Framework\Form\Fieldset;
use Nextend\Framework\Parser\Common;
use Nextend\SmartSlider3\Renderable\Item\AbstractItem;
use Nextend\SmartSlider3Pro\Form\Element\SplitTextAnimation;
class ItemHeading extends AbstractItem {
protected $ordering = 1;
protected $fonts = array(
'font' => array(
'defaultName' => 'item-heading-font',
'value' => '{"data":[{"color":"ffffffff","size":"36||px","align":"inherit"},{"extra":""}]}'
)
);
protected $styles = array(
'style' => array(
'defaultName' => 'item-heading-style',
'value' => ''
)
);
protected function isBuiltIn() {
return true;
}
public function getType() {
return 'heading';
}
public function getTitle() {
return n2_('Heading');
}
public function getIcon() {
return 'ssi_32 ssi_32--heading';
}
public function createFrontend($id, $itemData, $layer) {
return new ItemHeadingFrontend($this, $id, $itemData, $layer);
}
public function getValues() {
return parent::getValues() + array(
'priority' => 'div',
'fullwidth' => 1,
'nowrap' => 0,
'heading' => n2_('Heading layer'),
'title' => '',
'href' => '#',
'href-target' => '_self',
'href-rel' => '',
'split-text-transform-origin' => '50|*|50|*|0',
'split-text-backface-visibility' => 1,
'split-text-animation-in' => '',
'split-text-delay-in' => 0,
'split-text-animation-out' => '',
'split-text-delay-out' => 0,
'class' => ''
);
}
public function upgradeData($data) {
$linkV1 = $data->get('link', '');
if (!empty($linkV1)) {
list($link, $target, $rel) = array_pad((array)Common::parse($linkV1), 3, '');
$data->un_set('link');
if (is_array($link)) {
$data->set('href', implode('', $link));
} else {
$data->set('href', $link);
}
$data->set('href-target', $target);
$data->set('href-rel', $rel);
}
}
public function getFilled($slide, $data) {
$data = parent::getFilled($slide, $data);
$data->set('heading', $slide->fill($data->get('heading', '')));
$data->set('href', $slide->fill($data->get('href', '#|*|')));
return $data;
}
public function prepareExport($export, $data) {
parent::prepareExport($export, $data);
$export->addVisual($data->get('font'));
$export->addVisual($data->get('style'));
$export->addLightbox($data->get('href'));
}
public function prepareImport($import, $data) {
$data = parent::prepareImport($import, $data);
$data->set('font', $import->fixSection($data->get('font')));
$data->set('style', $import->fixSection($data->get('style')));
$data->set('href', $import->fixLightbox($data->get('href')));
return $data;
}
public function globalDefaultItemFontAndStyle($container) {
$table = new ContainerTable($container, $this->getType(), $this->getTitle());
$row1 = $table->createRow($this->getType() . '-1');
new Font($row1, 'item-heading-font', false, $this->fonts['font']['value'], array(
'mode' => 'hover'
));
new Style($row1, 'item-heading-style', false, $this->styles['style']['value'], array(
'mode' => 'heading'
));
}
public function renderFields($container) {
$settings = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-heading', n2_('General'));
new Textarea($settings, 'heading', n2_('Text'), n2_('Heading'), array(
'width' => 314
));
new Select($settings, 'priority', 'Tag', 'div', array(
'options' => array(
'div' => 'div',
'1' => 'H1',
'2' => 'H2',
'3' => 'H3',
'4' => 'H4',
'5' => 'H5',
'6' => 'H6'
)
));
new OnOff($settings, 'fullwidth', n2_('Full width'), 1);
new OnOff($settings, 'nowrap', n2_('No wrap'), 0, array(
'tipLabel' => n2_('No wrap'),
'tipDescription' => n2_('Prevents the text from breaking into more lines')
));
$link = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-heading-link', n2_('Link'));
new Url($link, 'href', n2_('Link'), '', array(
'width' => 248,
'relatedFields' => array(
'item_headinghref-target',
'item_headinghref-rel'
)
));
new LinkTarget($link, 'href-target', n2_('Target window'));
new Text($link, 'href-rel', n2_('Rel'), '', array(
'style' => 'width:195px;',
'tipLabel' => n2_('Rel'),
'tipDescription' => sprintf(n2_('Enter the %1$s rel attribute %2$s that represents the relationship between the current document and the linked document. Multiple rel attributes can be separated with space. E.g. nofollow noopener noreferrer'), '<a href="https://www.w3schools.com/TAGS/att_a_rel.asp" target="_blank">', '</a>')
));
new HiddenFont($settings, 'font', false, '', array(
'mode' => 'hover'
));
new HiddenStyle($settings, 'style', false, '', array(
'mode' => 'heading'
));
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Heading;
use Nextend\Framework\Misc\Base64;
use Nextend\Framework\Sanitize;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
class ItemHeadingFrontend extends AbstractItemFrontend {
public function render() {
return $this->getHtml();
}
private function getHtml() {
$owner = $this->layer->getOwner();
$attributes = array();
$font = $owner->addFont($this->data->get('font'), 'hover');
$style = $owner->addStyle($this->data->get('style'), 'heading');
$linkAttributes = array(
'class' => 'n2-ow'
);
if ($this->isEditor) {
$linkAttributes['onclick'] = 'return false;';
}
$title = $this->data->get('title', '');
if (!empty($title)) {
$attributes['title'] = $title;
}
$href = $this->data->get('href', '');
if (!empty($href) && $href != '#') {
$linkAttributes['class'] .= ' ' . $font . $style;
$font = '';
$style = '';
}
$linkAttributes['style'] = "display:" . ($this->data->get('fullwidth', 1) ? 'block' : 'inline-block') . ";";
$strippedHtml = Sanitize::filter_allowed_html($owner->fill($this->data->get('heading', '')));
return $this->heading($this->data->get('priority', 'div'), $attributes + array(
"id" => $this->id,
"class" => $font . $style . " " . $owner->fill($this->data->get('class', '')) . ' n2-ss-item-content n2-ss-text n2-ow',
"style" => "display:" . ($this->data->get('fullwidth', 1) ? 'block' : 'inline-block') . ";" . ($this->data->get('nowrap', 0) ? 'white-space:nowrap;' : '')
), $this->getLink(str_replace("\n", '<br>', $strippedHtml), $linkAttributes));
}
private function heading($type, $attributes, $content) {
if (is_numeric($type) && $type > 0) {
return Html::tag("h{$type}", $attributes, $content);
}
return Html::tag("div", $attributes, $content);
}
public function renderAdminTemplate() {
return $this->getHtml();
}
public function isAuto() {
return !$this->data->get('fullwidth', 1);
}
}

View File

@ -0,0 +1,179 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Image;
use Nextend\Framework\Form\Container\ContainerTable;
use Nextend\Framework\Form\Element\Hidden;
use Nextend\Framework\Form\Element\MixedField;
use Nextend\Framework\Form\Element\OnOff;
use Nextend\Framework\Form\Element\Select\LinkTarget;
use Nextend\Framework\Form\Element\Style;
use Nextend\Framework\Form\Element\Text;
use Nextend\Framework\Form\Element\Text\FieldImage;
use Nextend\Framework\Form\Element\Text\Url;
use Nextend\Framework\Form\Fieldset;
use Nextend\Framework\Parser\Common;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\SmartSlider3\Renderable\Item\AbstractItem;
class ItemImage extends AbstractItem {
protected $ordering = 3;
protected $layerProperties = array("desktopportraitwidth" => "300");
protected $styles = array(
'style' => array(
'defaultName' => 'item-image-style',
'value' => ''
)
);
protected function isBuiltIn() {
return true;
}
public function getType() {
return 'image';
}
public function getTitle() {
return n2_('Image');
}
public function getIcon() {
return 'ssi_32 ssi_32--image';
}
public function createFrontend($id, $itemData, $layer) {
return new ItemImageFrontend($this, $id, $itemData, $layer);
}
public function globalDefaultItemFontAndStyle($container) {
$table = new ContainerTable($container, $this->getType(), $this->getTitle());
$row1 = $table->createRow($this->getType() . '-1');
new Style($row1, 'item-image-style', false, $this->styles['style']['value'], array(
'mode' => 'box'
));
}
public function getValues() {
return parent::getValues() + array(
'image' => '$ss3-frontend$/images/placeholder/image.png',
'alt' => '',
'title' => '',
'href' => '#',
'href-target' => '_self',
'href-rel' => '',
'href-class' => '',
'size' => 'auto|*|auto',
'cssclass' => '',
'image-optimize' => 1
);
}
public function upgradeData($data) {
$linkV1 = $data->get('link', '');
if (!empty($linkV1)) {
list($link, $target, $rel) = array_pad((array)Common::parse($linkV1), 3, '');
$data->un_set('link');
$data->set('href', $link);
$data->set('href-target', $target);
$data->set('href-rel', $rel);
}
}
public function getFilled($slide, $data) {
$data = parent::getFilled($slide, $data);
$data->set('image', $slide->fill($data->get('image', '')));
$data->set('alt', $slide->fill($data->get('alt', '')));
$data->set('title', $slide->fill($data->get('title', '')));
$data->set('href', $slide->fill($data->get('href', '#|*|')));
return $data;
}
public function prepareExport($export, $data) {
parent::prepareExport($export, $data);
$export->addImage($data->get('image'));
$export->addVisual($data->get('style'));
$export->addLightbox($data->get('href'));
}
public function prepareImport($import, $data) {
$data = parent::prepareImport($import, $data);
$data->set('image', $import->fixImage($data->get('image')));
$data->set('style', $import->fixSection($data->get('style')));
$data->set('href', $import->fixLightbox($data->get('href')));
return $data;
}
public function prepareSample($data) {
$data->set('image', ResourceTranslator::toUrl($data->get('image')));
return $data;
}
public function renderFields($container) {
$settings = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-image', n2_('General'));
new FieldImage($settings, 'image', n2_('Image'), '', array(
'relatedAlt' => 'item_imagealt',
'width' => 220
));
$link = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-image-link', n2_('Link'));
new Url($link, 'href', n2_('Link'), '', array(
'style' => 'width:236px;',
'relatedFields' => array(
'item_imagehref-target',
'item_imagehref-rel'
),
'width' => 248
));
new LinkTarget($link, 'href-target', n2_('Target window'));
new Text($link, 'href-rel', n2_('Rel'), '', array(
'style' => 'width:195px;',
'tipLabel' => n2_('Rel'),
'tipDescription' => sprintf(n2_('Enter the %1$s rel attribute %2$s that represents the relationship between the current document and the linked document. Multiple rel attributes can be separated with space. E.g. nofollow noopener noreferrer'), '<a href="https://www.w3schools.com/TAGS/att_a_rel.asp" target="_blank">', '</a>')
));
$size = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-image-misc', n2_('Size'));
$misc = new MixedField($size, 'size', false, 'auto|*|auto');
new Text($misc, 'size-1', n2_('Width'), '', array(
'style' => 'width:60px;',
'tipLabel' => n2_('Width'),
'tipDescription' => sprintf(n2_('Fix width for the %1$s.'), $this->getTitle())
));
new Text($misc, 'size-2', n2_('Height'), '', array(
'style' => 'width:60px;',
'tipLabel' => n2_('Height'),
'tipDescription' => sprintf(n2_('Fix height for the %1$s.'), $this->getTitle())
));
$seo = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-image-seo', n2_('SEO'));
new Text($seo, 'alt', 'SEO - ' . n2_('Alt tag'), '', array(
'style' => 'width:133px;'
));
new Text($seo, 'title', 'SEO - ' . n2_('Title'), '', array(
'style' => 'width:133px;'
));
$dev = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-image-dev', n2_('Advanced'));
new Text($dev, 'href-class', n2_('CSS Class') . ' - ' . n2_('Link'), '', array(
'tipLabel' => n2_('CSS Class'),
'tipDescription' => sprintf(n2_('Class on the %s element.'), '&lt;a&gt;'),
'tipLink' => 'https://smartslider.helpscoutdocs.com/article/1833-image-layer#advanced',
'style' => 'width:133px;'
));
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Image;
use Nextend\Framework\Parser\Common;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
class ItemImageFrontend extends AbstractItemFrontend {
public function render() {
return $this->getHtml();
}
public function renderAdminTemplate() {
return $this->getHtml();
}
private function getHtml() {
$owner = $this->layer->getOwner();
$styles = array();
$linkStyles = array();
$size = (array)Common::parse($this->data->get('size', ''));
for ($i = 0; $i < 2; $i++) {
if (is_numeric($size[$i])) {
$size[$i] = $size[$i] . 'px';
}
}
if (!empty($size[0]) && $size[0] != 'auto') {
$styles[] = 'width:' . $size[0];
if ($this->hasLink() && substr($size[0], -1) == '%') {
$linkStyles[] = 'width:100%';
}
if (empty($size[1]) || $size[1] == 'auto') {
$styles[] = 'height:auto';
}
}
if (!empty($size[1]) && $size[1] != 'auto') {
if (empty($size[0]) || $size[0] == 'auto') {
$styles[] = 'width:auto';
}
$styles[] = 'height:' . $size[1];
}
$imageUrl = $this->data->get('image', '');
if (empty($imageUrl)) {
return '';
}
$image = $owner->fill($this->data->get('image', ''));
$imageAttributes = array(
"id" => $this->id,
"alt" => $owner->fill($this->data->get('alt', '')),
"class" => $owner->fill($this->data->get('cssclass', ''))
);
if (!empty($styles)) {
$imageAttributes['style'] = implode(';', $styles);
}
$linkAttributes = array();
if (!empty($linkStyles)) {
$linkAttributes['style'] = implode(';', $linkStyles);
}
$title = $owner->fill($this->data->get('title', ''));
if (!empty($title)) {
$imageAttributes['title'] = $title;
}
$html = $owner->renderImage($this, $image, $imageAttributes);
$style = $owner->addStyle($this->data->get('style'), 'heading');
return Html::tag("div", array(
"class" => $style . ' n2-ss-item-image-content n2-ss-item-content n2-ow-all'
), $this->getLink($html, $linkAttributes));
}
}

View File

@ -0,0 +1,192 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item;
use Exception;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Pattern\OrderableTrait;
use Nextend\Framework\Pattern\PluggableTrait;
use Nextend\Framework\Pattern\SingletonTrait;
use Nextend\SmartSlider3\BackupSlider\ExportSlider;
use Nextend\SmartSlider3\BackupSlider\ImportSlider;
use Nextend\SmartSlider3\Renderable\AbstractRenderableOwner;
use Nextend\SmartSlider3\Renderable\Component\ComponentLayer;
use Nextend\SmartSlider3\Renderable\Item\Button\ItemButton;
use Nextend\SmartSlider3\Renderable\Item\Heading\ItemHeading;
use Nextend\SmartSlider3\Renderable\Item\Image\ItemImage;
use Nextend\SmartSlider3\Renderable\Item\Missing\ItemMissing;
use Nextend\SmartSlider3\Renderable\Item\Text\ItemText;
use Nextend\SmartSlider3\Renderable\Item\Vimeo\ItemVimeo;
use Nextend\SmartSlider3\Renderable\Item\YouTube\ItemYouTube;
class ItemFactory {
use SingletonTrait, PluggableTrait, OrderableTrait;
public static $i = array();
/** @var AbstractItem[][] */
private static $itemGroups = array();
/**
* @var AbstractItem[]
*/
private static $items = array();
/**
* @return AbstractItem[]
*/
public static function getItems() {
return self::$items;
}
/**
* @param $type
*
* @return AbstractItem
*/
public static function getItem($type) {
return self::$items[$type];
}
/**
* @return AbstractItem[][]
*/
public static function getItemGroups() {
return self::$itemGroups;
}
/**
* @param ComponentLayer $layer
* @param array $itemData
*
* @return AbstractItemFrontend
* @throws Exception
*/
public static function create($layer, $itemData) {
if (!isset($itemData['type'])) {
throw new Exception('Error with itemData: ' . $itemData);
}
$type = $itemData['type'];
if ($type == 'missing') {
$type = $itemData['values']['type'];
}
if (!isset(self::$items[$type])) {
$itemData['values']['type'] = $type;
$type = 'missing';
}
/** @var AbstractItem $factory */
$factory = self::$items[$type];
$elementID = $layer->getOwner()
->getElementID();
if (!isset(self::$i[$elementID])) {
self::$i[$elementID] = 0;
}
self::$i[$elementID]++;
$id = $elementID . 'item' . self::$i[$elementID];
return $factory->createFrontend($id, $itemData['values'], $layer);
}
/**
* @param AbstractRenderableOwner $slide
* @param array $item
*/
public static function getFilled($slide, &$item) {
$type = $item['type'];
if (isset(self::$items[$type])) {
$item['values'] = self::$items[$type]->getFilled($slide, new Data($item['values']))
->toArray();
}
}
/**
* @param ExportSlider $export
* @param $item
*/
public static function prepareExport($export, $item) {
$type = $item['type'];
if (isset(self::$items[$type])) {
self::$items[$type]->prepareExport($export, new Data($item['values']));
}
}
/**
* @param ImportSlider $import
* @param $item
*
* @return mixed
*/
public static function prepareImport($import, $item) {
$type = $item['type'];
if (isset(self::$items[$type])) {
$item['values'] = self::$items[$type]->prepareImport($import, new Data($item['values']))
->toArray();
}
return $item;
}
public static function prepareSample($item) {
$type = $item['type'];
if (isset(self::$items[$type])) {
$item['values'] = self::$items[$type]->prepareSample(new Data($item['values']))
->toArray();
}
return $item;
}
/**
* @param AbstractItem $item
*/
public function addItem($item) {
self::$items[$item->getType()] = $item;
}
protected function init() {
new ItemHeading($this);
new ItemButton($this);
new ItemImage($this);
new ItemText($this);
new ItemVimeo($this);
new ItemYouTube($this);
$this->makePluggable('RenderableItem');
self::uasort(self::$items);
self::$itemGroups[n2_x('Basic', 'Layer group')] = array();
self::$itemGroups[n2_x('Media', 'Layer group')] = array();
foreach (self::$items as $type => $item) {
$group = $item->getGroup();
if (!isset(self::$itemGroups[$group])) {
self::$itemGroups[$group] = array();
}
self::$itemGroups[$group][$type] = $item;
}
new ItemMissing($this);
}
}
ItemFactory::getInstance();

View File

@ -0,0 +1,28 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Missing;
use Nextend\SmartSlider3\Renderable\Item\AbstractItem;
class ItemMissing extends AbstractItem {
public function createFrontend($id, $itemData, $layer) {
return new ItemMissingFrontend($this, $id, $itemData, $layer);
}
public function getTitle() {
return n2_x('Missing', 'Layer');
}
public function getIcon() {
return '';
}
public function getType() {
return 'missing';
}
public function renderFields($container) {
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Missing;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
class ItemMissingFrontend extends AbstractItemFrontend {
public function render() {
return '';
}
protected function renderAdminTemplate() {
return '<div>' . sprintf(n2_('Missing layer type: %s'), $this->data->get('type')) . '</div>';
}
}

View File

@ -0,0 +1,169 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Text;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Form\Container\ContainerTable;
use Nextend\Framework\Form\Element\Font;
use Nextend\Framework\Form\Element\Hidden\HiddenFont;
use Nextend\Framework\Form\Element\Hidden\HiddenStyle;
use Nextend\Framework\Form\Element\OnOff;
use Nextend\Framework\Form\Element\RichTextarea;
use Nextend\Framework\Form\Element\Style;
use Nextend\Framework\Form\Fieldset;
use Nextend\SmartSlider3\Renderable\Item\AbstractItem;
class ItemText extends AbstractItem {
protected $ordering = 2;
protected $layerProperties = array(
"desktopportraitleft" => 0,
"desktopportraittop" => 0,
"desktopportraitwidth" => 400,
"desktopportraitalign" => "left",
"desktopportraitvalign" => "top"
);
protected $fonts = array(
'font' => array(
'defaultName' => 'item-text-font',
'value' => '{"data":[{"color":"ffffffff","size":"14||px","align":"inherit"},{"color":"1890d7ff"},{"color":"1890d7ff"}]}'
)
);
protected $styles = array(
'style' => array(
'defaultName' => 'item-text-style',
'value' => ''
)
);
protected function isBuiltIn() {
return true;
}
public function getType() {
return 'text';
}
public function getTitle() {
return n2_('Text');
}
public function getIcon() {
return 'ssi_32 ssi_32--text';
}
public function createFrontend($id, $itemData, $layer) {
return new ItemTextFrontend($this, $id, $itemData, $layer);
}
public function globalDefaultItemFontAndStyle($container) {
$table = new ContainerTable($container, $this->getType(), $this->getTitle());
$row1 = $table->createRow($this->getType() . '-1');
new Font($row1, 'item-text-font', false, $this->fonts['font']['value'], array(
'mode' => 'paragraph'
));
new Style($row1, 'item-text-style', false, $this->styles['style']['value'], array(
'mode' => 'heading'
));
}
public function getValues() {
return parent::getValues() + array(
'content' => 'Lorem ipsum dolor sit amet, <a href="#">consectetur adipiscing</a> elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
'content-tablet-enabled' => 0,
'contenttablet' => '',
'content-mobile-enabled' => 0,
'contentmobile' => ''
);
}
/**
* @param Data $data
*/
public function upgradeData($data) {
if (!$data->has('content-tablet-enabled')) {
if ($data->get('contenttablet', '') != '') {
$data->set('content-tablet-enabled', 1);
}
}
if (!$data->has('content-mobile-enabled')) {
if ($data->get('contentmobile', '') != '') {
$data->set('content-mobile-enabled', 1);
}
}
}
public function getFilled($slide, $data) {
$data = parent::getFilled($slide, $data);
$data->set('content', $slide->fill($data->get('content', '')));
$data->set('contenttablet', $slide->fill($data->get('contenttablet', '')));
$data->set('contentmobile', $slide->fill($data->get('contentmobile', '')));
return $data;
}
public function prepareExport($export, $data) {
parent::prepareExport($export, $data);
$export->addVisual($data->get('font'));
$export->addVisual($data->get('style'));
}
public function prepareImport($import, $data) {
$data = parent::prepareImport($import, $data);
$data->set('font', $import->fixSection($data->get('font')));
$data->set('style', $import->fixSection($data->get('style')));
return $data;
}
public function renderFields($container) {
$settings = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-text', n2_('General'));
new RichTextarea($settings, 'content', n2_('Text'), '', array(
'fieldStyle' => 'height: 120px; width: 314px;resize: vertical;'
));
new HiddenFont($settings, 'font', false, '', array(
'mode' => 'paragraph'
));
new HiddenStyle($settings, 'style', false, '', array(
'mode' => 'heading'
));
new OnOff($settings, 'content-tablet-enabled', n2_('Tablet'), 0, array(
'relatedFieldsOn' => array(
'item_textcontenttablet'
),
'tipLabel' => n2_('Tablet'),
'tipDescription' => n2_('Custom text for tablet')
));
new RichTextarea($settings, 'contenttablet', n2_('Tablet text'), '', array(
'fieldStyle' => 'height: 120px; width: 314px;resize: vertical;'
));
new OnOff($settings, 'content-mobile-enabled', n2_('Mobile'), 0, array(
'relatedFieldsOn' => array(
'item_textcontentmobile'
),
'tipLabel' => n2_('Mobile'),
'tipDescription' => n2_('Custom text for mobile')
));
new RichTextarea($settings, 'contentmobile', n2_('Mobile text'), '', array(
'fieldStyle' => 'height: 120px; width: 314px;resize: vertical;'
));
}
}

View File

@ -0,0 +1,432 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Text;
use Nextend\Framework\Platform\Platform;
use Nextend\Framework\Sanitize;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
use function Nextend\Framework\Sanitize;
class ItemTextFrontend extends AbstractItemFrontend {
public function render() {
return $this->getHtml();
}
public function renderAdminTemplate() {
return $this->getHtml();
}
private function getHTML() {
$owner = $this->layer->getOwner();
$font = $owner->addFont($this->data->get('font'), 'paragraph');
$style = $owner->addStyle($this->data->get('style'), 'heading');
$tagName = 'p';
if (Platform::needStrongerCSS()) {
$tagName = 'ss-p';
}
$html = '';
$content = str_replace(array(
'<p>',
'</p>'
), array(
'<' . $tagName . ' class="' . $font . ' ' . $style . ' ">',
'</' . $tagName . '>'
), $this->wpautop(Sanitize::filter_allowed_html($this->closeTags($owner->fill($this->data->get('content', ''))), '<p>')));
$class = '';
$hasMobile = false;
if ($this->data->get('content-mobile-enabled')) {
$hasMobile = true;
$html .= Html::tag('div', array(
'data-hide-desktoplandscape' => 1,
'data-hide-desktopportrait' => 1,
'data-hide-tabletlandscape' => 1,
'data-hide-tabletportrait' => 1
), str_replace(array(
'<p>',
'</p>'
), array(
'<' . $tagName . ' class="' . $font . ' ' . $style . ' ">',
'</' . $tagName . '>'
), $this->wpautop(Sanitize::filter_allowed_html($this->closeTags($owner->fill($this->data->get('contentmobile', ''))), '<p>'))));
}
$hasTablet = false;
if ($this->data->get('content-tablet-enabled')) {
$hasTablet = true;
$attributes = array(
'class' => $class,
'data-hide-desktoplandscape' => 1,
'data-hide-desktopportrait' => 1,
);
if ($hasMobile) {
$attributes['data-hide-mobilelandscape'] = 1;
$attributes['data-hide-mobileportrait'] = 1;
} else {
$hasMobile = true;
}
$html .= Html::tag('div', $attributes, str_replace(array(
'<p>',
'</p>'
), array(
'<' . $tagName . ' class="' . $font . ' ' . $style . '">',
'</' . $tagName . '>'
), $this->wpautop(Sanitize::filter_allowed_html($this->closeTags($owner->fill($this->data->get('contenttablet', '')))), '<p>')));
$class = '';
}
$attributes = array(
'class' => $class
);
if ($hasMobile) {
$attributes['data-hide-mobilelandscape'] = 1;
$attributes['data-hide-mobileportrait'] = 1;
}
if ($hasTablet) {
$attributes['data-hide-tabletlandscape'] = 1;
$attributes['data-hide-tabletportrait'] = 1;
}
$html .= Html::tag('div', $attributes, $content);
return Html::tag('div', array(
'class' => 'n2-ss-item-content n2-ss-text n2-ow-all'
), $html);
}
public function closeTags($html) {
$html = str_replace(array(
'<>',
'</>'
), array(
'',
''
), $html);
// Put all opened tags into an array
preg_match_all('#<([a-z]+)(?: .*)?(?<![/| ])>#iU', $html, $result);
$openedtags = $result[1]; #put all closed tags into an array
preg_match_all('#</([a-z]+)>#iU', $html, $result);
$closedtags = $result[1];
$len_opened = count($openedtags);
# Check if all tags are closed
if (count($closedtags) == $len_opened) {
return $html;
}
$openedtags = array_reverse($openedtags);
# close tags
for ($i = 0; $i < $len_opened; $i++) {
if (!in_array($openedtags[$i], $closedtags)) {
if ($openedtags[$i] != 'br') {
// Ignores <br> tags to avoid unnessary spacing
// at the end of the string
$html .= '</' . $openedtags[$i] . '>';
}
} else {
unset($closedtags[array_search($openedtags[$i], $closedtags)]);
}
}
return $html;
}
private function wpautop($pee, $br = true) {
$pre_tags = array();
if (trim($pee) === '') {
return '';
}
// Just to make things a little easier, pad the end.
$pee = $pee . "\n";
/*
* Pre tags shouldn't be touched by autop.
* Replace pre tags with placeholders and bring them back after autop.
*/
if (strpos($pee, '<pre') !== false) {
$pee_parts = explode('</pre>', $pee);
$last_pee = array_pop($pee_parts);
$pee = '';
$i = 0;
foreach ($pee_parts as $pee_part) {
$start = strpos($pee_part, '<pre');
// Malformed HTML?
if (false === $start) {
$pee .= $pee_part;
continue;
}
$name = "<pre wp-pre-tag-$i></pre>";
$pre_tags[$name] = substr($pee_part, $start) . '</pre>';
$pee .= substr($pee_part, 0, $start) . $name;
$i++;
}
$pee .= $last_pee;
}
// Change multiple <br>'s into two line breaks, which will turn into paragraphs.
$pee = preg_replace('|<br\s*/?>\s*<br\s*/?>|', "\n\n", $pee);
$allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)';
// Add a double line break above block-level opening tags.
$pee = preg_replace('!(<' . $allblocks . '[\s/>])!', "\n\n$1", $pee);
// Add a double line break below block-level closing tags.
$pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee);
// Add a double line break after hr tags, which are self closing.
$pee = preg_replace('!(<hr\s*?/?>)!', "$1\n\n", $pee);
// Standardize newline characters to "\n".
$pee = str_replace(array(
"\r\n",
"\r"
), "\n", $pee);
// Find newlines in all elements and add placeholders.
$pee = self::wp_replace_in_html_tags($pee, array("\n" => ' <!-- wpnl --> '));
// Collapse line breaks before and after <option> elements so they don't get autop'd.
if (strpos($pee, '<option') !== false) {
$pee = preg_replace('|\s*<option|', '<option', $pee);
$pee = preg_replace('|</option>\s*|', '</option>', $pee);
}
/*
* Collapse line breaks inside <object> elements, before <param> and <embed> elements
* so they don't get autop'd.
*/
if (strpos($pee, '</object>') !== false) {
$pee = preg_replace('|(<object[^>]*>)\s*|', '$1', $pee);
$pee = preg_replace('|\s*</object>|', '</object>', $pee);
$pee = preg_replace('%\s*(</?(?:param|embed)[^>]*>)\s*%', '$1', $pee);
}
/*
* Collapse line breaks inside <audio> and <video> elements,
* before and after <source> and <track> elements.
*/
if (strpos($pee, '<source') !== false || strpos($pee, '<track') !== false) {
$pee = preg_replace('%([<\[](?:audio|video)[^>\]]*[>\]])\s*%', '$1', $pee);
$pee = preg_replace('%\s*([<\[]/(?:audio|video)[>\]])%', '$1', $pee);
$pee = preg_replace('%\s*(<(?:source|track)[^>]*>)\s*%', '$1', $pee);
}
// Collapse line breaks before and after <figcaption> elements.
if (strpos($pee, '<figcaption') !== false) {
$pee = preg_replace('|\s*(<figcaption[^>]*>)|', '$1', $pee);
$pee = preg_replace('|</figcaption>\s*|', '</figcaption>', $pee);
}
// Remove more than two contiguous line breaks.
$pee = preg_replace("/\n\n+/", "\n\n", $pee);
// Split up the contents into an array of strings, separated by double line breaks.
$pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY);
// Reset $pee prior to rebuilding.
$pee = '';
// Rebuild the content as a string, wrapping every bit with a <p>.
foreach ($pees as $tinkle) {
$pee .= '<p>' . trim($tinkle, "\n") . "</p>\n";
}
// Under certain strange conditions it could create a P of entirely whitespace.
$pee = preg_replace('|<p>\s*</p>|', '', $pee);
// Add a closing <p> inside <div>, <address>, or <form> tag if missing.
$pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', '<p>$1</p></$2>', $pee);
// If an opening or closing block element tag is wrapped in a <p>, unwrap it.
$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', '$1', $pee);
// In some cases <li> may get wrapped in <p>, fix them.
$pee = preg_replace('|<p>(<li.+?)</p>|', '$1', $pee);
// If a <blockquote> is wrapped with a <p>, move it inside the <blockquote>.
$pee = preg_replace('|<p><blockquote([^>]*)>|i', '<blockquote$1><p>', $pee);
$pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
// If an opening or closing block element tag is preceded by an opening <p> tag, remove it.
$pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', '$1', $pee);
// If an opening or closing block element tag is followed by a closing <p> tag, remove it.
$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', '$1', $pee);
// Optionally insert line breaks.
if ($br) {
// Replace newlines that shouldn't be touched with a placeholder.
$pee = preg_replace_callback('/<(script|style|svg).*?<\/\\1>/s', array(
$this,
'_autop_newline_preservation_helper'
), $pee);
// Normalize <br>
$pee = str_replace(array(
'<br>',
'<br/>'
), '<br />', $pee);
// Replace any new line characters that aren't preceded by a <br /> with a <br />.
$pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee);
// Replace newline placeholders with newlines.
$pee = str_replace('<WPPreserveNewline />', "\n", $pee);
}
// If a <br /> tag is after an opening or closing block tag, remove it.
$pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', '$1', $pee);
// If a <br /> tag is before a subset of opening or closing block tags, remove it.
$pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee);
$pee = preg_replace("|\n</p>$|", '</p>', $pee);
// Replace placeholder <pre> tags with their original content.
if (!empty($pre_tags)) {
$pee = str_replace(array_keys($pre_tags), array_values($pre_tags), $pee);
}
// Restore newlines in all elements.
if (false !== strpos($pee, '<!-- wpnl -->')) {
$pee = str_replace(array(
' <!-- wpnl --> ',
'<!-- wpnl -->'
), "\n", $pee);
}
return $pee;
}
/**
* Replace characters or phrases within HTML elements only.
*
* @param string $haystack The text which has to be formatted.
* @param array $replace_pairs In the form array('from' => 'to', ...).
*
* @return string The formatted text.
* @since 4.2.3
*
*/
private function wp_replace_in_html_tags($haystack, $replace_pairs) {
// Find all elements.
$textarr = self::wp_html_split($haystack);
$changed = false;
// Optimize when searching for one item.
if (1 === count($replace_pairs)) {
// Extract $needle and $replace.
foreach ($replace_pairs as $needle => $replace) {
}
// Loop through delimiters (elements) only.
for ($i = 1, $c = count($textarr); $i < $c; $i += 2) {
if (false !== strpos($textarr[$i], $needle)) {
$textarr[$i] = str_replace($needle, $replace, $textarr[$i]);
$changed = true;
}
}
} else {
// Extract all $needles.
$needles = array_keys($replace_pairs);
// Loop through delimiters (elements) only.
for ($i = 1, $c = count($textarr); $i < $c; $i += 2) {
foreach ($needles as $needle) {
if (false !== strpos($textarr[$i], $needle)) {
$textarr[$i] = strtr($textarr[$i], $replace_pairs);
$changed = true;
// After one strtr() break out of the foreach loop and look at next element.
break;
}
}
}
}
if ($changed) {
$haystack = implode($textarr);
}
return $haystack;
}
/**
* Separate HTML elements and comments from the text.
*
* @param string $input The text which has to be formatted.
*
* @return string[] Array of the formatted text.
* @since 4.2.4
*
*/
private function wp_html_split($input) {
return preg_split(self::get_html_split_regex(), $input, -1, PREG_SPLIT_DELIM_CAPTURE);
}
/**
* Retrieve the regular expression for an HTML element.
*
* @return string The regular expression
* @since 4.4.0
*
*/
private function get_html_split_regex() {
static $regex;
if (!isset($regex)) {
// phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- don't remove regex indentation
$comments = '!' // Start of comment, after the <.
. '(?:' // Unroll the loop: Consume everything until --> is found.
. '-(?!->)' // Dash not followed by end of comment.
. '[^\-]*+' // Consume non-dashes.
. ')*+' // Loop possessively.
. '(?:-->)?'; // End of comment. If not found, match all input.
$cdata = '!\[CDATA\[' // Start of comment, after the <.
. '[^\]]*+' // Consume non-].
. '(?:' // Unroll the loop: Consume everything until ]]> is found.
. '](?!]>)' // One ] not followed by end of comment.
. '[^\]]*+' // Consume non-].
. ')*+' // Loop possessively.
. '(?:]]>)?'; // End of comment. If not found, match all input.
$escaped = '(?=' // Is the element escaped?
. '!--' . '|' . '!\[CDATA\[' . ')' . '(?(?=!-)' // If yes, which type?
. $comments . '|' . $cdata . ')';
$regex = '/(' // Capture the entire match.
. '<' // Find start of element.
. '(?' // Conditional expression follows.
. $escaped // Find end of escaped element.
. '|' // ...else...
. '[^>]*>?' // Find end of normal element.
. ')' . ')/';
// phpcs:enable
}
return $regex;
}
public function _autop_newline_preservation_helper($matches) {
return str_replace("\n", '<WPPreserveNewline />', $matches[0]);
}
}

View File

@ -0,0 +1,254 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Vimeo;
use Nextend\Framework\Form\Element\Message\Notice;
use Nextend\Framework\Form\Element\Message\Warning;
use Nextend\Framework\Form\Element\OnOff;
use Nextend\Framework\Form\Element\Select;
use Nextend\Framework\Form\Element\Text;
use Nextend\Framework\Form\Element\Text\Color;
use Nextend\Framework\Form\Element\Text\FieldImage;
use Nextend\Framework\Form\Element\Text\Number;
use Nextend\Framework\Form\Fieldset;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\SmartSlider3\Renderable\Item\AbstractItem;
class ItemVimeo extends AbstractItem {
protected $ordering = 20;
protected $layerProperties = array(
"desktopportraitwidth" => 300,
"desktopportraitheight" => 'auto'
);
protected function isBuiltIn() {
return true;
}
public function getType() {
return 'vimeo';
}
public function getTitle() {
return 'Vimeo';
}
public function getIcon() {
return 'ssi_32 ssi_32--vimeo';
}
public function getGroup() {
return n2_x('Media', 'Layer group');
}
/**
* @param Data $data
*/
public function upgradeData($data) {
if (!$data->has('aspect-ratio')) {
$data->set('aspect-ratio', 'fill');
}
}
public function createFrontend($id, $itemData, $layer) {
return new ItemVimeoFrontend($this, $id, $itemData, $layer);
}
public function getValues() {
return parent::getValues() + array(
'vimeourl' => '75251217',
'privateid' => '',
'image' => '$ss3-frontend$/images/placeholder/video.png',
'aspect-ratio' => '16:9',
'autoplay' => 0,
'ended' => '',
'title' => 1,
'byline' => 1,
'portrait' => 0,
'color' => '00adef',
'loop' => 0,
'start' => 0,
'playbutton' => 1,
'playbuttonwidth' => 48,
'playbuttonheight' => 48,
'playbuttonimage' => '',
'scroll-pause' => 'partly-visible',
);
}
public function getFilled($slide, $data) {
$data = parent::getFilled($slide, $data);
$data->set('image', $slide->fill($data->get('image', '')));
$data->set('vimeourl', $slide->fill($data->get('vimeourl', '')));
return $data;
}
public function prepareExport($export, $data) {
parent::prepareExport($export, $data);
$export->addImage($data->get('image'));
$export->addImage($data->get('playbuttonimage'));
}
public function prepareImport($import, $data) {
$data = parent::prepareImport($import, $data);
$data->set('image', $import->fixImage($data->get('image')));
$data->set('playbuttonimage', $import->fixImage($data->get('playbuttonimage')));
return $data;
}
public function prepareSample($data) {
$data->set('image', ResourceTranslator::toUrl($data->get('image')));
return $data;
}
public function renderFields($container) {
$settings = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-vimeo', n2_('General'));
new Text($settings, 'vimeourl', n2_('Vimeo url or Video ID'), '', array(
'style' => 'width:302px;'
));
new FieldImage($settings, 'image', n2_('Cover image'), '', array(
'width' => 220
));
new Select($settings, 'aspect-ratio', n2_('Aspect ratio'), '16:9', array(
'options' => array(
'16:9' => '16:9',
'16:10' => '16:10',
'4:3' => '4:3',
'custom' => n2_('Custom'),
'fill' => n2_('Fill layer height')
),
'relatedValueFields' => array(
array(
'values' => array(
'custom'
),
'field' => array(
'item_vimeoaspect-ratio-width',
'item_vimeoaspect-ratio-height'
)
),
array(
'values' => array(
'fill'
),
'field' => array(
'item_vimeoaspect-ratio-notice'
)
)
)
));
new Text\Number($settings, 'aspect-ratio-width', n2_('Width'), '16', array(
'wide' => 4,
'min' => 1
));
new Text\Number($settings, 'aspect-ratio-height', n2_('Height'), '9', array(
'wide' => 4,
'min' => 1
));
new Notice($settings, 'aspect-ratio-notice', n2_('Fill layer height'), n2_('Set on Style tab.'));
$misc = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-vimeo-misc', n2_('Video settings'));
new Warning($misc, 'slide-background-notice', sprintf(n2_('Video autoplaying has a lot of limitations made by browsers. %1$sLearn about them.%2$s'), '<a href="https://smartslider.helpscoutdocs.com/article/1919-video-autoplay-handling" target="_blank">', '</a>'));
new OnOff($misc, 'autoplay', n2_('Autoplay'), 0, array(
'relatedFieldsOn' => array(
'item_vimeoautoplay-notice'
)
));
new Select($misc, 'ended', n2_('When ended'), '', array(
'options' => array(
'' => n2_('Do nothing'),
'next' => n2_('Go to next slide')
)
));
new Number($misc, 'start', n2_('Start time'), 0, array(
'min' => 0,
'unit' => 'sec',
'wide' => 5
));
new Select($misc, 'volume', n2_('Volume'), 1, array(
'options' => array(
'0' => n2_('Mute'),
'0.25' => '25%',
'0.5' => '50%',
'0.75' => '75%',
'1' => '100%',
'-1' => n2_('Default')
)
));
new Select($misc, 'scroll-pause', n2_('Pause on scroll'), 'partly-visible', array(
'options' => array(
'' => n2_('Never'),
'partly-visible' => n2_('When partly visible'),
'not-visible' => n2_('When not visible'),
),
'tipLabel' => n2_('Pause on scroll'),
'tipDescription' => n2_('You can pause the video when the visitor scrolls away from the slider')
));
new OnOff($misc, 'reset', n2_('Restart on slide change'), 0, array(
'tipLabel' => n2_('Restart on slide change'),
'tipDescription' => n2_('Starts the video from the beginning when the slide is viewed again.')
));
$display = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-youtube-display', n2_('Display'));
new Color($display, 'color', n2_('Color'), 0, array(
'tipLabel' => n2_('Color'),
'tipDescription' => n2_('Only works on videos of Vimeo Pro users.')
));
new OnOff($display, 'background', n2_('Remove controls'), 0, array(
'tipLabel' => n2_('Remove controls'),
'tipDescription' => n2_('Removes the controls of the video, but it only works on videos of Vimeo Pro users.')
));
new OnOff($display, 'title', n2_('Title'), 1, array(
'tipLabel' => n2_('Title'),
'tipDescription' => n2_('Hides the title of the video, but only if video owner allows it.')
));
new OnOff($display, 'byline', n2_('Users byline'), 1, array(
'tipLabel' => n2_('Users byline'),
'tipDescription' => n2_('Hides the user\'s byline of the video, but only if video owner allows it.')
));
new OnOff($display, 'portrait', n2_('Portrait'), 1, array(
'tipLabel' => n2_('Portrait'),
'tipDescription' => n2_('Hides the profile image of the author, but only if video owner allows it. ')
));
new Select($display, 'quality', n2_('Quality'), '-1', array(
'options' => array(
'270p' => '270p',
'360p' => '360p',
'720p' => '720p',
'1080p' => '1080p',
'-1' => n2_('Default')
),
'tipLabel' => n2_('Quality'),
'tipDescription' => n2_('Only works on videos of Vimeo Pro users.')
));
new Text($display, 'iframe-title', n2_('Iframe title'));
}
}

View File

@ -0,0 +1,156 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\Vimeo;
use Nextend\Framework\FastImageSize\FastImageSize;
use Nextend\Framework\Image\Image;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
use Nextend\SmartSlider3\Settings;
class ItemVimeoFrontend extends AbstractItemFrontend {
public function render() {
$owner = $this->layer->getOwner();
$url = $owner->fill($this->data->get("vimeourl"));
$urlParts = explode('?', $url);
$privateID = '';
if (preg_match('/https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/', $urlParts[0], $matches)) {
$videoID = $matches[3];
$privateID = str_replace($matches, '', $urlParts[0]);
} else {
$videoID = preg_replace('/\D/', '', $urlParts[0]);
}
$this->data->set("vimeocode", $videoID);
if (isset($urlParts[1])) {
$parsedUrl = parse_url('https://player.vimeo.com/video/' . $videoID . '?' . $urlParts[1]);
parse_str($parsedUrl['query'], $query);
if (isset($query['h'])) {
$privateID = $query['h'];
}
}
$this->data->set("privateid", $privateID);
$hasImage = 0;
$coverImageUrl = $owner->fill($this->data->get('image'));
$coverImage = '';
if (!empty($coverImageUrl)) {
$coverImageElement = $owner->renderImage($this, $coverImageUrl, array(
'class' => 'n2_ss_video_cover',
'alt' => n2_('Play')
), array(
'class' => 'n2-ow-all'
));
$hasImage = 1;
$playImage = '';
if ($this->data->get('playbutton', 1) == 1) {
$playWidth = intval($this->data->get('playbuttonwidth', '48'));
$playHeight = intval($this->data->get('playbuttonheight', '48'));
if ($playWidth > 0 && $playHeight > 0) {
$attributes = Html::addExcludeLazyLoadAttributes(array(
'style' => '',
'class' => 'n2_ss_video_play_btn'
));
if ($playWidth != 48) {
$attributes['style'] .= 'width:' . $playWidth . 'px;';
}
if ($playHeight != 48) {
$attributes['style'] .= 'height:' . $playHeight . 'px;';
}
$playButtonImage = $this->data->get('playbuttonimage', '');
if (!empty($playButtonImage)) {
$image = $this->data->get('playbuttonimage', '');
FastImageSize::initAttributes($image, $attributes);
$src = ResourceTranslator::toUrl($image);
} else {
$image = '$ss3-frontend$/images/play.svg';
FastImageSize::initAttributes($image, $attributes);
$src = Image::SVGToBase64($image);
}
$playImage = Html::image($src, 'Play', $attributes);
}
}
$coverImage = Html::tag('div', array(
'class' => 'n2_ss_video_player__cover',
'data-force-pointer' => ''
), $coverImageElement . $playImage);
}
$this->data->set('privacy-enhanced', intval(Settings::get('youtube-privacy-enhanced', 0)));
$owner->addScript('new _N2.FrontendItemVimeo(this, "' . $this->id . '", "' . $owner->getElementID() . '", ' . $this->data->toJSON() . ', ' . $hasImage . ', ' . $owner->fill($this->data->get('start', '0')) . ');');
$aspectRatio = $this->data->get('aspect-ratio', '16:9');
$style = '';
if ($aspectRatio == 'custom') {
$style = 'style="padding-top:' . ($this->data->get('aspect-ratio-height', '9') / $this->data->get('aspect-ratio-width', '16') * 100) . '%"';
}
return Html::tag('div', array(
'id' => $this->id,
'class' => 'n2_ss_video_player n2-ss-item-content n2-ow-all',
'data-aspect-ratio' => $aspectRatio
), '<div class="n2_ss_video_player__placeholder" ' . $style . '></div>' . $coverImage);
}
public function renderAdminTemplate() {
$aspectRatio = $this->data->get('aspect-ratio', '16:9');
$owner = $this->layer->getOwner();
$style = '';
if ($aspectRatio == 'custom') {
$style = 'style="padding-top:' . ($this->data->get('aspect-ratio-height', '9') / $this->data->get('aspect-ratio-width', '16') * 100) . '%"';
}
$playButtonImage = $this->data->get('playbuttonimage', '');
if (!empty($playButtonImage)) {
$playButtonImage = ResourceTranslator::toUrl($playButtonImage);
} else {
$playButtonImage = Image::SVGToBase64('$ss3-frontend$/images/play.svg');
}
$playButtonStyle = '';
$playButtonWidth = intval($this->data->get('playbuttonwidth', '48'));
$playButtonHeight = intval($this->data->get('playbuttonheight', '48'));
if ($playButtonWidth > 0) {
$playButtonStyle .= 'width:' . $playButtonWidth . 'px;';
}
if ($playButtonHeight > 0) {
$playButtonStyle .= 'height:' . $playButtonHeight . 'px;';
}
$playButton = Html::image($playButtonImage, n2_('Play'), Html::addExcludeLazyLoadAttributes(array(
'class' => 'n2_ss_video_play_btn',
'style' => $playButtonStyle
)));
return Html::tag('div', array(
"class" => 'n2_ss_video_player n2-ow-all',
'data-aspect-ratio' => $aspectRatio,
"style" => 'background: URL(' . ResourceTranslator::toUrl($owner->fill($this->data->getIfEmpty('image', '$ss3-frontend$/images/placeholder/video.png'))) . ') no-repeat 50% 50%; background-size: cover;'
), '<div class="n2_ss_video_player__placeholder" ' . $style . '></div>' . '<div class="n2_ss_video_player__cover">' . $playButton . '</div>');
}
}

View File

@ -0,0 +1,244 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\YouTube;
use Nextend\Framework\Data\Data;
use Nextend\Framework\Form\Element\Message\Notice;
use Nextend\Framework\Form\Element\Message\Warning;
use Nextend\Framework\Form\Element\OnOff;
use Nextend\Framework\Form\Element\Select;
use Nextend\Framework\Form\Element\Text;
use Nextend\Framework\Form\Element\Text\FieldImage;
use Nextend\Framework\Form\Element\Text\Number;
use Nextend\Framework\Form\Fieldset;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\SmartSlider3\Renderable\Item\AbstractItem;
class ItemYouTube extends AbstractItem {
protected $ordering = 20;
protected $layerProperties = array(
"desktopportraitwidth" => 300,
"desktopportraitheight" => 'auto'
);
protected function isBuiltIn() {
return true;
}
public function getType() {
return 'youtube';
}
public function getTitle() {
return 'YouTube';
}
public function getIcon() {
return 'ssi_32 ssi_32--youtube';
}
public function getGroup() {
return n2_x('Media', 'Layer group');
}
/**
* @param Data $data
*/
public function upgradeData($data) {
if (!$data->has('aspect-ratio')) {
$data->set('aspect-ratio', 'fill');
}
}
public function createFrontend($id, $itemData, $layer) {
return new ItemYouTubeFrontend($this, $id, $itemData, $layer);
}
public function getValues() {
return parent::getValues() + array(
'code' => 'qesNtYIBDfs',
'aspect-ratio' => '16:9',
'youtubeurl' => 'https://www.youtube.com/watch?v=3PPtkRU7D74',
'image' => '$ss3-frontend$/images/placeholder/video.png',
'autoplay' => 0,
'ended' => '',
'controls' => 1,
'defaultimage' => 'hqdefault',
'related' => '1',
'center' => 0,
'loop' => 0,
'modestbranding' => 1,
'reset' => 0,
'start' => '0',
'playbutton' => 1,
'playbuttonwidth' => 48,
'playbuttonheight' => 48,
'playbuttonimage' => '',
'scroll-pause' => 'partly-visible',
);
}
public function getFilled($slide, $data) {
$data = parent::getFilled($slide, $data);
$data->set('image', $slide->fill($data->get('image', '')));
$data->set('youtubeurl', $slide->fill($data->get('youtubeurl', '')));
return $data;
}
public function prepareExport($export, $data) {
parent::prepareExport($export, $data);
$export->addImage($data->get('image'));
$export->addImage($data->get('playbuttonimage'));
}
public function prepareImport($import, $data) {
$data = parent::prepareImport($import, $data);
$data->set('image', $import->fixImage($data->get('image')));
$data->set('playbuttonimage', $import->fixImage($data->get('playbuttonimage')));
return $data;
}
public function prepareSample($data) {
$data->set('image', ResourceTranslator::toUrl($data->get('image')));
return $data;
}
public function renderFields($container) {
$settings = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-youtube', n2_('General'));
new Text($settings, 'youtubeurl', n2_('YouTube URL or Video ID'), '', array(
'style' => 'width:302px;'
));
new FieldImage($settings, 'image', n2_('Cover image'), '', array(
'width' => 220
));
new Select($settings, 'aspect-ratio', n2_('Aspect ratio'), '16:9', array(
'options' => array(
'16:9' => '16:9',
'16:10' => '16:10',
'4:3' => '4:3',
'custom' => n2_('Custom'),
'fill' => n2_('Fill layer height')
),
'relatedValueFields' => array(
array(
'values' => array(
'custom'
),
'field' => array(
'item_youtubeaspect-ratio-width',
'item_youtubeaspect-ratio-height'
)
),
array(
'values' => array(
'fill'
),
'field' => array(
'item_youtubeaspect-ratio-notice'
)
)
)
));
new Text\Number($settings, 'aspect-ratio-width', n2_('Width'), '16', array(
'wide' => 4,
'min' => 1
));
new Text\Number($settings, 'aspect-ratio-height', n2_('Height'), '9', array(
'wide' => 4,
'min' => 1
));
new Notice($settings, 'aspect-ratio-notice', n2_('Fill layer height'), n2_('Set on Style tab.'));
$misc = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-youtube-misc', n2_('Video settings'));
new Warning($misc, 'slide-background-notice', sprintf(n2_('Video autoplaying has a lot of limitations made by browsers. %1$sLearn about them.%2$s'), '<a href="https://smartslider.helpscoutdocs.com/article/1919-video-autoplay-handling" target="_blank">', '</a>'));
new OnOff($misc, 'autoplay', n2_('Autoplay'), 0, array(
'relatedFieldsOn' => array(
'item_youtubeautoplay-notice'
)
));
new Select($misc, 'ended', n2_('When ended'), '', array(
'options' => array(
'' => n2_('Do nothing'),
'next' => n2_('Go to next slide')
)
));
new Number($misc, 'start', n2_('Start time'), 0, array(
'min' => 0,
'unit' => 'sec',
'wide' => 5
));
new Number($misc, 'end', n2_('End time'), 0, array(
'min' => 0,
'unit' => 'sec',
'wide' => 5
));
new Select($misc, 'volume', n2_('Volume'), 1, array(
'options' => array(
'0' => n2_('Mute'),
'0.25' => '25%',
'0.5' => '50%',
'0.75' => '75%',
'1' => '100%',
'-1' => n2_('Default')
)
));
new Select($misc, 'scroll-pause', n2_('Pause on scroll'), 'partly-visible', array(
'options' => array(
'' => n2_('Never'),
'partly-visible' => n2_('When partly visible'),
'not-visible' => n2_('When not visible'),
),
'tipLabel' => n2_('Pause on scroll'),
'tipDescription' => n2_('You can pause the video when the visitor scrolls away from the slider')
));
new OnOff($misc, 'loop', n2_x('Loop', 'Video/Audio play'), 0, array(
'relatedFieldsOff' => array(
'item_youtubeended'
)
));
new OnOff($misc, 'reset', n2_('Restart on slide change'), 0, array(
'tipLabel' => n2_('Restart on slide change'),
'tipDescription' => n2_('Starts the video from the beginning when the slide is viewed again.')
));
$display = new Fieldset\LayerWindow\FieldsetLayerWindow($container, 'item-youtube-display', n2_('Display'));
new OnOff($display, 'controls', n2_('Controls'), 1);
new OnOff($display, 'center', n2_('Centered'), 0, array(
'tipLabel' => n2_('Centered'),
'tipDescription' => n2_('Scales up and crops the video to cover the whole layer.'),
'tipLink' => 'https://smartslider.helpscoutdocs.com/article/1846-youtube-layer#centered'
));
new Select($display, 'related', n2_('Show related videos'), 1, array(
'options' => array(
'0' => n2_('Anywhere'),
'1' => n2_('Same channel')
),
'tipLabel' => n2_('Show related videos'),
'tipDescription' => n2_('YouTube no longer allows hiding the related videos at the end of the video. This setting defines whether the videos should come from the same channel as the video that was just played or from any other channel.'),
'tipLink' => 'https://smartslider.helpscoutdocs.com/article/1846-youtube-layer#show-related-videos',
));
}
}

View File

@ -0,0 +1,186 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Item\YouTube;
use Nextend\Framework\Data\Data;
use Nextend\Framework\FastImageSize\FastImageSize;
use Nextend\Framework\Image\Image;
use Nextend\Framework\ResourceTranslator\ResourceTranslator;
use Nextend\Framework\View\Html;
use Nextend\SmartSlider3\Renderable\Item\AbstractItemFrontend;
use Nextend\SmartSlider3\Settings;
class ItemYouTubeFrontend extends AbstractItemFrontend {
public function render() {
$owner = $this->layer->getOwner();
/**
* @var Data
*/
$this->data->fillDefault(array(
'image' => '',
'aspect-ratio' => '16:9',
'start' => 0,
'volume' => -1,
'autoplay' => 0,
'ended' => '',
'controls' => 1,
'center' => 0,
'loop' => 0,
'reset' => 0,
'related' => 1,
));
$aspectRatio = $this->data->get('aspect-ratio', '16:9');
if ($aspectRatio != 'fill') {
$this->data->set('center', 0);
}
$rawYTUrl = $owner->fill($this->data->get('youtubeurl', ''));
$url_parts = parse_url($rawYTUrl);
if (!empty($url_parts['query'])) {
parse_str($url_parts['query'], $query);
if (isset($query['v'])) {
unset($query['v']);
}
$this->data->set("query", $query);
}
$youTubeUrl = $this->parseYoutubeUrl($rawYTUrl);
$start = $owner->fill($this->data->get('start', ''));
$this->data->set("youtubecode", $youTubeUrl);
$this->data->set("start", $start);
$end = $owner->fill($this->data->get('end', ''));
$this->data->set("youtubecode", $youTubeUrl);
$this->data->set("end", $end);
$hasImage = 0;
$coverImageUrl = $owner->fill($this->data->get('image'));
$coverImage = '';
if (!empty($coverImageUrl)) {
$coverImageElement = $owner->renderImage($this, $coverImageUrl, array(
'class' => 'n2_ss_video_cover',
'alt' => n2_('Play')
), array(
'class' => 'n2-ow-all'
));
$hasImage = 1;
$playImage = '';
if ($this->data->get('playbutton', 1) == 1) {
$playWidth = intval($this->data->get('playbuttonwidth', '48'));
$playHeight = intval($this->data->get('playbuttonheight', '48'));
if ($playWidth > 0 && $playHeight > 0) {
$attributes = Html::addExcludeLazyLoadAttributes(array(
'style' => '',
'class' => 'n2_ss_video_play_btn'
));
if ($playWidth != 48) {
$attributes['style'] .= 'width:' . $playWidth . 'px;';
}
if ($playHeight != 48) {
$attributes['style'] .= 'height:' . $playHeight . 'px;';
}
$playButtonImage = $this->data->get('playbuttonimage', '');
if (!empty($playButtonImage)) {
$image = $this->data->get('playbuttonimage', '');
FastImageSize::initAttributes($image, $attributes);
$src = ResourceTranslator::toUrl($image);
} else {
$image = '$ss3-frontend$/images/play.svg';
FastImageSize::initAttributes($image, $attributes);
$src = Image::SVGToBase64($image);
}
$playImage = Html::image($src, 'Play', $attributes);
}
}
$coverImage = Html::tag('div', array(
'class' => 'n2_ss_video_player__cover',
'data-force-pointer' => ''
), $coverImageElement . $playImage);
}
$this->data->set('privacy-enhanced', intval(Settings::get('youtube-privacy-enhanced', 0)));
$owner->addScript('new _N2.FrontendItemYouTube(this, "' . $this->id . '", ' . $this->data->toJSON() . ', ' . $hasImage . ');');
$style = '';
if ($aspectRatio == 'custom') {
$style = 'style="padding-top:' . ($this->data->get('aspect-ratio-height', '9') / $this->data->get('aspect-ratio-width', '16') * 100) . '%"';
}
return Html::tag('div', array(
'id' => $this->id,
'class' => 'n2_ss_video_player n2-ss-item-content n2-ow-all',
'data-aspect-ratio' => $aspectRatio
), '<div class="n2_ss_video_player__placeholder" ' . $style . '></div>' . Html::tag('div', array(
'id' => $this->id . '-frame',
), '') . $coverImage);
}
public function renderAdminTemplate() {
$aspectRatio = $this->data->get('aspect-ratio', '16:9');
$style = '';
if ($aspectRatio == 'custom') {
$style = 'style="padding-top:' . ($this->data->get('aspect-ratio-height', '9') / $this->data->get('aspect-ratio-width', '16') * 100) . '%"';
}
$image = $this->layer->getOwner()
->fill($this->data->get('image'));
$this->data->set('image', $image);
$playButtonImage = $this->data->get('playbuttonimage', '');
if (!empty($playButtonImage)) {
$playButtonImage = ResourceTranslator::toUrl($playButtonImage);
} else {
$playButtonImage = Image::SVGToBase64('$ss3-frontend$/images/play.svg');
}
$playButtonStyle = '';
$playButtonWidth = intval($this->data->get('playbuttonwidth', '48'));
$playButtonHeight = intval($this->data->get('playbuttonheight', '48'));
if ($playButtonWidth > 0) {
$playButtonStyle .= 'width:' . $playButtonWidth . 'px;';
}
if ($playButtonHeight > 0) {
$playButtonStyle .= 'height:' . $playButtonWidth . 'px;';
}
$playButton = Html::image($playButtonImage, n2_('Play'), Html::addExcludeLazyLoadAttributes(array(
'class' => 'n2_ss_video_play_btn',
'style' => $playButtonStyle
)));
return Html::tag('div', array(
'class' => 'n2_ss_video_player n2-ow-all',
'data-aspect-ratio' => $aspectRatio,
"style" => 'background: URL(' . ResourceTranslator::toUrl($this->data->getIfEmpty('image', '$ss3-frontend$/images/placeholder/video.png')) . ') no-repeat 50% 50%; background-size: cover;'
), '<div class="n2_ss_video_player__placeholder" ' . $style . '></div>' . ($this->data->get('playbutton', 1) ? '<div class="n2_ss_video_player__cover">' . $playButton . '</div>' : ''));
}
private function parseYoutubeUrl($youTubeUrl) {
preg_match('#^(?:https?://)?(?:www\.)?(?:youtu\.be/|youtube(?:-nocookie)?\.com(?:/embed/|/shorts/|/v/|/watch\?v=|/watch\?.+&v=))([\w-]{11})(?:.+)?$#x', $youTubeUrl, $matches);
if ($matches && isset($matches[1]) && strlen($matches[1]) == 11) {
return $matches[1];
}
return $youTubeUrl;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Placement;
use Nextend\SmartSlider3\Renderable\Component\AbstractComponent;
abstract class AbstractPlacement {
/** @var AbstractComponent */
protected $component;
protected $index = 1;
protected $style = '';
protected $attributes = '';
/**
*
* @param AbstractComponent $component
* @param int $index
*/
public function __construct($component, $index) {
$this->component = $component;
$this->index = $index;
}
/**
* @param array $attributes
*/
public function attributes(&$attributes) {
}
/**
* @param array $attributes
*/
public function adminAttributes(&$attributes) {
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Placement;
class PlacementAbsolute extends AbstractPlacement {
public function attributes(&$attributes) {
$data = $this->component->data;
$attributes['data-pm'] = 'absolute';
$this->component->createProperty('responsiveposition', 1);
$this->component->createDeviceProperty('left', 0);
$this->component->createDeviceProperty('top', 0);
$this->component->createProperty('responsivesize', 1);
$this->component->createDeviceProperty('width');
$this->component->createDeviceProperty('height');
$this->component->createDeviceProperty('align');
$this->component->createDeviceProperty('valign');
// Chain
$attributes['data-parentid'] = $data->get('parentid');
$this->component->createDeviceProperty('parentalign');
$this->component->createDeviceProperty('parentvalign');
$isLegacyFontScale = $this->component->getOwner()
->getSlider()
->isLegacyFontScale();
if ($isLegacyFontScale) {
$adaptiveFont = intval($data->get('adaptivefont', 1));
if ($adaptiveFont === 0) {
$attributes['data-adaptivefont'] = 0;
}
}
}
public function adminAttributes(&$attributes) {
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Placement;
class PlacementDefault extends AbstractPlacement {
public function attributes(&$attributes) {
$attributes['data-pm'] = 'default';
}
}

View File

@ -0,0 +1,96 @@
<?php
namespace Nextend\SmartSlider3\Renderable\Placement;
use Nextend\SmartSlider3\Renderable\Component\AbstractComponent;
class PlacementNormal extends AbstractPlacement {
public function attributes(&$attributes) {
$data = $this->component->data;
$attributes['data-pm'] = 'normal';
$devices = $this->component->getOwner()
->getAvailableDevices();
$desktopPortraitSelfAlign = $data->get('desktopportraitselfalign', 'inherit');
$desktopPortraitMaxWidth = intval($data->get('desktopportraitmaxwidth', 0));
$desktopPortraitHeight = $data->get('desktopportraitheight', 0);
$desktopPortraitMargin = $data->get('desktopportraitmargin');
if (!empty($desktopPortraitMargin)) {
$desktopPortraitMargin = $this->component->spacingToPxValue($desktopPortraitMargin);
} else {
$desktopPortraitMargin = array(
0,
0,
0,
0
);
}
foreach ($devices as $device) {
$margin = $data->get($device . 'margin');
if (!empty($margin)) {
$marginValues = $this->component->spacingToPxValue($margin);
$cssText = array();
if (($marginValues[0] == 0 && $desktopPortraitMargin[0] != 0) || $marginValues[0] != 0) {
$cssText[] = '--margin-top:' . $marginValues[0] . 'px';
}
if (($marginValues[1] == 0 && $desktopPortraitMargin[1] != 0) || $marginValues[1] != 0) {
$cssText[] = '--margin-right:' . $marginValues[1] . 'px';
}
if (($marginValues[2] == 0 && $desktopPortraitMargin[2] != 0) || $marginValues[2] != 0) {
$cssText[] = '--margin-bottom:' . $marginValues[2] . 'px';
}
if (($marginValues[3] == 0 && $desktopPortraitMargin[3] != 0) || $marginValues[3] != 0) {
$cssText[] = '--margin-left:' . $marginValues[3] . 'px';
}
$this->component->style->add($device, '', implode(';', $cssText));
}
$height = $data->get($device . 'height');
if ($height === 0 || !empty($height)) {
if ($height == 0) {
if ($desktopPortraitHeight > 0) {
$this->component->style->add($device, '', 'height:auto');
}
} else {
$this->component->style->add($device, '', 'height:' . $height . 'px');
}
}
$maxWidth = intval($data->get($device . 'maxwidth', -1));
if ($maxWidth > 0) {
$this->component->style->add($device, '', 'max-width:' . $maxWidth . 'px');
} else if ($maxWidth === 0 && $device != 'desktopportrait' && $maxWidth != $desktopPortraitMaxWidth) {
$this->component->style->add($device, '', 'max-width:none');
}
$selfAlign = $data->get($device . 'selfalign', '');
if ($device == 'desktopportrait') {
if ($desktopPortraitSelfAlign != 'inherit') {
$this->component->style->add($device, '', AbstractComponent::selfAlignToStyle($selfAlign));
}
} else if ($desktopPortraitSelfAlign != $selfAlign) {
$this->component->style->add($device, '', AbstractComponent::selfAlignToStyle($selfAlign));
}
}
}
public function adminAttributes(&$attributes) {
$this->component->createDeviceProperty('maxwidth', 0);
$this->component->createDeviceProperty('margin', '0|*|0|*|0|*|0');
$this->component->createDeviceProperty('height', 0);
$this->component->createDeviceProperty('selfalign', 'inherit');
}
}