chameleon-backgrounds 2.0.1 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/chameleon-backgrounds.min.js +1 -1
- package/package.json +1 -1
- package/src/chameleon-backgrounds.js +64 -3
package/README.md
CHANGED
|
@@ -157,6 +157,23 @@ Stops any running slider, removes all injected DOM and styles, and restores the
|
|
|
157
157
|
|
|
158
158
|
Returns a read-only copy of the resolved options.
|
|
159
159
|
|
|
160
|
+
### `.reloadOptions(newOptions)`
|
|
161
|
+
|
|
162
|
+
Update options on the fly without destroying the instance. For example, you can change the transition duration or even convert a single background into a slider dynamically:
|
|
163
|
+
```javascript
|
|
164
|
+
bg.reloadOptions({
|
|
165
|
+
type: 'slider',
|
|
166
|
+
src: [
|
|
167
|
+
'./img/slide1.jpg',
|
|
168
|
+
'./img/slide2.jpg'
|
|
169
|
+
],
|
|
170
|
+
transitionDuration: 5000,
|
|
171
|
+
overlayColor: '#ff0000'
|
|
172
|
+
});
|
|
173
|
+
// To apply the updated options, simply reload the background
|
|
174
|
+
bg.reloadBackground();
|
|
175
|
+
```
|
|
176
|
+
|
|
160
177
|
---
|
|
161
178
|
|
|
162
179
|
## Migration from v1
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! For license information please see chameleon-backgrounds.min.js.LICENSE.txt */
|
|
2
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.ChameleonBackgrounds=t():e.ChameleonBackgrounds=t()}(this,()=>(()=>{"use strict";const e={d:(t,
|
|
2
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.ChameleonBackgrounds=t():e.ChameleonBackgrounds=t()}(this,()=>(()=>{"use strict";const e={d:(t,i)=>{if(Array.isArray(i))for(var n=0;n<i.length;){var o=i[n++],r=i[n++];e.o(t,o)?0===r&&n++:0===r?Object.defineProperty(t,o,{enumerable:!0,value:i[n++]}):Object.defineProperty(t,o,{enumerable:!0,get:r})}else for(var o in i)e.o(i,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:i[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};let t={};class i{static#e=Object.freeze({element:"body",type:"single",src:"",overlayColor:"#0f1e25",overlayImage:null,minOverlay:0,transitionDuration:2e3,sliderDuration:8e3,sliderLoop:!1});static#t=Object.freeze({transition_duration:"transitionDuration",slider_duration:"sliderDuration",slider_loop:"sliderLoop",min_overlay:"minOverlay",overlay_color:"overlayColor",overlay_image:"overlayImage"});#i;#n;#o;#r;#s=null;#l=null;#d=!1;constructor(e={}){const t=i.#a(e);this.#i={...i.#e,...t},this.#o=i.#h(),this.#n=i.#c(this.#i.element),this.#r=this.#n.innerHTML,this.#u()}destroy(){if(this.#d)return;this.#d=!0,null!==this.#l&&(clearInterval(this.#l),this.#l=null),this.#s?.parentNode&&(this.#s.parentNode.removeChild(this.#s),this.#s=null);const e=this.#n.querySelector(`#cbg-inner-${this.#o}`);if(e&&e.parentNode===this.#n){for(;e.firstChild;)this.#n.insertBefore(e.firstChild,e);this.#n.removeChild(e)}const t=this.#n.querySelector(`.cbg-loader-${this.#o}`);t&&t.remove(),this.#n.style.backgroundImage=""}get options(){return{...this.#i}}#u(){this.#m(),this.#y(),this.#n.matches("body")?queueMicrotask(()=>this.#p()):"complete"===document.readyState?this.#p():window.addEventListener("load",()=>this.#p(),{once:!0})}#m(){const e=this.#o,t="body"===this.#i.element||this.#n.matches("body")?"body":this.#i.element,i=this.#i.transitionDuration/1e3,n=`\n ${"string"==typeof t?t:`.cbg-host-${e}`} {\n position: relative;\n }\n\n #cbg-inner-${e} {\n z-index: 2;\n position: relative;\n }\n\n .cbg-loader-${e} {\n height: 100%;\n width: 100%;\n position: ${this.#n.matches("body")?"fixed":"absolute"};\n background-image: ${this.#i.overlayImage?`url(${this.#i.overlayImage})`:"none"};\n background-color: ${this.#i.overlayColor};\n opacity: 1;\n z-index: 1;\n transition: opacity ${i}s ease;\n top: 0;\n left: 0;\n }\n `,o=document.createElement("style");o.dataset.chameleonUid=e,o.textContent=n,document.head.appendChild(o),this.#s=o}#y(){const e=this.#o,t=document.createElement("div");for(t.id=`cbg-inner-${e}`;this.#n.firstChild;)t.appendChild(this.#n.firstChild);const i=document.createElement("div");i.classList.add(`cbg-loader-${e}`),this.#n.appendChild(t),this.#n.appendChild(i)}#p(){this.#d||("single"===this.#i.type?this.#g("string"==typeof this.#i.src?this.#i.src:this.#i.src[0]):"slider"===this.#i.type&&this.#f())}#g(e,t=!0){return this.#d?Promise.resolve():new Promise(t=>{const i=new Image;i.onload=()=>{if(this.#d)return t();this.#n.style.backgroundImage=`url(${e})`,this.#n.style.backgroundSize="cover";const i=this.#n.querySelector(`.cbg-loader-${this.#o}`);i&&(i.style.opacity=String(this.#i.minOverlay)),t()},i.onerror=()=>{console.warn(`[ChameleonBackgrounds] Failed to load image: ${e}`),t()},i.src=e})}reloadBackground(e){if(this.#d)return Promise.resolve();void 0!==e&&("slider"===this.#i.type&&"string"==typeof e?this.#i.src=e.includes(",")?e.split(",").map(e=>e.trim()):[e]:this.#i.src=e),null!==this.#l&&(clearInterval(this.#l),this.#l=null);const t=this.#n.querySelector(`.cbg-loader-${this.#o}`);return t&&(t.style.opacity="1"),new Promise(e=>{setTimeout(()=>{if(this.#d)return e();if("single"===this.#i.type){const t="string"==typeof this.#i.src?this.#i.src:this.#i.src[0];this.#g(t,!1).then(e)}else"slider"===this.#i.type&&(this.#f(),e())},this.#i.transitionDuration)})}reloadOptions(e){if(this.#d)return;const t=i.#a(e);this.#i={...this.#i,...t},this.#s?.parentNode&&(this.#s.parentNode.removeChild(this.#s),this.#s=null),this.#m()}#f(){if(this.#d)return;const e=this.#i.src;if(!Array.isArray(e)||0===e.length)return void console.warn("[ChameleonBackgrounds] Slider mode requires an array of image URLs in `src`.");let t=0;this.#g(e[t]).then(()=>{if(this.#d)return;if(t=1,1===e.length)return;const i=this.#i.sliderDuration+2*this.#i.transitionDuration;this.#l=setInterval(()=>{this.#d?clearInterval(this.#l):(this.#v(e[t]),t++,t>=e.length&&(this.#i.sliderLoop?t=0:(clearInterval(this.#l),this.#l=null)))},i)})}#v(e){if(this.#d)return;const t=this.#n.querySelector(`.cbg-loader-${this.#o}`);t&&(t.style.opacity="1"),setTimeout(()=>{this.#d||this.#g(e,!1)},this.#i.transitionDuration)}static#a(e){const t={};for(const[n,o]of Object.entries(e))t[i.#t[n]??n]=o;return t}static#c(e){if(e instanceof HTMLElement)return e;if("string"==typeof e){if("body"===e)return document.body;const t=document.querySelector(e);if(!t)throw new Error(`[ChameleonBackgrounds] Element not found: ${e}`);return t}throw new TypeError(`[ChameleonBackgrounds] Invalid element: ${e}`)}static#h(){return"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID().slice(0,8):Array.from({length:8},()=>"abcdefghijklmnopqrstuvwxyz0123456789".charAt(Math.floor(36*Math.random()))).join("")}}const n=i;return e.d(t,["default",0,n]),t=t.default,t})());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chameleon-backgrounds",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "A zero-dependency JavaScript library to dynamically load background images with elegant fade-in transitions and slideshow support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/chameleon-backgrounds.js",
|
|
@@ -292,14 +292,30 @@ class ChameleonBackgrounds {
|
|
|
292
292
|
});
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
+
/**
|
|
295
296
|
/**
|
|
296
297
|
* Reload background with a fade-out → swap → fade-in cycle.
|
|
297
|
-
* @param {string} src -
|
|
298
|
+
* @param {string} [src] - Optional new image URL. If omitted, reloads using current options.
|
|
298
299
|
* @returns {Promise<void>}
|
|
299
300
|
*/
|
|
300
301
|
reloadBackground(src) {
|
|
301
302
|
if (this.#destroyed) return Promise.resolve();
|
|
302
303
|
|
|
304
|
+
if (src !== undefined) {
|
|
305
|
+
if (this.#options.type === 'slider' && typeof src === 'string') {
|
|
306
|
+
// If the user passes a comma-separated string, split it. Otherwise wrap it.
|
|
307
|
+
this.#options.src = src.includes(',') ? src.split(',').map(s => s.trim()) : [src];
|
|
308
|
+
} else {
|
|
309
|
+
this.#options.src = src;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Stop any running slider
|
|
314
|
+
if (this.#sliderIntervalId !== null) {
|
|
315
|
+
clearInterval(this.#sliderIntervalId);
|
|
316
|
+
this.#sliderIntervalId = null;
|
|
317
|
+
}
|
|
318
|
+
|
|
303
319
|
const loader = this.#element.querySelector(`.cbg-loader-${this.#uid}`);
|
|
304
320
|
if (loader) {
|
|
305
321
|
loader.style.opacity = '1';
|
|
@@ -308,11 +324,38 @@ class ChameleonBackgrounds {
|
|
|
308
324
|
return new Promise((resolve) => {
|
|
309
325
|
setTimeout(() => {
|
|
310
326
|
if (this.#destroyed) return resolve();
|
|
311
|
-
|
|
327
|
+
|
|
328
|
+
if (this.#options.type === 'single') {
|
|
329
|
+
const singleSrc = typeof this.#options.src === 'string' ? this.#options.src : this.#options.src[0];
|
|
330
|
+
this.#loadBackground(singleSrc, false).then(resolve);
|
|
331
|
+
} else if (this.#options.type === 'slider') {
|
|
332
|
+
this.#startSlider();
|
|
333
|
+
resolve();
|
|
334
|
+
}
|
|
312
335
|
}, this.#options.transitionDuration);
|
|
313
336
|
});
|
|
314
337
|
}
|
|
315
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Update options on the fly without destroying the instance.
|
|
341
|
+
* @param {Object} newOptions - The new options to merge.
|
|
342
|
+
*/
|
|
343
|
+
reloadOptions(newOptions) {
|
|
344
|
+
if (this.#destroyed) return;
|
|
345
|
+
|
|
346
|
+
const normalized = ChameleonBackgrounds.#normalizeOptions(newOptions);
|
|
347
|
+
this.#options = { ...this.#options, ...normalized };
|
|
348
|
+
|
|
349
|
+
// Remove old styles
|
|
350
|
+
if (this.#styleElement?.parentNode) {
|
|
351
|
+
this.#styleElement.parentNode.removeChild(this.#styleElement);
|
|
352
|
+
this.#styleElement = null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Inject updated styles
|
|
356
|
+
this.#injectStyles();
|
|
357
|
+
}
|
|
358
|
+
|
|
316
359
|
// ---------------------------------------------------------------------------
|
|
317
360
|
// Slider
|
|
318
361
|
// ---------------------------------------------------------------------------
|
|
@@ -345,7 +388,7 @@ class ChameleonBackgrounds {
|
|
|
345
388
|
return;
|
|
346
389
|
}
|
|
347
390
|
|
|
348
|
-
this
|
|
391
|
+
this.#cycleSliderSlide(sources[index]);
|
|
349
392
|
index++;
|
|
350
393
|
|
|
351
394
|
if (index >= sources.length) {
|
|
@@ -360,6 +403,24 @@ class ChameleonBackgrounds {
|
|
|
360
403
|
});
|
|
361
404
|
}
|
|
362
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Cycle to a specific slide without resetting the slider instance.
|
|
408
|
+
* @param {string} src - The image URL to load.
|
|
409
|
+
*/
|
|
410
|
+
#cycleSliderSlide(src) {
|
|
411
|
+
if (this.#destroyed) return;
|
|
412
|
+
|
|
413
|
+
const loader = this.#element.querySelector(`.cbg-loader-${this.#uid}`);
|
|
414
|
+
if (loader) {
|
|
415
|
+
loader.style.opacity = '1';
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
setTimeout(() => {
|
|
419
|
+
if (this.#destroyed) return;
|
|
420
|
+
this.#loadBackground(src, false);
|
|
421
|
+
}, this.#options.transitionDuration);
|
|
422
|
+
}
|
|
423
|
+
|
|
363
424
|
// ---------------------------------------------------------------------------
|
|
364
425
|
// Static Helpers
|
|
365
426
|
// ---------------------------------------------------------------------------
|