gradient-array-slider / index.html
djuna's picture
Update index.html
99a6e86 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic Sliders with Editable Values and Array Upscaler</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 800px;
}
.input-section {
margin-bottom: 20px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 10px;
justify-content: center;
}
.input-section label {
font-weight: bold;
margin-bottom: 5px;
display: block;
}
.input-section input[type="number"] {
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
width: 100%;
box-sizing: border-box;
}
/* Add media query to adjust grid template columns on smaller screens */
@media (max-width: 768px) {
.input-section {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
}
@media (max-width: 480px) {
.input-section {
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
}
}
#sliders {
display: flex;
flex-direction: column;
}
.slider-container {
display: flex;
align-items: center;
width: 100%;
}
.slider-index {
width: 30px;
text-align: right;
font-weight: bold;
color: #333;
flex-shrink: 0;
}
.slider-wrapper {
flex-grow: 1;
display: flex;
align-items: center;
gap: 10px;
}
.slider-wrapper input[type="range"] {
width: 100%;
box-sizing: border-box;
}
.slider-number {
width: 70px;
text-align: left;
font-weight: bold;
color: #333;
flex-shrink: 0;
cursor: pointer;
}
.slider-number input {
width: 100%;
box-sizing: border-box;
}
.middle-slider .slider-index,
.middle-slider .slider-wrapper input[type="range"] {
background-color: #ffcccb;
}
.output {
margin-top: 20px;
font-weight: bold;
color: #333;
}
.output span {
color: #007bff;
}
.error-message {
color: red;
font-weight: bold;
margin-top: 10px;
}
.close-button {
cursor: pointer;
color: red;
font-weight: bold;
margin-left: 5px;
}
.array-upscaler {
margin-top: 40px;
}
.array-upscaler h2 {
margin-bottom: 10px;
}
.array-upscaler p {
margin: 10px 0;
}
.array-upscaler button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.array-upscaler button:hover {
background-color: #0056b3;
}
.array-upscaler #result {
margin-top: 20px;
font-weight: bold;
color: #333;
}
</style>
</head>
<body>
<div class="container">
<div class="input-section">
<div>
<label for="numSliders">Number of Sliders:</label>
<input type="number" id="numSliders" min="1" value="1" oninput="updateSliders()">
</div>
<div>
<label for="minValue">Minimum Value:</label>
<input type="number" id="minValue" step="0.01" value="0.00" oninput="updateSliders()">
</div>
<div>
<label for="maxValue">Maximum Value:</label>
<input type="number" id="maxValue" step="0.01" value="100.00" oninput="updateSliders()">
</div>
<div>
<label for="sliderWidth">Slider Width (%):</label>
<input type="number" id="sliderWidth" min="10" max="100" value="100" oninput="updateSliderStyles()">
</div>
<div>
<label for="sliderMargin">Slider Margin (px):</label>
<input type="number" id="sliderMargin" min="0" value="10" oninput="updateSliderStyles()">
</div>
<div>
<label for="sliderStep">Slider Step:</label>
<input type="number" id="sliderStep" min="0.01" step="0.01" value="0.01" oninput="updateSliderStep()">
</div>
</div>
<div id="sliders"></div>
<div class="output">
<label>Slider Values:</label>
<span id="sliderValues">[]</span>
</div>
<div id="errorMessage" class="error-message"></div>
<!-- Array Upscaler Section -->
<div class="array-upscaler">
<h2>Array Upscaler</h2>
<p>
Upscaled Length:
<input type="number" id="newLength" min="1" value="5">
</p>
<button onclick="upscaleArray()">Upscale Array</button>
<h3>Upscaled Array:</h3>
<div id="result"></div>
</div>
</div>
<script>
function updateSliderStyles() {
const sliderWidth = document.getElementById('sliderWidth').value;
const sliderMargin = document.getElementById('sliderMargin').value;
const sliders = document.querySelectorAll('.slider-wrapper input[type="range"]');
sliders.forEach(slider => {
slider.style.width = `${sliderWidth}%`;
});
const sliderContainers = document.querySelectorAll('.slider-container');
sliderContainers.forEach(sliderContainer => {
sliderContainer.style.margin = `${sliderMargin}px 0`;
});
}
function updateSliderStep() {
const step = document.getElementById('sliderStep').value;
const sliders = document.querySelectorAll('#sliders input[type="range"]');
sliders.forEach(slider => {
slider.step = step;
});
}
function createSliders() {
const numSliders = parseInt(document.getElementById('numSliders').value);
const minValue = parseFloat(document.getElementById('minValue').value);
const maxValue = parseFloat(document.getElementById('maxValue').value);
const sliderStep = parseFloat(document.getElementById('sliderStep').value);
const slidersContainer = document.getElementById('sliders');
slidersContainer.innerHTML = ''; // Clear previous sliders
for (let i = 0; i < numSliders; i++) {
const sliderContainer = document.createElement('div');
sliderContainer.className = 'slider-container';
const sliderIndex = document.createElement('span');
sliderIndex.className = 'slider-index';
sliderIndex.textContent = i + 1;
const sliderWrapper = document.createElement('div');
sliderWrapper.className = 'slider-wrapper';
const slider = document.createElement('input');
slider.type = 'range';
slider.min = minValue;
slider.max = maxValue;
slider.value = minValue;
slider.step = sliderStep;
slider.oninput = updateValues;
const sliderNumber = document.createElement('span');
sliderNumber.className = 'slider-number';
sliderNumber.textContent = minValue.toFixed(2);
sliderNumber.onclick = function() {
makeEditable(sliderNumber, slider);
};
sliderWrapper.appendChild(slider);
sliderWrapper.appendChild(sliderNumber);
sliderContainer.appendChild(sliderIndex);
sliderContainer.appendChild(sliderWrapper);
slidersContainer.appendChild(sliderContainer);
// Highlight the middle slider if the total number of sliders is odd
if (numSliders % 2 !== 0 && i === Math.floor(numSliders / 2)) {
sliderContainer.classList.add('middle-slider');
}
}
updateValues(); // Initial update
updateSliderStyles(); // Apply initial styles
}
function updateSliders() {
const numSlidersInput = document.getElementById('numSliders').value;
const minValue = parseFloat(document.getElementById('minValue').value);
const maxValue = parseFloat(document.getElementById('maxValue').value);
const sliderStep = parseFloat(document.getElementById('sliderStep').value);
const slidersContainer = document.getElementById('sliders');
const errorMessage = document.getElementById('errorMessage');
// Validate the number of sliders input
if (!numSlidersInput || isNaN(numSlidersInput) || parseInt(numSlidersInput) < 1) {
errorMessage.textContent = 'Please enter a valid number of sliders (greater than 0).';
slidersContainer.innerHTML = ''; // Clear sliders if input is invalid
return;
} else {
errorMessage.textContent = ''; // Clear error message if input is valid
}
const numSliders = parseInt(numSlidersInput);
const currentSliders = document.querySelectorAll('#sliders input[type="range"]');
// Preserve existing slider values when reducing number of sliders
const existingValues = Array.from(currentSliders).map(slider => parseFloat(slider.value));
slidersContainer.innerHTML = ''; // Clear existing sliders
for (let i = 0; i < numSliders; i++) {
const sliderContainer = document.createElement('div');
sliderContainer.className = 'slider-container';
const sliderIndex = document.createElement('span');
sliderIndex.className = 'slider-index';
sliderIndex.textContent = i + 1;
const sliderWrapper = document.createElement('div');
sliderWrapper.className = 'slider-wrapper';
const slider = document.createElement('input');
slider.type = 'range';
slider.min = minValue;
slider.max = maxValue;
slider.step = sliderStep;
slider.oninput = updateValues;
const sliderNumber = document.createElement('span');
sliderNumber.className = 'slider-number';
sliderNumber.onclick = function() {
makeEditable(sliderNumber, slider);
};
// Use preserved value or default to minValue
const preservedValue = existingValues[i] !== undefined
? Math.max(minValue, Math.min(maxValue, existingValues[i]))
: minValue;
slider.value = preservedValue;
sliderNumber.textContent = preservedValue.toFixed(2);
sliderWrapper.appendChild(slider);
sliderWrapper.appendChild(sliderNumber);
sliderContainer.appendChild(sliderIndex);
sliderContainer.appendChild(sliderWrapper);
slidersContainer.appendChild(sliderContainer);
// Highlight the middle slider if the total number of sliders is odd
if (numSliders % 2 !== 0 && i === Math.floor(numSliders / 2)) {
sliderContainer.classList.add('middle-slider');
}
}
updateValues(); // Update the displayed values
updateSliderStyles(); // Apply styles
}
function updateValues() {
const sliders = document.querySelectorAll('#sliders input[type="range"]');
const values = Array.from(sliders).map(slider => {
const value = parseFloat(slider.value);
slider.nextElementSibling.textContent = value.toFixed(2); // Update the number next to the slider
return value;
});
document.getElementById('sliderValues').textContent = JSON.stringify(values);
}
function makeEditable(sliderNumber, slider) {
const currentValue = sliderNumber.textContent;
const container = document.createElement('div'); // Create a container to hold input and button
const input = document.createElement('input');
input.type = 'number';
input.value = currentValue;
input.min = slider.min;
input.max = slider.max;
input.step = slider.step;
input.style.width = '100%';
input.style.boxSizing = 'border-box';
const closeButton = document.createElement('span');
closeButton.className = 'close-button';
closeButton.textContent = 'X';
closeButton.onclick = function() {
input.blur(); // Trigger blur event to revert to text
};
container.appendChild(input); // Append input and button to container
container.appendChild(closeButton);
const originalSliderNumber = sliderNumber.cloneNode(true); // Clone original sliderNumber for later use
originalSliderNumber.onclick = function() { makeEditable(originalSliderNumber, slider); }; // Reattach onclick event
sliderNumber.replaceWith(container); // Replace sliderNumber with the container
input.onblur = function() {
const newValue = parseFloat(input.value);
if (!isNaN(newValue) && newValue >= parseFloat(slider.min) && newValue <= parseFloat(slider.max)) {
slider.value = newValue;
originalSliderNumber.textContent = newValue.toFixed(2); // Update sliderNumber text
} else {
originalSliderNumber.textContent = currentValue; // Revert to original value if invalid
}
container.replaceWith(originalSliderNumber); // Replace container with original sliderNumber
updateValues(); // Update displayed values
};
input.onkeydown = function(event) {
if (event.key === 'Enter') {
input.blur(); // Trigger blur event on Enter key press
}
};
input.focus(); // Focus on the input field
}
// Initial call to create sliders
createSliders();
// Function to upscale the array
function upscaleArray() {
// Get slider values
const sliders = document.querySelectorAll('#sliders input[type="range"]');
const originalArray = Array.from(sliders).map(slider => parseFloat(slider.value));
const newLengthInput = document.getElementById('newLength').value;
const newLength = parseInt(newLengthInput, 10);
// Validate inputs
if (originalArray.length === 0 || isNaN(newLength) || newLength < 1) {
document.getElementById('result').innerHTML = 'Invalid input.';
return;
}
// If new length is less than or equal to original, return original array
if (newLength <= originalArray.length) {
document.getElementById('result').innerHTML = originalArray.join(', ');
return;
}
// Calculate the step size
const step = (originalArray.length - 1) / (newLength - 1);
// Create the upscaled array
const upscaledArray = [];
for (let j = 0; j < newLength; j++) {
const i = j * step;
const lower = Math.floor(i);
const upper = Math.ceil(i);
const fraction = i - lower;
// Handle edge cases where upper is out of bounds
if (upper >= originalArray.length) {
upper = originalArray.length - 1;
fraction = 0;
}
// Linear interpolation
const value = originalArray[lower] + fraction * (originalArray[upper] - originalArray[lower]);
upscaledArray.push(value.toFixed(3)); // Display one decimal place
}
// Display the result
document.getElementById('result').innerHTML = upscaledArray.join(', ');
}
</script>
</body>
</html>