Skip to content

Instantly share code, notes, and snippets.

@fgouin2014
Created July 9, 2024 09:51
Show Gist options
  • Save fgouin2014/fee97076c05f7170e6f92ab998d94ecd to your computer and use it in GitHub Desktop.
Save fgouin2014/fee97076c05f7170e6f92ab998d94ecd to your computer and use it in GitHub Desktop.
Base
<!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>
<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;
}
#masterControlSection {
border: 1px solid #ddd;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.bulb-icon {
margin-left: 10px;
width: 60px;
height: 60px;
}
.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="60" height="60" viewBox="0 0 60 60">
<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>
<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 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="60" height="60" viewBox="0 0 60 60">
<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>
`;
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 saveSettings() {
const settings = {
masterToggle: masterToggle.checked,
masterBrightness: masterBrightness.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
}))
};
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}%`;
settings.bulbs.forEach(bulb => {
const toggle = document.querySelector(`.bulbToggle[data-id="${bulb.id}"]`);
const brightnessSlider = document.querySelector(`.bulbBrightness[data-id="${bulb.id}"]`);
toggle.checked = bulb.isOn;
brightnessSlider.value = bulb.brightness;
brightnessSlider.nextElementSibling.textContent = `${bulb.brightness}%`;
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