What is the best way to modify the background of my li element when it is clicked on?

I stumbled upon this article: Modifying Li Element Colors in HTML <ul> Using onclick Event

It seems to address what I need, but I'm a little unsure of how to implement something similar in a rails app that also utilizes react/redux. Most of the rails apps I've worked on don't contain jquery, so I'm uncertain about where or how I would apply this concept. Any guidance would be appreciated!

I was considering utilizing the onClick event for the li elements and creating a function to toggle classes on the clicked element while removing the classes from the other li elements, but I'm not entirely sure if this approach is correct.

// Here's my component rendering the ul element

import React from 'react';
import TrackIndexItem from './track_index_item';

const TrackDetail = ({ tracks }) => (
  <ul>
    { tracks.map(track => <TrackIndexItem key={ track.id } track={track} />) } 
  </ul>
);

export default TrackDetail;

// This is the component rendering the li elements

import React from 'react';

const TrackIndexItem = ({ track }) => ( 
  <li>
    <div className="track-info">
      <i className="music-note-icon"></i>
      <div className="track-text">
        <p>{track.title}</p> 
        <p>{track.artist} • {track.album}</p>
      </div>
    </div>
  </li>
);

export default TrackIndexItem;

// Below is the CSS styling for the li elements:

li {
        display: flex;
        flex-direction: row;
        padding: 0 20px;

        .track-info {
          display: flex;
          flex-direction: column;
          position: relative;

          .music-note-icon {
            position: absolute;
            content: image_url('music-note-icon.png');
            width: 10px;
            height: 15px;
            top: 20px;
          }

          .track-text {
            margin-left: 25px;

            p {
              font-family: 'ProximaNova-Regular';
            }

            p:first-of-type {
              font-size: 18px;
              color: $white;
            }

            p:last-of-type {
              font-size: 16px;
              color: $gray;
              margin-top: -15px;
            }
          }
        }
      }

Answer №1

Example of an Anonymous Function

