Skip to content

Instantly share code, notes, and snippets.

@fgouin2014
Created July 9, 2024 09:47
Show Gist options
  • Save fgouin2014/bd2fb0956324d11309d84679f3710815 to your computer and use it in GitHub Desktop.
Save fgouin2014/bd2fb0956324d11309d84679f3710815 to your computer and use it in GitHub Desktop.
Base+Category Fork
<!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-direction: column;
gap: 10px;
margin-top: 10px;
}
.preset-category {
margin-bottom: 10px;
}
.preset-label {
font-weight: bold;
margin-bottom: 5px;
}
.preset-row {
display: flex;
gap: 5px;
}
.color-preset {
width: 20px;
height: 20px;
border-radius: 50%;
cursor: pointer;
}
#masterControlSection {
border: 1px solid #ddd;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.bulb-icon {
margin-left: 10px;
width: 48px;
height: 48px;
transition: all 0.3s ease;
}
.bulb-icon.on .bulb-inner {
fill: yellow;
filter: drop-shadow(0 0 5px yellow);
}
.bulb-icon.off .bulb-inner {
fill: #D3D3D3;
}
/* Switch styles */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.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: translateX(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="48" height="48" viewBox="0 0 48 48">
<path 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" fill="#000000"/>
<path class="bulb-inner" 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" fill="#FFEB3B"/>
</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');
const colorPresets = {
'White Tones': [
{ name: 'Cool White', color: 'F0F8FF' },
{ name: 'Daylight', color: 'F5F5F5' },
{ name: 'Neutral White', color: 'F5DEB3' },
{ name: 'Warm White', color: 'FFD700' },
{ name: 'Candlelight', color: 'FFA07A' }
],
'Basic Colors': [
{ name: 'Red', color: 'FF0000' },
{ name: 'Green', color: '00FF00' },
{ name: 'Blue', color: '0000FF' },
{ name: 'Yellow', color: 'FFFF00' },
{ name: 'Magenta', color: 'FF00FF' }
],
'Pastel Colors': [
{ name: 'Pastel Pink', color: 'FFB6C1' },
{ name: 'Pastel Blue', color: 'ADD8E6' },
{ name: 'Pastel Green', color: '98FB98' },
{ name: 'Pastel Yellow', color: 'FFFACD' },
{ name: 'Pastel Lavender', color: 'E6E6FA' }
]
};
function createColorPresets(container, colorPickerId) {
Object.entries(colorPresets).forEach(([category, presets]) => {
const categoryDiv = document.createElement('div');
categoryDiv.className = 'preset-category';
const labelDiv = document.createElement('div');
labelDiv.className = 'preset-label';
labelDiv.textContent = category;
categoryDiv.appendChild(labelDiv);
const presetRow = document.createElement('div');
presetRow.className = 'preset-row';
presets.forEach(preset => createPresetButton(preset, presetRow, colorPickerId));
categoryDiv.appendChild(presetRow);
container.appendChild(categoryDiv);
});
}
function createPresetButton(preset, container, colorPickerId) {
const presetElement = document.createElement('div');
presetElement.className = 'color-preset';
presetElement.style.backgroundColor = `#${preset.color}`;
presetElement.title = preset.name;
presetElement.addEventListener('click', () => {
const colorPicker = document.getElementById(colorPickerId);
if (colorPicker.jscolor) {
colorPicker.jscolor.fromString(preset.color);
updateBulbColor(colorPickerId, preset.color);
}
});
container.appendChild(presetElement);
}
function updateBulbColor(colorPickerId, color) {
const bulbId = colorPickerId.replace('color', '');
console.log(`Set bulb ${bulbId} color to #${color}`);
if (colorPickerId === 'masterColor') {
syncMasterColor(color);
}
saveSettings();
}
function createBulbControl(id) {
const bulbDiv = document.createElement('div');
bulbDiv.className = 'bulb-control';
bulbDiv.innerHTML = `
<h2>Bulb ${id}</h2>
<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="48" height="48" viewBox="0 0 48 48">
<path 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" fill="#000000"/>
<path class="bulb-inner" 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" fill="#FFEB3B"/>
</svg>
</div>
<div class="control-item">
<label for="brightness${id}">Brightness:</label>
<input type="range" id="brightness${id}" class="brightnessSlider" data-id="${id}" min="0" max="100" value="50">
<span class="brightnessValue" data-id="${id}">50%</span>
</div>
<div class="control-item">
<label for="color${id}">Color:</label>
<input type="text" id="color${id}" class="colorPicker" data-jscolor="" data-id="${id}" value="FFFFFF">
</div>
<div class="color-presets" id="colorPresets${id}"></div>
`;
bulbControls.appendChild(bulbDiv);
createColorPresets(bulbDiv.querySelector(`#colorPresets${id}`), `color${id}`);
}
// Create controls for each bulb
for (let i = 1; i <= bulbCount; i++) {
createBulbControl(i);
}
// Initialize jscolor for all color pickers
jscolor.install();
// Create color presets for master control
createColorPresets(masterColorPresets, 'masterColor');
// Add event listeners for individual bulb controls
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'}`);
if (masterToggle.checked) {
// Si le master est allumé, mettre à jour l'apparence normalement
bulbIcon.classList.toggle('on', isOn);
bulbIcon.classList.toggle('off', !isOn);
} else {
// Si le master est éteint, l'ampoule reste visuellement éteinte
bulbIcon.classList.remove('on');
bulbIcon.classList.add('off');
}
updateMasterToggle();
saveSettings();
});
});
document.querySelectorAll('.brightnessSlider').forEach(slider => {
slider.addEventListener('input', (e) => {
const id = e.target.dataset.id;
const brightness = e.target.value;
document.querySelector(`.brightnessValue[data-id="${id}"]`).textContent = `${brightness}%`;
console.log(`Set bulb ${id} brightness to ${brightness}%`);
saveSettings();
});
});
document.querySelectorAll('.colorPicker').forEach(picker => {
picker.addEventListener('change', (e) => {
const id = e.target.dataset.id;
const color = e.target.jscolor.toString();
console.log(`Set bulb ${id} color to #${color}`);
const bulbInner = document.querySelector(`.bulb-control:nth-child(${id}) .bulb-inner`);
if (bulbInner) {
bulbInner.style.fill = `#${color}`;
}
saveSettings();
});
});
// Add event listeners for master controls
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');
if (isOn) {
bulbIcon.classList.toggle('on', toggle.checked);
bulbIcon.classList.toggle('off', !toggle.checked);
} else {
bulbIcon.classList.remove('on');
bulbIcon.classList.add('off');
}
});
masterBulbIcon.classList.toggle('on', isOn);
masterBulbIcon.classList.toggle('off', !isOn);
saveSettings();
});
masterBrightness.addEventListener('input', (e) => {
const brightness = e.target.value;
masterBrightnessValue.textContent = `${brightness}%`;
console.log(`Set all bulbs brightness to ${brightness}%`);
syncMasterBrightness(brightness);
saveSettings();
});
masterColor.addEventListener('change', (e) => {
const color = e.target.jscolor.toString();
console.log(`Set all bulbs color to #${color}`);
syncMasterColor(color);
saveSettings();
});
// Helper functions for synchronization
function updateMasterToggle() {
const anyBulbOn = Array.from(document.querySelectorAll('.bulbToggle')).some(toggle => toggle.checked);
masterToggle.checked = anyBulbOn;
masterBulbIcon.classList.toggle('on', anyBulbOn);
masterBulbIcon.classList.toggle('off', !anyBulbOn);
const isOn = masterToggle.checked;
document.querySelectorAll('.bulbToggle').forEach(toggle => {
const bulbIcon = toggle.closest('.control-item').querySelector('.bulb-icon');
if (isOn) {
bulbIcon.classList.toggle('on', toggle.checked);
bulbIcon.classList.toggle('off', !toggle.checked);
} else {
bulbIcon.classList.remove('on');
bulbIcon.classList.add('off');
}
});
}
function syncMasterBrightness(brightness) {
document.querySelectorAll('.brightnessSlider').forEach(slider => {
slider.value = brightness;
const id = slider.dataset.id;
document.querySelector(`.brightnessValue[data-id="${id}"]`).textContent = `${brightness}%`;
});
}
function syncMasterColor(color) {
document.querySelectorAll('.colorPicker').forEach(picker => {
if (picker.jscolor) {
picker.jscolor.fromString(color);
}
const id = picker.dataset.id;
const bulbInner = document.querySelector(`.bulb-control:nth-child(${id}) .bulb-inner`);
if (bulbInner) {
bulbInner.style.fill = `#${color}`;
}
});
}
// Save settings to localStorage
function saveSettings() {
const settings = {
masterBrightness: masterBrightness.value,
masterColor: masterColor.value,
bulbs: {}
};
document.querySelectorAll('.bulb-control').forEach((bulb, index) => {
const id = index + 1;
settings.bulbs[id] = {
isOn: bulb.querySelector('.bulbToggle').checked,
brightness: bulb.querySelector('.brightnessSlider').value,
color: bulb.querySelector('.colorPicker').value
};
});
localStorage.setItem('bulbSettings', JSON.stringify(settings));
}
// Load settings from localStorage
function loadSettings() {
const settings = JSON.parse(localStorage.getItem('bulbSettings'));
if (settings) {
masterBrightness.value = settings.masterBrightness;
masterBrightnessValue.textContent = `${settings.masterBrightness}%`;
masterColor.jscolor.fromString(settings.masterColor);
Object.entries(settings.bulbs).forEach(([id, bulbSettings]) => {
const bulbControl = document.querySelector(`.bulb-control:nth-child(${id})`);
if (bulbControl) {
const bulbToggle = bulbControl.querySelector('.bulbToggle');
bulbToggle.checked = bulbSettings.isOn;
const bulbIcon = bulbControl.querySelector('.bulb-icon');
bulbIcon.classList.toggle('on', bulbSettings.isOn);
bulbIcon.classList.toggle('off', !bulbSettings.isOn);
const brightnessSlider = bulbControl.querySelector('.brightnessSlider');
brightnessSlider.value = bulbSettings.brightness;
bulbControl.querySelector('.brightnessValue').textContent = `${bulbSettings.brightness}%`;
const colorPicker = bulbControl.querySelector('.colorPicker');
colorPicker.jscolor.fromString(bulbSettings.color);
const bulbInner = bulbControl.querySelector('.bulb-inner');
if (bulbInner) {
bulbInner.style.fill = `#${bulbSettings.color}`;
}
}
});
updateMasterToggle();
}
}
// Load settings when the page loads
loadSettings();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment