I’m trying to format the entire text of a webpage to “Bionic Reading” from a button.
I saw an example on codepen that formated raw text that you needed to identify, but I wish to automatically apply the function everywhere.
Basically, Bionic Reading is an accessible tool to format font so it’s easier to read, especially for neurodivergent like ADHD. From my understanding, the list of criteria are:
- Wrap every word with span tag
- split the word in two
- Add a b tag with a class that will change the font-weight to bold
- Exclude numbers
You can test paragraphs here in the Bionic Reading editing tool.
Currently my function wraps word with <span tag, split the word in two and add a tag to go with the bootstrap class.
My main issue is that it doesn’t ignore other tags inside paragraph or list tags, such as
, specification of span class and <a href=”…”. I tried to exclude button tag, but when I have a button in a paragraph, it seems to ignore the paragraph outside of the button. The navbar made of list of icons seems to also output and replace icons to the full innerhtml.
I’m also using Vue and SCSS. Any help would be appreciated. Thanks!
/*----------
- Bionic Reading Accessibility
----------*/
function addBionicReadingToPage() {
const paragraphs = document.querySelectorAll("p, li");
for (let i = 0; i < paragraphs.length; i++) {
const words = paragraphs[i].innerHTML.split(" ");
let formattedText = "";
for (let j = 0; j < words.length; j++) {
const halfLength = Math.ceil(words[j].length / 2);
const aTag = paragraphs[i].querySelector(":root > p > a");
// Check if the current word is inside a <button> tag
const isInsideButton = paragraphs[i].querySelectorAll("button").length > 0 && paragraphs[i].querySelectorAll("button").some(button => button.contains(paragraphs[i].querySelectorAll("b")[j]));
// Check if the current word is inside an <li> tag inside an element with the "navbar" class
const isInsideNavbar = paragraphs[i].querySelectorAll(".nav-item a").length > 0 && paragraphs[i].querySelectorAll(".nav-item a")[0].contains(paragraphs[i].querySelectorAll("b")[j]);
// Add the formatted word to the text if it's not inside a <button> tag or inside an <li> tag inside an element with the "navbar" class
if (!isInsideButton && !isInsideNavbar) {
formattedText += "<b>" + words[j].substring(0, halfLength) + "</b>" + words[j].substring(halfLength) + " ";
} else {
formattedText += words[j] + " ";
}
// Check if the current word is inside an <a> tag inside a <p> tag
const formattedWord = aTag && aTag.contains(document.querySelector(":root > p > a > " + words[j]))
? words[j]
: words[j].replace(/</?[^>]+(>|$)/g, "") // Remove any HTML tags from the word
? "<span>" + words[j].substring(0, halfLength) + "<b class='font-weight-bold'>" + words[j].substring(halfLength) + "</b></span>" // Wrap the word in a span tag
: words[j]; // Don't wrap the word in a span tag
formattedText += formattedWord + " ";
}
paragraphs[i].innerHTML = formattedText;
}
}
.chat-picture img{
max-width: 150px;
}
<button onclick="addBionicReadingToPage()">Click me</button>
<section id="cl-02" class="mod-1 py-5">
<div class="container">
<div class="chat-item chat-bubble-right mb-3">
<div class="row no-gutters justify-content-end">
<div class="col-9 col-lg-5">
<div class="chat-bubble">
<p id="chatQuestion1" class="mb-0"><span class="sr-only">Bruno speaking. </span>Hey Mijin, I like your
poster! Nice work!<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
<div class="col-3 col-lg-2 chat-picture">
<img src="https://media.istockphoto.com/id/1345336329/photo/orange-and-domestic-cat.jpg?b=1&s=170667a&w=0&k=20&c=ll7YVHEhvDc06D7WeItYrrgNeheiDJox0Gang6rI58A=" alt="Bruno" class="img-fluid">
</div>
</div>
</div>
<div class="chat-item chat-bubble-left mb-3">
<div class="row no-gutters">
<div class="col-3 col-lg-2 chat-picture">
<img src="https://media.istockphoto.com/id/1348266054/photo/bengal-cat-head-with-green-eyes-close-up-on-a-white-background.jpg?b=1&s=170667a&w=0&k=20&c=QUVbZ1cmXt0P1ofGy3zUoDhHcwG1rO_dksEHG7xUczU=" alt="Mijin" class="img-fluid">
</div>
<div class="col-9 col-lg-5">
<div class="chat-bubble">
<p class="mb-0"><span class="sr-only">Mijin speaking. </span>Thanks Bruno, I like it too!<br>
No. As it says, <b>everyone</b> Proin maximus, metus eget auctor suscipit, eros odio congue neque, commodo consectetur dolor purus a est.</p>
</div>
</div>
</div>
</div>
<div class="chat-item chat-bubble-right mb-3">
<div class="row no-gutters justify-content-end">
<div class="col-9 col-lg-5">
<div class="chat-bubble">
<p id="chatQuestion1" class="mb-0"><span class="sr-only">Bruno speaking. </span>Oh, I guess not. Would
you give me a refresher?</p>
</div>
</div>
<div class="col-3 col-lg-2 chat-picture">
<img src="https://media.istockphoto.com/id/1345336329/photo/orange-and-domestic-cat.jpg?b=1&s=170667a&w=0&k=20&c=ll7YVHEhvDc06D7WeItYrrgNeheiDJox0Gang6rI58A=" alt="Bruno" class="img-fluid">
</div>
</div>
</div>
<div class="chat-item chat-bubble-left mb-3">
<div class="row no-gutters">
<div class="col-3 col-lg-2 chat-picture">
<img src="https://media.istockphoto.com/id/1348266054/photo/bengal-cat-head-with-green-eyes-close-up-on-a-white-background.jpg?b=1&s=170667a&w=0&k=20&c=QUVbZ1cmXt0P1ofGy3zUoDhHcwG1rO_dksEHG7xUczU=" alt="Mijin" class="img-fluid">
</div>
<div class="col-9 col-lg-5">
<div class="chat-bubble">
<p class="mb-0"><span class="sr-only">Mijin speaking. </span>Of course! Let's go have a coffee and
talk about it.<br>In 30 minutes, you'll be a Maecenas placerat!
</div>
</div>
</div>
</div>
</div>
</section>