Filtering data in Javascript - javascript

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'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!

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/

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/

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">

Related

Trouble setting the HTML of a variable in JQuery

What I've done is loaded some HTML from a file and I am attempting to modify some elements within that HTML.
The initialization looks like this:
var id = player_info["ID"];
$("#main_container").append(
$("<div />").attr({class: "player_container", id: "player_" + id}).css("display", "none")
);
// Add all information to the player container
var player_container = $("#player_" + id);
player_container.load("player_layout.html");
With player_layout.html looking like this:
<div class="player_name">
</div>
<div class="player_chips">
Chips:
<br/>
<span class='bidding'></span>/<span class='chips'></span>
</div>
<div class="player_stats">
Wins / Losses
<br/>
<span class="wins"></span>/<span class="losses"></span>(<span class="total_games"></span>)
<br/><br/>
Chips Won / Chips Lost
<br/>
<span class="chips_won"></span>/<span class="chips_lost"></span>
</div>
<button class="player_won">Player Has Won</button>
I then want to modify some of the elements, specifically classes. An example of the way I was initially doing this is:
player_container.find(".player_name").text(player_info['username']);
This wasn't working so I then tried to switch find with children and text with html but that didn't seem to work. I then tried this:
$('> .player_name', player_container).html(player_info['username']);
but that also didn't work. I understand that I can use DOM to grab the childNodes and compare the class names but there are a lot of classes that need modifying and I'd also like to know if this is possible in JQuery. Thanks in advance for any help.
You need to use complete callback method of .load()
var player_container = $("#player_" + id);
player_container.load("player_layout.html", function(){
player_container.find(".player_name").text(player_info['username']);
});

splitting up html returned from GET request on a certain class name

I am making a GET request which is returning two divs see below:
$.get('releases', function(data){
console.log(data);
}
data returns the following html
<div class="release">
<a href="link-1/">
<img src="image-1.jpg">
<h3>Test playlist 1</h3>
<p>This release is a playlist</p>
</a>
</div>
<div class="release">
<a href="link-1/">
<img src="image-1.jpg">
<h3>Test playlist 1</h3>
<p>This release is a playlist</p>
</a>
</div>
I am wondering how I can split the response up on the div with the classname release. The way I see it is that I would have each of the release divs and their contents in an array that I could then loop through and add responsive classes etc.
Instead of doing that, why not add the classes in the document ready function?
$(document).ready(function() {
$('div').find('.release').each(function(){
$(this).addClass( "myClass yourClass" );
});
});
Convert the data into a jquery Object and then use .find() to get the div's. Then loop through them to do what you need to do.
$.get('releases', function(data){
$(data).find('.release').each(function(i, el){
var $release = $(el);
$release.addClass('some-class');
});
}
I'm not sure what exactly what you were doing but this will loop through each div.
https://jsfiddle.net/ewsdnow6/
var data = '<div class="release"><img src="image-1.jpg"><h3>Test playlist 1</h3><p>This release is a playlist</p></div><div class="release"><img src="image-1.jpg"><h3>Test playlist 1</h3><p>This release is a playlist</p></div>';
var html = $.parseHTML(data);
$(html).each(function(){
console.log($(this));
});

too much HTML in an ajax script?

I read from this page that appending a lot of elements is bad practice and I should build up a string during each iteration of the loop and then set the HTML of the DOM element to that string. Does the same go for using too much HTML in the loop?
I have an AJAX script that parses JSON data. It requires adding data to different existing elements, like this:
$.ajax({
url: "url",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title, // A,B,C or D
age = item.age,
background = item.background,
ingredient = item.Ingredient;
$('.'+ title+'_ingredient').html(''+ingredient+'')
$('.'+ title+'_age').html(''+age+'')
$('.'+ title+'_background').html(''+background+'')
});
},
error: function () {}
});
HTML:
<div class="A_ingredient"></div>
<div class="B_ingredient"></div>
<div class="C_ingredient"></div>
<div class="D_ingredient"></div>
<div class="A_age"></div>
<div class="B_age"></div>
<div class="C_age"></div>
<div class="D_age"></div>
<div class="A_background"></div>
<div class="B_background"></div>
<div class="C_background"></div>
<div class="D_background"></div>
Is it necessary to build up a string first? If so, can you show me how to do that?
It is purely about the time it takes to process calls to html() so they simply recommend you reduce the number of calls. In this case you could build them once in a loop then sets the div html once for each.
Update:
Based on your update, aside from all the extra trailing quotes you don't need to add (a string is a string is a string), your code is fine as is. You only hit each item once.
e.g.
$.ajax({
url: "url",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title, // A,B,C or D
age = item.age,
background = item.background,
ingredient = item.Ingredient;
$('.'+ title+'_ingredient').html(ingredient);
$('.'+ title+'_age').html(age);
$('.'+ title+'_background').html(background);
});
},
error: function () {}
});
Note: If your item properties (Age, Background, Ingredient) are simple values (not objects or arrays), yo do not need the leading ''+s either.
Previous
Assuming you actually want to concatenate the results (you are only keeping the last ingredient at the moment), you could do something like this:
e.g.
$.ajax({
url: "url",
success: function (data) {
var ingredients = '';
$(data.query.results.json.json).each(function (index, item) {
var title = item.title;
var ingredient = item.Ingredient;
ingredients += ingredient;
});
$('.aclass').html(ingredients);
$('.bclass').html(ingredients);
$('.cclass').html(ingredients);
$('.dclass').html(ingredients);
},
error: function () {}
});
Which can be reduced to:
$('.aclass,.bclass,.cclass,.dclass').html(ingredients);
The contents of each div are identical in your example, so you only need a single string.
In this instance you would probably need some form of delimiter between ingredients, but your example is too vague.
e.g.
ingredients += ingredient + '<br/>';
In your example, you're setting the HTML on many different document elements.
If they're grouped in some way, for example all in a Div with ID #Container, you could build a string of the HTML and set the content of the whole Div at the end of it, something like this:
$.ajax({
url: "url",
success: function (data) {
var sHTML="";
$(data.query.results.json.json).each(function (index, item) {
var title = item.title,
background = item.background,
ingredient = item.Ingredient;
// not sure what your actual HTML is (div/span/td etc) but somethign like this?
sHTML+="<div>"; // an opening container for this item
sHTML+='<div class="'+title+'_ingredient">'+ingredient+'</div>')
sHTML+='<div class="'+title+'_age">'+title+'</div>')
sHTML+='<div class="'+title+'_background">'+background+'</div>')
sHTML+="</div>";
});
$("#Container").html(sHTML);
},
error: function () {}
});
Note I haven't tested this code, but you see the principal hopefully.
That is, build a string of the HTML then set one element at the end with the content.
I have done this a lot in a recent project and haven't seen any speed issues (maybe 50 'items' to set in my case).
HTML will initially look like this :
<div id="container">
</div>
Then end up like this (2 x items in this example) :
<div id="container">
<div>
<div class="<sometitle1>_ingredient">ingredient 1</div>
<div class="<sometitle1>_age">age 1</div>
<div class="<sometitle1>_background">background 1</div>
</div>
<div>
<div class="<sometitle2>_ingredient">ingredient 2</div>
<div class="<sometitle2>_age">age 2</div>
<div class="<sometitle2>_background">background 2</div>
</div>
</div>
subsequent calls will replace the element's content with new values, replacing the old items.
Building a string is, I would imagine, less processor-heavy than setting the html() on lots of elements individually. Each time you use html() I'm guessing that the browser has to go some way towards working out any knock-on effects like expanding the width of an element to accomodate it or whether events will still work as they did, etc - even if actual rendering is only run at the end of the process. This way you use html() once, although what you're setting is more complex.
Hope this helps.

