e-learning development
1562 TopicsLocalization File Issue
I’m hoping someone can help me troubleshoot an issue I ran into with the localization tool. Last week, I used the localization feature to translate one of my courses into French. While working on the version saved to my desktop, I was able to switch back and forth between the English and French versions without any trouble. I published the course to Review 360 on Wednesday for feedback from my boss, and I didn’t return to update the file again until this morning. Now, the option to switch to the French version has completely disappeared. I’ve checked my desktop and our shared folders, but I can’t locate the French version anywhere. I’ve attached a screenshot of what I’m currently seeing in Storyline in case it helps diagnose the issue. If anyone has experienced this before or has ideas on how to recover the translated version, I’d really appreciate your help!12Views0likes1CommentStoryline 360 Block Not Working in Rise 360 on iOS Mobile App
Storyline 360 blocks used in a Rise 360 course are not working in an iOS mobile app. The content works fine on desktop and iOS mobile browsers, but in the iOS app it shows a black screen with a play button and does not load. Sometimes the slide freezes when closing. An iOS debug error appears: TypeError: undefined is not an object (evaluating 'this.videoEl.webkitEnterFullscreen') Review Link: https://360.articulate.com/review/content/d3ff3040-3f50-4507-a337-65c621fa5a0c/review SCORM: https://drive.google.com/drive/folders/1PW4LeArcRaCBKUET6TCseIYpAogem9u4?usp=sharing Please confirm if this is a known issue and advise on a fix or workaround.Corner Radius Formatting - Toggle on/off?
Hello Community, Although I think the new corner radius adjustment handles are useful in some situations, I am finding them a hinderance in many circumstances. They get in the way when trying to adjust other dimensional aspects of smaller shapes, even when you max zoom in. I attached a SnagIt image to illustrate. I have not found a way to remove, disable, or toggle this feature on/off. Is there such a thing? If not, I believe it would be a nice update to give us the option to use this feature or not depending on the work we're doing. Thank you to anyone with advice or insights on this topic! -Nick-110Views0likes3Comments3D objects in Storyline
Hi Articulate Team, Are there any plans to bring support for 3D objects (such as .obj files) into Storyline? Essentially I'm referring to a 3D model viewer component function added to Storyline allowing for some basic manipulation of the 3D object itself such as rotate and move in X/Y/Z axis, exploded view, and part isolation. This would work wonders for so many learning projects and enhance the actual learning being achieved by the learner. Whilst Storyline has an insert web object feature, this requires additional overhead of the resource itself already being suitably hosted online or in a folder that can be hosted online (i.e. it contains HTML like files - index.html, etc. which is effectively asking for it to be web-ready). This isn't always suitable or practical for every company and their respective IP assets/resources. I have come across multiple threads asking for such a feature. Here's a few of them: 3D Models in Storyline | Articulate - Community Import 3d shapes into articulate storyline 360? | Articulate - Community How to put/import 3D moldels in Storyline | Articulate - Community In one of the threads I came across, there was a reply from Katie Riggo who stated "We're working on the ability to add 360° media assets to your courses". However, later on in the thread this turned out to be referring only to 360-degree images despite the thread being filled with people asking and requesting for 3D object support in terms of 3D models and being able to manipulate them like they can in PowerPoint. You can chalk this up as another +1 to the feature request for native 3D object support by way of being able to import and, to a basic level, manipulate them. Kind regards, Sam1.3KViews7likes19CommentsStoryline 360 Multiple Response Templates
Hi there, I'm trying to build out quiz questions from a legacy course and update with more modern look and design. However no where in the Articulate template library can I find Multiple Response quiz templates, only single selection answers? Does Articulate not support this function anymore, if not why?23Views0likes3CommentsChange HTML source language in Rise course
Dear community, We developed an e-learning in Dutch using Articulate Rise and have gotten it tested on accessibility. One of the comments on the course was that in the HTML of the course the source language is shown as English ("html lang=en"), even though the full course is in Dutch. This results in screen readers selecting the language as English instead of Dutch which causes issues in, for example, wrong pronunciation of words. To overcome this users will have to manually select a different language on their screen readers. I am wondering whether there is some kind of way to fix this and change the source language? Anyone experience with this? Many thanks for your help!803Views0likes28CommentsCourse performance issue on review link after attempting pre-assessment – slides loading very slow
Hello Community, I’m experiencing a performance issue in an Articulate Storyline course, when reviewing this course on review link and need technical guidance. Course details: ~250 content slides 55 assessment questions Structure: Pre-assessment → Course → Post-assessment For alpha review, all 55 questions were kept open/visible in the pre and post-assessment, and reviewing course from review link. Issue: When reviewing this course from review link, If I attempts all (or most) of the 55 questions first and then proceeds to the course, slide loading becomes very slow after ~50–60% course completion. Navigation turns sluggish and remaining slides take a long time to load. Query: Does Storyline retain assessment data in memory until course exit? Any recommended best practices or solution on this? Looking forward to technical insights or similar experiences. Thanks,33Views0likes2CommentsRise feature request: multiple block selection
Hi all, I'd love to see a new feature in Rise: the ability to select multiple blocks at once and then move or copy them as a group. Right now, adjusting the layout of a longer lesson can be quite time-consuming, since you have to move each block one at a time. The idea is simple: You select several blocks (for example: a text block, an image block, and a video block) Then you can move them up or down together, or copy and paste them as a group This would make editing and reorganizing lessons much faster and easier Let me know if others are also missing this feature or if maybe there’s already a smart workaround I’ve missed! Please upvote if you need this feature as well! Thanks, ThomSolved244Views3likes12CommentsRise code block feature requests
Hi there. My team uses code blocks heavily in our courses. We've created a custom code block template in order to provide code syntax highlighting, copy-paste functionality, and the ability for the learner to enlarge/shrink the code box size. Ideally, this would be available out of the box in the built-in Rise code tool (under Multimedia > Code snippet). We'd like to request implementing these features in the existing code block so that we don't have to use a custom block template as a workaround. Ideally, the code block should: Provide an input field where the elearning dev can paste a snippet of code that will be visible to the learner. Provide automatic syntax highlighting with the ability customize the code colors and background color. Resize automatically according to code snippet length and screen size. Provide copy/paste button and a "click to view larger" button. I've attached a GIF to show a demonstration of this functionality in the custom code block that we are currently using. Here is the code that we used to create it: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Code Block Highlighting</title> <script> var CODE_SNIPPET = `{ "type": "Hidden", "value": "io.camunda:watchserviceinbound:1", "binding": { "type": "zeebe:property", "name": "inbound.type" } } `; </script> <style> :root { color-scheme: dark; } body { margin: 0; padding: 1rem; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background-color: #1e1e1e; color: #d4d4d4; box-sizing: border-box; } .toolbar { position: absolute; top: 1rem; right: 1rem; z-index: 10; display: flex; gap: 0.5rem; } button.copy-btn { background-color: #0e639c; color: #ffffff; border: none; border-radius: 4px; padding: 0.3rem 0.8rem; font-size: 0.8rem; cursor: pointer; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); } button.copy-btn:hover { background-color: #1177bb; } button.copy-btn:active { background-color: #0b4f75; } .editor-container { display: none; /* hidden input area */ } .code-container { position: relative; background-color: #1e1e1e; border-radius: 6px; padding: 1rem; overflow: auto; max-height: 300px; transition: max-height 0.3s ease; box-sizing: border-box; } .code-container.maximized { max-height: none; } pre { margin: 0; font-family: "Fira Code", "Consolas", "Menlo", monospace; font-size: 0.9rem; line-height: 1.4; white-space: pre; } /* Syntax highlighting tokens */ .token-punctuation { color: #d4d4d4; } .token-key { color: #9cdcfe; /* keys */ } .token-string { color: #ce9178; /* string values */ } .token-number { color: #b5cea8; } .token-boolean { color: #569cd6; } .token-function { color: #dcdcaa; } .token-variable { color: #4ec9b0; } </style> </head> <body> <div class="toolbar"> <button class="copy-btn" id="maximizeButton">Maximize ↕</button> <button class="copy-btn" id="copyButton">Copy</button> </div> <!-- Hidden editor (used internally, not visible) --> <div class="editor-container"> <textarea id="codeInput"></textarea> </div> <div class="code-container"> <pre><code id="codeBlock"></code></pre> </div> <script> // ==================================================================== (function () { var button = document.getElementById("copyButton"); var maximizeButton = document.getElementById("maximizeButton"); var codeContainer = document.querySelector(".code-container"); var codeElement = document.getElementById("codeBlock"); var inputElement = document.getElementById("codeInput"); var currentSnippet = CODE_SNIPPET; var isMaximized = false; function escapeHtml(str) { return str .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """); } function highlightCode(code) { var out = ""; var i = 0; var len = code.length; function isDigit(ch) { return ch >= "0" && ch <= "9"; } function isIdentifierStart(ch) { return (ch >= "A" && ch <= "Z") || (ch >= "a" && ch <= "z") || ch === "_"; } function isIdentifierPart(ch) { return isIdentifierStart(ch) || isDigit(ch); } while (i < len) { var ch = code[i]; // Strings: distinguish keys vs string values if (ch === '"') { var start = i; var j = i + 1; var escaped = false; while (j < len) { var c = code[j]; if (!escaped && c === "\\") { escaped = true; j++; continue; } if (!escaped && c === '"') { j++; break; } escaped = false; j++; } var str = code.slice(start, j); // Look ahead to see if this string is a key (string followed by :) var k = j; while (k < len && /\s/.test(code[k])) k++; var isKey = code[k] === ":"; if (isKey) { out += '<span class="token-key">' + escapeHtml(str) + '</span>'; } else { out += '<span class="token-string">' + escapeHtml(str) + '</span>'; } i = j; continue; } // Numbers if (isDigit(ch) || (ch === "-" && i + 1 < len && isDigit(code[i + 1]))) { var nStart = i; var n = i + 1; while (n < len && (isDigit(code[n]) || code[n] === ".")) { n++; } var num = code.slice(nStart, n); out += '<span class="token-number">' + escapeHtml(num) + '</span>'; i = n; continue; } // Identifiers (variables, booleans, functions) if (isIdentifierStart(ch)) { var idStart = i; var t = i + 1; while (t < len && isIdentifierPart(code[t])) { t++; } var ident = code.slice(idStart, t); // Look ahead for function call var u = t; while (u < len && /\s/.test(code[u])) u++; var isFunc = code[u] === "("; if (ident === "true" || ident === "false") { out += '<span class="token-boolean">' + escapeHtml(ident) + '</span>'; } else if (isFunc) { out += '<span class="token-function">' + escapeHtml(ident) + '</span>'; } else { out += '<span class="token-variable">' + escapeHtml(ident) + '</span>'; } i = t; continue; } // Punctuation if ("{}[],:".indexOf(ch) !== -1) { out += '<span class="token-punctuation">' + escapeHtml(ch) + '</span>'; i++; continue; } // Everything else out += escapeHtml(ch); i++; } return out; } function renderCode(code) { codeElement.innerHTML = highlightCode(code); // Check if content needs scrolling after a brief moment to let rendering complete setTimeout(function() { var needsScroll = codeContainer.scrollHeight > codeContainer.clientHeight; if (needsScroll) { // Content is larger than container, show maximize button maximizeButton.style.display = "block"; } else { // Content fits, hide maximize button and adjust container height maximizeButton.style.display = "none"; codeContainer.style.maxHeight = "none"; codeContainer.classList.add("maximized"); } }, 10); } function copyText(text) { // Try modern Clipboard API first, but catch permission errors if (navigator.clipboard && navigator.clipboard.writeText) { return navigator.clipboard.writeText(text).catch(function() { // Fallback to execCommand if Clipboard API is blocked return fallbackCopy(text); }); } // Use fallback directly if Clipboard API is not available return fallbackCopy(text); } function fallbackCopy(text) { var textarea = document.createElement("textarea"); textarea.value = text; textarea.style.position = "fixed"; textarea.style.opacity = "0"; document.body.appendChild(textarea); textarea.select(); try { var success = document.execCommand("copy"); document.body.removeChild(textarea); return success ? Promise.resolve() : Promise.reject(new Error("Copy failed")); } catch (err) { document.body.removeChild(textarea); return Promise.reject(err); } } button.addEventListener("click", function () { copyText(currentSnippet).then(function () { var original = button.textContent; button.textContent = "Copied!"; setTimeout(function () { button.textContent = original; }, 1500); }).catch(function (err) { console.error("Copy failed:", err); var original = button.textContent; button.textContent = "Copy failed"; setTimeout(function () { button.textContent = original; }, 1500); }); }); maximizeButton.addEventListener("click", function () { isMaximized = !isMaximized; if (isMaximized) { codeContainer.style.maxHeight = "none"; maximizeButton.textContent = "Minimize ↕"; } else { codeContainer.style.maxHeight = "300px"; maximizeButton.textContent = "Maximize ↕"; } }); // Initial render from CODE_SNIPPET inputElement.value = CODE_SNIPPET; renderCode(CODE_SNIPPET); // External API: call window.setCodeBlock("...") to update from outside window.setCodeBlock = function (newCode) { currentSnippet = String(newCode || ""); inputElement.value = currentSnippet; renderCode(currentSnippet); }; })(); </script> </body> </html>Motion Path resests when returning to slide
This is probably a little tough... I have a training I am developing that has an object moving through a series of motion plaths based on user interactions. After certain motion paths end, the training automatically goes to a MC quiz question and then returns to the original slide after the quiz question is answered. Everything works as expected prior to the return to the original slide. What happens at the return to the original slide is that the objects resets to its original postition rather than returning to where it left off in the series of the Motion Paths. Base Layer is set to "Resume Saved State" when revisiting. Subject and training are propriatary so I cannot share the story file. Hopefully I have shared enough to elicit solutions. TIA BenSolved137Views0likes9Comments