Fixing the Qualtrics Modern Theme’s Text Entry Behavior

Matt Bloomfield
5 min readFeb 21, 2020

--

If you’re a Qualtrics user, you’re probably familiar with the latest move in the theme world — totally user-editable custom themes.

This was a pet project of mine while at the company that never made it to fruition due to some technical blockers that needed to be overcome. Needless to say, I was thrilled to see it make its way into the product! I love the ability to create my themes on the fly without any delays on waiting for Qualtrics to put it in my account.

The last box is a text entry box. There is very little context to distinguish it from another option choice.

I only have one problem. The Text Entry field within Multiple Choice questions is almost identical in look and feel to the answer choices in the Modern base theme!

I just put together a huge relational study and this was a major deal-breaker for me, despite liking that base on every other level. It completely breaks the “Don’t Make Me Think” principle in design and kept making me think there was a blank answer choice in my survey.

So what did I do? What do I always do? Wrote a little JavaScript.

If you’re not interested in the how, feel free to scroll to the bottom and grab the full snippet of code, drop it in the question, and it will just work.

Reimagining a Solution

The biggest problem with the existing Qualtrics look and feel is the confusion it creates around what is a choice and what is a text-entry field. This is compounded by the fact that most users won’t want/need the text-entry field.

I considered removing the borders, adding a left-margin, or changing the width of the text-entry box. All those things seemed like hacky solutions. I also thought about adding a simple placeholder text. Unfortunately, that made it look even more like a button.

Regardless of what I chose to do, I knew it needed to work even if the JavaScript failed to load, as that could be catastrophic. That means that I couldn’t hide anything with pure CSS and rely on it reappearing later.

Finally, I came upon the perfect solution. Only show the text-entry field for users who need it. For everyone else, hide it! As a bonus, I figured adding some placeholder text once it appears would help alleviate any confusion.

Writing the Code

The first step in making a reusable Qualtrics JavaScript snippet is to detect all IDs rather than hardcoding. Conveniently, the Qualtrics JS API makes this relatively easy by allowing you to grab the QuestionID using this.questionId.

Qualtrics questions are encased in a div with the ID of the QuestionID, so you can use this as a way to limit the rest of your scope.

Qualtrics questions are wrapped in a div with an ID matching the Question ID. Use this to scope all your JavaScript selectors.

Finding the Text Entry Boxes

Next, we need to find any text entry boxes and choices within the question. I do this by using the built-in jQuery library in Qualtrics. A simple jQuery('#' + questionId + ' .TextEntryBox') will do the trick here.

Now, let’s organize the results: Loop through the returned text-entry elements (there could be more than one) using the .each() method. We need to grab the immediately previous element as well, which will be the choice element. This is easy using the .prev() method in jQuery.

Now that we have the text boxes and associated choices, we can easily update the placeholder text, hide the textbox, and add an event listener to the choice element. Remember, we only want to show the textbox when the person has selected the associated choice.

Handling the clicks

Now every time a user clicks on a choice with a text-entry option, we are calling a function. This function needs to hide and show the textbox. To start, we need to grab the ChoiceID. This is more difficult than grabbing the QuestionID and it would be nice if Qualtrics offered a better API for this. The best way I’ve found is to grab the element ID, then .split() that on a and extract it from there.

Hiding and Showing

I’ve never liked it when elements quickly appear or disappear on a page, so I think we should use some type of animation here. Luckily, jQuery has a built-in .slideUp() and .slideDown() method. But wait, that looks all janky. Ok, let’s just write our own.

If we just set the height of the textbox to zero, that should work, right? Ah, wait. There’s still a border. And padding. Ok, let’s try again. Something like this should work:

TEBox.css({
'margin-top': '0px',
'height': '0px',
'min-height': '0px',
'border-color': 'transparent',
'border': 'none'
});

But wait, we forgot about the transition. CSS3 to the rescue! Let’s add a transition: .2s all to the element for now.

Ok, great! It hides really nicely. But now when we show it again we’ll need to know all the original values, right? No! jQuery allows you to simply pass empty strings for each CSS attribute and it will remove them entirely from the element, thus setting them back to whatever the CSS states. Wow, they really knew what they were doing on the web in the 90s 😉.

TEBox.css({
'margin-top': '',
'height': '',
'min-height': '',
'border-color': '',
'border': ''
});

One Last Hiccup

Just when we thought we were done — We see one last thing in testing. It seems like the textbox is only showing when we hit the choice box, but not the text. Looks like we need to account for the span tags.

This is easy to do since the span is always a child of the label we want to target. This one-liner gets us the ID we need every time:

var id = (ev.target.tagName == 'SPAN') ? ev.target.parentNode.id : ev.target.id;

Copy and Paste Coding 😎

Copy and paste this code into the Qualtrics JavaScript Editor (you can replace everything currently there. If for some reason this JavaScript fails to work (browser, connection, versioning issues) the question will appear and function the same way it would out of the box.

Live Example

https://co1.qualtrics.com/jfe/preview/SV_3Eo1SUBMP8ElPTL?Q_SurveyVersionID=current&Q_CHL=preview

--

--

Matt Bloomfield

Operations Specialist, Process Thinker, Tinkerer, Off Road Enthusiast, Husband, Father, Follower of Christ