Jquery - $(this) id from selector group

So
I've defined a simple list and an output
<div class="item-list">
<p id="One">First Item</p>
<p id="Two">Second Item</p>
<p id="Three">Third Item</p>
</div>
<div class="box">Add Stuff in Here!</div>
And
I've written this script
$(".item-list > p").click(function(){
var thisId = (this.id);
$(".box").append('<p>' + thisId + '</p>');
});
I want
each item, on click, to append its id as text inside .box element
Like So
<div class="box>One</div>
And this works
just like you'd expect. JS Fiddle of the simplified Working Example.
But in my more complex example:
the id of the selected element
(this.id)
comes back as ...
Ew..
undefined.
Here's a JS Fiddle of the more complex version of this:
http://jsfiddle.net/pQz3W/4/
What's causing these id's to return undefined?
To be clear, In the more complex example, I'm doing the same thing, it's just crowded by other functionality. Something in there is causing my id to come back as undefined.
I'll keep posting updates to this fiddle as I clean the code up more and more to pertain only to what's necessary to be there for this question!
You have an array
ServiceArray = [
[
["SplashPage", "Splash Page", "hey!"],
["GamingWebsite", "Gaming Website", "yo!"],
["BasicWebsite", "Basic Website", "hi!"],
["AdvancedWebsite", "Advanced Website", "ooh!"],
["FlexWebsite", "Flex Website", "ahh!"],
......etc
and you have ID's that you're trying to look up in that array like this
var thisId = this.id;
var outputList = ServiceArray[0][thisId][2];
but there are no associative arrays in javascript, and the keys you're looking for doesn't exist. You need to rebuild that array with objects that has keys and values that actually match what you're looking for.
try this: var thisId = $(this).attr("id");

Get the id of elements dynamically created

I want to select the elements created dynamically using ajax by id, the code is:
$(function(){
$('#loadFeed').bind('click',function(){
$.getJSON('getData.php', function(json) {
var output="<ul id='feedsList'>";
for(var i=json.posts.length-1;i>=json.posts.length-31;i--){
output+="<li class='post'>";
output+="<div class='text' id='"+json.posts[i].id+"'>"+json.posts[i].shortmsg+"</div>";
output+="</li>";
}
output+="</ul>"
$(output).appendTo('.posts');
});
});
});
The html codes:
<div class="posts">
<!--dynamic content here-->
</div>
I tried to get the id using $(this).attr("id"):
$(".post").on("click",".text",function(){
var this_id =$(this).attr("id");
alert(this_id);
});
But it said undefined. How could I get the id correctly?Thanks!
$(".post") should be $('div.post'), because you're creating li from ajax request with same class. As div.post is existing in your DOM and you're appending you list to it.
That is,
$("div.post").on("click","li.post div.text",function(){
var this_id = this.id;
alert(this_id);
});
Numbers are not valid ids. Ids need to start with letters.
You will need to use something like this:
output+="<div class='text' id='post_"+json.posts[i].id+"'>"+json.posts[i].shortmsg+"</div>";
Here'se the structure of a valid id: What are valid values for the id attribute in HTML?

Categories