Custom code js works in question preview but not survey | XM Community
Skip to main content

I believe similar questions have been asked quite a bit, but I have not seen a solution. I made a drag-and-drop question, which works just fine when I preview the question but does not work if I preview the block, preview the survey, or take the survey. The JS portion of the code is below, and I would appreciate it if anyone has any insight on how I could make it work! Thank you!

 

Qualtrics.SurveyEngine.addOnload(function () {
const draggableIcons = document.querySelectorAll('#breakfast, #dinner');

draggableIcons.forEach(icon => {
let isDragging = false;
let offsetX, offsetY;

// Start dragging
icon.addEventListener("mousedown", (event) => {
isDragging = true;
offsetX = event.clientX - icon.getBoundingClientRect().left;
offsetY = event.clientY - icon.getBoundingClientRect().top;
icon.style.cursor = "grabbing"; // Change cursor on drag
event.preventDefault();

document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
});

// Handle dragging
function onMouseMove(event) {
if (isDragging) {
icon.style.left = `${event.clientX - offsetX}px`;
icon.style.top = `${event.clientY - offsetY}px`;
}
}

// Stop dragging and reset cursor
function onMouseUp() {
isDragging = false;
icon.style.cursor = "grab"; // Reset cursor
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
}
});
});

 

Try this out -

 

Qualtrics.SurveyEngine.addOnload(function () {
const draggableIcons = document.querySelectorAll('#breakfast, #dinner');


draggableIcons.forEach(icon => {
let isDragging = false;
let offsetX, offsetY;

icon.style.position = 'absolute';
icon.style.zIndex = '1000';

// Start dragging
icon.addEventListener("mousedown", (event) => {
isDragging = true;
offsetX = event.clientX - icon.getBoundingClientRect().left;
offsetY = event.clientY - icon.getBoundingClientRect().top;
icon.style.cursor = "grabbing"; // Change cursor on drag
event.preventDefault();

document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
});

// Handle dragging
function onMouseMove(event) {
if (isDragging) {
icon.style.left = `${event.clientX - offsetX}px`;
icon.style.top = `${event.clientY - offsetY}px`;
}
}

// Stop dragging and reset cursor
function onMouseUp() {
isDragging = false;
icon.style.cursor = "grab"; // Reset cursor
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
}
});

});

 


@resh_kr thank you so much! Unfortunately, this still doesn’t work! I tried out some console.log statements, and when I am on ‘question preview’ I get the correct logs (e.g., “breakfast is being dragged to: (248.333px, 244.333px), Stop dragging breakfast at final position: (248.333px, 244.333px)”). So I can both drag, and see that the items are being loaded/the correct names and positions are being logged. When I am taking the survey or using ‘preview block’, the logs are suggesting that the items and the coordinates aren’t loading (e.g., “  is being dragged to: (, ), Stop dragging  at final position: (, )”). Using addOnload or addOnready didn’t make a difference and I cannot seem to figure out what is causing the issue here!


@baharsener, can you try the below code:

 

Qualtrics.SurveyEngine.addOnload(function () {
    const container = this.getQuestionContainer();

    function initializeDragAndDrop() {
        const draggableIcons = container.querySelectorAll('#breakfast, #dinner');

        if (draggableIcons.length === 0) {
            // Retry after 100ms if elements are not found
            setTimeout(initializeDragAndDrop, 100);
            return;
        }

        draggableIcons.forEach(icon => {
            let isDragging = false;
            let offsetX, offsetY;

            // Start dragging
            icon.addEventListener("mousedown", (event) => {
                isDragging = true;
                offsetX = event.clientX - icon.getBoundingClientRect().left;
                offsetY = event.clientY - icon.getBoundingClientRect().top;
                icon.style.cursor = "grabbing"; // Change cursor on drag
                event.preventDefault();

                document.addEventListener("mousemove", onMouseMove);
                document.addEventListener("mouseup", onMouseUp);
            });

            // Handle dragging
            function onMouseMove(event) {
                if (isDragging) {
                    icon.style.left = `${event.clientX - offsetX}px`;
                    icon.style.top = `${event.clientY - offsetY}px`;
                    console.log(`${icon.id} is being dragged to: (${icon.style.left}, ${icon.style.top})`);
                }
            }

            // Stop dragging and reset cursor
            function onMouseUp() {
                if (isDragging) {
                    console.log(`Stop dragging ${icon.id} at final position: (${icon.style.left}, ${icon.style.top})`);
                }
                isDragging = false;
                icon.style.cursor = "grab"; // Reset cursor
                document.removeEventListener("mousemove", onMouseMove);
                document.removeEventListener("mouseup", onMouseUp);
            }
        });
    }

    initializeDragAndDrop();
});
 


@Nanditha MM thank you so much for taking the time to reply! I just tried this, but unfortunately it does not work!


You can’t evaluate expressions inside javascript template literals, as those are reserved for Qualtrics. Remove them and your code should be fine. 

Since you haven’t shared the HTML, I can’t be sure, but another issue I forsee is position of your icons. Add CSS to ensure their position property is set to absolute.


@ahmedA thank you for your response! Could you please clarify what I need to remove? I am including my HTML code below (the property is set to absolute). My problem with the custom CSS on Qualtrics has been that it seems to be required that I apply it to the whole survey rather than particular questions or blocks. Could I possibly only apply it to this question/block? Thank you!

<div style="position: relative; width: 600px; height: 400px; margin: 20px auto; 
background: url('https://uwartsandsciences.pdx1.qualtrics.com/ControlPanel/Graphic.php?IM=IM_eXemGs5D7yFpvhz')
no-repeat center; background-size: contain; border: 1px solid #ccc;"
id="slide-container">

<img style="width: 50px; position: absolute; top: 150px; left: 450px; cursor: grab;"
src="https://uwartsandsciences.pdx1.qualtrics.com/ControlPanel/Graphic.php?IM=IM_vrPsqekWIt26Rxt"
id="breakfast" alt="Breakfast">
<img style="width: 50px; position: absolute; top: 180px; left: 230px; cursor: default;"
src="https://uwartsandsciences.pdx1.qualtrics.com/ControlPanel/Graphic.php?IM=IM_F7HsYTB4JUTYy8v"
id="lunch" alt="Lunch">
<img style="width: 50px; position: absolute; top: 250px; left: 450px; cursor: grab;"
src="https://uwartsandsciences.pdx1.qualtrics.com/ControlPanel/Graphic.php?IM=IM_aWecqmidZuBBznx"
id="dinner" alt="Dinner">

</div>


<input type="hidden" id="breakfast-coordinates" name="breakfast-coordinates">
<input type="hidden" id="dinner-coordinates" name="dinner-coordinates">
<button id="saveImageBtn">Save Image</button>

 


This part of your code: `${event.clientX - offsetX}px`  needs to be: event.clientX - offsetX + “px”  

Same for any other place where you are using: `${any code here}` 

 


Leave a Reply