Using intersection observer and scroll top to determine div percentage when scrolling up

I’m working on creating a special fade-out animation that only happens when a user is scrolling up through a div (it has a separate animation when scrolling down that I don’t want to alter and it happens at a different time so I can’t just toggle classes).

I have the animation working as far as CSS goes, but I’ve stripped down the code to get the trigger working as that’s my last hurdle. I can trigger when I enter the middle div section (as seen in the console log) but the hiccup seems to be where I determine scroll direction.

As you can see in the example, if you scroll back up into the div the console log does appear. However, when I call the handleScroll function and try to log the scroll direction it doesn’t show anything. That’s my last remaining step is just determining scroll direction upon div entry and then if the user is indeed scrolling up just check to see if they’re 50% through the div.

Why aren’t these triggers occurring?

document.addEventListener("DOMContentLoaded", function () {
  const section = document.querySelector('.mountain-sect');

  // Function to handle intersection changes
  function handleIntersection(entries, observer) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        // Add scroll listener when entering the div
        console.log('in section ');
        section.addEventListener('scroll', handleScroll);
      } else {
        // Remove scroll listener when leaving the div
        section.removeEventListener('scroll', handleScroll);
      }
    });
  }

  // Function to handle scroll event
function handleScroll(event) {
    console.log('scrolling');
  const target = event.target;
  const scrollTop = target.scrollTop;
  const scrollDirection = scrollTop > previousScrollTop ? 'down' : 'up';
  const scrollHeight = target.scrollHeight;
  const clientHeight = target.clientHeight;
  const scrollPercentage = (scrollTop / (scrollHeight - clientHeight)) * 100;
  console.log(scrollDirection);

  if (scrollDirection === 'up' && scrollPercentage < 50) {
    window.alert('You are more than 50% through the div while scrolling up.');
  }

  previousScrollTop = scrollTop;
}


  // Create an Intersection Observer instance
  const observer = new IntersectionObserver(handleIntersection);

  // Observe the target element
  observer.observe(section);
});
<div class="container">
<div style="position: relative;"><img src="https://placehold.co/600x400" /></div>
<div class="mountain-sect" style="position: relative;"><img src="https://placehold.co/600x400" /></div>
<div style="position: relative;"><img src="https://placehold.co/600x400" /></div>
</div>

How to edit/remove content inside a iFrame?

I have a simple question about editing/removing content within an iFrame. I tried editing the content directly using this:

const doc = Frame.contentDocument || Frame.contentWindow.document;

$(doc).find(".el").remove();

but received a CORS error. then, question is “How to edit/remove elements inside an iFrame”?

How to render only specific pages with Paged.js

I am using Paged.js to render an HTML coming from an HTTP request. My aim is to show only the first page of generated result rather than display all pages of the result generated by Pagedjs.

My initial guess is to use Chunker for this but not sure if it has the power to control pages in the output.

Why does chord.value keep changing while the view layer {{ chord }} only updates once?

enter image description here

I have tried many methods but still can’t solve it.

nexttick:

 for (let input of inputs) {
            // 绑定事件监听器
            input.onmidimessage = (message) => {
                nextTick(() => {
                    chord.value = getMIDIMessage(message);
                });
            };

        }

forceUpdate:

// 遍历每个 MIDI 输入设备
        for (let input of inputs) {
            input.onmidimessage = (message) => {
                chord.value = getMIDIMessage(message);
                this.$forceUpdate();
            };
        }

HTML table seaching freezes in all web browsers except firefox

I have a multi-column searchable html table. The search works fine when entering a search term in firefox (both Linux and Win10) but freezes completely in other browsers (tried Avast, Brave, Chrome (both Linux and Win10), Chromium, Edge, Opera).

The code (modified to show only one of 15 columns) permits to search an HTML table for a given term in the textbox, and hides table rows not matching this query. What is the difference between firefox and the other browsers?

How do javascript decide how to print a class name

I’m trying to write an inheritence logic where I clone an input class and inherit from remaining parent classes. In order to do that, I need to create a new class, deep copying one of the classes exactly. I’m trying to achieve something like:

class Original {static b=1; static test2(){}; test(){}}
var CopyClass = DeepCopySomehow(Original)

class NotWorking extends Original{}

console.log(Object.getOwnPropertyNames(NotWorking))
// [ 'length', 'name', 'prototype']

console.log(Object.getOwnPropertyNames(Original))
// [ 'length', 'name', 'prototype', 'test2', 'b' ]

console.log(Object.getOwnPropertyNames(NotWorking.prototype))
// ['constructor']

console.log(Object.getOwnPropertyNames(Class.prototype))
// ['constructor', 'test']

I have something like (simplified):

function inherit(Class1, Class2) {
  class Base extends Class1 {...stuff...}
  Object.defineProperty(Base, 'name', {value: Class1.name});
 
  copy_props(Base.prototype, Class1.prototype);
  copy_props(Base, Class1.prototype);
  copy_props(Base.prototype, Class2.prototype);
  copy_props(Base, Class2.prototype);
}

however, this still keeps the information of “Base” somehow.
Browser side — Here is a reproducable example:

class SpecificParentName{constructor() {return new Proxy(this, {})}}
const Base = class extends SpecificParentName{constructor(...args){super(...args)}}
Base.toString = () => SpecificParentName.toString()
Object.defineProperty(Base, 'name', {value: SpecificParentName.name});
console.log(Base)
// class extends SpecificParentName{constructor(...args){super(...args)}}
// reasonable output, although I would have wanted it to be just class SpecificParentName if possible

console.log(new Base())
// Proxy(Base) {} // definitely not desired, because it doesn't point to SpecificParentName

console.log(new Proxy(Base, {}))
// Proxy(Function) {length: 0, name: 'SpecificParentName', prototype: SpecificParentName}
// it's ok since points to SpecificParentName

Nodejs side — I also had a similar problem in nodejs side before:

class SpecificParentName{}
console.log(SpecificParentName)
// "[class SpecificParentName]"
const Base = class extends SpecificParentName{}
console.log(Base)
// [class Base extends SpecificParentName]
// I'd like this^ to be just "[class SpecificParentName]"

// hacky fix on nodejs:
const Base2 = class extends SpecificParentName{
    static [require('util').inspect.custom]() {return `[class ${SpecificParentName.name}]`}
console.log(Base2)
// "[class SpecificParentName]"
}

so my question is, why and how javascript knows about the variable name I use when defining a class when printing, and is there a way to customize it?

react why ternary operator is not working inside jsx with context value

Please see below code ternary operator is not working in react inside jsx with value from context api

const { isSortex, isTransportLocal, setAcessLevel, isTransportOutside } = useContext(accessLevel);

//isTransportOutside is false and 
//isTransportLocal is true
return (
    <>
        <div className="R3-my-Blue-dark" style={style}>
            <PannelButtonContainer>
                {isTransportOutside ? <PannelButton buttontext="Truck Freight Outside" /> : null}
                {isTransportLocal ? <PannelButton buttontext="Workslip" /> : null}
            </PannelButtonContainer>
        </div>
    </>
);

both component are rendering while true should render and false should not

Is there a way to make this query more optimal?

I have two MongoDB collections Contact and ContactGroup. In a contact document, there’s a field called groups which stores the Object IDs of a contact group (ContactGroup) in an array to easily allow querying for all contacts that belong to a specific contact group. Now the issue is with a small number of documents in the database this modeling worked fine but as the contacts in the Contact collection as scaled to over 800k documents running a query to count all contacts that belong to a contact group is very slow which is roughly about 16-25s. What is a more optimal way to go about this?

This is the query I’m running:

const countdocs = async (query) => {
  return Contact.countDocuments(query);
};

const dt = await countdocs({
        $expr: {
          $in: [mongoose.Types.ObjectId(group._id), "$groups"]
        }
       });

Here’s the schema for Contact:

const Contact = new mongoose.Schema(
  {
    name: {
      type: String,
    },
    email: {
      type: String,
      required: true,
    },
    user: {
      type: mongoose.Schema.Types.ObjectId,
      ref: "User",
    },
    groups: {
      type: [
        {
          type: mongoose.Schema.Types.ObjectId,
          ref: "ContactGroup",
        },
      ],
      default: [],
    },
  },
  { timestamps: true }
);

Here’s the schema for ContactGroup:

const ContactGroup = new mongoose.Schema(
  {
    title: {
      type: String,
      required: true,
    },
    description: {
      type: String,
      default: "",
    },
    verified: {
      type: Boolean,
      default: false,
    },
    user: {
      type: mongoose.Schema.Types.ObjectId,
      ref: "User",
    },
    campaign: {
      type: mongoose.Schema.Types.ObjectId,
      ref: "Campaign",
    },
    totalContacts: {
      type: Number,
      default: 0,
    },
  },
  { timestamps: true }
);

I’ve tried creating an index on the groups field but that also didn’t make the query more optimal.

Two player stone paper scissors game [closed]

 const playerTwo=()=>{

computer.classList.add("hide");
userTwo.classList.remove("hide");
    
        score.forEach((score)=>{
            score.addEventListener("click",()=>{
                const userOneScore=score.getAttribute("id");
                console.log("player one choice=",userOneScore);
                
                if(userOneScore==="user-1")
        {
        choice.forEach((choice) => {
            choice.addEventListener("click",()=>{
                console.log("clic by player one");
                let userOneChoice=choice.getAttribute("id");
                console.log("player one choice=",userOneChoice);
            })
        });
    }else if(userOneScore==="user-2"){
        choice.forEach((choice) => {
            choice.addEventListener("click",()=>{
                console.log("clic by player Two");
                let userTwoChoice=choice.getAttribute("id");
                console.log("player two choice=",userTwoChoice);
            })
        }); 
    }   
            })
        })           
           
     }

player one choice= user-1

app.js:116 clic by player one

app.js:118 player one choice= paper

app.js:110 player one choice= user-2

app.js:116 click by player one

app.js:118 player one choice= scissors

app.js:12 click by player Two

app.js:126 player two choice= scissors

I don’t follow the logic of event queue scheduling in javascript code

The order of output on the browser console is not what I expected in the code given below.

I have two functions, each with a simple counter. Each time the counter reaches a multiple of some value two things are output. First the current value of the counter is output to the console and a letter (either “a” or “c”, depending on the function being processed) is scheduled for output via a callback in a setTimeout function that has a specified delay of 0.

In the main code, function a() is first called, then an arbitrary variable is assigned, then function c() is called. When I run the code, the counter values are printed followed by the return values for each function (and in the expected order). Only after the those values for BOTH functions are printed do I get the letters “a” and “c” on the console (five times each).

My understanding is that the setTimeout() function schedules a call to the callback functions when the call stack is empty.

Is the call stack empty between function calls to a() and c()? If so, why does the setTimeout() function of function a() schedule its output after BOTH functions a() and c() have completed? Or, if not, how do I make sure the call stack is (periodically) empty in order to get output from callback functions?

function a() {
  for (let b = 0; b < 5000000000; b++) {
    if (b % 1000000000 == 0) {
      console.log(b);
      setTimeout(function() {
        console.log("a")
      }, 0);
    }
  }
  return 2;
}

function c() {
  for (let b = 0; b < 5000000000; b++) {
    if (b % 1000000000 == 0) {
      console.log(b);
      setTimeout(function() {
        console.log("c")
      }, 0);
    }
  }
  return 4;
}

console.log( a() );
let z = 0;
console.log ( c() );

Expected output

I expected that, at least, “a” would be printed before function c() was called.

Element does not scroll vertically on mobile

The element doesn’t scroll vertically on mobile.

I followed a JS code reference to create a slider component for practice.

The slider works but can’t be scrolled when viewed on mobile.

I would like to know why it doesn’t scroll vertically.

The slider works when you drag it from side to side. But, when I touch the slider section of the website, the page freezes and doesn’t scroll vertically anymore.


<div class="wrapper">
    <i id="left" class="fa-solid fa-angle-left"></i>
    <div class="carousel">

      <div class="card card-content">
        <p id="content-s-heading">title</p>
        <h1 id="content-b-heading">content</h1>
        <p id="slide_content">sentence<br> sentence</p>
        <button><a href="#">see more</p></a></button>
      </div>
      <div class="card card_prd">
        <a href="#">
          <img src="slider_prd_combo_1.jpg" alt="img" draggable="false">
          <h1 id="slider_prd_title">combo title</h1>
          <p id="slider_prd_price">price 5%</p>
        </a>
      </div>
      <div class="card card_prd">
        <a href="#">
          <img src="선물세트1.jpg" alt="img" draggable="false">
          <h1 id="slider_prd_title">combo title</h1>
          <p id="slider_prd_price">price 5%</p



        </a>
      </div>
      <div class="card card_prd">
        <a href="#">
          <img src="선물세트2.jpg" alt="img" draggable="false">
          <h1 id="slider_prd_title">combo title</h1>
          <p id="slider_prd_price">price 5%</p>
        </a>
      </div>
        
        
        
    </div>
    <i id="right" class="fa-solid fa-angle-right"></i>
  </div>


*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  margin: 0 auto;
}

.wrapper{
  display: flex;
  max-width: 1500px;
  position: relative;
  margin: 0 auto;
}
.wrapper i{
    top: 50%;
    width: 80px;
    height: 80px;
    cursor: pointer;
    position: absolute;
    font-size: 1.2rem;
    text-align: center;
    line-height: 80px;
    background: #000;
    color: #fff;
    transform: translateY(-50%);
    transition: 0.5s ease-in-out;
    
    opacity: 0;
}
.wrapper i:active{
  transform: translateY(-50%) scale(0.9);
}
.wrapper:hover i{
  opacity: 1;
}
.wrapper i:first-child{
  left: -80px; /* needs position: absolute */
  display: none; /* hide button */
}
.wrapper i:last-child{
  right: -80px; /* needs position: absolute */
}
.wrapper .carousel{
  font-size: 0px;
  cursor: pointer;
  white-space: nowrap;
  scroll-behavior: smooth;

  display: flex;
  overflow-x: auto;
  margin-bottom: 48px;
  padding: 0 0 48px;
}


.carousel::-webkit-scrollbar{
  height: 3px;
}
.carousel::-webkit-scrollbar-thumb{
  background: #000;
  border-radius: 10px;
}
.carousel::-webkit-scrollbar-track{
  background-color: rgba(0, 0, 0, .2);
}

.card-content {
  padding: 60px 185px 60px 0;
}
.card-content #content-s-heading {
  margin-bottom: 5px;
  font-size: 14px;
}
.card-content #content-b-heading {
  margin-bottom: 10px;
  font-size: 30px;
  font-weight: 400;
}
.card-content #slide_content {
  font-size: 14px;
  margin: 30px 0;
}
.card-content button{
  border: none;
  background-color: #fff;
}
.card-content button:hover a{
  text-decoration: underline;
}
.card-content button a{
  text-decoration-line: none;
  color: #000;
  font-size: 15px;
}



.card a{
  text-decoration: none;
  text-align: center;
  font-size: 0;
}
.card #slider_prd_title {
  font-size: 20px;
  color: #000;
  margin: 10px 0;
}
.card #slider_prd_price{
  font-size: 16px;
  color: #000;
}





.carousel.dragging{
  cursor: grab;
  scroll-behavior: auto;
}
.carousel.dragging img{
  pointer-events: none;
}
.carousel img{
  width: 484px;
  height: auto;
  object-fit: cover;
  user-select: none;
    
  display:block;
  margin-left:16px;
}




@media all and (max-width: 1023px){  
  .wrapper{
    max-width: 941px;
  }
  .card-content {
    padding: 60px 172px 60px 0;
  }
  .carousel img{
    width: 450px;
  }
  .carousel img:first-child{
    margin-left: 0;
  }    
}




@media all and (max-width: 428px){  
    .wrapper{
      max-width: 395px;
    }
    .wrapper .carousel{
      margin-bottom: 45px;
      padding: 0 0 8px;
    }
    .card-content {
      display:none;
    }
    .card_prd {
    margin-left: 0;
  }
    .carousel img{
      width: 395px;
    }    
    
    .wrapper i:first-child{
      left: 0px; /* needs position: absolute */
    }
    .wrapper i:last-child{
      right: 0px; /* needs position: absolute */
    }    
  
}

@media all and (max-width: 375px){ 
  .wrapper{
    max-width: 344px;
  }
  .carousel img{
    width: 344px;
  }    

}


const carousel = document.querySelector(".carousel"),
firstImg = carousel.querySelectorAll("img")[0],
arrowIcons = document.querySelectorAll(".wrapper i");

let isDragStart = false, isDragging = false, prevPageX, prevScrollLeft, positionDiff;

const showHideIcons = () => {
    // showing and hiding prev/next icon according to carousel scroll left value
    let scrollWidth = carousel.scrollWidth - carousel.clientWidth; // getting max scrollable width
    arrowIcons[0].style.display = carousel.scrollLeft == 16 ? "none" : "block";
    arrowIcons[1].style.display = carousel.scrollLeft == scrollWidth ? "none" : "block";
}

arrowIcons.forEach(icon => {
    icon.addEventListener("click", () => {
        let firstImgWidth = firstImg.clientWidth + 16; // getting first img width & adding 14 margin value
        // if clicked icon is left, reduce width value from the carousel scroll left else add to it
        carousel.scrollLeft += icon.id == "left" ? -firstImgWidth : firstImgWidth;
        setTimeout(() => showHideIcons(), 60); // calling showHideIcons after 60ms
    });
});

const autoSlide = () => {
    // if there is no image left to scroll then return from here
    if(carousel.scrollLeft - (carousel.scrollWidth - carousel.clientWidth) > -1 || carousel.scrollLeft <= 0) return;

    positionDiff = Math.abs(positionDiff); // making positionDiff value to positive
    let firstImgWidth = firstImg.clientWidth + 16;
    // getting difference value that needs to add or reduce from carousel left to take middle img center
    let valDifference = firstImgWidth - positionDiff;

    if(carousel.scrollLeft > prevScrollLeft) { // if user is scrolling to the right
        return carousel.scrollLeft += positionDiff > firstImgWidth / 3 ? valDifference : -positionDiff;
    }
    // if user is scrolling to the left
    carousel.scrollLeft -= positionDiff > firstImgWidth / 3 ? valDifference : -positionDiff;
}

const dragStart = (e) => {
    // updatating global variables value on mouse down event
    isDragStart = true;
    prevPageX = e.pageX || e.touches[0].pageX;
    prevScrollLeft = carousel.scrollLeft;
}

const dragging = (e) => {
    // scrolling images/carousel to left according to mouse pointer
    if(!isDragStart) return;
    e.preventDefault();
    isDragging = true;
    carousel.classList.add("dragging");
    positionDiff = (e.pageX || e.touches.pageX) - prevPageX;
    carousel.scrollLeft = prevScrollLeft - positionDiff;
    showHideIcons();
}

const dragStop = () => {
    isDragStart = false;
    carousel.classList.remove("dragging");

    if(!isDragging) return;
    isDragging = false;
    autoSlide();
}

carousel.addEventListener("mousedown", dragStart);
carousel.addEventListener("touchstart", dragStart);

document.addEventListener("mousemove", dragging);
carousel.addEventListener("touchmove", dragging);

document.addEventListener("mouseup", dragStop);
carousel.addEventListener("touchend", dragStop);

Why does my JavaScript lexer split my floats as an identifier and a float?

I am currently trying to make my own little programming language for the first time. I am, as of now, creating the basic lexer. I am trying to allow floating point values in my code, but alas, it gets split into an identifier and a float value (see output below)

Question: How do I fix my lexer to properly handle floats?

Output:
let value = 7.24
const pi = 3.14

Code:

function lexer(input) {
    const tokens = [];
    const keywords = new Set(['let', 'var', 'const', 'def', 'float', 'floater', 'double', 'int', 'integer', 'bool', 'boolean', 'string', 'char']);
    const alphaNumericRegex = /[a-zA-Z0-9]/;
    const digitRegex = /d/;

    let current = 0;
    let length = input.length;

    while (current < length) {
        let char = input[current];

        if (char === ' ' || char === 'n') {
            current++;
            continue;
        }

        if (alphaNumericRegex.test(char)) {
            let wordStart = current;
            while (alphaNumericRegex.test(char)) {
                char = input[++current];
            }
            let word = input.slice(wordStart, current);

            if (keywords.has(word)) {
                tokens.push({ type: 'keyword', value: word });
            } else {
                tokens.push({ type: 'identifier', value: word });
            }

            continue;
        }

        if (digitRegex.test(char) || char === '.') {
            let numStart = current;
            let hasDecimal = false;
        
            while (digitRegex.test(char) || (!hasDecimal && char === '.')) {
                if (char === '.') {
                    hasDecimal = true;
                }
                char = input[++current];
            }
        
            let numStr = input.slice(numStart, current);
            let num = parseFloat(numStr);
        
            if (isNaN(num)) {
                throw new SyntaxError("Invalid number");
            }
        
            if (Number.isInteger(num)) {
                tokens.push({ type: 'number', value: num });
            } else {
                tokens.push({ type: 'number', value: parseFloat(numStr) });
            }
        
            continue;
        }

        if (char === '"') {
            let strStart = ++current;
            while (input[current] !== '"') {
                if (++current >= length) throw new SyntaxError("Unterminated string literal");
            }
            let str = input.slice(strStart, current++);
            tokens.push({ type: 'string', value: str });
            continue;
        }

        if (char === "'") {
            let charValue = input[++current];
            if (input[++current] === "'") {
                tokens.push({ type: 'char', value: charValue });
                current++;
            } else {
                throw new SyntaxError("Invalid character literal");
            }
            continue;
        }

        if (char === '=') {
            tokens.push({ type: 'assign' });
            current++;
            continue;
        }

        if (char === ';') {
            tokens.push({ type: 'semicolon' });
            current++;
            continue;
        }

        if (char === '.') {
            tokens.push({ type: 'dot' });
            current++;
            continue;
        }

        current++;
    }

    return tokens;
}

