বাংলা Page Reader auto Scroll: select text to start reading

🔊 বাংলায় শুনুন

এটি একটি নমুনা অনুচ্ছেদ।

 

Code:

Html:

<!-- ❌ Top Start --📱 Media query-->
<style>
  @media screen and (max-width: 768px) {
    #smartReaderBtn {
      right: 25px !important;
      top: 40px !important;
    }
  }
</style>

<!--✅ Speaker Icon Button-->
<div id="smartReaderBtn" onclick="toggleSmartReader()" style="align-items: center; background-color: #ff9900; border-radius: 50%; border: 2px solid white; box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 8px; color: white; cursor: pointer; display: flex; padding: 10px; position: fixed; right: 100px; top: 80px; z-index: 999;">
  <span style="font-size: 24px; margin-right: 5px;">🔊</span>
  <span id="smartReaderLabel" style="font-size: 16px;">বাংলায় শুনুন</span>
</div>

<!--✅ Main Content Area-->
<div class="post-body">
<p>শুরু করা হচ্ছে!</p>
<!-- ❌ Top End --📱 Main Content Area Start -->



<!-- ❌ Bottom html Start --📱 Main Content Area End -->
<p>শেষ হলো!</p>
</div>

<-- JS: -->

<script>
// Start 🔉 Speech all function
let smartQueue = [];
let currentIndex = 0;
let isReading = false;
let isPaused = false;
let wakeLock = null;

// ✅ Toggle Start / Pause / Resume
function toggleSmartReader() {
  if (!isReading && !isPaused) {
    startSmartReader();
  } else if (isReading) {
    pauseSmartReader();
  } else if (isPaused) {
    showRestartPrompt();
  }
}

// ✅ Start Reading
function startSmartReader() {
  const content = document.querySelector(".post-body");
  if (!content) {
    alert("❌ Content not found.");
    return;
  }

  smartQueue = Array.from(
    content.querySelectorAll(
      'p, li, td, th, h1, h2, h3, h4, h5, h6, span, b, strong, em, i, u, div:not(:has(p,div,table,ul,ol)'
    )
  ).filter(el => {
    const text = el.innerText.trim();

    // ❌ Skip empty text
    if (!text) return false;

    // ❌ Skip long blocks
    if (text.length > 300) return false;

    // ❌ Skip Smart Reader button / UI text
    if (el.closest('#smartReaderBtn')) return false;

    // ❌ Skip only emoji / symbol (👇 ❌ ✅ ➡️ ⭐ etc.)
    // Must contain at least one letter or number (English or Bengali)
    if (!/[a-zA-Z0-9\u0980-\u09FF]/.test(text)) return false;

    // ❌ Skip etc, etc., ...
    if (/^(etc\.?|\.{2,})$/i.test(text)) return false;

    return true;
  });

  if (smartQueue.length === 0) {
    alert("❌ No readable sections.");
    return;
  }

  currentIndex = 0;
  isReading = true;
  isPaused = false;
  updateButtonUI("reading");
  requestWakeLock();
  readNextLine();
}

// ✅ Read Element by Element
function readNextLine() {
  if (currentIndex >= smartQueue.length) {
    stopSmartReader();
    return;
  }

  const el = smartQueue[currentIndex];
  const text = el.innerText.trim();
  currentIndex++;

  // 🔦 Highlight current reading line
  smartQueue.forEach(e => e.style.backgroundColor = "");
  el.style.backgroundColor = "lightskyblue";

  // 📍 Auto scroll to current line
  el.scrollIntoView({ behavior: "smooth", block: "center" });

  // 🎧 Active button highlight
  document.getElementById("smartReaderBtn").style.backgroundColor = "lightskyblue";

  // 🔊 Cancel previous speech
  window.speechSynthesis.cancel();

  const speak = new SpeechSynthesisUtterance(text);

  // ✅ Safe language handling (no silence issue)
  if (/[\u0980-\u09FF]/.test(text)) {
    speak.lang = "bn-IN"; // Bengali text
  } else {
    speak.lang = "en-US"; // English / mixed text
  }

  speak.rate = 1;
  speak.pitch = 1;
  speak.volume = 1;

  // ➡️ Move to next line after speech ends
  speak.onend = () => {
    if (isReading) {
      setTimeout(readNextLine, 400);
    }
  };

  window.speechSynthesis.speak(speak);
}

// ✅ Pause and Ask
function pauseSmartReader() {
  window.speechSynthesis.cancel();
  isReading = false;
  isPaused = true;
  releaseWakeLock();
  updateButtonUI("paused");

  setTimeout(() => {
    const choose = confirm(
      "📍 Select start point to restart reading?\n\nOK = Scroll and select\nCancel = Return to the page"
    );

    if (!choose) {
      smartQueue.forEach(e => e.style.backgroundColor = "");
      isPaused = false;
      updateButtonUI("default");
    } else {
      alert("🔎 Scroll to a new point. Then click the button again.");
    }
  }, 200);
}

// ✅ Restart After Scroll
function showRestartPrompt() {
  const visibleElement = smartQueue.find(el => {
    const rect = el.getBoundingClientRect();
    return rect.top > 0 && rect.top < window.innerHeight;
  });

  currentIndex = visibleElement
    ? smartQueue.indexOf(visibleElement)
    : 0;

  setTimeout(() => {
    const resume = confirm(
      "✅ Start reading from selected point?\n\nOK = Start Reading\nCancel = Return to page"
    );

    if (resume) {
      isPaused = false;
      isReading = true;
      updateButtonUI("reading");
      requestWakeLock();
      readNextLine();
    } else {
      smartQueue.forEach(e => e.style.backgroundColor = "");
      isPaused = false;
      updateButtonUI("default");
    }
  }, 100);
}

// ✅ Stop All
function stopSmartReader() {
  isReading = false;
  isPaused = false;
  currentIndex = 0;
  smartQueue.forEach(e => e.style.backgroundColor = "");
  updateButtonUI("default");
  releaseWakeLock();
  window.speechSynthesis.cancel();
}

// ✅ Button UI Updates
function updateButtonUI(state) {
  const btn = document.getElementById("smartReaderBtn");
  const label = document.getElementById("smartReaderLabel");

  if (state === "reading") {
    btn.style.backgroundColor = "lightskyblue";
    label.textContent = "Reading is in progress";
  } else if (state === "paused") {
    btn.style.backgroundColor = "#f0ad4e";
    label.textContent = "Read Again";
  } else {
    btn.style.backgroundColor = "#ff9900";
    label.textContent = "Listen in Bengali";
  }
}

// ✅ Wake Lock Request
async function requestWakeLock() {
  if ('wakeLock' in navigator) {
    try {
      wakeLock = await navigator.wakeLock.request('screen');
      console.log("✅ Wake Lock activated");
    } catch (err) {
      console.warn("❌ Wake Lock failed:", err);
    }
  }
}

// ✅ Wake Lock Release
async function releaseWakeLock() {
  try {
    if (wakeLock) {
      await wakeLock.release();
      wakeLock = null;
      console.log("🔓 Wake Lock released");
    }
  } catch (err) {}
}

// ✅ Reacquire Wake Lock on Return
document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "visible" && isReading) {
    requestWakeLock();
  }
});
// End 🔉 Speech all function
</script>
<!-- ❌ Bottom html End --📱 after Main Content Area End -->

এই বাক্যটি বাংলায় পড়া হবে।

Comments

Popular posts from this blog

বাংলা/हिंदी/English Input Text Reader auto Scroll: select text to start reading

हिंदी Page Reader auto Scroll: select text to start reading