$(function() {
  $("li").click(function(e) {
    $(".clicked").removeClass();
    $(this).addClass("clicked");
  });
});
.clicked {
  border: 1px solid #CCC;
  border-radius: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ol>
  <li>
    <div className="track-info">
      <i className="music-note-icon"></i>
      <div className="track-text">
        <p>{track.title}</p>
        <p>{track.artist} • {track.album}</p>
      </div>
    </div>
  </li>
  <li>
    <div className="track-info">
      <i className="music-note-icon"></i>
      <div className="track-text">
        <p>{track.title}</p>
        <p>{track.artist} • {track.album}</p>
      </div>
    </div>
  </li>
  <li>
    <div className="track-info">
      <i className="music-note-icon"></i>
      <div className="track-text">
        <p>{track.title}</p>
        <p>{track.artist} • {track.album}</p>
      </div>
    </div>
  </li>
</ol>

This code specifically targets all elements with the clicked class, removes that class, and then adds it to the element clicked by the user.

Answer №2

Check out this JavaScript version I was working on at the same time. You can also find it on CodePen: https://codepen.io/edlucas/pen/LYEwjxO

If you're using React, you have the option to add onClick() directly in your JSX rather than following the code example.

const TrackIndexItem = ({ track }) => ( 
  <li onClick={e => highlight(e)}>
    ...
  </li>
);

In that scenario, you could consolidate the selectors into the highlight function as they are only used there.

function highlight(e) {
    const list = document.getElementById('trackList');
    const items = list.querySelectorAll('li');

    targetItem = e.target;
    ...
}

You can include these functions within your TrackIndexItem component file. If desired, you may move removeClass() and addClass() to a separate file with helper/utility functions and import them into your TrackIndexItem file.

Here's some sample code that works:

// Using pure JS, jQuery not needed
const list = document.getElementById('trackList');
const items = list.querySelectorAll('li');

items.forEach((item) => {
item.onclick = (e) => highlight(e);
});

function highlight(e) {
targetItem = e.target;

// Remove the class from all items
items.forEach((item) => {
removeClass(item, 'active');
});

// Add the class to the "clicked" item
addClass(targetItem, 'active');
}

function removeClass(item, classVal) {
classList = item.className.split(' ');
item.className = classList.filter(item => item !== classVal).join(' ');
}

function addClass(item, classVal) {
classList = item.className.split(' ');

// Only add the class if it's not already there
if (!classList.includes(classVal)) {
classList.push(classVal);
}
item.className = classList.join(' ');
}
li {
width: 100px;
padding: 5px;
margin-bottom: 5px;
}

li.bordered {
border: 1px solid green;
}

li.active {
background-color: yellow;
}
<html>
<body>
<ul id="trackList">
<li class="bordered test">Test 1</li>
<li class="bordered">Test 2</li>
<li class="bordered">Test 3</li>
</ul>
</body>
</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Converting CSS code into JavaScript

I am currently working with the following code: .mr15 > * margin-right: 15px &:last-child margin-right: 0 I need help translating this code to Javascript. Should I use JQuery or pure Javascript for this scenario? Thank you. ...

JavaScript function to validate percentages

I am looking to create a function that will determine whether a given value is a percentage. The function should return true for numbers followed by a '%' symbol or decimal values representing percentages. Here's how I want it to work: /* ...

What is the process for updating a placeholder text after the user makes a guess or enters

My latest project involves creating a fun guessing game where players have to identify the driver based on the teams they have driven for. The game displays the number of guesses allowed and keeps track of how many attempts the player has made so far. For ...

The Typescript compiler is throwing an error in a JavaScript file, stating that "type aliases can only be used in a .ts file."

After transitioning a react js project to react js with typescript, I made sure to move all the code to the typescript react app and added types for every necessary library. In this process, I encountered an issue with a file called HeatLayer.js, which is ...

Verifying credentials using Chromium pop-up window with Playwright

In my current project, I am using Playwright to automate the configuration of multiple devices. However, I have encountered a challenge with certain models that require authentication through a popup dialog box in Chrome. https://i.stack.imgur.com/jgnYM.p ...

Displaying a blank column in a table using JavaScript

I am trying to write a JavaScript function that will add a new column to a table. I want this new column to be displayed at the index where it is added, and then hidden once the addition is complete. Here is the code for my method: function addColumnToTa ...

Ways to showcase Form utilizing function

I've just started learning React JS and bootstrap. I'm attempting to load a login form using a React JS class with an embedded function, but when the function is triggered on click event, it's not rendering the Form and instead displaying co ...

What are some ways to maintain consistent audio levels on a jquery volume slider?

My html5 webpage features a slider and an audio track, but I am not using the sound tag property controls="controls". I want the slider to control the volume of the audio file. When I include the following code in the body tags, everything works perfectly: ...

Using Bootstrap to send an HTML form data to a PHP server for processing

When I try to submit an HTML form to a PHP server side on the same page, it works fine when using pure HTML without Bootstrap. However, if I mix in some Bootstrap tags, I encounter issues when trying to submit the form (which is supposed to upload a file a ...

Utilize tween.js to create dynamic color animations in Three.js

var color="#FF0000"; function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)} function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)} function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)} function cutHex(h) {return (h.c ...

Is the runTest.ts class in the vscode-test setup ever utilized in the project? Its purpose remains unclear even in the example project

Being a novice to Typescript, JavaScript, and VScode Extensions I have set up a vscode-test following the guidelines provided here: https://code.visualstudio.com/api/working-with-extensions/testing-extension#custom-setup-with-vscodetest Based on the hel ...

Ways to usually connect forms in angular

I created a template form based on various guides, but they are not working as expected. I have defined two models: export class User { constructor(public userId?: UserId, public firstName?: String, public lastName?: String, ...

Button submission for modifying several files

Current Scenario: On my article page (article.php), I have divided the content into two separate sections - one for the title (pulled from title.php) and another for the content (pulled from content.php). I recently added a feature that allows the author ...

How can I implement BoxHelper on an Object3D containing children in Three.js?

I am exploring the possibility of using the THREE.BoxHelper to generate a bounding box for an Object3D that has children. My goal is to render a wireframe bounding box for the object while omitting diagonals on the box's faces. Upon inspecting the sou ...

What is the best way to retrieve a value from one array based on its index in React Native?

Looking to populate the centreValues array with values from another array const centreValues=[ { title:'Type', value:centreDetail.location_type }, { title:'Address', value:centreDetail.address1+centreDetail.ad ...

JQuery does not recognize $(this) after the HTML has been altered

I manage a website that includes several href links and 2 buttons that have the ability to modify those links dynamically. <div class="links"> <p class="hlCategory">Classical Mechanics</p> <ul> <li><a cl ...

Turning a JSON formatted string into parameters for a function

Looking to convert a string of JavaScript objects into function arguments. The string format is as follows: "{ "item1": "foo 1", "item2": "bar 1" }, { "item1": "foo 1", "item2": "bar 2" }" While I can use JSON.parse to turn it into an array, the challeng ...

Blurring of text that occurs after resizing in CSS

When I use scale transform to zoom a div in HTML, the text inside becomes blurred. Is there a solution to make the text clear like the original? @keyframes scaleText { from { transform: scale(0.5, 0.5); } to { transform: scale(2, 2); } } ...

Interactive Image Button - Transforming Image On Click

I am experimenting with a mix of HTML and basic jQuery to create an image that acts as a button. When the image is clicked, the source of the image (src1) changes to another source (src2), giving the impression that the button has been pushed down. I want ...

Passing parameters through the URL with Angular's ui-router

Instead of passing parameters when changing pages like this: $state.go('index.my_route', {my_param : value}); Is it possible to pass the parameter in the URL string while still using $state.go? For example: $state.go('index.my_route?my_pa ...