Forum Discussion

SamHill's avatar
SamHill
Super Hero
2 years ago

Always on top

I just set myself the challenge of having elements that are "always on top".

I've worked on a handful of courses in the past, that had an irregular shaped header graphic (sometimes with drop shadow), where it would have been great to be able to set some elements in the Master Template to appears always on top of other elements within the module.

For those courses, I had to create a slice of the header (the irregular shaped part) and paste on each slide, where the header appeared over another element on the slide.

I have had some success, and of course it is a JavaScript implementation. This is very much an ALPHA release.

Here's the implementation if interested in having a play with it or extending it. I'm sure there will be some elements, that I haven't played with, that may need some extra logic in the JS.

  1. For each element you would like to appear always on top, add the string "{AOT}" in the "Alternative text" field. If the element is decorative, you can just add "{AOT}". This will be taken care of during processing (removed, and set to aria-hidden=true). If the element is non-decorative, for example an exit button, you would just add "{AOT}Exit" to the alternative text. This would also be process, and "{AOT}" removed and "Exit" retained in the ALT text.
  2. Add the following script to the "timeline starts" on the SLIDE MASTER. This ensures that the script will process on every slide.
const init = () => {
	// inititial value for z-index
	let z = 999;
	// get all elements with data-acc-text attribute starting with "{AOT}"
	const elements = document.querySelectorAll('[data-acc-text^="{AOT}"]');
	// loop through each element
	elements.forEach(element => {
		// get the modelId and accText from the element's dataset
		const { modelId, accText } = element.dataset;
		// get the root element with the same modelId
		const rootElement = document.querySelector(`[data-model-id="${modelId}"]`);
		// set the z-index of the root element (incrementing by 1 each time)
		rootElement.style.zIndex = z++;
		// get the alternative text by removing "{AOT}" from accText and trimming the result
		const alt = String(accText).replace('{AOT}', '').trim();
		// get the alt element with the id "acc-${modelId}"
		const altElement = document.getElementById(`acc-${modelId}`);
		// set the alternative text to the element's dataset
		element.dataset.accText = alt;
		// re-write the inner text of the alt element
		altElement.innerText = alt;
		// if the alternative text is empty (decorative), set the aria-hidden attribute to true and the z-index to -1
		if (!alt) {
			altElement.setAttribute('aria-hidden', 'true');
			altElement.style.zIndex = '-1';
		} else {
			if (altElement.hasAttribute('aria-label')) altElement.setAttribute('aria-label', alt);
		}
	});
};
requestAnimationFrame(() => {
	init();
});

I've also including a very simple example file. This just demonstrates that the designated "Always on top" elements will appear over the image on the slide.

4 Replies

  • I don’t think I understand. If I make a layer on a master slide template, that layer will always appear on a higher depth/Z-layer than anything on the base master slide of the template, including every other slide using that template.

    A Show Layer when Timeline Starts on that master and Bob’s your uncle, no?

    • SamHill's avatar
      SamHill
      Super Hero

      Technically you can do it, but you build a bit of a rod for your own back with regards to managing layers in slides. That's the method I had used, and why I experimented with this new method.

      There are lots of times when the "Hide other slide lavers" option is handy, and means you don't have to write triggers to hide specific layers. If you put the navigation elements/header on a layer on the master slide and then show a layer on another slide, if you have "Hide other slide layers" selected, the nav elements and header would be hidden. Just a PIA.

       

      • AndrewBlemings-'s avatar
        AndrewBlemings-
        Community Member

        I understand what your code block brings then, yeah. Using Storyline about 8 years now, I've consciously moved away from layers as much as possible. It's interesting you mention the Hide other slide layers option because I agree, my default is to disable that on every layer made now unless I already know the slide needs or would be indifferent to any other layer being hidden.

        I'm sure your particular need differs, but for a more concrete example, I was part of a team that developed a "Fisher Price" version of a CRM in Storyline, removing the more complex features and functions in order to create a scaffolded version with lighter cognitive load. The real CRM has a header bar with a dropdown menu to change screens/sections

        A carefully designed master slide layer made sure it and its drop shadow appeared not only on every slide we needed it to (unifying the slides into a perceived web-app) but also guaranteed that when the learner opened the "drop down menu" it would always exist higher than any of the text or shapes on the lower-level slide using that master template. Keeping the number of layers few definitely seems to be key, good call. If a single paste in a master slide template can keep me from pasting on 23 individual slides, yes please.