Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
5.9 kB
2
Indexable
Never
<script>
	class Timer {
		constructor(selectors) {
			this.sec = 0;
			this.min = 0;
			this.running = false;
			this.startTime = 0; // Timestamp.
			this.timerTime = [0, 0]; // Minutes and seconds.
			this.timerCastInterval;
			this.selectors = {
				wrapper: '',
				inputMin: '',
				inputSec: '',
				btnStart: '',
				btnStop: '',
				timerPreview: '',
				timerPreviewCast: ''
			};
			this.uiElements = {
				wrapper: null,
				inputMin: null,
				inputSec: null,
				btnStart: null,
				btnStop: null,
				timerPreview: null,
				timerPreviewCast: null,
			}

			this.setInterface(selectors);
			this.addInterfaceListeners();
		}

		setInterface(selectors) {
			const that = this;
			this.selectors = {...this.selectors, ...selectors};

			Object.keys(this.selectors).forEach(key => {
				if (that.selectors[key].length > 0) {
					const el = document.querySelector(that.selectors[key]);
					if (el !== null) {
						that.uiElements[key] = el;
					}
				}
			});

		}

		addInterfaceListeners() {
			const that = this;

			// Start.
			if (this.uiElements.btnStart !== null) {
				this.uiElements.btnStart.addEventListener('click', function () {
					if (!that.isRunning()) {
						that.start();
					}
				});
			}

			// Stop.
			if (this.uiElements.btnStop !== null) {
				this.uiElements.btnStop.addEventListener('click', function () {
					if (that.isRunning()) {
						that.stop();

					}
				});
			}
		};

		setSec(sec) {

			if (this.isRunning() || isNaN(sec)) {
				return;
			}

			this.sec = this.sanitizeSec(sec);
		}

		setMin(min) {

			if (this.isRunning() || isNaN(min)) {
				return;
			}

			this.min = this.sanitizeMin(min);
		}

		sanitizeSec(sec) {
			if (isNaN(sec)) {
				sec = 0;
			}
			sec = parseInt(sec);

			if (sec < 0) {
				sec = 0;
			}

			if (sec > 59) {
				sec = 59;
			}
			return sec;
		}

		sanitizeMin(min) {
			if (isNaN(min)) {
				min = 0;
			}
			min = parseInt(min);
			if (min < 0) {
				min = 0;
			}
			return min;
		}

		isRunning() {
			return this.running;
		}

		getCurrentTime() {
			// Timestamp.
			return Math.floor(new Date().getTime() / 1000);
		}

		setStartTime() {
			this.startTime = this.getCurrentTime() - this.sec - this.min * 60;
		}

		resetStartTime() {
			this.startTime = 0;
		}

		manageDynamicClasses(action) {

			// Wrapper class.
			if (this.uiElements.wrapper !== null) {
				const toAdd = action === 'stop' ? 'timer-stopped' : 'timer-running';
				const toRemove = action === 'stop' ? 'timer-running' : 'timer-stopped';
				this.uiElements.wrapper.classList.add(toAdd);
				this.uiElements.wrapper.classList.remove(toRemove);
			}

			if (action === 'start') {
				this.uiElements.btnStart.disabled = true;
				this.uiElements.inputMin.disabled = true;
				this.uiElements.inputSec.disabled = true;

				this.uiElements.btnStop.disabled = false;
			}

			if (action === 'stop') {
				this.uiElements.btnStart.disabled = false;
				this.uiElements.inputMin.disabled = false;
				this.uiElements.inputSec.disabled = false;

				this.uiElements.btnStop.disabled = true;
			}

		}

		start() {

			if (this.isRunning()) {
				return;
			}

			this.updateTimeFromInputs();
			this.setStartTime();
			this.updateTime();
			this.cast();
			this.manageDynamicClasses('start');

			this.running = true;
		}

		stop() {
			this.updateTime();
			this.running = false;
			this.resetStartTime();
			this.stopCast();
			this.manageDynamicClasses('stop');
			this.updateTimeInputs();
		}

		updateTime() {

			if (!this.isRunning()) {
				return;
			}

			const diffSeconds = this.getCurrentTime() - this.startTime;

			this.min = Math.floor(diffSeconds / 60);
			this.sec = diffSeconds % 60;
		}

		getTimerTime() {
			this.updateTime();
			return [this.min, this.sec];
		}

		formatTimeNumber(number) {
			return number < 10 ? '0' + number : number;
		}

		getFormattedTimerTime() {
			const time = this.getTimerTime();
			const minutesFormatted = this.formatTimeNumber(time[0]);
			const secondsFormatted = this.formatTimeNumber(time[1]);

			return minutesFormatted + ':' + secondsFormatted;
		}

		updateTimeFromInputs() {
			const sec = this.uiElements.inputSec.value;
			const min = this.uiElements.inputMin.value;

			if (sec.length > 0 && !isNaN(sec)) {
				this.setSec(sec);
				this.uiElements.inputSec.value = this.formatTimeNumber(this.sanitizeSec(sec));
			}

			if (min.length > 0  && !isNaN(min)) {
				this.setMin(min);
				this.uiElements.inputMin.value = this.formatTimeNumber(this.sanitizeMin(min));
			}
		}

		updateTimeInputs() {
			this.uiElements.inputMin.value = this.formatTimeNumber(this.min);
			this.uiElements.inputSec.value = this.formatTimeNumber(this.sec);
		}

		cast() {
			const that = this;

			this.timerCastInterval = setInterval(function () {
				const time = that.getFormattedTimerTime();
				if (that.uiElements.timerPreview !== null) {
					that.uiElements.timerPreview.innerHTML = time;
				}
			}, 100);
		}

		stopCast() {
			clearInterval(this.timerCastInterval);
		}
	}


	document.addEventListener("DOMContentLoaded", function () {
		window.timer = new Timer({
			wrapper: '.js-timer-wrapper',
			inputMin: '.js-timer-min',
			inputSec: '.js-timer-sec',
			btnStart: '.js-timer-start',
			btnStop: '.js-timer-stop',
			timerPreview: '.timer-preview',
			timerPreviewCast: ''
		});
	});


</script>

<div class="js-timer-wrapper">
	<div class="timer-preview">00:00</div>
	<input type="text" value="" name="timer-min" class="js-timer-min" placeholder="min">
	<input type="text" value="" name="timer-sec" class="js-timer-sec" placeholder="sec">
	<button class="js-timer-start">Start</button>
	<button class="js-timer-stop">Stop</button>
</div>
Leave a Comment