Forum Discussion
Highlight portions of text as it is read
Attached is my contribution: a pure JavaScript synchronization engine. Unlike traditional methods that require manual cue points, hard-coded timestamps or states, this script is fully dynamic. It targets the active audio stream and the corresponding text container, then uses a Character-to-Duration algorithm to calculate high-precision highlight timings automatically. Simply replace the audio file, update the text in the text box, and adjust the corresponding data-model-id value in the code.
- ThierryEMMANUEL1 month agoCommunity Member
Very impressive, very useful, and very easy to use and adjust. I tried it with an AI voice, to which I added pauses (..............). I changed the text to bold and italics. Changed the highlight color. Everything is perfect.
Another gem in my collection of Nedim's amazing tools.
One small problem, however, which is quite obvious. If I have black text on a white background (it can happen! 😀), the text turns “white” when the code runs. I foolishly tried changing "white" to “black” on line 22, but it had no effect (probably a completely stupid idea). It would be perfect if the text before highlighting retained its original color, black or any other color. Is that possible?
- Nedim1 month agoCommunity Member
Hi ThierryEMMANUEL
If your default font color is #ffffff (or any other hex value), be sure to update both instances of "white" in the code to match the font color selected in the Storyline interface.
UPDATE:During development, I identified a specific issue regarding how Articulate Storyline handles media across multiple slides. Storyline doesn't "delete" or remove audio when you move from Slide 1 to Slide 2. Instead, it keeps every audio file the learner has encountered loaded in the background. (Try to run two slides with the same script)
Because of this "piling up" behavior:
- Targeting Confusion: A standard script often gets "confused" and tries to sync the text on Slide 2 with the hidden audio from Slide 1.
- Zombie Listeners: When a learner returns to a previous slide, multiple versions of the script can end up "fighting" over the same audio track, causing the highlighting to flicker or fail entirely.
To ensure 100% accuracy, I have refined the script to move away from a "static" search to an Active Listener model.
- Interaction-Based Locking: Since our audio is triggered by a user button click, the script now waits for that specific "Play" signal. It no longer guesses which audio to use; it waits for the learner to "tell" it which one is active.
- Dynamic Source Resolution: The moment a button is clicked, the script identifies the unique currentSrc (the specific file path) of that audio. It locks the highlighting logic to that specific file and ignores all "zombie" audio files idling in the background.
- State Reset: Every time a new audio track begins, the script clears any stale "listeners" from previous slides. This ensures a clean, high-performance sync even if the learner navigates back and forth through the course non-linearly.
This upgrade makes the synchronization "slide-aware." Whether the learner clicks a button on Slide 1 or Slide 10, the code dynamically recalibrates to the active media. Even with a sequence of 10 different audio tracks across 10 consecutive slides, the script intelligently identifies and locks onto the specific audio file belonging to the current slide the moment it is triggered.
Of course, this only applies if JavaScript is being used to manipulate other elements or control audio through triggers. For more advanced coding and manipulation, it’s important to be aware of these limitations.
I’ve attached an updated version with two slides, including both B&W and W&B variants, along with an updated script.- ThierryEMMANUEL1 month agoCommunity Member
This seems perfect for the colors Nedim (I hadn't seen the two occurrences of "white" in the code... because I didn't know where to look). Regarding the audio track identification by slide, I hadn't noticed that bug either (I tested it slide by slide). Thank you very much for sharing.