JSFiddle - React, Tailwind, and code Playground

by Imri Paloja

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">


<div class="container">

    <h1>Bold/Unbold Editor</h1>
    <p>Select text in the editor below and use the Bold button or Ctrl+B to toggle bold formatting.</p>
    
    <div id="editor" contenteditable="true">
        <p>This is a <strong>bold text</strong> example. Select some text and try the bold toggle!</p>
        <p>You can also select <strong>partially bold</strong> text and toggle it.</p>
    </div>
  
</div>

CSS

body {
  font-family: Arial, sans-serif;
  padding: 20px;
  max-width: 800px;
  margin: 0 auto;
}

#editor {
  min-height: 150px;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  margin: 10px 0;
  outline: none;
}

#editor:focus {
  border-color: #4a86e8;
  box-shadow: 0 0 0 2px rgba(74, 134, 232, 0.2);
}

#boldButton {
  padding: 5px 15px;
  font-weight: bold;
  cursor: pointer;
  border: 1px solid #ccc;
  background: white;
  border-radius: 4px;
  transition: all 0.2s;
}

#boldButton:hover {
  background-color: #f0f0f0;
}

#boldButton.active {
  background-color: #4a86e8;
  color: white;
  border-color: #4a86e8;
}

JavaScript

// Save and restore selection utilities
function saveSelection() {
    const selection = window.getSelection();
    if (selection.rangeCount === 0) return null;
    
    return selection.getRangeAt(0).cloneRange();
}

function restoreSelection(range) {
    if (!range) return;
    
    const selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
}

// Main bold toggle function
function toggleBold() {
    const editor = document.getElementById('editor');
    if (!editor) {
        console.error('Editor element not found');
        return;
    }
    
    // Save current selection
    const savedRange = saveSelection();
    if (!savedRange) return;
    
    // Check if we have a valid selection
    const selection = window.getSelection();
    if (selection.isCollapsed) {
        // Handle cursor position (no text selected)
        handleCollapsedSelection(savedRange);
        restoreSelection(savedRange);
        return;
    }
    
    // Check if selection is already bold
    if (isSelectionBold(selection)) {
        // Remove bold
        removeBoldFromSelection(savedRange);
    } else {
        // Apply bold
        applyBoldToSelection(savedRange);
    }
    
    // Restore focus to editor
    editor.focus();
}

// Check if selected text is already bold
function isSelectionBold(selection) {
    const range = selection.getRangeAt(0);
    
    // Check if selection contains any non-bold text
    const walker = document.createTreeWalker(
        range.commonAncestorContainer.parentNode || range.commonAncestorContainer,
        NodeFilter.SHOW_TEXT,
        null,
        false
    );
    
    let currentNode;
    while (currentNode = walker.nextNode()) {
        // Check if this text node is in the selection
        if (!isNodeInRange(currentNode, range)) continue;
        
        // Check if this text node has bold parent
        if...