Skip to content

Instantly share code, notes, and snippets.

@fgouin2014
Created July 9, 2024 02:53
Show Gist options
  • Save fgouin2014/622d5eb0081cadde676494ebc4886f2c to your computer and use it in GitHub Desktop.
Save fgouin2014/622d5eb0081cadde676494ebc4886f2c to your computer and use it in GitHub Desktop.
Hey5
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Multi-Bulb Smart Light Control</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.4.5/jscolor.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
text-align: center;
}
.bulb-control {
border: 1px solid #ddd;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.control-item {
margin-bottom: 10px;
display: flex;
align-items: center;
}
.color-presets {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.preset-category {
width: 100%;
}
.preset-label {
font-weight: bold;
margin-bottom: 5px;
}
.preset-row {
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.color-preset {
width: 30px;
height: 30px;
border-radius: 50%;
cursor: pointer;
}
#masterControlSection {
border: 1px solid #ddd;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.bulb-icon {
margin-left: 10px;
width: 34px;
height: 34px;
}
.bulb-icon.on .bulb-fill {
fill: yellow;
filter: drop-shadow(0 0 5px yellow);
}
.bulb-icon.off .bulb-fill {
fill: #CCD2D8;
}
.bulb-outline {
fill: #000000;
}
.switch {
position: relative;
display: inline-block;
width: 34px;
height: 60px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 34px;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
input:checked + .slider {
background-color: #2196F3;
}
input:checked + .slider:before {
transform: translateY(-26px);
}
</style>
</head>
<body>
<h1>Multi-Bulb Smart Light Control</h1>
<div id="masterControlSection">
<h2>Master Control</h2>
<div class="control-item">
<label class="switch">
<input type="checkbox" id="masterToggle">
<span class="slider"></span>
</label>
<svg class="bulb-icon" width="34" height="34" viewBox="0 0 48 48">
<path class="bulb-outline" d="M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6C7.8 12.16 7 10.63 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z" />
<path class="bulb-fill" d="M11 4c-2.76 0-5 2.24-5 5c0 1.63.8 3.16 2.15 4.1l.85.6V16h4v-2.3l.85-.6C15.2 12.16 16 10.63 16 9c0-2.76-2.24-5-5-5z" />
</svg>
</div>
<div class="control-item">
<label for="masterBrightness">Master Brightness:</label>
<input type="range" id="masterBrightness" min="0" max="100" value="50">
<span id="masterBrightnessValue">50%</span>
</div>
<div class="control-item">
<label for="masterColor">Master Color:</label>
<input type="text" id="masterColor" data-jscolor="{}" value="#FFFFFF">
</div>
<div class="color-presets" id="masterColorPresets"></div>
</div>
<div id="bulbControls"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const bulbCount = 5;
const bulbControls = document.getElementById('bulbControls');
const masterToggle = document.getElementById('masterToggle');
const masterBrightness = document.getElementById('masterBrightness');
const masterBrightnessValue = document.getElementById('masterBrightnessValue');
const masterColor = document.getElementById('masterColor');
const masterColorPresets = document.getElementById('masterColorPresets');
const masterBulbIcon = document.querySelector('#masterControlSection .bulb-icon');
function createBulbControl(id) {
const bulbControl = document.createElement('div');
bulbControl.className = 'bulb-control';
bulbControl.innerHTML = `
<h3>Bulb ${id}</h3>
<div class="control-item">
<label class="switch">
<input type="checkbox" class="bulbToggle" data-id="${id}">
<span class="slider"></span>
</label>
<svg class="bulb-icon" width="34" height="34" viewBox="0 0 48 48">
<path class="bulb-outline" d="M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6C7.8 12.16 7 10.63 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z" />
<path class="bulb-fill" d="M11 4c-2.76 0-5 2.24-5 5c0 1.63.8 3.16 2.15 4.1l.85.6V16h4v-2.3l.85-.6C15.2 12.16 16 10.63 16 9c0-2.76-2.24-5-5-5z" />
</svg>
</div>
<div class="control-item">
<label for="brightness${id}">Brightness:</label>
<input type="range" id="brightness${id}" class="bulbBrightness" min="0" max="100" value="50" data-id="${id}">
<span class="brightnessValue">50%</span>
</div>
<div class="control-item">
<label for="color${id}">Color:</label>
<input type="text" id="color${id}" class="bulbColor" data-jscolor="{}" data-id="${id}">
</div>
<div class="color-presets"></div>
`;
return bulbControl;
}
for (let i = 1; i <= bulbCount; i++) {
bulbControls.appendChild(createBulbControl(i));
}
function updateBulbIcon(bulbIcon, isOn) {
bulbIcon.classList.toggle('on', isOn);
bulbIcon.classList.toggle('off', !isOn);
}
masterToggle.addEventListener('change', (e) => {
const isOn = e.target.checked;
console.log(`Master toggle ${isOn ? 'on' : 'off'}`);
document.querySelectorAll('.bulbToggle').forEach(toggle => {
const bulbIcon = toggle.closest('.control-item').querySelector('.bulb-icon');
updateBulbIcon(bulbIcon, toggle.checked && isOn);
});
updateBulbIcon(masterBulbIcon, isOn);
saveSettings();
});
function updateMasterToggle() {
const anyBulbOn = Array.from(document.querySelectorAll('.bulbToggle')).some(toggle => toggle.checked);
masterToggle.checked = anyBulbOn;
updateBulbIcon(masterBulbIcon, anyBulbOn);
}
document.querySelectorAll('.bulbToggle').forEach(toggle => {
toggle.addEventListener('change', (e) => {
const id = e.target.dataset.id;
const isOn = e.target.checked;
const bulbIcon = e.target.closest('.control-item').querySelector('.bulb-icon');
console.log(`Toggle bulb ${id} ${isOn ? 'on' : 'off'}`);
updateBulbIcon(bulbIcon, isOn && masterToggle.checked);
updateMasterToggle();
saveSettings();
});
});
masterBrightness.addEventListener('input', (e) => {
const brightness = e.target.value;
masterBrightnessValue.textContent = `${brightness}%`;
document.querySelectorAll('.bulbBrightness').forEach(slider => {
slider.value = brightness;
slider.nextElementSibling.textContent = `${brightness}%`;
});
saveSettings();
});
document.querySelectorAll('.bulbBrightness').forEach(slider => {
slider.addEventListener('input', (e) => {
const id = e.target.dataset.id;
const brightness = e.target.value;
e.target.nextElementSibling.textContent = `${brightness}%`;
console.log(`Set bulb ${id} brightness to ${brightness}%`);
saveSettings();
});
});
function updateColor(color, updateAll = false) {
if (updateAll) {
masterColor.jscolor.fromString(color);
document.querySelectorAll('.bulbColor').forEach(picker => {
picker.jscolor.fromString(color);
});
}
}
masterColor.addEventListener('change', (e) => {
const color = e.target.value;
updateColor(color, true);
saveSettings();
});
document.querySelectorAll('.bulbColor').forEach(picker => {
picker.addEventListener('change', (e) => {
const id = e.target.dataset.id;
const color = e.target.value;
console.log(`Set bulb ${id} color to ${color}`);
saveSettings();
});
});
function createColorPresets(container, updateAll = false) {
const presets = [
{ label: 'Warm', colors: ['#FF8C00', '#FFA500', '#FFD700', '#FF6347', '#FF4500'] },
// Autres catégories peuvent être ajoutées ici plus tard
];
presets.forEach(preset => {
const category = document.createElement('div');
category.className = 'preset-category';
category.innerHTML = `<div class="preset-label">${preset.label}</div>`;
const presetRow = document.createElement('div');
presetRow.className = 'preset-row';
preset.colors.forEach(color => {
const presetColor = document.createElement('div');
presetColor.className = 'color-preset';
presetColor.style.backgroundColor = color;
presetColor.addEventListener('click', () => updateColor(color, updateAll));
presetRow.appendChild(presetColor);
});
category.appendChild(presetRow);
container.appendChild(category);
});
}
createColorPresets(masterColorPresets, true);
document.querySelectorAll('.bulb-control .color-presets').forEach(container => createColorPresets(container));
function saveSettings() {
const settings = {
masterToggle: masterToggle.checked,
masterBrightness: masterBrightness.value,
masterColor: masterColor.value,
bulbs: Array.from(document.querySelectorAll('.bulb-control')).map(bulb => ({
id: bulb.querySelector('.bulbToggle').dataset.id,
isOn: bulb.querySelector('.bulbToggle').checked,
brightness: bulb.querySelector('.bulbBrightness').value,
color: bulb.querySelector('.bulbColor').value
}))
};
localStorage.setItem('bulbSettings', JSON.stringify(settings));
}
function loadSettings() {
const settings = JSON.parse(localStorage.getItem('bulbSettings'));
if (settings) {
masterToggle.checked = settings.masterToggle;
masterBrightness.value = settings.masterBrightness;
masterBrightnessValue.textContent = `${settings.masterBrightness}%`;
updateColor(settings.masterColor, true);
settings.bulbs.forEach(bulb => {
const toggle = document.querySelector(`.bulbToggle[data-id="${bulb.id}"]`);
const brightnessSlider = document.querySelector(`.bulbBrightness[data-id="${bulb.id}"]`);
const colorPicker = document.querySelector(`.bulbColor[data-id="${bulb.id}"]`);
toggle.checked = bulb.isOn;
brightnessSlider.value = bulb.brightness;
brightnessSlider.nextElementSibling.textContent = `${bulb.brightness}%`;
colorPicker.jscolor.fromString(bulb.color);
updateBulbIcon(toggle.closest('.control-item').querySelector('.bulb-icon'), bulb.isOn && masterToggle.checked);
});
updateBulbIcon(masterBulbIcon, settings.masterToggle);
}
}
loadSettings();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment