Custom JavaScript for Decipher (Basic to Advanced)
1) Basic DOM Selection and Value Read
document.addEventListener("DOMContentLoaded", function () {
const nextBtn = document.querySelector("button[type='submit']");
const qInput = document.querySelector("input[name='Q_NAME']");
if (qInput) {
qInput.addEventListener("input", function () {
if (nextBtn) nextBtn.disabled = qInput.value.trim().length === 0;
});
}
});
2) Character Counter for Open-End
document.addEventListener("DOMContentLoaded", function () {
const txt = document.querySelector("textarea[name='Q_FEEDBACK']");
if (!txt) return;
const counter = document.createElement("div");
counter.style.fontSize = "12px";
txt.parentNode.appendChild(counter);
function updateCount() { counter.textContent = "Characters: " + txt.value.length; }
txt.addEventListener("input", updateCount);
updateCount();
});
3) Basic Client-Side Range Guard
document.addEventListener("DOMContentLoaded", function () {
const age = document.querySelector("input[name='Q_AGE']");
const form = document.querySelector("form");
if (!age || !form) return;
form.addEventListener("submit", function (e) {
const v = parseInt(age.value, 10);
if (!Number.isNaN(v) && (v < 18 || v > 99)) {
e.preventDefault();
alert("Please enter age between 18 and 99.");
}
});
});
4) Dynamic Question Visibility
document.addEventListener("DOMContentLoaded", function () {
const ownCarYes = document.querySelector("input[name='OWN_CAR'][value='1']");
const ownCarNo = document.querySelector("input[name='OWN_CAR'][value='2']");
const carCountWrap = document.querySelector(".question-CAR_COUNT");
if (!carCountWrap || !ownCarYes || !ownCarNo) return;
function toggleCarCount() { carCountWrap.style.display = ownCarYes.checked ? "" : "none"; }
ownCarYes.addEventListener("change", toggleCarCount);
ownCarNo.addEventListener("change", toggleCarCount);
toggleCarCount();
});
5) Decipher Grid Rule: One Select per Row
document.addEventListener("DOMContentLoaded", function () {
const grid = document.querySelector(".question-Q_GRID");
if (!grid) return;
grid.addEventListener("change", function (e) {
const t = e.target;
if (!t.matches("input[type='checkbox']")) return;
const row = t.closest("tr");
if (!row) return;
row.querySelectorAll("input[type='checkbox']").forEach(function (cb) {
if (cb !== t) cb.checked = false;
});
});
});
6) Script Placement Notes for Decipher XML
Use JS when:
- UI behavior is needed.
- Client-side helper checks improve experience.
Use Decipher XML logic (cond/validate/exec) when:
- Routing, quota, and hard validation rules are required.
- Logic must be reliable in exported data.
Custom jQuery for Decipher (Basic to Advanced)
1) Basic Event Binding
$(function () {
$("input[name='Q_BRAND']").on("change", function () {
console.log("Selected brand value:", $(this).val());
});
});
2) Show/Hide Follow-up Question
$(function () {
function toggleFollowUp() {
if ($("input[name='Q_SAT'][value='4']").is(":checked")) {
$(".question-Q_REASON").show();
} else {
$(".question-Q_REASON").hide();
}
}
$("input[name='Q_SAT']").on("change", toggleFollowUp);
toggleFollowUp();
});
3) Validate Best/Worst in MaxDiff
$(function () {
$("form").on("submit", function (e) {
const best = $("input[name='MD_1_BEST']:checked").val();
const worst = $("input[name='MD_1_WORST']:checked").val();
if (best && worst && best === worst) {
e.preventDefault();
alert("Please select different options for Most and Least.");
}
});
});
4) Reusable Helper Function
function bindMinChars(selector, minChars, msg) {
$(selector).on("blur", function () {
const val = $.trim($(this).val());
if (val.length > 0 && val.length < minChars) {
alert(msg || ("Please enter at least " + minChars + " characters."));
}
});
}
$(function () {
bindMinChars("textarea[name='Q_FEEDBACK']", 15, "Please provide more detail.");
});
5) jQuery + Decipher XML Integration Notes
Do:
- Use jQuery for UI enhancement.
- Keep business logic in Decipher XML (<validate>, <exec>, cond, quota).
Avoid:
- Moving critical routing only to jQuery.
- Using fragile selectors tied to temporary wrappers.