JS-controlled Next button not showing up anymore | XM Community
Skip to main content
Solved

JS-controlled Next button not showing up anymore

  • February 10, 2025
  • 9 replies
  • 74 views

Forum|alt.badge.img+5
  • Level 2 ●●
  • 41 replies

I have an active survey and today there are suddenly people reporting a new issue. 

There’s a page where they watch a tv episode, and when the episode is over the Continue button appears so they can continue to the post-video questions (buttons shows when video is actually finished playing, or if they cheat and drag vimeo scrubber to end and wait for the full time to elapse). Today, the last two people to take the survey have not been shown the continue button and they’re stuck. One is on Chrome, one is on Safari, both are on Mac. A lot of my participants have been on Mac (including me) and this hasn’t happened before. on the responses in progress data, it shows the last question answered as the last question on the page before the tv episode. When the Safari person emailed me I was sure it was probably a browser extension conflict, but then in the data I saw another person stuck on the same question in Chrome, so an extension seems less probable?

 

The video question has custom js for the hidden continue button, gained from an older thread in this forum. 

The js:

Qualtrics.SurveyEngine.addOnload(function()
{
	/*Place your JavaScript here to run when the page loads*/
this.hideNextButton();
this.getChoiceContainer().hide();
});

Qualtrics.SurveyEngine.addOnReady(function()
{
	/*Place your JavaScript here to run when the page is fully displayed*/
var my_vid = document.querySelector("myvideo");
const player = new Vimeo.Player("myvideo");
that = this;

	document.addEventListener("visibilitychange", () => {
	if (document.visibilityState !== 'visible') {
		player.pause();
		 }
		  }); 

	player.on("play", function () {
my_vid.style.pointerEvents = "none";
});



player.on("ended", function () {
that.showNextButton();
});


jQuery("#"+this.questionId).prev(".Separator").hide();
});

Qualtrics.SurveyEngine.addOnUnload(function()
{
	/*Place your JavaScript here to run when the page is unloaded*/

});

And the html on the actual question (a text/graphic question):

