Mixing logical AND and OR in jQuery selector - javascript

I have to filter a list of items, that contain two crucial data attributes:
<li class="song" data-title="freedom" data-id="7" data-tags="tag-18-eot,tag-2-eot" data-category="1">Freedom</li>
Category
Tags
Filtering by category should be by logical OR but filtering by tags should be by logical AND.
Filtering using one of these two is not a problem.
I applied, for example:
$(collection).filter('li[data-tags*="tag-50-eot"][data-tags*="tag-51-eot"]');
to filter by tags. Or:
$(collection).filter('[data-category="1"], [data-category="2"]);
to filter by category.
This works fine. However, i could not find a way to combine these two selectors into one single query that i can pass to the filter() function, and chaining two filter() calls does not lead to the desired result, because the first call might filter out items that the second call would leave behind.
I found this question with a similar topic, but the problem is a little different and the approach as well.
How can I filter those items correctly?

You should be able to get what you are looking for with chaining, as long as you use the AND condition first. For example:
var res = $('#collection li')
.filter('li[data-tags*="tag-50-eot"][data-tags*="tag-51-eot"]')
.filter('[data-category="1"], [data-category="2"]');
Fiddle here.

the filter function can receive a function as input...
You may end up with a construct like:
var set = $(collection).filter(
function( index, element )
{
return ($(element).attr(...) == "...");
}
);

Related

why is d3 each() function only iterating through first item in list?

For some reason, when I implement the d3 each() function it only acts upon the first item in an array. For example, in the following function, only the user ID of the first user in the array is alerted:
https://jsbin.com/hayedeh/edit?html,js
What am I missing here?
Using selectAll instead of select will iterate the entire array. That said, you need to read up on selections. This is an odd use case (selecting an array). It's meant to be used with selectors or node elements to traverse collections of DOM elements. I see little need to use it to traverse regular arrays. Just use good old fashioned array methods.
U can do forEach like this:
users.forEach(function(user)
{
alert(user.userID);
});

Pass index to custom orderBy function

This might be simple and stupid but I can't seem to figure it out. I have created a ng-repeat structure that I use multiple times on different objects. Basically, I iterate through elements in an array inside those objects and depending on some variable I either need to apply custom orderBy, or leave it in the original order.
So I've created that custom orderBy like that:
<li ng-repeat="tag in filter.tags | orderBy: customSort(filter.customSort)">
Basically, filter object contains array of tags and a boolean variable that states if custom sort needs to be applied. Within my customSort function I check if passed on parameter is true and perform that custom sort. But if it's false - I cannot seem to be able to output tags in their original order in that array.
I cannot pass $index because at that point it is always 0, it only becomes index inside that ng-repeat tag. I cannot do something like that filter.tags.indexOf(tag) because tag doesn't exist yet.
I'm kinda stuck, is there a way to apply orderBy conditionally?
Further explaination:
I iterate over an array of tags and print their localized values, some of those tags should be in their original order, some should be ordered alphabetically in their localized version. So my stripped custom sort does something like this:
$scope.customSort = function(language) {
return function(tag) {
return $scope.tags.[language][tag];
}
}
So far this is the only solution I came up with, I will wait a little to see if anyone answers with a better one before I mark this one as correct.
I had to pass the entire array to the sorting function, along with boolean variable used to determine whether original order or custom sort is desired and then used indexOf like this:
$scope.customSort = function(perform, tags, language) {
return function(tag) {
if (!perform) return tags.indexOf(tag);
return $scope.tags.[language][tag];
}
}

Underscore JS, Grouping by an array Attribute.

I'm trying to use Javascript to group an array by one of it's attributes.
Essentially I have a list of e-mail templates, and I'm trying to group them by the category that they are in so that I can make a collapsible accordion with it later.
I think I might have the syntax of underscore JS wrong, or I'm addressing my array incorrectly. Currently I am calling groupby using the following command:
console.log(_.groupBy(result, 'im_category'));
but my array looks like the 'im_category' property is hidden under the attributes function. I'm not sure how to get there.
I've attached my console.log of what the array looks like and what happens when I run that command. (I get three different objects when I should get 2 if it's working correctly. )
Your im_category is a property of the attributes object in your businessEntity - _.groupBy is looking for properties of businessEntity. You need to create a function as iteratee:
var grouped = _.groupBy(result, function (item) {
return item.attributes.im_category;
});
http://jsfiddle.net/jwnzh8w0/

Is there any alternative to search element in knockout js array instead of ko.utils.arrayFirst

I have one array which contains two things. First is Id and second is Value. I have all Id different but for some Id Values are common. The problem is when I am using ko.utils.arrayFirst it is giving me that Id which is available before than selected one, if the values are same. What I should do to display selected Id and Value.
You really haven't included enough into in your question to give you a solid answer, but it sounds like what you want to do is make a computedArray
However, something like this would be along the lines of what you want:
vm.arrayOfWantedThings = ko.computed(function () {
return ko.utils.arrayFilter(vm.arrayOfEverything(), function(item) {
return item.id() !== vm.wantedId()
});
});
You may use Underscore.js Arrays or some of jQuery utilites to perform common actions on arrays.

How can I reorder/sort a NodeList in JavaScript?

I have what I think should be a straightforward question; let me quickly explain:
In my JavaScript, food.xml is read in with:
getMenuXml.open("GET","food.xml",false);
getMenuXml.send();
xmlDoc=getMenuXml.responseXML;
xmlFoodList = xmlDoc.getElementsByTagName("food");
so that now I have a NodeList xmlFoodList with all the food elements. Great so far. The problem is I want to sort the nodes based on an element <category> inside. I can read that with:
xmlFoodList[i].getElementsByTagName("category")[0].childNodes[0].nodeValue
Later in my code, the food items are displayed in a list, and as you'd expect, I want food of the same category to be listed together. So, my question is: How can I reorder the nodes in xmlFoodList based on their category?
Notes: I can't change food.xml coming in, and I don't want to edit my later code to do the sorting as the list is populated. I don't want to convert the NodeList to an array, since I'd have to rewrite a lot of later code. Performance isn't actually much of a concern, so feel free to clone/nested loop all you want. Thanks for your time.
You can order the elements of the NodeList, if you convert them to an array first:
var foods = xmlDoc.getElementsByTagName("food");
var foodsArray = Array.prototype.slice.call(foods, 0);
Then you can use the sort method:
foodsArray.sort(function(a,b) {
var aCat = a.getElementsByTagName("category")[0].childNodes[0].nodeValue;
var bCat = b.getElementsByTagName("category")[0].childNodes[0].nodeValue;
if (aCat > bCat) return 1;
if (aCat < bCat) return -1;
return 0;
});
This is highly dependent on your XML schema though - if, for example, you had foods which were in more than one category they would only be sorted by the first category in the code above.
It's a good idea to use a Javascript library to get ready-made functions w.r.t Node List operations such as re-ordering, sorting, foreach etc. I would recommend YUI-3, please refer YUI-3 NodeList .
Take a look at this: Xml, xsl Javascript sorting. Worst case scenario, you transform the data into precisely the same xml, but sorted. As long as you're paying the transformation penalty, you might consider transforming it into a form more useful for whatever the next step is.

Categories

Resources