Friday, July 21, 2023

Thank You chatGPT. How You Can Add User-Editable Buttons On Your Blog

Back to list

How to Add a Single Editable Button to Your Blog

This guide shows you how to add a single editable button with a fixed title and editable body. The input field auto-resizes as the user types.

Step 1: Add HTML

<div class="eb-widget" data-title="Reminder" data-body="Click to edit."></div>

Step 2: Add CSS

<style>
.eb-widget {
  font-family: sans-serif;
  display: inline-block;
  margin: 1rem;
  max-width: 100%;
  vertical-align: top;
}
.eb-display {
  display: inline-block;
  padding: 0.4rem 0.6rem;
  border: 1px solid #ccc;
  border-radius: 0.5rem;
  background: #f9f9f9;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
  cursor: pointer;
  white-space: pre-line;
  width: fit-content;
  max-width: 100%;
}
.eb-title {
  font-weight: bold;
  font-size: 1rem;
  color: #222;
  margin-bottom: 0.2rem;
}
.eb-body {
  font-size: 0.95rem;
  color: #333;
  white-space: pre;
}
.eb-edit {
  display: none;
  padding: 0.4rem 0.6rem;
  border: 1px solid #aaa;
  border-radius: 0.5rem;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
  max-width: 100%;
  position: relative;
}
.eb-edit .eb-title {
  font-weight: bold;
  margin-bottom: 0.3rem;
  color: #222;
}
.eb-textarea {
  font-size: 1rem;
  font-family: inherit;
  line-height: 1.4;
  padding: 0.4rem;
  border: 1px solid #aaa;
  border-radius: 0.3rem;
  resize: none;
  width: auto;
  min-width: 4ch;
  box-sizing: content-box;
  overflow: hidden;
  display: block;
  transition: width 0.1s ease;
}
.eb-mirror {
  position: absolute;
  visibility: hidden;
  white-space: pre-wrap;
  padding: 0.4rem;
  font-size: 1rem;
  font-family: inherit;
  line-height: 1.4;
  border: 1px solid transparent;
  box-sizing: content-box;
  max-width: 100%;
}
.eb-widget.editing .eb-display { display: none; }
.eb-widget.editing .eb-edit { display: block; }
</style>

Step 3: Add JavaScript

<script>
(function () {
  function createEditableWidget(root, titleText, bodyText) {
    root.innerHTML = `
      <div class="eb-display" tabindex="0" role="button">
        <div class="eb-title">${titleText}</div>
        <div class="eb-body">${bodyText}</div>
      </div>
      <div class="eb-edit">
        <div class="eb-title">${titleText}</div>
        <textarea class="eb-textarea" rows="1" placeholder="Enter body text..."></textarea>
        <div class="eb-mirror"></div>
      </div>
    `;

    const display = root.querySelector('.eb-display');
    const body = display.querySelector('.eb-body');
    const textarea = root.querySelector('.eb-textarea');
    const mirror = root.querySelector('.eb-mirror');

    function resize() {
      mirror.textContent = textarea.value || textarea.placeholder || '';
      mirror.style.display = 'inline-block';
      textarea.style.height = 'auto';
      textarea.style.height = textarea.scrollHeight + 'px';
      textarea.style.width = mirror.offsetWidth + 5 + 'px';
    }

    function enterEditMode() {
      root.classList.add('editing');
      textarea.value = body.textContent.trim();
      resize();
      setTimeout(() => {
        textarea.focus();
        textarea.select();
      }, 0);
    }

    function commitEdit() {
      const newText = textarea.value.trim();
      if (newText) body.textContent = newText;
      root.classList.remove('editing');
    }

    function cancelEdit() {
      root.classList.remove('editing');
    }

    display.addEventListener('click', enterEditMode);
    display.addEventListener('keydown', e => {
      if (e.key === 'Enter') {
        e.preventDefault();
        enterEditMode();
      }
    });

    textarea.addEventListener('input', resize);

    textarea.addEventListener('keydown', e => {
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        commitEdit();
      } else if (e.key === 'Escape') {
        e.preventDefault();
        cancelEdit();
      } else {
        requestAnimationFrame(resize);
      }
    });

    textarea.addEventListener('blur', commitEdit);
  }

  document.querySelectorAll('.eb-widget').forEach(root => {
    const title = root.dataset.title || 'Title';
    const body = root.dataset.body || '';
    createEditableWidget(root, title, body);
  });
})();
</script>

Step 4: Copy Button Script

<script>
function copyCode(btn) {
  const codeElement = btn.nextElementSibling;
  if (!codeElement) return;
  const text = codeElement.innerText;
  navigator.clipboard.writeText(text).then(() => {
    btn.classList.add('copied');
    setTimeout(() => btn.classList.remove('copied'), 1000);
  });
}
</script>

No comments: