jQuery toggleClass not working!?

My code snippet is about a data grid that displays 10 rows of data. The user is supposed to be able to click on a row, and that row's background color should change to indicate it's selected. I am using jQuery's toggleClass to change its background color, but it won't work. If you look at the DOM elements through Chrome's webkit, you will see the class toggling in the <tr> tag as expected, but the background color is not changing.

Can someone please tell me what I'm doing wrong? Thanks.

<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<style>
        
    .selectedRow { /* This is the class I'm toggling */
        background: green;
    }

    #gridContents tr {
        background: lightgray;
        cursor: pointer;
        -webkit-user-select: none;
        -moz-user-select: none;
        -o-user-select: none;
        -ms-user-select: none;
        user-select: none;
    }
    
    #gridContents tr:nth-child(2n) {
        background: #A3C5FF;
    }
    
    #gridContents tr:hover {
        background: #FFF6C7; /* #FFFDC5 should be selected color */
        cursor: pointer;
    }
</style>
<script>
$(function() {
    var objPrev = null;
    var selectedRow = null;
    
    $("#gridContents").on("click", "tr", function() {
        if ($(this).attr("custID") !== "-1") {
            console.log("CLICK! custID=" + $(this).attr("custID"));
            processGridSelection($(this));
        }
    });
    
    var objPrev = null;
    function processGridSelection(objThis) {
        if (objThis.attr("custID") !== "-1") {
            if (objPrev !== null) {
                objPrev.toggleClass("selectedRow");
            }
            objThis.toggleClass("selectedRow");
            objPrev = objThis;
            selectedRow = objThis.attr("custID");
        }
    }
});
</script>
</head>
<body>
<table id="gridContents">
    <tr custID="1"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="2"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="3"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="4"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="5"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="6"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="7"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="8"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="9"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr custID="10"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
</table>
    <div id="timer"></div>
</body>
</html>

Open in new window

elepilAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SwapnilSoftware ArchitectCommented:
Add !important after the color name will solve your problem.

.selectedRow { /* This is the class I'm toggling */
        background: green !important;
    }

Thanks,
NetSwap.
0
elepilAuthor Commented:
NetSwap, I tried what you said, it didn't have any effect.
0
Julian HansenCommented:
Try defining your selectedRow class like this

#gridContents tr.selectedRow { /* This is the class I'm toggling */
    background: green;
}

Open in new window

You will also need to move it further down the style declaration - see code sample below.

This should work but there is still a problem with your code that clicking a selected row won't turn it off.

You should also consider using the HTML5 data attribute for custom data attributes rather than creating your own - so  your custID attribute becomes data-custID - which you can access with the JQuery .data() method like so
$(element).data('custID');

Open in new window

The following code should do what you want. I have removed the processGridSelection function as it is not really necessary - it can all be done in the click handler.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<style>
    #gridContents tr {
        background: lightgray;
        cursor: pointer;
        -webkit-user-select: none;
        -moz-user-select: none;
        -o-user-select: none;
        -ms-user-select: none;
        user-select: none;
    }
    
    #gridContents tr:nth-child(2n) {
        background: #A3C5FF;
    }
    
    #gridContents tr:hover {
        background: #FFF6C7; /* #FFFDC5 should be selected color */
        cursor: pointer;
    }

    #gridContents tr.selectedRow { /* This is the class I'm toggling */
        background: green;
    }
        
</style>
<script type="text/javascript">
$(function() {
    var selectedRow = null;
    
    $("#gridContents").on("click", "tr", function() {
        if ($(this).attr("custID") !== "-1") {
      if (!$(this).hasClass('selectedRow')) {
        $('.selectedRow').removeClass('selectedRow');
      }
      $(this).toggleClass('selectedRow');
      // Use this for custom attribute
      selectedRow = $(this).data('custID');
        }
    });
  
});
</script>
</head>
<body>
<table id="gridContents">
    <tr data-custID="1"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="2"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="3"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="4"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="5"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="6"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="7"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="8"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="9"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
    <tr data-custID="10"><td>12345</td><td>Doe</td><td>John</td><td>8005551212</td><td>8005551213</td><td>8005551214</td><td>8005551215</td></tr>
</table>
    <div id="timer"></div>
</body>
</html>

Open in new window

Working sample here http://www.marcorpsa.com/ee/t777.html
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

elepilAuthor Commented:
To JulianH, thanks for responding.

You nailed that row selection problem! But I have some questions about your revised code:

1) I have read about the HTML5 data- feature. I'm asking this out of ignorance, but do some browsers today still run versions earlier than HTML5, and if so, wouldn't that feature fail?

2) Why is $(this.data("custID") always returning 'undefined'? Specifically, if you were to add the following line after line 42: console.log($(this).data("custID")), you get 'undefined'.

Thanks.
0
Julian HansenCommented:
1. The .data() method of JQuery will work in all browsers in operation today - tested back to IE7 and it works.

2. A little anomaly in JQuery - when you use the .data() method it lower cases the identifier - if you have
data-custID

Open in new window

Then you should access like so
$(this).data('custid'); // Note the lower case

Open in new window

0
elepilAuthor Commented:
julianH, thank you very much for your help, I really liked your solution!

May I ask one last thing though -- why didn't .selectedRow work? It confuses my understanding of jQuery in that it would traverse the DOM and find the elements with that class name, but it clearly isn't doing so here.
0
Julian HansenCommented:
It was being overwritten by
 #gridContents tr {

Open in new window


You would have needed to do something like this

move the .selectedRow definition after the #gridContents tr style and change to

#gridContents tr.selectedRow

Open in new window

0
elepilAuthor Commented:
julianH, thank you for explaining. I think I remember now that CSS issues "points" internally on how it decides which gets priority. If I remember right, the id gets 10 points while a class gets only 1 point.

Thank you for you help, much appreciated!
0
Julian HansenCommented:
You are welcome - good luck with your project.
0
elepilAuthor Commented:
julianH, if I may ask you just one more question. You said in one of your responses to me:

"You should also consider using the HTML5 data attribute for custom data attributes rather than creating your own - so  your custID attribute becomes data-custID"

Why do you say that? Are you advising that as a matter of convention? Or are there any technological disadvantages in doing it the way I did?

Thanks.
0
Julian HansenCommented:
Why do you say that? Are you advising that as a matter of convention? Or are there any technological disadvantages in doing it the way I did?

Technically your solution does work - my recommendation was based on the following

1. It is always best to stay within the framework of whatever system you are working in simply because the framework allows you to go outside of it does not mean it is right

2. In terms of document validation - if you use the data attribute and validate against HTML 5 where as with your approach it won't.
Consider the two html pages below
Valid HTML5 - using data attribute
<!doctype html>
<html>
<head>
<title>The Title</title>
</head>
<body>
<div data-custID="1">Valid markup</div>
</body>
</html>

Open in new window

Invalid using custom attribute
<!doctype html>
<html>
<head>
<title>The Title</title>
</head>
<body>
<div custID="1">Invalid markup</div>
</body>
</html>

Open in new window

The latter gives the following error when validating
line 7 column 16 - Error: Attribute custid not allowed on element div at this point.

With any form of coding it is always best to stick to the documented standards to ensure that your code behaves consistently both now and in the future. There is no saying how a future version of a browser will deal with your deviation from the standards - which could lead to unpredictable results.
0
elepilAuthor Commented:
Thank you for explaining your thoughts, julianH. Once again, greatly appreciate your time and effort.
0
Julian HansenCommented:
You are most welcome
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
jQuery

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.