0

I have a list of elements (DIVs) on my html page as below.

There is a list of hashtags on the same page.

I need that when the user clicks on the hashtag (e.g. #bacteria) only those DIVs that contain that hashtag are shown.

What would be the most lightweight and easy way to implement that?

<div class='entry'>
    <p>#antibiotics destroy #e-coli and that&#39;s not good!!!!</p>
    <!-- Hashtags: #antibiotics #eColi -->
    <!-- UID: 755a2a60-972e-11e3-a464-872f2fc4dea2 -->
</div>

<div class='entry'>
    <p>#bacteria can be #friendly, such as #e-coli for example</p>
    <!-- Hashtags: #bacteria #friendly #eColi -->
    <!-- UID: 6cc66d00-972e-11e3-a464-872f2fc4dea2 -->
</div>

<div class='entry'>
    <p>#antibiotics can fight #bacteria</p>
    <!-- Hashtags: #antibiotics #bacteria -->
    <!-- UID: b37992c0-9686-11e3-8b2c-c97ae6645b3b -->
</div>

I know that Angular is powerful for this kind of stuff, but I'd like to use something lightweight and easy. Like maybe it's possible to do it with jQuery or something...

FYI the whole thing runs on Node.Js / Express.Js with EJS rendering.

Thank you!

UPDATE

Suppose now I have several hashtags I need to check for. Like as if contains variable is not a string but an array and i need to only show entries that contain ALL of this array's values. How would I change the code? Trying to do that, but can't manage... Thank you so much!

Aerodynamika
  • 7,883
  • 16
  • 78
  • 137
  • 1
    can you add the hashtags to an attribute? something like `data-hash="bacteria friendly"`? It would make doing this a little easier – Matt Greer Feb 16 '14 at 20:07
  • You need something like `$('*:contains("#antibiotics")');` to find the hashtag inside each `.entry` class. For the matched one you then select and execute your action. This might greatly impact your performance tho. Especially if your page contains thousands of these. –  Feb 16 '14 at 20:10

3 Answers3

1

Ideally, you'd incorporate your hash-tag data into the divs themselves...perhaps with the data-* attribute:

<div class='entry' data-hashtags='antibiotics bacteria'>

Then via jQuery you could loop through them hiding the ones that don't match:

var clickedHashtag = x //get the clicked on hashtag however you like

$('.entry').each(function(){
    if($(this).data('hashtags').indexOf(clickedHashtag)>=0){
        $(this).hide()
    }
})

Fiddle: http://jsfiddle.net/Jz3gZ/

DA.
  • 39,848
  • 49
  • 150
  • 213
  • looks like a nice solution, but didn't work for me... Are you sure all the DIV elemenets are referenced right? And I did move the name into the tags as per your suggestion, but no luck.. – Aerodynamika Feb 17 '14 at 08:39
  • @deemeetree ah, my fault. You need to treat the data attribute as a string and look for the index of your matched item within. I've updated my answer and included a working jsfiddle. – DA. Feb 17 '14 at 15:08
  • Thanks! and could I use .indexOf on just the .entry div element? I tried, but can't manage to make it work... Thanks! – Aerodynamika Feb 18 '14 at 12:12
  • @deemeetree I don't know that I follow your question. In this example, there'd be multiple `.entry` elements. But yes, you could use nearly any selector you want as long as it returns the nodes you are wanting to interact with. – DA. Feb 18 '14 at 16:48
1

Use the :contains jquery selector

$(document).ready(function(){
    $('.entry').hide();
    $('.links').on('click','a',function(e){
        var $ctx = $(e.target);
        var contains = $ctx.text();
        $('.entry').hide();
        $('.entry:contains('+contains+')').show();
        return false;
    });    
});

Sample : http://jsfiddle.net/LA3tD/

EDIT

you can use text with commas and then split, or use data attribute with some separator and split it afterwards for a concatenated filter selector

$(document).ready(function(){
    $('.entry').hide();
    $('.links').on('click','a',function(e){
        var $ctx = $(e.target);
        var contains = $ctx.text();
        $('.entry').hide();
        if(contains.indexOf(',')!=-1){
            var tags = contains.split(',');
            var filt = '';
            $.each(tags,function(i,el){
                filt += ':contains('+el+')';
            });
            // :contains can be concatenated multiple times f.e.: ":contains(foo):contains(bar)"
            $('.entry'+filt).show();
        }else{
            $('.entry:contains('+contains+')').show();
        };
        return false;
    });    
});

Updated sample: http://jsfiddle.net/LA3tD/1/

markcial
  • 9,041
  • 4
  • 31
  • 41
  • btw what is the return false; here for? – Aerodynamika Feb 18 '14 at 12:11
  • is just a coding habit i have, if you want to prevent event bubbling just return false, but that's another topic non related,you can skip that – markcial Feb 18 '14 at 12:12
  • and one more question, suppose now I have several hashtags I need to check for. like as if contains is not a string but an array and i need to only show entries that contain ALL of them. how would i change the code? trying to do that, but can't manage... thank you so much!!! – Aerodynamika Feb 18 '14 at 12:17
  • Sure, maybe it can help with that topic http://stackoverflow.com/questions/1357118/event-preventdefault-vs-return-false – markcial Feb 18 '14 at 12:17
  • 1
    @deemeetree edit your question with new requirements and when i have some spare time i will update answer, if you don't mind – markcial Feb 18 '14 at 12:19
0

Untested:

$('.entry').each(function(item) { $(item).show($item.is('.' + hashtag)); });

You would have to add the hashtag as a class, of course:

<div class="entry antibiotics">
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144