Calculating AGE from MM and YYYY (not DD) collected via a side by side question using Javascript | XM Community
Skip to main content
Solved

Calculating AGE from MM and YYYY (not DD) collected via a side by side question using Javascript


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

Hello,

Does anyone know how to calculate approximate age using the following side by side question design in the simple layout using Javascript? i.e., Assuming all respondents are born in the middle of the month.

The question asks for the month and year respondents were born, but not the day/date they were born.

 

Best answer by Deepak

Try this: 
Do check the id’s and update as required
Do load jQuery in header by including 
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
the embedded data would be __js_CalculatedAge

Qualtrics.SurveyEngine.addOnload(function() {
	var qid= this.questionId;

    // Attach event listener to both dropdowns (assuming similar structure for year)
    jQuery('#question-'+qid).find(".menu-item").click(function() {
        setTimeout(calculateAge, 100); // Delay to allow selection update
    });
    function calculateAge() {
        // Get selected month text
        let selectedMonthText = jQuery("#select-menu-sbs-dropdown-"+qid+"-1-1 .menu-item.selected .rich-text").text().trim();
        let selectedYearText = jQuery("#select-menu-sbs-dropdown-"+qid+"-1-2 .menu-item.selected .rich-text").text().trim();
        if (!selectedMonthText || !selectedYearText || selectedMonthText === "Select one" || selectedYearText === "Select one") {
            return; // Ensure both values are selected
        }
        // Convert month name to number
        const monthMap = {
            "January": 1, "February": 2, "March": 3, "April": 4, "May": 5, "June": 6,
            "July": 7, "August": 8, "September": 9, "October": 10, "November": 11, "December": 12
        };
        let selectedMonth = monthMap[selectedMonthText] || 0;
        let selectedYear = parseInt(selectedYearText, 10);
        if (!selectedMonth || !selectedYear) return;
        // Assume birth date is the 15th of the selected month
        let birthDate = new Date(selectedYear, selectedMonth - 1, 15);
        let today = new Date();
        // Calculate age
        let age = today.getFullYear() - birthDate.getFullYear();
        let monthDiff = today.getMonth() - birthDate.getMonth();
        // Adjust age if birth month hasn't been reached yet
        if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < 15)) {
            age--;
        }

        // Save to Qualtrics Embedded Data if needed
        Qualtrics.SurveyEngine.setJSEmbeddedData("CalculatedAge", age);
		console.log(age)
    }
});

 

View original

9 replies

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

See if this code works for you:

Qualtrics.SurveyEngine.addOnReady(function () {
	const quest = this;
	const qc = quest.getQuestionContainer();

	const today = new Date();
	const currentMonth = today.getMonth() + 1;
	const currentYear = today.getFullYear();

	const monthMapper = { Jan: 1, Feb: 2, Mar: 3, Apr: 4, May: 5, Jun: 6, Jul: 7, Aug: 8, Sep: 9, Oct: 10, Nov: 11, Dec: 12 };

	const getOptionValue = function (selector) {
		const el = qc.querySelector(selector);
		const value = el.value;
		const text = el.options[value].innerHTML;
		return text;
	};

	const getAge = function () {
		// Get values from the respective dropdowns
		const dobMonth = monthMapper[getOptionValue(".SBS1 select")];
		const dobYear = parseInt(getOptionValue(".SBS2 select"));

		const monthDiff = (currentYear - dobYear) * 12 - dobMonth + currentMonth;

		// Calculate different EDs
		const ageDecimal = Number((monthDiff / 12).toFixed(30));
		const ageExtraMonths = monthDiff % 12;
		const ageYearsOnly = (monthDiff - ageExtraMonths) / 12;
		const ageYearMonth = [ageYearsOnly, ageExtraMonths];

		// Store different ages as their respective EDs
		Qualtrics.SurveyEngine.setEmbeddedData("monthDiff", JSON.stringify(monthDiff));
		Qualtrics.SurveyEngine.setEmbeddedData("ageDecimal", JSON.stringify(ageDecimal));
		Qualtrics.SurveyEngine.setEmbeddedData("ageExtraMonths", JSON.stringify(ageExtraMonths));
		Qualtrics.SurveyEngine.setEmbeddedData("ageYearsOnly", JSON.stringify(ageYearsOnly));
		Qualtrics.SurveyEngine.setEmbeddedData("ageYearMonth", JSON.stringify(ageYearMonth));
	};

	// Add listeners to update the ED on every selection
	qc.querySelector(".SBS1 select").oninput = getAge;
	qc.querySelector(".SBS2 select").oninput = getAge;
});

 


Forum|alt.badge.img+2
  • Author
  • Level 2 ●●
  • 26 replies
  • February 8, 2025

Thanks ​@ahmedA but that unfortunately didn’t work.

I asked ChatGPT to adapt code I have to calculate age/time difference from a DDMMYYYY question where respondents select the date from a calendar. It suggested the below but this doesn’t work either. Any ideas?

 

