Grey out part of an image on event | XM Community
Skip to main content

Hello,
One of my questions includes an image similar to the one on the left of the attachment ("Initial image").
The question type is not hotspot: respondents are asked to choose a number between 0 and 10. Depending on their choice, I want to "grey out" a certain area of the picture, i.e. everything to the left and above the n-th ball, where n is the number between 0 and 10 which they chose. This should happen before they submit their answer, and they should be able to play with different values and see what happens before submitting their answer.
I'm assuming this can be done using a filter in JavaScript, but I'm not sure how to do it. I do not wish to call the already greyed-out images from the Gallery: this is because the "Initial images" are more complex and too many
IMG_1981.jpg, while the size of the greyed out area always varies with the respondents' input, regardless of the image under this filter.
It seems that what I want to do is similar to a graphic slider, in that the image adjusts to participants' input: however, I can't use a slider, as I need more complex background images.

Hi there!
I found a solution for this. You can add the below custom JavaScript code to the 'addOnLoad()' function to any questions on the page.
You will have to find your input elements (input field where users enter the number) and your output element (the parent div of your image) in the html DOM (dev tools --> inspect, depends on browser) and replace it with the elements from my example in line 1 and 2.
Hope this helps!
BR, Nico


inputElement = document.getElementsByTagName("input")[0];
outputElement = document.getElementsByClassName("QuestionBody")[4];

//event listener so function is being called with every change in input field
inputElement.addEventListener("keyup", updateImage);

//new wrapper div is created and appended to image
var newDiv = document.createElement("div");
newDiv.style.position = "absolute";
newDiv.style.height = "100%";
newDiv.style.width = "100%";
newDiv.style.top = "0";
newDiv.style.left = "0";
newDiv.style.display = "flex";
newDiv.style.flexDirection = "row";
newDiv.style.justifyContent = "flex-start";
newDiv.style.alignItems = "flex-start";
newDiv.style.flexWrap = "wrap";
outputElement.appendChild(newDiv);

//10 new divs are created and appended to newly created wrapper div
var newDivInside = document.createElement("div");
newDivInside.style.display = "none";
newDivInside.style.height = "50%";
newDivInside.style.width = "20%";
newDivInside.style.backgroundColor = "rgba(0,0,0,.5)"; //modify color/transparency here
newDivInside.className = "myInsideDivs";
for (i = 0; i < 10; i++) {
newDiv.appendChild(newDivInside.cloneNode(true));
}

//function to update the image
function updateImage () {
//hide all inside divs
listOfInsideDivs = document.getElementsByClassName("myInsideDivs");
for (i = 0; i < listOfInsideDivs.length; i++) {
listOfInsideDivssi].style.display = "none";
}

//show n divs
for (i = 0; i <  inputElement.value; i++) {
listOfInsideDivsii].style.display = "flex";
}
}

Screenshot 2021-02-17 at 16.36.51.pngScreenshot 2021-02-17 at 16.37.01.png


Thank you, nicolaigeburek !
I'm quite busy these days, but I'll try to implement your solution by the end of the week, and let you know how it went.


nicolaigeburek, many, many thanks! It does exactly what I had hoped :)


Leave a Reply