Skip to content

Instantly share code, notes, and snippets.

@shubham43MP
Created January 14, 2025 07:47
Show Gist options
  • Select an option

  • Save shubham43MP/37ebf9a92fc47af80bc3bd8b95770ca2 to your computer and use it in GitHub Desktop.

Select an option

Save shubham43MP/37ebf9a92fc47af80bc3bd8b95770ca2 to your computer and use it in GitHub Desktop.
Proj Overview

Speechify Hover Button Feature

Purpose

This project allows users to hover over a paragraph (<p>) element, where a play button appears. Upon clicking the button, the text is read aloud using the Web Speech API, and the words being spoken are highlighted in real-time.

Features

  • Hover-to-Activate Button: On hovering over a paragraph, a play button appears next to the text.
  • Text-to-Speech: Clicking the play button reads the paragraph text aloud.
  • Word Highlighting: Words are highlighted as they are spoken aloud to provide visual context.

Tech Stack

  • JavaScript: Core scripting language for the feature.
  • Web Speech API: Utilized for speech synthesis to read text aloud.
  • CSS: For styling and highlighting the text.

Usage

  1. Include the provided JavaScript code in your HTML file.
  2. Ensure that your browser supports the Web Speech API (most modern browsers support it).
  3. Hover over any <p> element, and the play button will appear.
  4. Click the play button to hear the text read aloud with real-time word highlighting.

Code Implementation

export function createHoverPlayer() {
  document.addEventListener("mouseover", (event) => {
    const target = event.target;
    if (target.tagName === "P") {
      let playButton = target.querySelector(".hover-play-button");

      if (!playButton) {
        playButton = document.createElement("button");
        playButton.className = "hover-play-button";
        playButton.textContent = "▶";
        playButton.style.position = "absolute";
        playButton.style.right = "-30px";
        playButton.style.top = "0";

        target.style.position = "relative";
        target.appendChild(playButton);

        playButton.addEventListener("click", () => {
          speechify(target);
        });
      }

      playButton.style.display = "inline";
    }
  });

  document.addEventListener("mouseout", (event) => {
    const target = event.target;
    if (target.tagName === "P") {
      const playButton = target.querySelector(".hover-play-button");
      if (playButton) {
        playButton.style.display = "none";
      }
    }
  });
}

export function speechify(element) {
  const speechSynthesis = window.speechSynthesis;
  const utterance = new SpeechSynthesisUtterance(element.textContent || "");

  speechSynthesis.cancel();
  CSS.highlights.clear();

  utterance.onboundary = (event) => {
    const startIndex = event.charIndex;
    const endIndex = event.charIndex + event.charLength;
    const wordRange = getWordRange(element, startIndex, endIndex - startIndex);
    const highlight = new Highlight(wordRange);
    CSS.highlights.set("speechify-word-highlight", highlight);
  };

  utterance.onend = () => {
    CSS.highlights.clear();
  };

  const wholeElementRange = document.createRange();
  wholeElementRange.selectNode(element);
  const highlight = new Highlight(wholeElementRange);
  CSS.highlights.set("speechify-paragraph-highlight", highlight);

  speechSynthesis.speak(utterance);
}

function getWordRange(element, startIndex, length) {
  const range = document.createRange();
  const textNode = element.childNodes[0];
  range.setStart(textNode, startIndex);
  range.setEnd(textNode, startIndex + length);
  return range;
}

Installation Instructions

  1. Include the JavaScript code in your project.
  2. Ensure your browser supports the Web Speech API (most modern browsers support it).
  3. Customize the CSS styles for button positioning and text highlighting to suit your design.

Limitations

  • This feature works with <p> elements, but can be easily extended to other elements with slight modifications.
  • Compatibility with older browsers or unsupported versions of the Web Speech API may cause issues.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment