Assign classes to most recently clicked element
P粉021854777
P粉021854777 2024-04-03 16:36:09
0
1
556

I have a calendar that looks like this, styled using Tailwind CSS:

8 Wednesday is currently clicked, so it has a pink background and a pink shadow. The 7th one is the previously clicked element, that's why it only has pink shadow (I removed the pink background class but kept the pink shadow).

What I want is to keep the latest previously clicked element so that I can add a pink shadow, but only to the latest element, not all previously clicked elements.

This is what my JavaScript code looks like:

//select needed elements from HTML
const calendarDates = document.querySelectorAll('.clickable')
const dateDisplay = document.getElementById('show-details');
const selectedDateDayElement = document.getElementById('selected-date-day');
const selectedDateElement = document.getElementById('selected-date');

let latestClicked = null;
let latestPreviouslyClicked = null;

// if there is no date, dont add hover efects
for (let i = 0; i < calendarDates.length; i++) {
    if (calendarDates[i].textContent.trim() === '') {
        calendarDates[i].classList.remove('hover:bg-pink-500', 'hover:shadow-md', 'hover:cursor-pointer', 'hover:shadow-pink-500');
        calendarDates[i].classList.add('empty')
    }
}

// select only elements that are not empty
const clickableDates = document.querySelectorAll('.clickable:not(.empty)');


clickableDates.forEach(dateElement => {
    dateElement.addEventListener('click', () => {
        const dateValue = dateElement.textContent.trim();
        const year = 2017;
        const month = 1;

        if (latestClicked !== null) {
            latestPreviouslyClicked = latestClicked;
            latestClicked = null;
            latestPreviouslyClicked.classList.remove('bg-pink-500');
        }

        dateElement.classList.add('bg-pink-500', 'shadow-md', 'shadow-pink-500');
        latestClicked = dateElement;

        const selectedDate = new Date(year, month, parseInt(dateValue));

        const daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
        const dayOfWeek = daysOfWeek[selectedDate.getDay()];

        selectedDateDayElement.textContent = dayOfWeek;
        selectedDateElement.textContent = dateValue;

        dateDisplay.style.display = 'block';
    });
});



// Close the date details when clicked outside, and this works at it should
document.addEventListener('click', event => {
    if (!event.target.classList.contains('clickable')) {
        clickableDates.forEach(element => {
            element.classList.remove('bg-pink-500');
        });
        dateDisplay.style.display = 'none';
    }
});

The problem I'm facing is that it retains the shadow of all previously clicked elements:

The expected behavior is:

  • I click on date A - it will appear with a pink background and shadow ('bg-pink-500 Shadow-md Shadow-pink-500')
  • I click on date B - it comes up with pink background and shadow, date A only has shadow
  • I click on date C - it gets pink background and shadow, date B only has shadow, date A doesn't have any extra classes added.

P粉021854777
P粉021854777

reply all(1)
P粉237689596

Okay, I also misread your question.

The problem lies in part

if (latestClicked !== null) {
            latestPreviouslyClicked = latestClicked;
            latestClicked = null;
            latestPreviouslyClicked.classList.remove('bg-pink-500');
        }

You actually only removed the background from the latestClicked element, never the shadow style.

This should work:

if(latestPreviouslyClicked !== null) {
  latestPreviouslyClicked.classList.remove('shadow-md', 'shadow-pink-500');
}
// update second latest element after changing the classes
latestPreviouslyClicked = latestClicked;
if(latestClicked !== null) {
  latestClicked.classList.remove('bg-pink-500');
}
latestClicked = dateElement;

The important part is to mutate the element before reassigning it to the next element.

Alternatively, if optional link works in your environment (bundler or only new browser support):

latestPreviouslyClicked?.classList.remove('shadow-md', 'shadow-pink-500');
// update second latest element after changing the classes
latestPreviouslyClicked = latestClicked;

latestClicked?.classList.remove('bg-pink-500');
latestClicked = dateElement;
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template