Your IP : 3.146.178.241


Current Path : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/ui/lib/buttons/
Upload File :
Current File : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/ui/lib/buttons/basebutton.php

<?php

namespace Bitrix\UI\Buttons;


use Bitrix\Main\ArgumentException;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Security\Random;
use Bitrix\Main\UI\Extension;
use Bitrix\UI\Contract;

//We know about lazy load. So, the code loads common messages for default buttons,
//which implemented by subclasses of BaseButton.
Loc::loadLanguageFile(__FILE__);

class BaseButton implements Contract\Renderable
{
	const UNIQ_ID_DATA_ATTR      = 'btn-uniqid';
	const JSON_OPTIONS_DATA_ATTR = 'json-options';

	/** @var string */
	protected $id;
	/** @var string */
	protected $text;
	/** @var string */
	protected $tag = Tag::BUTTON;
	/** @var string */
	protected $baseClass = "ui-btn";
	/** @var string */
	protected $link;
	/** @var integer|string */
	protected $counter;
	/** @var array */
	protected $events = [];
	/** @var ButtonAttributes */
	private $attributes;

	final public function __construct(array $params = [])
	{
		$this->attributes = new ButtonAttributes();
		$this->attributes->addDataAttribute(self::UNIQ_ID_DATA_ATTR, $this->generateUniqid());
		$this->addClass($this->getBaseClass());

		$this->init($params);
	}

	/**
	 * @return array
	 */
	protected function getDefaultParameters()
	{
		return [];
	}

	protected function init(array $params = [])
	{
		$this->buildFromArray(array_merge(
			$this->getDefaultParameters(),
			$params
		));
	}

	final public static function create(array $params = [])
	{
		return new static($params);
	}

	protected function buildFromArray($params)
	{
		if (isset($params['text']))
		{
			$this->setText($params['text']);
		}

		if (!empty($params['styles']))
		{
			$this->setStyles($params['styles']);
		}

		if (!empty($params['maxWidth']))
		{
			$this->setMaxWidth($params['maxWidth']);
		}

		if (!empty($params['className']) && is_string($params['className']))
		{
			$params['classList'] = array_filter(explode(' ', $params['className']));
		}

		if (empty($params['classList']))
		{
			$params['classList'] = [];
		}

		$params['classList'] = array_merge(
			[$this->getBaseClass()],
			$params['classList']
		);

		$this->getAttributeCollection()->setClassList($params['classList']);

		if (!empty($params['counter']))
		{
			$this->setCounter($params['counter']);
		}

		if (!empty($params['id']))
		{
			$this->setId($params['id']);
		}

		if (!empty($params['tag']))
		{
			$this->setTag($params['tag']);
		}

		if (!empty($params['link']))
		{
			$this->setLink($params['link']);
		}

		if (!empty($params['click']))
		{
			$this->bindEvent('click', $params['click']);
		}

		if (!empty($params['onclick']))
		{
			$this->bindEvent('click', $params['onclick']);
		}

		if (!empty($params['events']))
		{
			$this->bindEvents($params['events']);
		}

		if (isset($params['dataset']) && is_array($params['dataset']))
		{
			foreach ($params['dataset'] as $name => $value)
			{
				$this->addDataAttribute($name, $value);
			}
		}
	}

	protected function listExtensions()
	{
		return [];
	}

	public static function getJsClass()
	{
		return 'BX.UI.' . (new \ReflectionClass(get_called_class()))->getShortName();
	}

	protected function appendDefaultJsonOption(ButtonAttributes $attributes)
	{
		if (count($this->getEvents()) > 0)
		{
			$attributes->addJsonOption('events', $this->getEvents());
		}

		return $attributes;
	}

	public function render($jsInit = true)
	{
		Extension::load($this->listExtensions());

		$output = '';
		$tagName = $this->getTag();
		$attributes = clone $this->getAttributeCollection();
		$this->appendDefaultJsonOption($attributes);

		switch ($tagName)
		{
			case Tag::LINK:
			case Tag::BUTTON:
				if ($tagName === Tag::LINK && $this->getLink())
				{
					$attributes['href'] = $this->getLink();
				}

				$inner = $this->renderInner();
				$output = "<{$tagName} {$attributes}>{$inner}</{$tagName}>";
				break;
			case Tag::INPUT:
			case Tag::SUBMIT:
				$attributes['value'] = htmlspecialcharsbx($this->getText());
				$attributes['type'] = Tag::BUTTON;

				if ($tagName === Tag::SUBMIT)
				{
					$tagName = Tag::INPUT;
					$attributes['type'] = Tag::SUBMIT;
				}

				$output = "<{$tagName} {$attributes}/>";
				break;
		}

		if ($jsInit)
		{
			$js = $this->renderJavascript();
			if ($js)
			{
				$output .= "<script>BX.ready(function(){ {$js} });</script>";
			}
		}

		return $output;
	}

	protected function generateUniqid()
	{
		return 'uibtn-' . Random::getString(8);
	}

	public function isInputTag()
	{
		return $this->isInputType();
	}

	public function isInputType()
	{
		return in_array($this->tag, [
			Tag::INPUT,
			Tag::SUBMIT,
		], true);
	}

	protected function renderInner()
	{
		$counter = $this->getCounter();
		return (
			(!empty($this->getText()) ? '<span class="ui-btn-text">'.htmlspecialcharsbx($this->getText()).'</span>' : '').
			($counter !== null ? '<span class="ui-btn-counter">'.htmlspecialcharsbx($counter).'</span>' : '' )
		);
	}

	protected function renderJavascript()
	{
		$selector = $this->getQuerySelector();

		return "BX.UI.ButtonManager.createFromNode(document.querySelector('{$selector}'));";
	}

