Spaces:
Running
Running
<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> |