如何解决Qualtrics多选题选项无法动态填充JavaScript生成的候选人姓名问题
如何解决Qualtrics多选题选项无法动态填充JavaScript生成的候选人姓名问题
Hey Reuben, 我看了你的问题和完整代码,马上就找到问题所在了——你当前的代码只处理了**问题文本区域(.QuestionText)**里的[PROFILE1]/[PROFILE2]标签,完全没碰多选题的选项元素!咱们来快速修复这个问题:
核心问题分析
Qualtrics里,多选题的选项文本和问题标题是完全独立的DOM元素,你的原代码用document.querySelectorAll(".QuestionText")只选中了标题区域,所以选项里的标签根本没被替换,自然显示空白。
解决方案:扩展代码处理选项元素
你只需要在现有的setTimeout回调里,加上对选项文本元素的遍历和替换逻辑就行。Qualtrics的选项文本通常用.ChoiceText类名(部分版本可能用.LabelContainer,所以咱们两个都加上做兼容)。
修改后的关键代码片段
把你原代码里最后那段setTimeout部分替换成下面的代码:
setTimeout(function () { // 处理问题文本区域的标签 document.querySelectorAll(".QuestionText").forEach(q => { q.innerHTML = q.innerHTML .replace(/\[PROFILE1\]/g, profile1Name) .replace(/\[PROFILE2\]/g, profile2Name); }); // 新增:处理多选题选项里的标签 document.querySelectorAll(".ChoiceText, .LabelContainer").forEach(choice => { choice.innerHTML = choice.innerHTML .replace(/\[PROFILE1\]/g, profile1Name) .replace(/\[PROFILE2\]/g, profile2Name); }); }, 500);
完整的更新后代码
下面是整合了修复的完整代码,你可以直接替换原来的代码:
Qualtrics.SurveyEngine.addOnload(function() { // Arrays containing all attribute levels: var EducationArray = ["High school diploma", "Bachelor's degree"]; var GenderArray = ["Male","Female"]; // Gender is still randomized normally var RaceArray = ["White", "Black", "Hispanic"]; // Political Experience Array var PoliticalExperienceArray = ["None", "State legislator", "Congress"]; // Name arrays var MaleNames = ["James", "Michael", "William", "John", "David"]; var FemaleNames = ["Susan", "Jennifer", "Emily", "Olivia", "Barbara"]; // Fisher-Yates shuffle function function shuffle(array) { for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; // Swap elements } return array; } // Function to shuffle and return a single element function shuffle_one(theArray) { return shuffle(theArray.slice())[0]; // Avoid modifying original array } // Function to select two different names from respective lists function getRandomNames(gender1, gender2) { let name1, name2; if (gender1 === "Male") { let shuffledMales = shuffle(MaleNames); name1 = shuffledMales[0]; name2 = gender2 === "Male" ? shuffledMales[1] : shuffle_one(FemaleNames); } else { let shuffledFemales = shuffle(FemaleNames); name1 = shuffledFemales[0]; name2 = gender2 === "Female" ? shuffledFemales[1] : shuffle_one(MaleNames); } return [name1, name2]; } // Generate profile pairs function genprof() { var gender1 = shuffle_one(GenderArray); var gender2 = shuffle_one(GenderArray); var [name1, name2] = getRandomNames(gender1, gender2); var attributes = [ { label: "Education", value1: shuffle_one(EducationArray), value2: shuffle_one(EducationArray) }, { label: "Race", value1: shuffle_one(RaceArray), value2: shuffle_one(RaceArray) }, { label: "Political Experience", value1: shuffle_one(PoliticalExperienceArray), value2: shuffle_one(PoliticalExperienceArray) }, { label: "Age", value1: "44", value2: "44" } // Now included in the randomization ]; // Ensure "Congress" is gendered appropriately attributes.forEach(attr => { if (attr.label === "Political Experience") { if (attr.value1 === "Congress") { attr.value1 = gender1 === "Male" ? "Congressman" : "Congresswoman"; } if (attr.value2 === "Congress") { attr.value2 = gender2 === "Male" ? "Congressman" : "Congresswoman"; } } }); // Retrieve attribute order if already set, otherwise shuffle and set it let storedAttributeOrder = Qualtrics.SurveyEngine.getEmbeddedData("attribute_order"); if (storedAttributeOrder) { // Use the stored order (convert from JSON string back to array) let orderedLabels = JSON.parse(storedAttributeOrder); // Reorder attributes based on stored order attributes.sort((a, b) => orderedLabels.indexOf(a.label) - orderedLabels.indexOf(b.label)); } else { // First repetition: Shuffle attributes and save order shuffle(attributes); let attributeOrderLabels = attributes.map(a => a.label); // Store in Qualtrics Embedded Data Qualtrics.SurveyEngine.setEmbeddedData("attribute_order", JSON.stringify(attributeOrderLabels)); } return { profiles: [[name1, gender1], [name2, gender2]], attributes }; } // Get current round from embedded data, default to 1 if not set let currentRound = parseInt(Qualtrics.SurveyEngine.getEmbeddedData("current_round")) || 1; console.log("Current Round:", currentRound); // Debugging // Generate profiles let { profiles, attributes } = genprof(); // Format the names with "(First candidate)" and "(Second candidate)" let profile1Name = profiles[0][0] + " (First candidate)"; let profile2Name = profiles[1][0] + " (Second candidate)"; // Store data for this round with unique keys Qualtrics.SurveyEngine.setEmbeddedData("profile1_round" + currentRound, profile1Name); Qualtrics.SurveyEngine.setEmbeddedData("profile2_round" + currentRound, profile2Name); Qualtrics.SurveyEngine.setEmbeddedData("attribute_order" + currentRound, JSON.stringify(attributes.map(a => a.label))); // Store attribute data for profiles attributes.forEach((attr, index) => { let attrKey = attr.label.replace(/\s+/g, "_").toLowerCase(); // Convert to a safe format Qualtrics.SurveyEngine.setEmbeddedData("profile1_" + attrKey + "_round" + currentRound, attr.value1); Qualtrics.SurveyEngine.setEmbeddedData("profile2_" + attrKey + "_round" + currentRound, attr.value2); }); // Increment round number for next iteration let nextRound = currentRound + 1; Qualtrics.SurveyEngine.setEmbeddedData("current_round", nextRound); console.log("Next Round Set to:", nextRound); // Debugging // Update table headers with names document.getElementById("profile1_name").textContent = profiles[0][0]; document.getElementById("profile2_name").textContent = profiles[1][0]; // Clear and repopulate the table body dynamically let tableBody = document.querySelector("#conjointTable tbody"); tableBody.innerHTML = ""; // Clear previous rows attributes.forEach(attr => { let row = document.createElement("tr"); let labelCell = document.createElement("td"); labelCell.textContent = attr.label; let profile1Cell = document.createElement("td"); profile1Cell.textContent = attr.value1; let profile2Cell = document.createElement("td"); profile2Cell.textContent = attr.value2; row.appendChild(labelCell); row.appendChild(profile1Cell); row.appendChild(profile2Cell); tableBody.appendChild(row); }); // Increment and save the round number for the next task Qualtrics.SurveyEngine.setEmbeddedData("current_round", currentRound + 1); // **Dynamically update question text AND choice options** setTimeout(function () { // 处理问题文本区域 document.querySelectorAll(".QuestionText").forEach(q => { q.innerHTML = q.innerHTML .replace(/\[PROFILE1\]/g, profile1Name) .replace(/\[PROFILE2\]/g, profile2Name); }); // 新增:处理多选题选项 document.querySelectorAll(".ChoiceText, .LabelContainer").forEach(choice => { choice.innerHTML = choice.innerHTML .replace(/\[PROFILE1\]/g, profile1Name) .replace(/\[PROFILE2\]/g, profile2Name); }); }, 500); });
额外调试小技巧
如果替换后还是没生效,你可以:
- 打开浏览器开发者工具(F12),切换到Elements标签,找到多选题选项的元素,看看它的类名到底是什么(比如可能是
qq-choices-label之类的),然后把那个类名加到querySelectorAll的参数里。 - 在
setTimeout里加一行console.log(profile1Name, profile2Name),确认这两个变量确实有值,不是空的。 - 把延迟时间从500ms调到800ms,有时候Qualtrics加载选项的速度会慢一点。
这样修改后,你在多选题选项里插入[PROFILE1]和[PROFILE2],就会和问题文本一样正确显示候选人姓名了!
备注:内容来源于stack exchange,提问作者Reuben Long
相关产品推荐
相关产品推荐