const code = `let value = 7.24;
var count = 5;
const pi = 3.14;
bool isTrue = true;
string message = "Hello";
char initial = 'A';`;

console.log(JSON.stringify(lexer(code), null, 2));

I’m still somewhat new to JavaScript and completely new to lexers, so I tried getting help from ai tools such as ChatGPT and AskCodi. They attempted to fix the problem and any changes I made from their recommendations made no difference.

How to keep 1:1 aspect ratio for the child canvas element?

I have prepared a simple test web page at Github (using the main.css file) for my question:

animated screenshot

In a vertical flexbox layout I am trying to use ResizeObserver to watch a parent div element with flex-grow:1 and then keep the 1:1 aspect ratio on its child canvas element.

The reason I am trying to the keep the canvas aspect ratio is that in my real app I try to embed a PixiJS canvas in a ReactJS app and if I just scale the canvas element to fill the div parent, then the PixiJS content is stretched:

screenshot

Unfortunately, the parent div element pushes the status div element off the bottom of the screen.

I think, that something minor is missing in my code, please recommend a fix:

  const parentElement = document.getElementById("parent");
  const childElement = document.getElementById("child");

  const resizeObserver = new ResizeObserver((entries) => {
    for (let entry of entries) {
      const { width, height } = entry.contentRect;
      const minDimension = Math.min(width, height);
      console.log(
        `parent: ${width} x ${height} -> child: ${minDimension} x ${minDimension}`
      );
      childElement.style.width = minDimension + "px";
      childElement.style.height = minDimension + "px";
    }
  });

  resizeObserver.observe(parentElement);
html,
body {
  margin: 0;
  padding: 0;
  overflow: hidden;
}

.flexRoot {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: stretch;
  width: 100%;
  height: 100vh;
}

/* the parent holds: status, canvas, hint */
.parent {
  border: 4px solid red;
  flex-grow: 1;
}

canvas {
  width: 1020px;
  height: 1020px;
  background-color: yellow;
  border: 4px green dotted;
  box-sizing: border-box;
}

.hint,
.status {
  background: lightblue;
  font-style: italic;
  text-align: center;
  flex-grow: 0;
}
<div class="flexRoot">
  <div class="hint">Game #1 Score1:Score2</div>
  <div class="parent" id="parent">
    <canvas id="child"></canvas>
  </div>
  <div class="status">A game hint to do this and that...</div>
</div>

How to customize values in a qualtrics’ slider question?

I’m trying to custom a slider question in qualtrics. I am working with a question scaled in 4 increments (0, 25, 50, 75, 100), where the answers are snaped to increments, so I can make a Likert question more visual (so using labels as “Strongly disagree”, “Neutral” and “Strongly agree”). However, I’d like to change the value shown at each bar, that refers to the numeric increments by default, presenting instead a custom text for each option (for example: “Strongly disagree”, “somewhat disagree”, “Neutral”, “somewhat agree” and “Strongly agree”).

After some research, I guess the only way to implement this is through javascript. However, I have no idea of this language and only found this code that I’d need to modify:

Qualtrics.SurveyEngine.addOnload(function()
{
jQuery('.ResultsInput').change(function()
{
updateTT(jQuery(this));
});

jQuery('.trackHolderRel').mousedown(function()
{
updateTT(jQuery(this));
});

function updateTT(element)
{
console.log(jQuery(element).find('.sliderToolTipBox').length)
if(jQuery(element).find('.sliderToolTipBox').length==1)
jQuery(element).find('.sliderToolTipBox').parent().append('<div class="sliderToolTipBox">2</div>')
jQuery(element).find('.sliderToolTipBox').eq(0).hide();
jQuery(element).find('.sliderToolTipBox').eq(1).html('Strongly disagree')
}

});

I guess it’s a silly thing (hopefully) but I don’t know how to proceed. Right now, it’s always showing “Strongly disagree” for every option, as you can see in the picture. Also, when i select the left option, half of the text is cutted off the window, but this would rather be a secondary problem…

enter image description here

I’d very much appreciate your help! Thanks 🙂