I am trying to use JavaScript to read the selected values from a manually built Side by Side question with three dropdown columns (Month, Day, Year) in order to calculate a decimal-year age and write it to embedded data fields using setJSEmbeddedData.
I have confirmed the following are all working correctly:
• JavaScript is executing
• addOnload and addOnReady are both firing
• Qualtrics.SurveyEngine.setJSEmbeddedData is writing to embedded data correctly
• The Survey Flow has the three fields declared with the _js prefix
• The Gratitude block is in place so the DOB question is not on the final page
The problem is that I cannot read the dropdown values from the Side by Side question. I have tried:
• document.querySelectorAll(‘select’) — returns zero elements
• document.querySelectorAll(’#’+qid+’ select’) — returns zero elements
• document.getElementById(qid) — returns null
• document.body.innerHTML — shows question text is present but no select elements visible in the DOM when addOnReady fires
My question is: what is the correct method for reading the selected values from a Side by Side dropdown question under the New Survey Taking Experience?
Dropdowns aren't <select> — they're now ARIA comboboxes (div + ul/li), so querySelectorAll('select') finds nothing. The value lives in the <li class="menu-item selected">.
Naming — Classic used QR~{qid}#{col}~{row}. New uses ids: sbs-dropdown-{qid}-{statement}-{column} per cell. The old getElementsByName('QR~...') matches nothing.
The attached script reads selections from this structure, scanning every sbs-dropdown combobox so it handles any number of dropdown columns. Add it to your question and check your console log to get the information you need to adapt your script.
Qualtrics.SurveyEngine.addOnReady(function () { var qid = this.questionId; var container = document.getElementById('question-' + qid); if (!container) { console.warn('No container for', qid); return; }
// READ ALL DROPDOWN SELECTIONS // Returns array of { id, statement, column, answer, label } // Scans every sbs-dropdown combobox in the question, regardless of column count. function readDropdowns() { var results = []; var buttons = container.querySelectorAll('[id^="sbs-dropdown-' + qid + '-"][role="combobox"]');
for (var i = 0; i < buttons.length; i++) { var btn = buttons[i];
// id format: sbs-dropdown-{qid}-{statement}-{column} var idMatch = btn.id.match(new RegExp('^sbs-dropdown-' + qid + '-(\\d+)-(\\d+)$')); if (!idMatch) continue; var statement = idMatch[1]; var column = idMatch[2];
// selected option lives in the associated listbox var listId = btn.getAttribute('aria-controls'); var sel = listId ? document.querySelector('#' + listId + ' .menu-item.selected') : null; if (!sel) continue;
// answer index = trailing segment of li id; empty = "Select one" (unanswered) var ansMatch = sel.id.match(/-(\d*)$/); var answer = ansMatch ? ansMatch[1] : ''; if (answer === '') continue;
var labelEl = sel.querySelector('.rich-text'); var label = labelEl ? labelEl.textContent.trim() : sel.textContent.trim();
Dropdowns aren't <select> — they're now ARIA comboboxes (div + ul/li), so querySelectorAll('select') finds nothing. The value lives in the <li class="menu-item selected">.
Naming — Classic used QR~{qid}#{col}~{row}. New uses ids: sbs-dropdown-{qid}-{statement}-{column} per cell. The old getElementsByName('QR~...') matches nothing.
The attached script reads selections from this structure, scanning every sbs-dropdown combobox so it handles any number of dropdown columns. Add it to your question and check your console log to get the information you need to adapt your script.
Qualtrics.SurveyEngine.addOnReady(function () { var qid = this.questionId; var container = document.getElementById('question-' + qid); if (!container) { console.warn('No container for', qid); return; }
// READ ALL DROPDOWN SELECTIONS // Returns array of { id, statement, column, answer, label } // Scans every sbs-dropdown combobox in the question, regardless of column count. function readDropdowns() { var results = []; var buttons = container.querySelectorAll('[id^="sbs-dropdown-' + qid + '-"][role="combobox"]');
for (var i = 0; i < buttons.length; i++) { var btn = buttons[i];
// id format: sbs-dropdown-{qid}-{statement}-{column} var idMatch = btn.id.match(new RegExp('^sbs-dropdown-' + qid + '-(\\d+)-(\\d+)$')); if (!idMatch) continue; var statement = idMatch[1]; var column = idMatch[2];
// selected option lives in the associated listbox var listId = btn.getAttribute('aria-controls'); var sel = listId ? document.querySelector('#' + listId + ' .menu-item.selected') : null; if (!sel) continue;
// answer index = trailing segment of li id; empty = "Select one" (unanswered) var ansMatch = sel.id.match(/-(\d*)$/); var answer = ansMatch ? ansMatch[1] : ''; if (answer === '') continue;
var labelEl = sel.querySelector('.rich-text'); var label = labelEl ? labelEl.textContent.trim() : sel.textContent.trim();
Wow, that worked! Thank you so much for answering my question. Sorry it took me so long to test. I was busy, and I also found a “one weird trick” workaround that enabled me to bypass the problem. I’ve prepared documentation to help other developmental researchers conduct similar studies. May I include your script in the updated documentation, and if so, how do you want to be credited?