Forum Moderators: open

Message Too Old, No Replies

jQuery: hide all matching elements using data-foo

         

csdude55

6:29 pm on Apr 25, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I have a list of elements that look like this:

<div id="list_1234" data-listid="1234" data-user="ZHJpZnRlcmd1eTMzMzM">
Blah
</div>


The 1234 will be unique for each element, but data-user is the encrypted username of whom submitted the listing. I can change these to whatever, though, they're really just here to give an identifier for this specific script.

When the site visitor clicks a button, I want to hide all elements where data-user matches the button clicked. So in this case, the button looks like:

<p onClick="$('div').data('user', 'ZHJpZnRlcmd1eTMzMzM').hide();">
Hide all from this user
</p>


But instead of hiding the matching elements, it blanks out the entire page (nothing but the background color showing) with no errors in the console.

I found that changing it to this works correctly, though:

<div id="list_1234" data-listid="1234" class="user-ZHJpZnRlcmd1eTMzMzM">
Blah
</div>

<p onClick="$('div .user-ZHJpZnRlcmd1eTMzMzM').hide();">
Hide all from this user
</p>


I added the "user-" before the username so that there's practically no chance of someone creating a username that, encrypted, would possibly start with "user-" and match an existing class name.

So this works, but the one using data-user doesn't. Why?

NickMNS

7:47 pm on Apr 25, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Try this:
$('*[data-user="ZHJpZnRlcmd1eTMzMzM"]').hide();


from here:
[stackoverflow.com...]

Fotiman

12:25 am on Apr 26, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The first example you gave was selecting all div elements, but not filtering the results. So you end up hiding all div.

csdude55

12:47 am on Apr 26, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I can't get that work, either, Nick... I keep getting a console error about a "missing argument", but no clarification. I thought maybe it was because of the nested double quotes, but escaping didn't help, either:

<p onClick="$('*[data-user=\"ZHJpZnRlcmd1eTMzMzM\"]').hide();">



The first example you gave was selecting all div elements, but not filtering the results. So you end up hiding all div.

Ahh, I see. I'm not sure where I found that particular snippet of code to work with, either, but that probably means that something else in my development is messed up somewhere like that, too...

NickMNS

1:59 am on Apr 26, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I think you may need to add div to the selector in place of the *. Like this:
$('div[data-user=\"ZHJpZnRlcmd1eTMzMzM\"]').hide()


This hard for me to test to know for sure.

csdude55

6:39 am on Apr 26, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



That still gave me an error:

Invalid or unexpected token


The problem is definitely with the double quotes, though. I can't explain it, but switching to escaped single quotes, or just no quotes at all, worked correctly:

<p onClick="$('div[data-user=\'ZHJpZnRlcmd1eTMzMzM\']').hide();">

<p onClick="$('div[data-user=ZHJpZnRlcmd1eTMzMzM]').hide();">


I guess a more complicated solution would be to do something like this (just typed up for the example, not tested):

$('p[data-name]').on('click', function() {
$("div[data-user=" + $(this).data('name') + "]").hide();
});

<p data-name="ZHJpZnRlcmd1eTMzMzM">


Being totally honest, I'm thrown off by all of the double quotes in jQuery examples, anyway. From a Perl background, I only use double quotes when I need a string to be interpreted inside the quotes... so I rarely use them outside of HTML. Is there a reason why they're used so heavily in jQuery?

And since we're talking about it... is there any particular advantage to doing it any of these ways instead using a dynamic class name?

NickMNS

12:34 pm on Apr 26, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The problem is definitely with the double quotes,

Yes, I see why now, fromyour code block.
<p onClick=" ~OPEN DOUBLE~ $(" ~CLOSE DOUBLE~ div[data-user=' ~OPEN SINGLE~ ZHJpZnRlcmd1eTMzMzM'~CLOSE SINGLE~]"~OPEN DOUBLE~).hide();" ~CLOSE DOUBLE~>


I guess a more complicated solution would be to do something like this

I would say that this is the preferred and more elegant solution. But one question, is there going to be only one on 'click' event listener for p[data-name] on each page or will there be many?

From a Perl background, I only use double quotes when I need a string to be interpreted inside the quotes...

It is technically the same here, your are passing a string to the function. The use of single versus double quote is a convenience that allows you to stringify something that already has a single or double quote without the need to escape the characters. But as you noticed escaping works just as well and may be required in some case, such as this one.

advantage to doing it any of these ways instead using a dynamic class name?

Practically I'm not sure there is one, but according to convention classes are CSS and thus should be used for styling. Now they are often used as selector, and there is no issue but they primary purpose is styling. To create classes for sake of using them as selectors is pushing this limit. The argument I've heard is that someone may at some point return to the code and then start using the class to style an element only find out later that it changes dynamically, thus causing bugs in the code.

Fotiman

8:27 pm on Apr 26, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



advantage to doing it any of these ways instead using a dynamic class name?

Well, a class sort of implies some presentation, but you're not really styling it. Using a data attribute selector makes sense here.

Going back to your original example:

<div id="list_1234" data-listid="1234" data-user="ZHJpZnRlcmd1eTMzMzM">
Blah
</div>

You would select that div using this selector (note, you should avoid including any extra details like the element or a wildcard, as those are not needed):

[data-user="ZHJpZnRlcmd1eTMzMzM"]


Part of your problem is that you are trying to include this code within your HTML, so you have to wrap the JavaScript code in whatever quotes you use for attributes in your HTML (double quotes in your example). Within that code, you need to include a string, which needs to be wrapped in whatever quotes you didn't use for the HTML attribute quotes (single quotes in your example). Then within your string, you need to include additional quotes, which must be escaped using the same quotes that wrap your string (not the ones use as the HTML attribute quotes. For example:

<p onClick="$('[data-user=\'ZHJpZnRlcmd1eTMzMzM\']').hide();">
Hide all from this user
</p>


Quoting is discussed here:
[api.jquery.com...]