Qualtrics.SurveyEngine.addOnready(function() {
    let questionContainer = this.getQuestionContainer();
    let monthInput = questionContainer.querySelector("select[name$='M']");  // Ensure this targets a select element for the month
    let yearInput = questionContainer.querySelector("input[name$='Y']");

    let that = this; // Store reference to Qualtrics object

    // Mapping full month names to one-based indices
    const monthMap = {
        "January": 1, "February": 2, "March": 3, "April": 4, "May": 5, "June": 6,
        "July": 7, "August": 8, "September": 9, "October": 10, "November": 11, "December": 12
    };

    function calculateAgreeTime() {
        let day = 15; // Hardcoded day (fixed to the 15th)
        let monthText = monthInput.value.trim();  // Get the full month name from the dropdown
        let year = parseInt(yearInput.value, 10);  // Get the year from the input field

        let month = monthMap[monthText];  // Map month name to month index

        // If either the month or year is invalid, just return without performing any calculation
        if (month === undefined || isNaN(year)) {
            console.log("Invalid date input, skipping calculation.");
            return;
        }

        // Create a new Date object for the 15th of the selected month and year
        let agree_date = new Date(year, month - 1, day);  // Adjust month for zero-based index
        let today = new Date();  // Get the current date

        // Calculate the difference in months between today and the agree_date
        let agree_yearDiff = today.getFullYear() - agree_date.getFullYear();
        let agree_monthDiff = today.getMonth() - agree_date.getMonth();
        let agree_time = agree_yearDiff * 12 + agree_monthDiff;

        // Adjust for the day if today's date is before the 15th of the selected month
        if (today.getDate() < agree_date.getDate()) {
            agree_time--;
        }

        // Log the results for debugging
        console.log("Agree Date entered:", agree_date.toDateString());
        console.log("Calculated Agree Time:", agree_time);

        // Set the calculated time difference as an embedded data field in Qualtrics
        that.setEmbeddedData("GTAgreeTime", agree_time);
    }

    // Event listeners to recalculate when the month or year is changed
    monthInput.addEventListener("change", calculateAgreeTime);
    yearInput.addEventListener("change", calculateAgreeTime);
});

 


Deepak
QPN Level 8 ●●●●●●●●
Forum|alt.badge.img+44
  • 1549 replies
  • Answer
  • February 10, 2025

Try this: 
Do check the id’s and update as required
Do load jQuery in header by including 
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
the embedded data would be __js_CalculatedAge

Qualtrics.SurveyEngine.addOnload(function() {
	var qid= this.questionId;

    // Attach event listener to both dropdowns (assuming similar structure for year)
    jQuery('#question-'+qid).find(".menu-item").click(function() {
        setTimeout(calculateAge, 100); // Delay to allow selection update
    });
    function calculateAge() {
        // Get selected month text
        let selectedMonthText = jQuery("#select-menu-sbs-dropdown-"+qid+"-1-1 .menu-item.selected .rich-text").text().trim();
        let selectedYearText = jQuery("#select-menu-sbs-dropdown-"+qid+"-1-2 .menu-item.selected .rich-text").text().trim();
        if (!selectedMonthText || !selectedYearText || selectedMonthText === "Select one" || selectedYearText === "Select one") {
            return; // Ensure both values are selected
        }
        // Convert month name to number
        const monthMap = {
            "January": 1, "February": 2, "March": 3, "April": 4, "May": 5, "June": 6,
            "July": 7, "August": 8, "September": 9, "October": 10, "November": 11, "December": 12
        };
        let selectedMonth = monthMap[selectedMonthText] || 0;
        let selectedYear = parseInt(selectedYearText, 10);
        if (!selectedMonth || !selectedYear) return;
        // Assume birth date is the 15th of the selected month
        let birthDate = new Date(selectedYear, selectedMonth - 1, 15);
        let today = new Date();
        // Calculate age
        let age = today.getFullYear() - birthDate.getFullYear();
        let monthDiff = today.getMonth() - birthDate.getMonth();
        // Adjust age if birth month hasn't been reached yet
        if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < 15)) {
            age--;
        }

        // Save to Qualtrics Embedded Data if needed
        Qualtrics.SurveyEngine.setJSEmbeddedData("CalculatedAge", age);
		console.log(age)
    }
});

 


Forum|alt.badge.img+2
  • Author
  • Level 2 ●●
  • 26 replies
  • February 11, 2025

Thanks ​@Deepak! Is it possible to avoid having to specify the QID? I need to use this formula multiple times across various surveys and I’m keen to avoid having to specify this.

Also, can I please ask for more information about: “Do load jQuery in header by including 
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>” - what does this mean?


Deepak
QPN Level 8 ●●●●●●●●
Forum|alt.badge.img+44
  • 1549 replies
  • February 11, 2025

@sally_ 
I have made the code generalized only where it would autopickup the QID so you don’t have to worry about it. But if it doesn’t work, do check by hovering over the two dropdowns after inspecting you should be able to see the id of those and modify as required. 
For loading jQuery you can simply navigate to Look and feel - General -header section click on source and paste this <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>”. Since simple layout doesn’t support jQuery this is an additional step.
 


Forum|alt.badge.img+2
  • Author
  • Level 2 ●●
  • 26 replies
  • February 12, 2025

Hi ​@Deepak - thank you so much for your help! Unfortunately, no data is appearing in the embedded data field column. I’ve attached screenshots of the question JavaScript code and the general header section. Do you have any idea as to what I might be doing wrong?
 

 


Deepak
QPN Level 8 ●●●●●●●●
Forum|alt.badge.img+44
  • 1549 replies
  • February 12, 2025

The embedded data name is “__js_CalculatedAge”, have you included this? or just CalculatedAge
@sally_ can you also check console if the data is coming there?


Forum|alt.badge.img+2
  • Author
  • Level 2 ●●
  • 26 replies
  • February 12, 2025

Hi ​@Deepak - it’s defined as “__js_CalculatedAge” (screenshot below).

If I hit F12 and have this panel open when I complete the survey, the following error appears when I complete the date question and move to the next page (screenshot also below).
 

 


Deepak
QPN Level 8 ●●●●●●●●
Forum|alt.badge.img+44
  • 1549 replies
  • February 12, 2025

The code does work on my end I am using simple layout.
Cannot attach the QSF here, hence unable to help.


Leave a Reply