Your IP : 216.73.216.86


Current Path : /var/www/homesaver/www/bitrix/js/landing/ui/field/color/src/control/gradient/
Upload File :
Current File : /var/www/homesaver/www/bitrix/js/landing/ui/field/color/src/control/gradient/gradient.js

import {Event, Tag, Text, Dom, Loc} from 'main.core';
import {Popup, PopupManager} from 'main.popup';
import {BaseEvent} from "main.core.events";
import BaseControl from "../base_control/base_control";
import Colorpicker from "../colorpicker/colorpicker";
import Preset from '../../layout/preset/preset';

import 'ui.fonts.opensans';
import './css/gradient.css';
import GradientValue from "../../gradient_value";
import ColorValue from '../../color_value';

export default class Gradient extends BaseControl
{
	static DISABLE_CLASS = 'disable';

	popupId: string;
	popupTargetContainer: ?HTMLElement;

	preset: ?Preset;
	colorpickerFrom: Colorpicker;
	colorpickerTo: Colorpicker;

	+ROTATE_STEP = 45;

	constructor(options)
	{
		super();
		this.setEventNamespace('BX.Landing.UI.Field.Color.Gradient');
		this.popupId = 'gradient_popup_' + Text.getRandom();
		this.popupTargetContainer = options.contentRoot;

		this.colorpickerFrom = new Colorpicker(options);
		this.colorpickerFrom.subscribe('onChange', (event) => {
			this.onColorChange(event.getData().color, null);
		});

		this.colorpickerTo = new Colorpicker(options);
		this.colorpickerTo.subscribe('onChange', (event) => {
			this.onColorChange(null, event.getData().color);
		});

		Event.bind(this.getPopupButton(), 'click', this.onPopupOpen.bind(this));
		Event.bind(this.getRotateButton(), 'click', this.onRotate.bind(this));
		Event.bind(this.getSwitchTypeButton(), 'click', this.onSwitchType.bind(this));
		Event.bind(this.getSwapButton(), 'click', this.onSwap.bind(this));

		this.preset = null;
	}

	onColorChange(fromValue: ?ColorValue, toValue: ?ColorValue)
	{
		if (fromValue === null && toValue === null)
		{
			return;
		}

		const valueToSet = this.getValue() || new GradientValue();
		const fromValueToSet = fromValue || valueToSet.getFrom() || (new GradientValue()).getFrom();
		const toValueToSet = toValue || valueToSet.getTo() || (new GradientValue()).getTo();
		valueToSet.setValue({
			from: fromValueToSet,
			to: toValueToSet,
		});

		this.setValue(valueToSet);
		this.preset.unsetActive();
		this.onChange();
	}

	onPopupOpen()
	{
		this.getPopup().toggle();
	}

	onRotate(event: MouseEvent)
	{
		// todo: not set colorpicker active
		if (!Gradient.isButtonEnable(event.target))
		{
			return;
		}

		const value = this.getValue();
		if (value !== null)
		{
			value.setValue({
				angle: ((value.getAngle() + this.ROTATE_STEP) % 360),
			});
			this.setValue(value);
			this.onChange();
		}
		this.getPopup().close();
	}

	onSwitchType(event: MouseEvent)
	{
		// todo: not set colorpicker active
		if (!Gradient.isButtonEnable(event.target))
		{
			return;
		}

		const value = this.getValue();
		if (value !== null)
		{
			if (value.getType() === GradientValue.TYPE_LINEAR)
			{
				value.setValue({type: GradientValue.TYPE_RADIAL});
				Gradient.disableButton(this.getRotateButton());
			}
			else
			{
				value.setValue({type: GradientValue.TYPE_LINEAR});
				Gradient.enableButton(this.getRotateButton());
			}
			this.setValue(value);
			this.onChange();
		}
		this.getPopup().close();
	}

	onSwap(event: MouseEvent)
	{
		// todo: not set colorpicker active
		if (!Gradient.isButtonEnable(event.target))
		{
			return;
		}

		const value = this.getValue();
		if (value !== null)
		{
			value.setValue({
				to: value.getFrom(),
				from: value.getTo(),
			});
			this.setValue(value);
			this.onChange();
		}
		this.getPopup().close();
	}

	static disableButton(button: HTMLDivElement)
	{
		Dom.addClass(button, Gradient.DISABLE_CLASS);
	}

