The jQuery script effectively applies a class when needed, but encounters difficulties when trying to remove the class afterwards

Essentially, I am looking for an element that, when clicked, activates a jQuery script to add or remove a specific class (in this case, adding a class that changes the background image CSS attribute) to only that particular element.

function readMore() {
    var subID = event.target.id;
    var footerTarget = $('[id='+subID+'][class="articleFooter"]');
    var newTarget = $('[id='+subID+'][class="showArticlePara"]');

    newTarget.toggle();

    var footerTarget = $('[id='+subID+'][class="articleFooter"]');

    if (newTarget.css("display") == "block") {
        footerTarget.addClass("changeBackgroundImage");
    }
    else {
        footerTarget.removeClass("changeBackgroundImage");
    }

    alert(footerTarget.class());
}

$(document).ready(function() {
});
.articleSection {
width: 100%;
display: block;
font-family: Trebuchet MS;
font-size: 1.1em;
color: white;
margin-bottom: 25px;
padding-bottom: 3px;

background-color: RGBA(255, 255, 255, 0.1);
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
border-radius: 2px;

box-sizing:border-box; 
     -moz-box-sizing:border-box; 
     -webkit-box-sizing:border-box; 
     -ms-box-sizing:border-box;
}
.articleContent {
/*height: 70px;*/
padding: 10px 15px 5px 15px;

box-sizing:border-box; 
     -moz-box-sizing:border-box; 
     -webkit-box-sizing:border-box; 
     -ms-box-sizing:border-box;
}
.articleVotes {
}
.voteBox {
}
.articleFooter {
width: 100%;
height: 10px;
content: 'more';

background-image:url('../Images/Icons/showMoreBlack13030.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center center;

transition: 0.2s ease-in-out;
}
.articleFooter:hover {
background-image: url('../Images/Icons/chevron13040Blue.png');
}
.changeBackgroundImage {
width: 100%;
height: 10px;
content: 'less';

background-image:url('../Images/Icons/showLessBlack13030.png');
background-size: contain;
background-repeat: no-repeat;
background-position: 15px center;

transition: 0.2s ease-in-out;
}
.changeBackgroundImage:hover {
background-image: url('../Images/Icons/chevron13040BlueRotated.png');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div class="articleSection">
    <div class="articleContent">
        <h2>Exciting new study shows that in any male group, at least one is gay</h2>
        <div class="showArticlePara" id="one">
            <p>
                I really hope it's Luke, he's cute af.
            </p>
        </div>
    </div>
    <div class="articleVotes">
        <div class="voteBox"></div>
    </div>
    <div class="articleFooter" id="one" onclick="readMore()"></div>
</div>

When clicking on .articleFooter with id=subID, the paragraph associated with it toggles its display property using simple jQuery toggle(). I have experimented with toggleClass(), which successfully adds the class but does not remove it on the second click.

Finally, I attempted an if/else statement to check if the affected paragraph has display: none and then add or remove a class based on the result. However, this method also fails to remove the class on the second click.

Thank you for any suggestions or assistance provided.

jsfiddle link: https://jsfiddle.net/hm3y3848/

Answer №1

It appears that the root of your problem (aside from the pesky "duplicate id" issue ;) ) lies in how you are targeting your elements:

var footerTarget = $('[id='+subID+'][class="articleFooter"]');

When you use [class="articleFooter"], you are essentially saying "find me the element with a class of ONLY 'articleFooter' (i.e., class="articleFooter") . . . but once you add the "changeBackgroundImage" class, the element's class becomes "articleFooter changeBackgroundImage" (i.e.,

class="articleFooter changeBackgroundImage"
), so it no longer matches.

There are a couple of ways to tackle this issue . . .

1) The more commonly used method is to utilize the shorthand selectors for jQuery such as "#MY_ID" for ids and ".MY_CLASS" for classes. For example:

$("#" + subID + ".articleFooter")

Or, a more efficient alternative:

$("#" + subID).filter(".articleFooter")

In both cases, the selector will target elements with both the specified id and class (although the element may have additional classes).

2) A less conventional approach, but one that would resolve the issue, is to modify the attribute pattern in your current code. You are currently using [attribute='value'], which requires an exact match between the attribute value and the selector value (due to the =). To allow for other classes within the element's class list, you can utilize the "contains" selector: [attribute*='value'], meaning the attribute value must contain, but is not limited to, the selector value.

Both approaches should solve the problem, but the former is more commonly used due to its simplicity. ;)

Lastly, do address the duplicate id issue to prevent further complications. :D

Answer №2

The readMore() function starts with

event.target.id

Where can you access the event object from? This is resulting in a

ReferenceError: event is not defined

Resolution 1

1) Include id as a parameter when invoking the readMore function in a traditional way

<div class="articleFooter" id="one" onclick="readMore(this.id)"></div>

2) Pass it as an argument and modify the initial line in the function

function readMore(id) {
    var subID = id;
    .
    .
}

3) There is no function called .class(). Delete this line

alert(footerTarget.class());

Resolution 2

An alternative approach is to utilize jQuery's method of handling events, especially since you are already utilizing jQuery

<div class="articleFooter" id="one"></div>

This is the JavaScript code

$(document).ready(function() {
    $(".articleFooter").click(function() {
        var subID = $(this).attr('id');
        var footerTarget = $('[id=' + subID + '][class="articleFooter"]');
        var newTarget = $('[id=' + subID + '][class="showArticlePara"]');

        newTarget.toggle();

        var footerTarget = $('[id=' + subID + '][class="articleFooter"]');

        if (newTarget.css("display") == "block") {
            footerTarget.addClass("changeBackgroundImage");
        } else {
            footerTarget.removeClass("changeBackgroundImage");
        }
    });
});

