Image On-Off

Description

(initial)

04.26c24v2 Image On Off

(on-click)

04.26c24v2 Image On Off

#1. Install Code

if you use Personal/Basic Plan and you can’t have Code Injection, see step #2.2.

#1.1. First, add a Text Block with 2 texts: lighton-lightoff

04.26c24v2 Image On Off

#1.2. Highlight text lighton > Click Link icon

04.26c24v2 Image On Off

#1.3. Next, upload Image (at URL in screenshot, click down arrow to choose File then you able to upload image) or paste Image URL

04.26c24v2 Image On Off

#1.4. Repeat similar for lightoff text

#1.5. Hover on Page where you use Text > Click Gear icon

04.26c24v2 Image On Off

Click Advanced > Paste this code

<!-- 04.26c24v2 Image On-Off -->
<script>
window.LIGHT_TOGGLE_CONFIG = {
  selector: '.sqs-block-html',
  onText: 'lighton',
  offText: 'lightoff',
  imgFormat: '?format=2500w',
  iconSize: 10,
  fadeDuration: 400,
};
</script>
<!-- <script src="https://code.beaverhero.com/imageblock/0426c24v2imageonoff.js"></script>
-->
<script>
(function() {
  document.addEventListener('DOMContentLoaded', init);
  document.addEventListener('mercury:load', init);

  function init() {
    const C = window.LIGHT_TOGGLE_CONFIG;

    document.querySelectorAll(C.selector).forEach(block => {
      if (block.dataset.lightInit) return;

      const content = block.querySelector('.sqs-html-content');
      if (!content) return;

      const links = content.querySelectorAll('a');
      let onUrl = null, offUrl = null;

      links.forEach(a => {
        const t = a.textContent.trim();
        if (t === C.onText) onUrl = new URL(a.getAttribute('href'), location.origin).href;
        if (t === C.offText) offUrl = new URL(a.getAttribute('href'), location.origin).href;
      });

      if (!onUrl || !offUrl) return;

      block.dataset.lightInit = '1';

      const isSquarespaceUrl = url => url.includes('squarespace-cdn.com') || url.includes('sqspcdn.com');
      const formatUrl = url => isSquarespaceUrl(url) ? url.split('?')[0] + C.imgFormat : url;

      const s = C.iconSize;
      const btnW = s * 5.2;
      const btnH = s * 2.8;
      const fade = C.fadeDuration;

      const wrapper = document.createElement('div');
      wrapper.style.cssText = 'position:relative;display:inline-block;width:100%;';

      const skeleton = document.createElement('div');
      skeleton.style.cssText = `
        position:absolute;
        top:0;left:0;
        width:100%;
        height:100%;
        background:linear-gradient(90deg,#e0e0e0 25%,#ececec 50%,#e0e0e0 75%);
        background-size:200% 100%;
        animation:lightSkeletonShimmer 1.4s infinite;
        display:block;
        z-index:1;
      `;

      const sharedImgStyle = `position:absolute;top:0;left:0;display:block;width:100%;transition:opacity ${fade}ms ease;`;

      const imgOn = document.createElement('img');
      imgOn.style.cssText = sharedImgStyle + 'opacity:0;z-index:2;';
      imgOn.src = formatUrl(onUrl);

      const imgOff = document.createElement('img');
      imgOff.style.cssText = sharedImgStyle + 'opacity:0;z-index:2;';
      imgOff.src = formatUrl(offUrl);

      const sizer = document.createElement('div');
      sizer.style.cssText = 'width:100%;visibility:hidden;display:block;';
      const sizerImg = document.createElement('img');
      sizerImg.style.cssText = 'display:block;width:100%;';
      sizerImg.src = formatUrl(onUrl);
      sizer.appendChild(sizerImg);

      imgOn.addEventListener('load', () => {
        skeleton.style.display = 'none';
        imgOn.style.opacity = '1';
      });
      imgOn.addEventListener('error', () => {
        skeleton.style.display = 'none';
        imgOn.style.opacity = '1';
      });

      const btn = document.createElement('button');
      btn.setAttribute('aria-label', 'Toggle light');
      btn.innerHTML = svgIcon(true, s);
      btn.style.cssText = `
        position:absolute;
        bottom:14px;
        right:14px;
        width:${btnW}px;
        height:${btnH}px;
        border-radius:999px;
        border:1.5px solid rgba(255,255,255,1);
        cursor:pointer;
        display:flex;
        align-items:center;
        justify-content:center;
        padding:0;
        transition:background 0.25s;
        background:rgba(255,255,255,0);
        backdrop-filter:blur(6px);
        -webkit-backdrop-filter:blur(6px);
        z-index:3;
      `;

      let isOn = true;
      let busy = false;

      btn.addEventListener('click', () => {
        if (busy) return;
        busy = true;
        isOn = !isOn;

        const incoming = isOn ? imgOn : imgOff;
        const outgoing = isOn ? imgOff : imgOn;

        incoming.style.zIndex = '3';
        outgoing.style.zIndex = '2';
        incoming.style.opacity = '1';
        outgoing.style.opacity = '0';

        btn.innerHTML = svgIcon(isOn, s);
        btn.style.background = isOn ? 'rgba(255,255,255,0)' : 'rgba(255,255,255,1)';

        setTimeout(() => { busy = false; }, fade);
      });

      if (!document.getElementById('light-toggle-keyframes')) {
        const style = document.createElement('style');
        style.id = 'light-toggle-keyframes';
        style.textContent = `@keyframes lightSkeletonShimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}`;
        document.head.appendChild(style);
      }

      content.innerHTML = '';
      wrapper.appendChild(skeleton);
      wrapper.appendChild(sizer);
      wrapper.appendChild(imgOn);
      wrapper.appendChild(imgOff);
      wrapper.appendChild(btn);
      content.appendChild(wrapper);
    });
  }

  function svgIcon(isOn, s) {
    const color = isOn ? '#ffffff' : '#000000';
    return `<svg xmlns="http://www.w3.org/2000/svg" width="${s}" height="${s}" viewBox="0 0 24 24" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <circle cx="12" cy="12" r="4"/>
      <line x1="12" y1="2" x2="12" y2="5"/>
      <line x1="12" y1="19" x2="12" y2="22"/>
      <line x1="4.22" y1="4.22" x2="6.34" y2="6.34"/>
      <line x1="17.66" y1="17.66" x2="19.78" y2="19.78"/>
      <line x1="2" y1="12" x2="5" y2="12"/>
      <line x1="19" y1="12" x2="22" y2="12"/>
      <line x1="4.22" y1="19.78" x2="6.34" y2="17.66"/>
      <line x1="17.66" y1="6.34" x2="19.78" y2="4.22"/>
    </svg>`;
  }
})();
</script>

04.26c24v2 Image On Off

#2. Customize

#2.1. You can change options (icon size, fade speed) here

window.LIGHT_TOGGLE_CONFIG = {
  selector: '.sqs-block-html',
  onText: 'lighton',
  offText: 'lightoff',
  imgFormat: '?format=2500w',
  iconSize: 10,
  fadeDuration: 400,
};

#2.2. If you use Personal/Basic Plan and you can’t add code to Code Injection, you can add a Markdown Block to Page.

04.26c10v2 Header Sound Icon

Then paste this code into Markdown Block.

<script>
window.LIGHT_TOGGLE_CONFIG = {
  selector: '.sqs-block-html',
  onText: 'lighton',
  offText: 'lightoff',
  imgFormat: '?format=2500w',
  iconSize: 10,
  fadeDuration: 400,
};
</script>
<script src="https://code.beaverhero.com/imageblock/0426c24v2imageonoff.js"></script>

04.26c24v2 Image On Off

 

 

Buy me a coffee