Forum Discussion
JAVAscript does not work in LMS Moodle
This silde has a Javascript which works in storyline and review360 but doesn't working on the LMS platform Moodle.
What can i do?
2 Replies
- JohnCooper-be3cCommunity Member
What’s happening probably isn’t GSAP — it’s more likely the SCORM runtime environment.
When you publish to Moodle, your Storyline content runs inside a SCORM iframe. Storyline dynamically injects the slide DOM at runtime, so code like:
document.querySelectorAll("[data-acc-text='target']");
may execute:
- before the slide objects exist
- or against the wrong DOM scope
- or before layers have finished rendering
In Preview and Review 360 everything loads faster and flatter, so you don’t see the issue.
In Moodle, the slide content is injected into the #slide-window container inside the SCORM frame — so querying document immediately on timeline start can return an empty NodeList.
What to Try
Delay execution slightly:
setTimeout(function() { // your code here }, 500);
Scope your selector to the slide window instead of the whole document:
var slideWindow = document.querySelector("#slide-window"); var targets = slideWindow ? slideWindow.querySelectorAll("[data-acc-text='target']") : [];
Open Moodle → F12 → Console
Add:console.log(targets.length);
If it logs 0, your selector is running before the objects exist.
Even Better
Accessibility attributes (data-acc-text) can be fragile across LMS publishing.
If possible, give the objects unique names and select by ID or custom class instead — that’s more reliable in SCORM environments.
- NedimCommunity Member
I tested your file on MoodleCloud and the JavaScript works just fine there.
I don’t have much experience with Moodle LMS, so this is only a guess, but it’s possible that the LMS environment loads or renders SCORM content differently than MoodleCloud, which can impact JavaScript timing.
Because of this, the behavior may be related to the LMS setup rather than the code itself. To me, it appears to be a timing issue where the Storyline slide content may be loaded or rendered slightly later, causing the JavaScript to run before the elements it depends on are available.
One possible workaround would be to run the JavaScript after a small delay (for example, when the Storyline timeline reaches around 0.25 seconds), or to use a version of the code that waits until the required elements are present before initializing.
IMO:- The SCORM player loads
- Your JS runs
- Storyline has not rendered the slide yet
- querySelectorAll(...) returns an empty NodeList
- targets.forEach(...) runs on nothing
- No listeners → no interaction → code doesn’t work
- No error is thrown (an empty NodeList is still a valid object, so calling .forEach on it is completely legal, it just silently does nothing
Try:
(function initWhenReady() { var targets = document.querySelectorAll("[data-acc-text='target']"); if (!targets.length) { setTimeout(initWhenReady, 100); return; } let activeTarget = null; let inTakeover = false; function takeover(target) { gsap.killTweensOf(targets); gsap.set(targets, { opacity: 0 }); gsap.set(target, { opacity: 1 }); targets.forEach(t => { t.style.pointerEvents = (t === target) ? "auto" : "none"; }); activeTarget = target; inTakeover = true; GetPlayer().SetVar("isBlinking", false); } function startBlink(target) { gsap.killTweensOf(targets); gsap.set(targets, { opacity: 1 }); gsap.to(targets, { opacity: 0, duration: 0.5, repeat: -1, yoyo: true, ease: "power1.inOut" }); targets.forEach(t => t.style.pointerEvents = "auto"); activeTarget = target; inTakeover = false; GetPlayer().SetVar("isBlinking", true); } targets.forEach(target => { target.addEventListener('click', () => { if (inTakeover && activeTarget === target) { startBlink(target); } else if (inTakeover && activeTarget !== target) { return; } else { takeover(target); } }); }); })();