	protected function getQuerySelector()
	{
		$tag = $this->getTag();
		$uniqId = $this->getUniqId();
		$uniqIdName = "data-" . self::UNIQ_ID_DATA_ATTR;

		return "{$tag}[{$uniqIdName}=\"{$uniqId}\"]";
	}

	public function getUniqId()
	{
		return $this->getAttributeCollection()->getDataAttribute(self::UNIQ_ID_DATA_ATTR);
	}

	public function getId()
	{
		return $this->id;
	}

	public function setId($id)
	{
		$this->id = $id;

		return $this;
	}

	public function getMaxWidth()
	{
		return isset($this->getAttributeCollection()['style']['max-width'])?
			$this->getAttributeCollection()['style']['max-width'] : null;
	}

	public function setMaxWidth($width)
	{
		if (!isset($this->getAttributeCollection()['style']))
		{
			$this->getAttributeCollection()['style'] = [];
		}

		$this->getAttributeCollection()['style']['max-width'] = $width;

		return $this;
	}

	public function getLink()
	{
		return $this->link;
	}

	public function setLink($link)
	{
		if (is_string($link) && !empty($link))
		{
			$this->link = $link;
			$this->setTag(Tag::LINK);
		}

		return $this;
	}

	public function getCounter()
	{
		return $this->counter;
	}

	public function setCounter($counter)
	{
		if (in_array($counter, [0, '0', '', null, false], true))
		{
			$this->counter = null;
		}
		else if ((is_int($counter) && $counter > 0) || (is_string($counter) && mb_strlen($counter)))
		{
			$this->counter = $counter;
		}

		return $this;
	}

	public function addClass($className)
	{
		$this->getAttributeCollection()->addClass($className);

		return $this;
	}

	public function unsetClass($className)
	{
		$this->getAttributeCollection()->removeClass($className);

		return $this;
	}

	public function removeClass($className)
	{
		return $this->unsetClass($className);
	}

	public function hasClass($className)
	{
		return $this->getAttributeCollection()->hasClass($className);
	}

	public function getClassList()
	{
		return $this->getAttributeCollection()['class']?: [];
	}

	public function addAttribute($name, $value = null)
	{
		if (mb_strtolower($name) === 'class')
		{
			throw new ArgumentException('Could not add "class" attribute. You should use ::addClass()', 'class');
		}

		$this->getAttributeCollection()[$name] = $value;

		return $this;
	}

	public function unsetAttribute($name)
	{
		unset($this->getAttributeCollection()[$name]);

		return $this;
	}

	public function removeAttribute($name)
	{
		return $this->unsetAttribute($name);
	}

	public function getAttribute($name, $defaultValue = null)
	{
		return $this->getAttributeCollection()->getAttribute($name, $defaultValue);
	}

	public function addDataAttribute($name, $value = null)
	{
		$this->getAttributeCollection()->addDataAttribute($name, $value);

		return $this;
	}

	public function getDataAttribute($name, $defaultValue = null)
	{
		return $this->getAttributeCollection()->getDataAttribute($name, $defaultValue);
	}

	public function setDataRole($dataRole)
	{
		$this->addDataAttribute('role', $dataRole);

		return $this;
	}

	public function getDataRole()
	{
		return $this->getDataAttribute('role');
	}

	public function setStyles(array $styles)
	{
		$this->getAttributeCollection()['style'] = $styles;
	}

	public function getStyles()
	{
		return $this->getAttributeCollection()['style'];
	}

	/**
	 * @return ButtonAttributes
	 */
	public function getAttributeCollection()
	{
		return $this->attributes;
	}

	/**
	 * @return string
	 */
	public function getText()
	{
		return $this->text;
	}

	/**
	 * @param string $text
	 *
	 * @return static
	 */
	public function setText($text)
	{
		$this->text = $text;

		return $this;
	}

	/**
	 * @return string
	 */
	public function getTag()
	{
		return $this->tag;
	}

	/**
	 * @param string $tag
	 *
	 * @return static
	 */
	public function setTag($tag)
	{
		$this->tag = $tag;

		return $this;
	}

	/**
	 * @return string
	 */
	public function getBaseClass()
	{
		return $this->baseClass;
	}

	/**
	 * @param bool $flag
	 * @return static
	 */
	public function setDisabled($flag = true)
	{
		if ($flag === false)
		{
			unset($this->getAttributeCollection()['disabled']);
		}
		else
		{
			$this->getAttributeCollection()['disabled'] = true;
		}

		return $this;
	}

	/**
	 * @return bool
	 */
	public function isDisabled()
	{
		return $this->getAttributeCollection()['disabled'] === true;
	}

	/**
	 * @return array
	 */
	public function getEvents()
	{
		return $this->events;
	}

	/**
	 * @param string $eventName
	 * @param string|JsHandler $fn Link to js function which will be invoked.
	 * @see in js BX.UI.BaseButton.handleEvent to know order of arguments in event handler.
	 *
	 * @return $this
	 */
	public function bindEvent($eventName, $fn)
	{
		if (is_string($fn))
		{
			$fn = new JsHandler($fn);
		}

		$this->events[$eventName] = $fn;

		return $this;
	}

	/**
	 * @param array $events
	 *
	 * @return $this
	 */
	public function bindEvents(array $events)
	{
		foreach ($events as $name => $fn)
		{
			$this->bindEvent($name, $fn);
		}

		return $this;
	}

	/**
	 * @param string $eventName
	 *
	 * @return $this
	 */
	public function unbindEvent($eventName)
	{
		unset($this->events[$eventName]);

		return $this;
	}

	/**
	 * @return $this
	 */
	public function unbindEvents()
	{
		unset($this->events);

		return $this;
	}
}