	static enableButton(button: HTMLDivElement)
	{
		Dom.removeClass(button, Gradient.DISABLE_CLASS);
	}

	static isButtonEnable(button: HTMLDivElement)
	{
		return !Dom.hasClass(button, Gradient.DISABLE_CLASS);
	}

	correctColorpickerColors()
	{
		const value = this.getValue();
		if (value !== null)
		{
			const angle = value.getAngle();
			const hexFrom = this.colorpickerFrom.getHexPreviewObject();
			const hexTo = this.colorpickerTo.getHexPreviewObject();
			const colorFrom = value.getFrom();
			const colorTo = value.getTo();
			if (value.getType() === GradientValue.TYPE_LINEAR)
			{
				if (angle === 270 || angle === 90)
				{
					const median = ColorValue.getMedian(colorFrom, colorTo).getContrast().getHex();
					hexFrom.adjustColors(median, 'transparent');
					hexTo.adjustColors(median, 'transparent');
				}
				else if (angle >= 135 && angle <= 225)
				{
					hexFrom.adjustColors(colorFrom.getContrast().getHex(), 'transparent');
					hexTo.adjustColors(colorTo.getContrast().getHex(), 'transparent');
				}
				else
				{
					hexFrom.adjustColors(colorTo.getContrast().getHex(), 'transparent');
					hexTo.adjustColors(colorFrom.getContrast().getHex(), 'transparent');
				}
			}
			else if (value.getType() === GradientValue.TYPE_RADIAL)
			{
				hexFrom.adjustColors(colorTo.getContrast().getHex(), 'transparent');
				hexTo.adjustColors(colorTo.getContrast().getHex(), 'transparent');
			}
		}
	}

	getPopup(): Popup
	{
		return this.cache.remember('popup', () => {
			return PopupManager.create({
				id: this.popupId,
				className: 'landing-ui-field-color-gradient-preset-popup',
				autoHide: true,
				bindElement: this.getPopupButton(),
				bindOptions: {
					forceTop: true,
					forceLeft: true,
				},
				offsetLeft: 15,
				angle: {offset: -5},
				padding: 0,
				contentPadding: 7,
				content: this.getPopupContent(),
				closeByEsc: true,
				targetContainer: this.popupTargetContainer,
			});
		});
	}

	getPopupContent(): HTMLDivElement
	{
		return this.cache.remember('popupContainer', () => {
			return Tag.render`
				<div class="landing-ui-field-color-gradient-preset-popup-container">
					${this.getRotateButton()}
					${this.getSwapButton()}
				</div>
			`;
		});
	}

	buildLayout(): HTMLDivElement
	{
		if (this.preset)
		{
			Dom.clean(this.getPresetContainer());
			Dom.append(this.preset.getLayout(), this.getPresetContainer());
		}
		return Tag.render`
			<div class="landing-ui-field-color-gradient">
				${this.getPresetContainer()}
				<div class="landing-ui-field-color-gradient-container">
					<div class="landing-ui-field-color-gradient-from">${this.colorpickerFrom.getLayout()}</div>
					${this.getPopupButton()}
					<div class="landing-ui-field-color-gradient-to">${this.colorpickerTo.getLayout()}</div>
				</div>
				<div class="landing-ui-field-color-gradient-switch-type-container">
					${this.getSwitchTypeButton()}
				</div>
			</div>
		`;
	}

	getContainerLayout(): HTMLDivElement
	{
		// todo: do better after change vyorstka
		return this.getLayout().querySelector('.landing-ui-field-color-gradient-container');
	}

	getPresetContainer(): HTMLDivElement
	{
		return this.cache.remember('presetContainer', () => {
			return Tag.render`<div class="landing-ui-field-color-gradient-preset-container"></div>`;
		});
	}

	getPopupButton(): HTMLDivElement
	{
		return this.cache.remember('popupButton', () => {
			return Tag.render`<span class="landing-ui-field-color-gradient-open-popup"></span>`;
		});
	}

	getSwitchTypeButton(): HTMLDivElement
	{
		return this.cache.remember('switchTypeButton', () => {
			return Tag.render`
				<span
					class="landing-ui-field-color-gradient-switch-type"
					title="${Loc.getMessage('LANDING_FIELD_COLOR-GRADIENT_SWITCH_TYPE')}"
				></span>`;
		});
	}

