বাংলা 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
Post a Comment