<div id="myvideo">Now you’re going to watch the full episode those clips were taken from. Please watch the entire video before proceeding to the questions on the next page. <br><br><i>Make the video full-screen using the arrows icon in the bottom right of the video player.</i><br><br> ${lm://Field/34}<br></div>

Field 34 is the video embed code stored in a loop & merge table, and the video played fine for the reporting participant. 

 

Any suggestions on why the continue button isn’t showing up as expected?

Best answer by TomG

Whether you are using this.getChoiceContainer() or this.getChoiceContainer() the same thing applies - both return an html element, not a jQuery object. So, to use hide() you need to first make it a jQuery object:

jQuery(this.getChoiceContainer()).hide();

 

View original

9 replies

Forum|alt.badge.img+5
  • Author
  • Level 2 ●●
  • 41 replies
  • February 10, 2025

I should have mentioned two things:

  1. The same code is on all videos in the survey, so by the time they get to the full episode page where it’s getting stuck, they’ve already encountered it 2 or 3 times on short video clips, where it worked fine. 
  2. The question has display logic to only display the question if they have been assigned to certain shows. A second question with the same code but slightly different intro text uses display logic to only display if they’re watching one of the other shows (everyone gets one or the other). Other questions on the page in clude two hidden questions that use js to record loop & merge info to the dataset, and a timing question (no timing question settings turned on). For the sake of completeness, the js on the two hidden questions is below.

First hidden question:

Qualtrics.SurveyEngine.addOnload(function()
{
this.hidePreviousButton();	

	  jQuery( this.questionContainer ).hide();

// record the clip ID	
	jQuery( this.questionContainer ).find('input').val( '${lm://Field/2}');


});
Qualtrics.SurveyEngine.addOnReady(function()
{
	/*Place your JavaScript here to run when the page is fully displayed*/
  jQuery("#"+this.questionId).prev(".Separator").hide();
});

Qualtrics.SurveyEngine.addOnUnload(function()
{
	/*Place your JavaScript here to run when the page is unloaded*/

});

Second hidden question:

Qualtrics.SurveyEngine.addOnload(function()
{


	  jQuery( this.questionContainer ).hide();

	jQuery( this.questionContainer ).find('input').val('${lm://CurrentLoopNumber}');


});
Qualtrics.SurveyEngine.addOnReady(function()
{
	/*Place your JavaScript here to run when the page is fully displayed*/
  jQuery("#"+this.questionId).prev(".Separator").hide();
});

Qualtrics.SurveyEngine.addOnUnload(function()
{
	/*Place your JavaScript here to run when the page is unloaded*/

});

 


TomG
Level 8 ●●●●●●●●
Forum|alt.badge.img+27
  • Level 8 ●●●●●●●●
  • 5909 replies
  • February 10, 2025

Your issue is probably related to the Vimeo player since it appears it’s “ended” event isn’t getting fired.


Forum|alt.badge.img+5
  • Author
  • Level 2 ●●
  • 41 replies
  • February 25, 2025

The person checked their console log so they could show me what it was showing for error messaging and it looked like it was tied to my qualtrics js:

[Error] SE API Error:  (3)

TypeError: undefined is not an object (evaluating 'this.getChoiceContainer().hide')

function() { /*Place your JavaScript here to run when the page loads*/ this.hideNextButton(); this.getChoiceContainer().hide(); }

"https://bgsu.az1.qualtrics.com/jfe/static/dist/jfeLib.fa2484b7040929bdf0ac.min.js:2:29153"

i (jfeLib.fa2484b7040929bdf0ac.min.js:2:35473)

error (jfeLib.fa2484b7040929bdf0ac.min.js:2:36509)

(anonymous function) (jsApi.8c8dd06a862b12e2d92e.min.js:1:4907)

r (jfeLib.fa2484b7040929bdf0ac.min.js:2:29154)

s (jfeLib.fa2484b7040929bdf0ac.min.js:2:28410)

_trigger (jfeLib.fa2484b7040929bdf0ac.min.js:2:30010)

r (jfe.470d357534991cd8b337.min.js:2:359433)

(anonymous function) (jfe.470d357534991cd8b337.min.js:2:274044)

(anonymous function) (jfe.470d357534991cd8b337.min.js:2:372403)

a (jfeLib.fa2484b7040929bdf0ac.min.js:2:117346)

(anonymous function) (jfeLib.fa2484b7040929bdf0ac.min.js:2:84493)

(anonymous function) (jfeLib.fa2484b7040929bdf0ac.min.js:2:84645)

(anonymous function) (jfeLib.fa2484b7040929bdf0ac.min.js:2:86982)

(anonymous function) (jfeLib.fa2484b7040929bdf0ac.min.js:2:89184)

(anonymous function) (jfeLib.fa2484b7040929bdf0ac.min.js:2:55524)

(anonymous function) (jfeLib.fa2484b7040929bdf0ac.min.js:2:54995)

(anonymous function) (jfeLib.fa2484b7040929bdf0ac.min.js:2:108782)

 

...but I’m not really sure what it’s telling me (and it’s still weird that it worked fine for them on earlier pages but not this one).


TomG
Level 8 ●●●●●●●●
Forum|alt.badge.img+27
  • Level 8 ●●●●●●●●
  • 5909 replies
  • February 25, 2025

The script shown in the console doesn’t match the JS you shared above.

Anyway, the script in the console throws an error because hide() is a jQuery function and this.getQuestionContainer() isn’t a jQuery object. You could either do this:

jQuery(this.getQuestionContainer()).hide();

or this:

this.getQuestionContainer().style.display = "none";

 


Forum|alt.badge.img+5
  • Author
  • Level 2 ●●
  • 41 replies
  • February 25, 2025

@TomG  I’m trying to determine which code doesn’t match, since my original post and the error log both reference this.getChoiceContainer, not this.getQuestionContainer (which is what you have in your reply). Pasted in my original post was this bit at the start:

Qualtrics.SurveyEngine.addOnload(function()
{
	/*Place your JavaScript here to run when the page loads*/
this.hideNextButton();
this.getChoiceContainer().hide();
});

and in the error log it has this:

function() { /*Place your JavaScript here to run when the page loads*/ this.hideNextButton(); this.getChoiceContainer().hide(); }

These look the same to me, so is it something else in the error log that made you say it doesn’t match and then say I needed to change to this.getQuestionContainer() (or am I looking right at it and missing something)?

(For reference, this is the thread where I got the original ‘hide the next button until video ends’ code.)

 

I do have some this.QuestionContainer (not this.getQuestionContainer()) to hide a couple of other questions and record data elsewhere on the same page (which I’d put in a reply to my own original post in case they were causing a conflict). This code has been working, though I guess it’s possible there’s a conflict that’s just never cropped up before.

So I’m not sure which of these is what you’re saying:

  • The this.getChoiceContainer() code in the original question and in the error log is wrong and causing the error, and it should be using. this.getQuestionContainer() as you wrote in your last reply
  • The this.QuestionContainer code from hidden questions elsewhere in the block/page is causing the error, and it should be changed to the this.getQuestionContainer() code you wrote in your last reply, and the this.getChoiceContainer in the original question and log don’t need fixing.
  • Or, they got conflated by accident when you were responding, like maybe you scrolled up to see what code I’d originally pasted, but looked at the code in my follow-up comment for the other questions instead of my original post, and that’s why you responded with this.getQuestionContainer()? Otherwise, I’m not sure why the this.getChoiceContainer() error in the log would mean adjusting the this.QuestionContainer code in different questions.

If I’m completely misinterpreting what you were trying to tell me, I apologize! 


TomG
Level 8 ●●●●●●●●
Forum|alt.badge.img+27
  • Level 8 ●●●●●●●●
  • 5909 replies
  • Answer
  • February 25, 2025

Whether you are using this.getChoiceContainer() or this.getChoiceContainer() the same thing applies - both return an html element, not a jQuery object. So, to use hide() you need to first make it a jQuery object:

jQuery(this.getChoiceContainer()).hide();

 


Forum|alt.badge.img+5
  • Author
  • Level 2 ●●
  • 41 replies
  • March 11, 2025

@TomG Got it. I checked with my js-writing friend to be sure I understood before coming back to post this, but wanted to follow up just in case anyone else has the same question or experience after using incorrect code from other threads in the forum: Why does the bad code usually work?

I went back and looked at the threads where that line of code came from originally, and it seems that although ​@TomG  weighed in on a couple of them (the first link is the thread where got my code) and didn’t specifically call out that being an invalid format, the this.getChoiceContainer().hide(); code recommendation came from ​@ahmedA each time in different forum threads (ended with people marking it best answer and/or saying ‘it worked, yay!’). And other people have clearly grabbed that code because it sounds from those threads like it works and then not gotten responses to their later forum questions.

My js-writing friend said he didn’t know why it would have worked most of the time but not always, and said I should ask if maybe there’s been an API change at some point. Otherwise he was stumped because like ​@TomG he said it shouldn’t have worked. So I’m just wondering if anyone can guess why it usually works but not always, and if it’s definitely wrong, should we go add a comment on those earlier threads so more people won’t assume it’s the right code to use?

 

(Also, thanks ​@TomG!)

 


Forum|alt.badge.img+22
  • Level 7 ●●●●●●●
  • 2028 replies
  • March 11, 2025

this.getChoiceContainer().hide(); and several other functions do not work on the new simple layout. If you want to use old code without any modifications its advisable to use the old layouts.


Forum|alt.badge.img+5
  • Author
  • Level 2 ●●
  • 41 replies
  • March 12, 2025

@ahmedA I’m still using the old static layout theme my university has had in place for years. Can you address the thing that TomG said, “hide() is a jQuery function and this.getQuestionContainer() isn’t a jQuery object,” and explain what your code is doing? That might help make sense of why it works sometimes and not other times. 


Leave a Reply