Copy link to clipboard
Copied
Our customer want us to 'speak' the quiz questions and answers by default. Problem is that the audio keeps playing when the submit button is pressed and overlaps with the spoken responses. Is there any workaround that will enable us to play the audio until the submit buttons is pressed without overlapping on the responses. This questions was asked in another audio forum post, but the workaround to default the audio to 'off' is not acceptable in our case. Any workarounds?
Copy link to clipboard
Copied
Hello,
Will try to explain how I understand the way a Question slide works:
First thing you can change is the pausing point of the question slide, but once an audio clip started playing, this will continue and thus not solve your problem.
It is only in that second step that you can do more customising by changing the Success/Failure actions, perhaps to an advanced action.
Are you using this default behavior? And the audio is attached to what: to the slide or to the text captions for the questions and to the Success/Failure captions for the answers?
I think the solution will be to skip the first step, by deleting the Success/Failure captions. When clicking on the Submit button in that situation, the Success/Failure actions will be executed immediately (and the playhead will be released). Attach the audio for the questions to an invisible object (rectangle without fill or stroke), that you hide with the advanced actions to be triggered by Success/Failure and show custom Text Captions for Success/Failure with audio attached to them. Because the playhead is now released, you will either have to time correctly so that the user will have to listen to the audio totally or to insert a static button widget that pauses the slide. But here I'm a bit stuck because I do not know which version of CP you are using, please?
I blogged about using audio objects a while ago, but did not offer detailed explanations because no one asked for it until now. Have a look:
Playtime with audio and widgets
Lilybiri
Copy link to clipboard
Copied
Hi Lilybirl,
Thank you so much for jumping in and helping to explain the question slide behavior. Thanks to you, I now understand how to delete the success/failure captions, and attach audio to an invisible object for the question, and a captions for the custom success/failure responces.
Unfortunately, I'm now stuck on how to pause the playhead and then create an action that prompts the user to "click anywhere or press 'y' to continue". I'm using Captivate 5.5, and I don't see a pause option for the static button widget. Thanks for any further guidance you can provide.
Copy link to clipboard
Copied
Hello,
I didn't know which version you were using. In Captivate 5.0 the Buttons widget was static but had pausing. In 5.5 it was replaced by both a Static widget (without pausing) and an interactive one (with pausing). I complained about it, because you cannot add an interactive widget on a question slide nor on a master slide. The Adobe team did listen to my complaint and they offered me a new version of the static widget that pauses at half its duration. You cannot change tha pausing point, just change the timeline (shorter and later on the slide timeline) to influence the pausing point.
Oh, yes, they allowed me to make this widget public, you can download it on my blog in this post:
What I (dis)like in Captivate 5.5
The paragraph is in red. You can add this static button, and just put Next on it, perhaps make it appear (with its pausing) just at the pausing point of the question slide, where the playhead will be released on the moment the user clicks on Submit. That way there will not be confusion, because the widget will only appear after the Submit has been clicked.
Lilybiri
Copy link to clipboard
Copied
Thank you Lilybiri, I will try this and report back. I obviously have much to learn about advanced actions, and the widgets that are available.
Copy link to clipboard
Copied
Unfortunately, this link is no longer valid, and links to a static page that states: "Posterous Spaces is [SIC] no longer available."
Is there any chance you've updated this content to the new blog?
Copy link to clipboard
Copied
Unfortunately, this link is no longer valid, and links to a static page that states: "Posterous Spaces is [SIC] no longer available."
Is there any chance you've updated this content to the new blog?
Copy link to clipboard
Copied
New blog is http://blog.lilybiri.com It is impossible to update all links
in Jive.
Copy link to clipboard
Copied
You can also use CPGuru's Hide Submit Button Widget: http://www.cpguru.com/2011/01/06/hide-submit-button-widget-for-adobe-captivate-5/. This will hide the Submit Button while the audio is playing.
Copy link to clipboard
Copied
Thanks much Chris_Cap. I will also try this and report back. This may be the path of least resistance if we can live with the limitations until a better solution is identified or developed.
Copy link to clipboard
Copied
I've been messing around with this for a while now as it's an irritating thing that the client wants me to fix. Adobe, this is a feature it would be handy to build into Captivate 10
However, today I found a little workaround that will keep the client happy and is simple to execute.
I changed my fancy Submit button graphic to a transparent button and deleted all of the wording associated with it (so the word submit). I then inserted a straight image, which was my original submit button graphic. I then applied a fade to this and placed it at the end of the timeline AFTER the audio finishes.
Therefore to a user, the submit button is only visible once the audio has finished. Incidentally, I bought a widget for $10 that is discussed a lot from cpguru which hides the submit button until the audio stops, but it only works in flash, not HTML5, so is therefore no use for my (HTML5) project.
It's a bit of a dodgy workaround, because (of course) the transparent button is there all of the time. But I figure if they're maverick enough to click a button they can't see, they'll have to suffer the double talking consequences
It will suffice for me as a workaround, until Adobe fix this issue - which, judging by the amount of times the question has been asked in the forum, is a features users would find helpful.
Copy link to clipboard
Copied
Thanks for posting your solution. However, it is annoying to the learner that they must listen to the full audio clip before they can click submit and navigate to the next slide.
I have the same issue that I want to stop audio on a quiz slide when the submit button is clicked. Has there been any improvements in Captivate 9 that would make this possible?
Copy link to clipboard
Copied
Put this in the head of the index file just under the opening <script> tag:
var interfaceObj, eventEmitterObj;
window.addEventListener( 'moduleReadyEvent', function ( e )
{
interfaceObj = e.Data;
eventEmitterObj = interfaceObj.getEventEmitter();
initializeEventListeners();
});
function initializeEventListeners()
{
eventEmitterObj.addEventListener( 'CPAPI_SLIDEENTER', function ( e )
{
for ( var i = 0; i < e.Data.si.length; i++ )
{
if ( cp.model.data[ e.Data.si[ i ].n + 'c' ].accstr.indexOf( 'Submit' ) != -1 )
{
var str = cp.model.data[ e.Data.si[ i ].n ].mdi;
str = str.substring( 0, str.length - 1 );
var submit_btn = document.getElementById( str );
submit_btn.addEventListener( 'click', function()
{
var mySlideAud = cp.movie.am.slideAudios[ e.Data.audioName ];
mySlideAud.nativeAudio.pause();
mySlideAud.nativeAudio.currentTime = 0;
});
break;
}
}
});
}
Copy link to clipboard
Copied
Thank you, TLCmediadesign! Can't wait to try this out!
I'm not too tech saving when it comes to code. Where would I find the index file for Captivate 9? I looked in the Templates > Publish folder but didn't see it there.
Copy link to clipboard
Copied
You can put it in the index file that is published or you can put it in the template file located here:
C:\Program Files\Adobe\Adobe Captivate 9 x64\HTML\index.html
Copy link to clipboard
Copied
I added the code but unfortunately the audio still continued playing after hitting the submit button when viewing the published file in a browser.
Copy link to clipboard
Copied
This is slide audio correct?
Can you show the code from the top of the html file down to the bottom of the code?
This is what mine looks like and it stops the slide audio when clicked:
<!DOCTYPE html>
<html lang="en">
<head>
<meta name='viewport' content='initial-scale = 1, minimum-scale = 1, maximum-scale = 1'/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
<style type="text/css">#initialLoading{background:url(assets/htmlimages/loader.gif) no-repeat center center;background-color:#ffffff;position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;z-index:10010;}</style>
<script>
var interfaceObj, eventEmitterObj;
window.addEventListener( 'moduleReadyEvent', function ( e )
{
interfaceObj = e.Data;
eventEmitterObj = interfaceObj.getEventEmitter();
initializeEventListeners();
});
function initializeEventListeners()
{
eventEmitterObj.addEventListener( 'CPAPI_SLIDEENTER', function ( e )
{
for ( var i = 0; i < e.Data.si.length; i++ )
{
if ( cp.model.data[ e.Data.si[ i ].n + 'c' ].accstr.indexOf( 'Submit' ) != -1 )
{
var str = cp.model.data[ e.Data.si[ i ].n ].mdi;
str = str.substring( 0, str.length - 1 );
var submit_btn = document.getElementById( str );
submit_btn.addEventListener( 'click', function()
{
var mySlideAud = cp.movie.am.slideAudios[ e.Data.audioName ];
mySlideAud.nativeAudio.pause();
mySlideAud.nativeAudio.currentTime = 0;
});
break;
}
}
});
}
function initializeCP()
Copy link to clipboard
Copied
This is what it looks like:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="x-ua-compatible" content="IE=10">
<title>Captivate Responsive Project</title>
<link rel="stylesheet" href="assets/css/start/jquery-ui-1.11.4.custom.css">
<script type="text/javascript" src="assets/js/jquery-1.11.3.min.js"></script>
var interfaceObj, eventEmitterObj;
window.addEventListener( 'moduleReadyEvent', function ( e )
{
interfaceObj = e.Data;
eventEmitterObj = interfaceObj.getEventEmitter();
initializeEventListeners();
});
function initializeEventListeners()
{
eventEmitterObj.addEventListener( 'CPAPI_SLIDEENTER', function ( e )
{
for ( var i = 0; i < e.Data.si.length; i++ )
{
if ( cp.model.data[ e.Data.si[ i ].n + 'c' ].accstr.indexOf( 'Submit' ) != -1 )
{
var str = cp.model.data[ e.Data.si[ i ].n ].mdi;
str = str.substring( 0, str.length - 1 );
var submit_btn = document.getElementById( str );
submit_btn.addEventListener( 'click', function()
{
var mySlideAud = cp.movie.am.slideAudios[ e.Data.audioName ];
mySlideAud.nativeAudio.pause();
mySlideAud.nativeAudio.currentTime = 0;
});
break;
}
}
});
}
<script type="text/javascript" src="assets/js/jquery-ui-1.11.4.custom.min.js"></script>
</head>
<body style="background-color:#2f2f2f">
<style>
.body
{
font-family: Calibri;
font-size: 24px;
font-style: bold;
}
.button
{
border-width: 10px;
border-color: black;
display: block;
float: left;
}
#contentDiv
{
padding-top: 10px;
margin: 0 auto;
display: block;
z-index: 100;
}
iframe
{
border: 0px;
width: 100%;
height: 100%;
}
.contentSlider
{
margin-left: auto;
margin-right: auto;
margin-top: 10px;
display: block;
}
.controlButtons
{
margin-left: auto;
margin-right: auto;
display: block;
background-color: #2f2f2f;
/*border: 1px solid #ddd;*/
text-align: center;
}
.sliderValue
{
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-color: #000000;
opacity: 0.5;
z-index: 101;
text-align: center;
display: none;
position: absolute;
color: #ffffff;
font-size: 24px;
font-family: Verdana;
font-weight: bold;
}
#cpFakeGeo
{
position:fixed;
top:15px;
left:15px;
background-color: gray;
}
#cpFakeGeoTitle
{
background-color: black;
color:white;
padding:3px;
margin:3px;
float:left;
}
#cpFakeGeoList
{
padding:2px;
margin:4px;
}
</style>
<div id="control_buttons" class="controlButtons">
</div>
<div id="contentSlider" class="contentSlider"></div>
<div id="sliderValueDiv" class="sliderValue"></div>
<div id="contentDiv">
<iframe name="preview" id="content" src="index.html" class="preview"></iframe>
</div>
<script>
var reverseOffsetH = 0;
var reverseOffsetV = 0;
function resizeIFrameToWidth(iWidth)
{
var content = document.getElementById("contentDiv");
content.width = iWidth;
content.style.width = iWidth + "px";
}
function resizeIFrameToHeight(iHeight)
{
var content = document.getElementById("contentDiv");
content.height = iHeight;
content.style.height = (iHeight) + "px";
}
function createHeightSlider(iHeight)
{
$( "#contentVerticalSlider" ).slider( "value", reverseOffsetV-(iHeight) );
}
function selectLabel(value)
{
$("#control_buttons label").removeClass("ui-state-active ui-state-focus");
var lOtherCB1 = $("#control_buttons label");
for(var i = lOtherCB1.length - 1; i >=0 ; --i)
{
var lLabel = lOtherCB1;
if(Number(lLabel.htmlFor) >= (value))
{
$(lLabel).addClass("ui-state-active ui-state-focus");
return Number(lLabel.htmlFor);
}
}
}
function onSliderChange(e,ui)
{
var value = ui.value;//$( "#contentSlider" ).slider("value");
value = reverseOffsetH - value;
resizeIFrameToWidth(value);
var labelVal = selectLabel(value);
if(preview.cp && preview.cp.getCurrentSlideResponsiveHeight)
{
var lHeight = preview.cp.getCurrentSlideResponsiveHeight(labelVal);
resizeIFrameToHeight(lHeight);
}
$("#sliderValueDiv").html("<span style='display:inline-block; vertical-align:middle'>" + value + "</span>");
$("#sliderValueDiv").css("display","block");
$("#sliderValueDiv").css("line-height", window.innerHeight +"px");
}
function onSliderChanged(e,ui)
{
onSliderChange(e,ui);
$("#sliderValueDiv").css("display","none");
}
function resizeIFrame(e)
{
var CB_button = e.target;
var lWidth = Number(CB_button.id);
lWidth = reverseOffsetH - lWidth;
selectLabel(lWidth);
resizeIFrameToWidth(lWidth);
$( "#contentSlider" ).slider( "value", lWidth );
}
function createSliders(iBreakpointsArr,iHeight,iCurrentWidth)
{
var totalBreakpoints = iBreakpointsArr.length;
reverseOffsetH = (Number(iBreakpointsArr[totalBreakpoints - 1]) + 320);
$("#contentSlider").width(Number(iBreakpointsArr[totalBreakpoints - 1]) + "px");
$("#contentSlider").slider({
min: 320,
max: Number(iBreakpointsArr[totalBreakpoints - 1]),
slide: onSliderChange,
change: onSliderChanged
});
$( "#contentSlider" ).slider( "value", reverseOffsetH-iCurrentWidth );
}
function initializeResponsivePreview(iBreakpointsArr,iWidth,iHeight,iCurrentWidth,isRunningOnDesktop)
{
if(!isRunningOnDesktop)
{
var location = window.location.href;
if(location.indexOf("?") != -1)
{
var lURLComponents = location.split("?");
var lURLParams = lURLComponents[1];
var lURLParamsNameValuePairs = lURLParams.split("&");
var lRedirect = false;
for(var i = 0; i < lURLParamsNameValuePairs.length; ++i)
{
var lPairStr = lURLParamsNameValuePairs;
if(lPairStr.indexOf("=") == -1)
continue;
var lNameValArr = lPairStr.split("=");
if(lNameValArr[0] == "CPEdgeInspectPreview" && lNameValArr[1] == "true")
{
lRedirect = true;
break;
}
}
if(lRedirect)
{
location = location.split('rindex.html')[0];
location += "index.html";
window.location = location;
return;
}
}
}
if(!iBreakpointsArr || iBreakpointsArr.length <= 0)
return;
var content = document.getElementById("contentDiv");
content.style.width = iWidth + "px";
content.style.height = (iHeight) + "px";
var totalBreakpoints = iBreakpointsArr.length;
var controlButtonsHolder = document.getElementById("control_buttons");
controlButtonsHolder.style.width = iWidth + "px";
if(!controlButtonsHolder)
return;
for(var i = totalBreakpoints-1; i >= 0; --i)
{
var lCurrBreakPointWidth = iBreakpointsArr;
var lButton = document.createElement("input");
lButton.type = "radio";
lButton.name = "radio";
lButton.id = lCurrBreakPointWidth;
lButton.onclick = resizeIFrame;
controlButtonsHolder.appendChild(lButton);
var label = document.createElement("label");
label.setAttribute("for",lCurrBreakPointWidth);
label.innerHTML = lCurrBreakPointWidth;
controlButtonsHolder.appendChild(label);
}
$( "#control_buttons" ).buttonset();
window.addEventListener('message', function (e){
if (!window.location.origin) {
window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
}
if(window.location.origin != e.origin)
return;
if(e.data == 'cpindexInited'){
e.source.postMessage('cpgetGeoVarsInfo', e.origin);
}
else if(e.data.substr(0,9) == 'cpfakeGeo'){
var JSONObj = JSON.parse(e.data.substr(9));
var geoVars = JSONObj.geoVarsInfo;
if(geoVars.length > 0){
if(!window.fakeGeo){
window.fakeGeo = document.createElement('div');
window.fakeGeo.id = 'cpFakeGeo';
var fakeGeoTitle = document.createElement('div');
fakeGeoTitle.innerHTML = JSONObj.title || 'Emulate Geolocation';
fakeGeoTitle.id = 'cpFakeGeoTitle';
window.fakeGeo.appendChild(fakeGeoTitle);
var fakeGeoList = document.createElement('select');
fakeGeoList.id = 'cpFakeGeoList';
var fakeGeoLocationNowhere = JSONObj.dfltLoc;
if(!fakeGeoLocationNowhere)
fakeGeoLocationNowhere = 'nowhere';
fakeGeoList.options[0] = new Option('<' + fakeGeoLocationNowhere + '>', '');
for(var i =0; i < geoVars.length; ++i){
fakeGeoList.options[fakeGeoList.options.length] = new Option(geoVars.name, JSONObj.geoValues);
}
fakeGeoList.addEventListener('change', function(evt){
//console.log('faking cpInfoGeoLocation to ' + fakeGeoList.value);
e.source.postMessage('cpfakeGeo' + fakeGeoList.value, e.origin);
});
window.fakeGeo.appendChild(fakeGeoList);
document.body.appendChild(window.fakeGeo);
}
}
}
}, false);
}
</script>
</body>
</html>
Copy link to clipboard
Copied
You need to surround the script I gave you with an opening <script> tag and put a closing </script> tag at the end.
<script>
var interfaceObj, eventEmitterObj;
window.addEventListener( 'moduleReadyEvent', function ( e )
{
interfaceObj = e.Data;
eventEmitterObj = interfaceObj.getEventEmitter();
initializeEventListeners();
});
function initializeEventListeners()
{
eventEmitterObj.addEventListener( 'CPAPI_SLIDEENTER', function ( e )
{
for ( var i = 0; i < e.Data.si.length; i++ )
{
if ( cp.model.data[ e.Data.si[ i ].n + 'c' ].accstr.indexOf( 'Submit' ) != -1 )
{
var str = cp.model.data[ e.Data.si[ i ].n ].mdi;
str = str.substring( 0, str.length - 1 );
var submit_btn = document.getElementById( str );
submit_btn.addEventListener( 'click', function()
{
var mySlideAud = cp.movie.am.slideAudios[ e.Data.audioName ];
mySlideAud.nativeAudio.pause();
mySlideAud.nativeAudio.currentTime = 0;
});
break;
}
}
});
}
</script>
Copy link to clipboard
Copied
Thanks so much for your patience with me. The script is working with html output. Should it also work with swf?
Copy link to clipboard
Copied
No, it will not work with swf only HTML5.
Copy link to clipboard
Copied
Many thanks for all your help!
Copy link to clipboard
Copied
Hey TLCMedia, You wouldn't happen to know how to adjust that code to work in Cap8? I tried it as is but it's causing my HTML presentation to not load. If you have any tips on adjustments I'd love to hear them! Thanks!
Copy link to clipboard
Copied
I would imagine that it's the same for CP8. There must be some other issue. Can you open the developer tools (F12) and see if there are any errors in the console?
Copy link to clipboard
Copied
I think the only error is regarding the SCORM settings applied to the code and the fact that there's no LMS driver but here's the whole error in case you see something else!
Uncaught TypeError: Cannot read property 'document' of null
at ShowDebugWindow (scormdriver.js:1035)
at DisplayError (scormdriver.js:1036)
at InitializeExecuted (scormdriver.js:1023)
at LMSStandardAPI.SCORM_Initialize [as Initialize] (scormdriver.js:381)
at Start (scormdriver.js:1021)
at cp.LoadActivities (CPM.js:1001)
at Function.cp.DoCPInit (CPM.js:1634)
at cpInit (index_SCORM.html:49)
at initializeCP (index_SCORM.html:57)
at constructDIVs (index_SCORM.html:91)