3

I have a table that's generated through php. Whenever "bob" is the name of the person who this data belongs to, I generate a tr id to denote that:

<tr id="0bob">...</tr>
  <td>...</td>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>

The data inside each of the tds inside of the trs is different, and the user has to select which of these rows they want, using this checkbox:

print "<input type=\"checkbox\" id=\"check\" data-border=\"$border\" data-z=\"$z\" data-x=\"$x\" data-pn=\"$pn\" value=\"\">";

Then, in my JavaScript, I have the following line which is supposed to dim all of these lines whenever one of the checkboxes in these trs is clicked.

var pn = this.dataset.pn;
var x = this.dataset.x;

//anytime a checkbox with the id 'check' is clicked, (this is every checkbox on the page)    
$('input[type="checkbox"][id="check"]').change(function() {
    $( "#" + x + PN ).fadeTo( "slow" , 0.7, function() { });
}

The code, in my mind, is accurate - I'm asking for any td with the id of 0bob to be faded to 70%. The issue is that while the code "works," it only fades the first instance of this, then stops, like so:

enter image description here

It always fades the first instance, (red in this example,) regardless of which color the user selects, (blue, pink, or yellow).

I also can't use a tr class because I'm already using the class to change other aspects of the formatting. What am I doing wrong here?

Brian Powell
  • 3,336
  • 4
  • 34
  • 60
  • 4
    Basically, you want the browser to work in a way it isn't meant to. Use another class or a `data-*` attribute. Or a different ID schema. Or something else other than the same ID. They must be unique. An ID is an IDentifier. How can you identify 2 things that have the same identifier? – Ismael Miguel Apr 14 '15 at 14:33
  • 6
    Your biggest issue is that IDs cannot duplicate. – rfornal Apr 14 '15 at 14:33
  • If you want some functionality to work on same type of html element then go for class rather than id. – Alive to die - Anant Apr 14 '15 at 14:33
  • 2
    "I'm already using the class to change other aspects of the formatting" - you can add more than one class to an element, and use them for different purposes. – Paul Roub Apr 14 '15 at 14:34
  • http://stackoverflow.com/questions/11079756/using-same-id-for-in-multiple-html-tags – Chip Dean Apr 14 '15 at 14:34
  • I kind of wish that any use of a number inside of an ID in html prompted a warning in the console saying "_You probably wanted to use a `class`, not an `id` here._" – Katana314 Apr 14 '15 at 14:35
  • @PaulRoub, I wasn't aware I could use multiple classes! Let me give that a try as that would be the easiest solution. And thanks Chip Dean for the link! I feel like there's almost always duplicates of questions I ask but I can never find them :) – Brian Powell Apr 14 '15 at 14:36

3 Answers3

2

You must use class. Ids must be unique and the browser will get angry if you duplicate them. You can pass multiple classes as follows:

<element id="some-id" class="class1 class2 class3">

From JavaScript classes can be added or removed using classList. JQuery has https://api.jquery.com/addclass/ method.

Georgi-it
  • 3,676
  • 1
  • 20
  • 23
  • If I change from `id` to `class`, do I need to change the syntax of my jquery string? `$( "#" + x + pn ).fadeTo( "slow" , 0.7, function() { });` is no longer fading anything now that I've changed it to a class. – Brian Powell Apr 14 '15 at 14:40
  • You need to change your selector to start with a `.` as this is the selector for class. – Georgi-it Apr 14 '15 at 14:41
  • ahh yes - silly me. Adding the second class, instead of using an ID, works perfectly once I changed the selector to `.`. Thank you so much! You learn something new each day with SO :) – Brian Powell Apr 14 '15 at 14:42
  • Since this is working for you, I would recommend using CSS animations instead of Jquery. GL. – Georgi-it Apr 14 '15 at 14:44
  • how would css animations benefit me in a way that jQuery does not? I just want to give the user a visual indicator that they've made a selection, and while it's not the prettiest thing ever, fading it to 70% definitely shows a visual difference that says to the user "ahhh, I've made a choice for this block of ``s... – Brian Powell Apr 14 '15 at 14:46
  • Performance isn't actually a big effect given JavaScript/JQuery's speed; but it changes the animations from being command-driven (playAnimation()) to state-driven (opacity = 0.3); like how when you change HTML, you don't need to call "refreshHTML()". Both ends have a few benefits; state-driven means it'll automatically animate at times you forgot it needed to, although it may mean it animates at times you didn't want it to, and you then have to work around it. – Katana314 Apr 14 '15 at 19:49
