mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 09:56:15 +02:00
268 lines
9.2 KiB
JavaScript
268 lines
9.2 KiB
JavaScript
// draggableNumber.js
|
|
//
|
|
// Created by David Back on 7 Nov 2018
|
|
// Copyright 2018 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
|
|
const DELTA_X_FOCUS_THRESHOLD = 1;
|
|
const ENTER_KEY = 13;
|
|
|
|
function DraggableNumber(min, max, step, decimals, dragStart, dragEnd) {
|
|
this.min = min;
|
|
this.max = max;
|
|
this.step = step !== undefined ? step : 1;
|
|
this.multiDiffModeEnabled = false;
|
|
this.decimals = decimals;
|
|
this.dragStartFunction = dragStart;
|
|
this.dragEndFunction = dragEnd;
|
|
this.dragging = false;
|
|
this.initialMouseEvent = null;
|
|
this.lastMouseEvent = null;
|
|
this.valueChangeFunction = null;
|
|
this.multiDiffStepFunction = null;
|
|
this.initialize();
|
|
}
|
|
|
|
DraggableNumber.prototype = {
|
|
showInput: function() {
|
|
this.elText.style.visibility = "hidden";
|
|
this.elLeftArrow.style.visibility = "hidden";
|
|
this.elRightArrow.style.visibility = "hidden";
|
|
this.elInput.style.opacity = 1;
|
|
},
|
|
|
|
hideInput: function() {
|
|
this.elText.style.visibility = "visible";
|
|
this.elLeftArrow.style.visibility = "visible";
|
|
this.elRightArrow.style.visibility = "visible";
|
|
this.elInput.style.opacity = 0;
|
|
},
|
|
|
|
mouseDown: function(event) {
|
|
if (event.target === this.elText && !this.isDisabled()) {
|
|
this.initialMouseEvent = event;
|
|
this.lastMouseEvent = event;
|
|
document.addEventListener("mousemove", this.onDocumentMouseMove);
|
|
document.addEventListener("mouseup", this.onDocumentMouseUp);
|
|
}
|
|
},
|
|
|
|
mouseUp: function(event) {
|
|
if (!this.dragging && event.target === this.elText && this.initialMouseEvent) {
|
|
let dx = event.clientX - this.initialMouseEvent.clientX;
|
|
if (Math.abs(dx) <= DELTA_X_FOCUS_THRESHOLD) {
|
|
this.showInput();
|
|
this.elInput.focus();
|
|
}
|
|
this.initialMouseEvent = null;
|
|
}
|
|
},
|
|
|
|
documentMouseMove: function(event) {
|
|
if (!this.dragging && this.initialMouseEvent) {
|
|
let dxFromInitial = event.clientX - this.initialMouseEvent.clientX;
|
|
if (Math.abs(dxFromInitial) > DELTA_X_FOCUS_THRESHOLD) {
|
|
if (this.dragStartFunction) {
|
|
this.dragStartFunction();
|
|
}
|
|
this.dragging = true;
|
|
}
|
|
this.lastMouseEvent = event;
|
|
}
|
|
if (this.dragging && this.lastMouseEvent) {
|
|
let dragDelta = event.clientX - this.lastMouseEvent.clientX;
|
|
if (dragDelta !== 0) {
|
|
if (this.multiDiffModeEnabled) {
|
|
if (this.multiDiffStepFunction) {
|
|
this.multiDiffStepFunction(dragDelta * this.step);
|
|
}
|
|
} else {
|
|
if (dragDelta > 0) {
|
|
this.elInput.stepUp(dragDelta);
|
|
} else {
|
|
this.elInput.stepDown(-dragDelta);
|
|
}
|
|
this.inputChange();
|
|
if (this.valueChangeFunction) {
|
|
this.valueChangeFunction();
|
|
}
|
|
}
|
|
}
|
|
this.lastMouseEvent = event;
|
|
}
|
|
},
|
|
|
|
documentMouseUp: function(event) {
|
|
if (this.dragging) {
|
|
if (this.dragEndFunction) {
|
|
this.dragEndFunction();
|
|
}
|
|
this.dragging = false;
|
|
}
|
|
this.lastMouseEvent = null;
|
|
document.removeEventListener("mousemove", this.onDocumentMouseMove);
|
|
document.removeEventListener("mouseup", this.onDocumentMouseUp);
|
|
},
|
|
|
|
stepUp: function() {
|
|
if (!this.isDisabled()) {
|
|
if (this.multiDiffModeEnabled) {
|
|
if (this.multiDiffStepFunction) {
|
|
this.multiDiffStepFunction(this.step, true);
|
|
}
|
|
} else {
|
|
this.elInput.value = parseFloat(this.elInput.value) + this.step;
|
|
this.inputChange();
|
|
if (this.valueChangeFunction) {
|
|
this.valueChangeFunction();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
stepDown: function() {
|
|
if (!this.isDisabled()) {
|
|
if (this.multiDiffModeEnabled) {
|
|
if (this.multiDiffStepFunction) {
|
|
this.multiDiffStepFunction(-this.step, true);
|
|
}
|
|
} else {
|
|
this.elInput.value = parseFloat(this.elInput.value) - this.step;
|
|
this.inputChange();
|
|
if (this.valueChangeFunction) {
|
|
this.valueChangeFunction();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
setValue: function(newValue, isMultiDiff) {
|
|
if (isMultiDiff !== undefined) {
|
|
this.setMultiDiff(isMultiDiff);
|
|
}
|
|
|
|
if (isNaN(newValue)) {
|
|
console.error("DraggableNumber.setValue() > " + newValue + " is not a number.");
|
|
return;
|
|
}
|
|
|
|
if (newValue !== "" && this.decimals !== undefined) {
|
|
this.elInput.value = parseFloat(newValue).toFixed(this.decimals);
|
|
} else {
|
|
this.elInput.value = newValue;
|
|
}
|
|
this.elText.firstChild.data = this.elInput.value;
|
|
},
|
|
|
|
setMultiDiff: function(isMultiDiff) {
|
|
this.multiDiffModeEnabled = isMultiDiff;
|
|
if (isMultiDiff) {
|
|
this.elDiv.classList.add('multi-diff');
|
|
} else {
|
|
this.elDiv.classList.remove('multi-diff');
|
|
}
|
|
},
|
|
|
|
setValueChangeFunction: function(valueChangeFunction) {
|
|
this.valueChangeFunction = valueChangeFunction.bind(this.elInput);
|
|
this.elInput.addEventListener("change", this.valueChangeFunction);
|
|
},
|
|
|
|
setMultiDiffStepFunction: function (multiDiffStepFunction) {
|
|
this.multiDiffStepFunction = multiDiffStepFunction;
|
|
},
|
|
|
|
inputChange: function() {
|
|
let value = this.elInput.value;
|
|
if (this.max !== undefined) {
|
|
value = Math.min(this.max, value);
|
|
}
|
|
if (this.min !== undefined) {
|
|
value = Math.max(this.min, value);
|
|
}
|
|
this.setValue(value);
|
|
},
|
|
|
|
inputBlur: function(ev) {
|
|
this.hideInput();
|
|
},
|
|
|
|
keyPress: function(event) {
|
|
if (event.keyCode === ENTER_KEY) {
|
|
if (this.valueChangeFunction) {
|
|
this.valueChangeFunction();
|
|
}
|
|
this.inputBlur();
|
|
}
|
|
},
|
|
|
|
isDisabled: function() {
|
|
return this.elText.getAttribute("disabled") === "disabled";
|
|
},
|
|
|
|
updateMinMax: function(min, max) {
|
|
this.min = min;
|
|
this.max = max;
|
|
if (this.min !== undefined) {
|
|
this.elInput.setAttribute("min", this.min);
|
|
}
|
|
if (this.max !== undefined) {
|
|
this.elInput.setAttribute("max", this.max);
|
|
}
|
|
},
|
|
|
|
initialize: function() {
|
|
this.onMouseDown = this.mouseDown.bind(this);
|
|
this.onMouseUp = this.mouseUp.bind(this);
|
|
this.onDocumentMouseMove = this.documentMouseMove.bind(this);
|
|
this.onDocumentMouseUp = this.documentMouseUp.bind(this);
|
|
this.onStepUp = this.stepUp.bind(this);
|
|
this.onStepDown = this.stepDown.bind(this);
|
|
this.onInputChange = this.inputChange.bind(this);
|
|
this.onInputBlur = this.inputBlur.bind(this);
|
|
this.onKeyPress = this.keyPress.bind(this);
|
|
|
|
this.elDiv = document.createElement('div');
|
|
this.elDiv.className = "draggable-number";
|
|
|
|
this.elText = document.createElement('span');
|
|
this.elText.className = "text";
|
|
this.elText.innerText = " ";
|
|
this.elText.style.visibility = "visible";
|
|
this.elText.addEventListener("mousedown", this.onMouseDown);
|
|
this.elText.addEventListener("mouseup", this.onMouseUp);
|
|
|
|
this.elLeftArrow = document.createElement('span');
|
|
this.elRightArrow = document.createElement('span');
|
|
this.elLeftArrow.className = 'left-arrow';
|
|
this.elLeftArrow.innerHTML = 'D';
|
|
this.elLeftArrow.addEventListener("click", this.onStepDown);
|
|
this.elRightArrow.className = 'right-arrow';
|
|
this.elRightArrow.innerHTML = 'D';
|
|
this.elRightArrow.addEventListener("click", this.onStepUp);
|
|
|
|
this.elMultiDiff = document.createElement('span');
|
|
this.elMultiDiff.className = 'multi-diff';
|
|
|
|
this.elInput = document.createElement('input');
|
|
this.elInput.className = "input";
|
|
this.elInput.setAttribute("type", "number");
|
|
this.updateMinMax(this.min, this.max);
|
|
if (this.step !== undefined) {
|
|
this.elInput.setAttribute("step", this.step);
|
|
}
|
|
this.elInput.style.opacity = 0;
|
|
this.elInput.addEventListener("change", this.onInputChange);
|
|
this.elInput.addEventListener("blur", this.onInputBlur);
|
|
this.elInput.addEventListener("keypress", this.onKeyPress);
|
|
this.elInput.addEventListener("focus", this.showInput.bind(this));
|
|
|
|
this.elDiv.appendChild(this.elLeftArrow);
|
|
this.elDiv.appendChild(this.elText);
|
|
this.elDiv.appendChild(this.elInput);
|
|
this.elDiv.appendChild(this.elMultiDiff);
|
|
this.elDiv.appendChild(this.elRightArrow);
|
|
}
|
|
};
|