Source: frontend-js-web/src/main/resources/META-INF/resources/liferay/compat/slider/Slider.es.js

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

import core from 'metal';
import Component from 'metal-component';
import dom from 'metal-dom';
import {Drag} from 'metal-drag-drop';
import Position from 'metal-position';
import Soy from 'metal-soy';

import templates from './Slider.soy';

/**
 * Slider component.
 * @deprecated since 7.2
 */

class Slider extends Component {
	/**
	 * @inheritDoc
	 */

	attached() {
		this.drag_ = new Drag({
			axis: 'x',
			constrain: this.constrainToRail_.bind(this),
			container: this.element,
			handles: '.handle',
			sources: '.rail-handle'
		});
		this.on('elementChanged', this.handleElementChanged_);

		this.attachDragEvents_();
	}

	/**
	 * Attaches the drag events to handle value updates when dragging the rail handle.
	 * protected
	 */

	attachDragEvents_() {
		this.drag_.on(
			Drag.Events.DRAG,
			this.updateValueFromDragData_.bind(this)
		);
		this.drag_.on(
			Drag.Events.END,
			this.updateValueFromDragData_.bind(this)
		);
	}

	/**
	 * Constrains the given region to be inside the rail. This is being used
	 * instead of `Drag`'s default behavior, because `Drag` would require the
	 * whole handle to be inside the rail element, while we just want to make sure
	 * that the left side of the handle is inside it.
	 * @param {!Object} region
	 * @protected
	 */

	constrainToRail_(region) {
		const constrain = Position.getRegion(this.refs.rail, true);
		if (region.left < constrain.left) {
			region.left = constrain.left;
		} else if (region.left > constrain.right) {
			region.left -= region.left - constrain.right;
		}
		region.right = region.left + region.width;
	}

	/**
	 * @inheritDoc
	 */

	disposeInternal() {
		super.disposeInternal();
		this.drag_.dispose();
	}

	/**
	 * Returns the `Drag` instance being used.
	 * @return {!Drag}
	 */

	getDrag() {
		return this.drag_;
	}

	/**
	 * Handles the `elementChanged` event. Updates the drag container to the new
	 * element, and also updates the constrain element.
	 * @param {!Object} data
	 * @protected
	 */

	handleElementChanged_(data) {
		if (data.newVal) {
			this.drag_.container = data.newVal;
		}
	}

	/**
	 * Handles mouse down actions on the slider rail and updates the slider value accordingly.
	 * @param {!Event} event
	 * @protected
	 */

	onRailClick_(event) {
		if (
			dom.hasClass(event.target, 'rail') ||
			dom.hasClass(event.target, 'rail-active')
		) {
			const prevValue = this.value;
			this.updateValue_(event.offsetX, 0, true);
			if (prevValue === this.value) {
				const handleRegion = Position.getRegion(this.refs.handle);
				if (event.offsetX < handleRegion.left) {
					this.value -= 1;
				} else {
					this.value += 1;
				}
			}
		}
	}

	/**
	 * Synchronizes the slider UI with the `max` state key.
	 * @param {number} newVal The new value of the state key.
	 */

	syncMax(newVal) {
		if (newVal < this.value) {
			this.value = newVal;
		}
	}

	/**
	 * Synchronizes the slider UI with the `min` state key.
	 * @param {number} newVal The new value of the state key.
	 */

	syncMin(newVal) {
		if (newVal > this.value) {
			this.value = newVal;
		}
	}

	/**
	 * Updates the slider value based on the UI state of the handle element.
	 * @param {number} handlePosition Position of the handle in px.
	 * @param {number} offset Offset to be added to normalize relative inputs.
	 * @param {boolean=} opt_relative If the given position is relative to the
	 *     rail or not.
	 * @protected
	 */

	updateValue_(handlePosition, offset, opt_relative) {
		var region = Position.getRegion(this.element);
		if (!opt_relative) {
			handlePosition -= region.left;
		}
		this.value = Math.round(
			offset + (handlePosition / region.width) * (this.max - this.min)
		);
	}

	/**
	 * Handles Drag events from the rail handle and updates the slider value accordingly.
	 * @param {!Object} data
	 * @protected
	 */

	updateValueFromDragData_(data, event) {
		this.updateValue_(data.x, this.min);
		event.preventDefault();
	}
}
Soy.register(Slider, templates);

/**
 * `Slider`'s state definition.
 */

Slider.STATE = {
	/**
	 * Name of the hidden input field that holds the slider value. Useful when slider is embedded
	 * inside a form so it can automatically send its value.
	 * @type {string}
	 */

	inputName: {
		validator: core.isString
	},

	/**
	 * Defines the maximum value handled by the slider.
	 * @type {number}
	 * @default 100
	 */

	max: {
		value: 100
	},

	/**
	 * Defines the minimum value handled by the slider.
	 * @type {number}
	 * @default 0
	 */

	min: {
		value: 0
	},

	/**
	 * Defines the currently selected value on the slider.
	 * @type {number}
	 * @default 0
	 */

	value: {
		validator(val) {
			return core.isNumber(val) && this.min <= val && val <= this.max;
		},
		value: 0
	}
};

export {Slider};
export default Slider;