See Demo

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

Creating a dynamic overlay div on responsive block columns using Bootstrap

I am currently working on creating a responsive webpage with 4 blocks using rows and columns, each featuring an image background with an overlay and title. Everything is functioning as expected except for the width of the overlay. My issue can be better u ...

utilizing YouTube API for real-time updates

Is there a YouTube API equivalent to the HTML5 video's ontimeupdate event that is not documented or known? I have attempted using a setInterval method but it requires additional checks for video play status. Has anyone encountered this problem before? ...

Is there a way in Reactjs Material UI 5 (MUI5) to unselect only the star that was clicked, without affecting the rest of the stars in the

For instance: I selected the 3rd star on the rating component, but when I click on it again, all the previous stars disappear and it shows 0 stars. How can I make it so that if I click on the 3rd star a second time, only the 3rd star is removed, leaving ...

JavaScript Error: Uncaught TypeMismatchError

(function IIFE() { 'use strict'; var buttons = document.getElementsByTagName('button'); for (let i = 0, l = buttons.length; i <= l; i += 1) { buttons[i].onclick = function () { f ...

Display or conceal a field based on the content of another field using jQuery

Is there a way to hide or show a field on my website based on the value in the shopping cart? I've created a function for this, but I'm struggling with the condition. Can you help me figure out how to write it correctly? <script> $(docume ...

Enhance PHP URL rewrite by incorporating multiple parameters

Hello, I am currently attempting to implement URL rewriting using PHP with the following code: .htaccess file <IfModule mod_rewrite.c> RewriteEngine On #prevent access to (includes) folder RewriteCond %{REQUEST_URI} !-f RewriteRule ...

Django: Automatically redirecting if the URL was manually entered by the user

Is there a way to prevent users from manually entering a URL of a specific page? For instance, let's assume I have two pages - somepage.com/home and someplace.com/other. On the home page, there is a button that directs users to the /other site. I wan ...

Strategies for aligning tooltips with the locations of dragged elements

One of my projects involves a simple drag element example inspired by Angular documentation. The example features a button that can be dragged around within a container and comes with a tooltip. <div class="example-boundary"> <div ...

ReactJS and MaterialUI: Creating a Dynamic Triangle Button Slider

I am facing a challenge in creating a triangle-shaped button for a slider in Material UI and ReactJS, instead of the current pizza slice shape. Here is an example of the desired outcome: https://i.sstatic.net/pNn93.png Here is the current state of the sl ...

I'm confused as to why MongoDB is flagging this as an invalid JavaScript object when attempting to run the update method

Encountering an error while attempting to update a record: (node:2018) UnhandledPromiseRejectionWarning: MongoError: document must be a valid JavaScript object Here's the code in question: global.db.collection("groups").find ...

Converting a PHP string into a JSON array

Currently, I am working on making a cURL request and receiving a response that is in the following format when using var_dump: string(595) "{"user_id":1,"currency":"eur","purchase_packs":{"1":{"amount":500,"allowed_payment_methods":["ideal","paypal","visa ...

What is the best way to determine the number of rows various div elements occupy within a wrapper using javascript?

The reference for this code snippet can be found at http://jsfiddle.net/4fV3k/ I have a function called SetGridBorder that takes a border style parameter like 1px solid red and a selector of the wrapper element such as box-wrapper. In my example, there a ...

We are currently experiencing issues with Internet Explorer retrieving data from input type text

My HTML code includes input elements with type="text" like this: <input type="text" class="f_taskname" value=""/> Once the user enters text and hits enter, the following script is triggered: var task_name=$('#filter_body').find('.f_ ...

Choose only the options that are present in both arrays

I am working on creating a multiple select feature that displays all nodes, but only checks the ones that are present in 2 arrays. My front end is developed using Angular 8 and TypeScript. private mountSelect(nodesInRelation, lineApiKey) { console.lo ...

What is the process for activating an event when a window undergoes a change?

I created a window using the window.open method to display a form. Once the user submits the form, they are redirected to a page called success.html. Is there a way to trigger an event after success.html finishes loading? I attempted the following approach ...

How about designing a button with a dual-layered border for a unique touch

Looking for a specific button: My attempted CSS code that's not working: button { font-family: 'Ubuntu', sans-serif; font-size: 1em; font-weight: bold; color: white; border: 3px double #f26700; background: #f26700; ...

Developing desktop applications with Angular 2 using NWjs

Looking to create an Angular 2 Desktop App using NWjs. Where can I find the entry point? Could someone provide some examples of developing Angular 2 Desktop Apps with NW.js? ...

Steps to sending a request with a custom user agent

In my Angular app, I have successfully implemented server-side pre-rendering with the condition that it will only pre-render if a search bot is sending the request. Now, I need to verify if everything is pre-rendered correctly. However, when I visit my w ...

Display the content within the preformatted tag

As a Python and Selenium novice, I am eager to extract the text within the pre tag of the provided snippet using Python Selenium. <body><pre style="word-wrap: break-word; white-space: pre-wrap;"> " Here is some sample text that I need to re ...

Using Three JS Circle Line Geometry to Color Negative Values

I've been experimenting with different methods to change the color of a circle based on positive and negative Z values. One approach I tried involved creating two separate line segments with different materials, but I encountered issues when the segme ...