	getRotateButton(): HTMLDivElement
	{
		return this.cache.remember('rotateButton', () => {
			return Tag.render`
				<span
					class="landing-ui-field-color-gradient-rotate"
					title="${Loc.getMessage('LANDING_FIELD_COLOR-GRADIENT_ROTATE')}"
				></span>`;
		});
	}

	getSwapButton(): HTMLDivElement
	{
		return this.cache.remember('swapButton', () => {
			return Tag.render`
				<span
					class="landing-ui-field-color-gradient-swap"
					title="${Loc.getMessage('LANDING_FIELD_COLOR-GRADIENT_SWAP')}"
				></span>`;
		});
	}

	setPreset(preset: Preset)
	{
		this.preset = preset;
		this.preset.unsetActive();
		this.preset.subscribe('onChange', (event) => {
			this.setValue(event.getData().color);
			this.unsetColorpickerActive();
			this.onChange(event);
		});

		Dom.clean(this.getPresetContainer());
		Dom.append(preset.getLayout(), this.getPresetContainer());
	}

	getPreset(): ?Preset
	{
		return this.preset;
	}

	getValue(): ?GradientValue
	{
		return this.cache.remember('value', () => {
			if (
				this.colorpickerFrom.getValue() === null
				|| this.colorpickerTo.getValue() === null
			)
			{
				return null;
			}

			let rotate = this.getRotateButton().dataset.rotate;
			rotate = rotate ? Text.toNumber(rotate) : 0;
			const type = this.getSwitchTypeButton().dataset.type || GradientValue.TYPE_LINEAR;

			return new GradientValue({
				from: this.colorpickerFrom.getValue(),
				to: this.colorpickerTo.getValue(),
				angle: rotate,
				type: type,
			});
		});
	}

	setValue(value: ?GradientValue)
	{
		super.setValue(value);

		if (value === null)
		{
			this.colorpickerFrom.setValue(null);
			this.colorpickerTo.setValue(null);

			this.unsetActive();

			Dom.style(this.getContainerLayout(), 'background', (new GradientValue).getStyleString());

			Gradient.disableButton(this.getRotateButton());
			Gradient.disableButton(this.getSwitchTypeButton());
			Gradient.disableButton(this.getSwapButton());
		}
		else
		{
			// todo: how set default type and rotation?
			this.colorpickerFrom.setValue(value.getFrom());
			this.colorpickerTo.setValue(value.getTo());
			this.correctColorpickerColors();

			this.getRotateButton().dataset.rotate = value.getAngle();
			this.getSwitchTypeButton().dataset.type = value.getType();

			Dom.style(this.getRotateButton(), 'transform', `rotate(${value.getAngle()}deg)`);
			Dom.style(this.getContainerLayout(), 'background', this.getValue().getStyleString());

			Gradient.enableButton(this.getSwitchTypeButton());
			Gradient.enableButton(this.getSwapButton());
			if (value.getType() === GradientValue.TYPE_RADIAL)
			{
				Gradient.disableButton(this.getRotateButton())
				this.getSwitchTypeButton().innerText = Loc.getMessage('LANDING_FIELD_COLOR-GRADIENT_DO_LINEAR');
			}
			else
			{
				Gradient.enableButton(this.getRotateButton());
				this.getSwitchTypeButton().innerText = Loc.getMessage('LANDING_FIELD_COLOR-GRADIENT_DO_RADIAL');
			}

			this.setActive();
		}
	}

	onChange(event: ?BaseEvent)
	{
		this.cache.delete('value');
		this.emit('onChange', {gradient: this.getValue()});
	}

	setActive(): void
	{
		const value = this.getValue();
		if (this.preset.isPresetValue(value))
		{
			this.preset.setActiveValue(value);
			this.unsetColorpickerActive();
		}
		else
		{
			this.preset.unsetActive();
			this.setColorpickerActive();
		}
	}

	unsetActive(): void
	{
		this.preset.unsetActive();
		this.unsetColorpickerActive();
	}

	setColorpickerActive(): void
	{
		Dom.addClass(this.getContainerLayout(), Gradient.ACTIVE_CLASS);
	}

	unsetColorpickerActive(): void
	{
		this.colorpickerFrom.unsetActive();
		this.colorpickerTo.unsetActive();
		Dom.removeClass(this.getContainerLayout(), Gradient.ACTIVE_CLASS);
	}
}