1

You should be using data-* attribute since ID is meant to occur once in the document. You can however work around this limitation by using an attribute selector like $('[id=0bob]'). See for example http://jsfiddle.net/Lk7dqbp6/

Nick Caballero
  • 944
  • 1
  • 8
  • 19
1

Your problem is that id attributes must be unique.

And the browser does that: finds the first element with that id and stops there, as it should.

Using repeated ids is invalid HTML and must be avoided like plague.

There are many alternatives for this.

I will only write the HTML structure for this.

Solution 1: a data-* attribute

You already use those, so, just use another one!

<tr data-user="bob"></tr>

These were made with the goal of providing aditional data about an element.

Solution 2: another class

You can have multiple classes per element.

Just make sure they are separated by a space:

<tr class="user-bob another-class more classes"></tr>

This may be harder to use.

Solution 3: another id schema

If you have a primary key on your SQL, you can use it to identify the user:

<tr id="user_bob_0"></tr>
<tr id="user_bob_1"></tr>
<tr id="user_bob_2"></tr>

This may be a bad idea in some situations but it will have all the data ready to use without many troubles.


Outside the scope of the answer, you have another problem:

You have this code:

var pn = this.dataset.pn;
var x = this.dataset.x;

//anytime a checkbox with the id 'check' is clicked, (this is every checkbox on the page)    
$('input[type="checkbox"][id="check"]').change(function() {
    $( "#" + x + PN ).fadeTo( "slow" , 0.7, function() { });
}

You see the comment?

Same problem: non-unique ids...

For this one, you would be better off using classes.

Instead of

$('input[type="checkbox"][id="check"]')

You would use

$('input.check')

Or

$('.check')

This is the right way to do it.
Also, the performance gain will be HUGE!

Attribute selectors (like [type="checkbox"] and [id="check"]) are one of the slowest selectors!
The only selectors slower than these are the pseudo-element selectors (:before, :after, ::selection, ...).

You can read more here: Is CSS faster when you are specific?

You may be thinking that this won't affect jQuery, but it will.
jQuery uses document.querySelectorAll() which runs a CSS selector in the DOM to select Javascript objects. (When it fails or isn't available, jQuery uses other methods)

Imagine your jQuery looking for over 300 elements for the selector in each of them.
Now imagine a basic table with the classes, where a few elements are connected to an entry.
See the difference?

This is the difference between your code taking 200ms and 30ms (non-measured).

Community
  • 1
  • 1
Ismael Miguel
  • 4,185
  • 1
  • 31
  • 42
  • Wow, I already selected the correct answer for this thread, but I really appreciate the time you took to explain this. As someone who's entirely self taught, i feel like sometimes there are basic things I just don't fully understand. I'll definitely use this information in the future. Thank you so much! – Brian Powell Apr 14 '15 at 14:51
  • @JohnWu You are welcome. At least consider upvoting the answer(s) that helped you. – Ismael Miguel Apr 14 '15 at 14:55
  • I thought I already did that :) You are now the proud owner of 1 additional internet point. :) and I wish I could give you so much more for your addendum.... geez this is so helpful! Again, thank you so much for the time you put into helping me, kind internet stranger! – Brian Powell Apr 14 '15 at 15:19
  • @JohnWu Thank you. I hope that this helps someone else with the same issue, in the future. – Ismael Miguel Apr 14 '15 at 15:21