select multiple array elements at once - javascript

a very basic Array question but I don't know how to do this in the best possible way.
I have an array
var pathArr = [element1, element2, element3, element4, element5, element6]
what can I do if I want to select multiple elements of this path at once.
Lets say:
pathArr[0-2].dofunction()
in this example I'm doing the function on the first three elements.
or
pathArr[1,6].dofunction()
in this example only on element1 and element6
Is there something I can do with an array?

No.
Iterate through your array and apply your method to each appropriate item.
You could use slice to return a range of items in an array, which might make it easier for you, depending on what you're doing.

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);
});

Mixing logical AND and OR in jQuery selector

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(...) == "...");
}
);

d3.select.reverse() has no effect

I'm confused why reverse() works for regular arrays but not d3.select objects, which are based on the array as well. I'm basically trying to traverse the elements I selected from the DOM in reverse order via each but the following seem to traverse them in the same order:
d3.selectAll('.someclass').each(function(){console.log(this);})
d3.selectAll('.someclass').reverse().each(function(){console.log(this);})
I figured it out. d3.select IS an array, it's in their documentation (https://github.com/mbostock/d3/wiki/Selections), but it's a container array of size 1, the actual array of DOM elements is contained within that first element. The following, while a bit uglier, works as expected:
selection = d3.selectAll('.someclass')
selection[0].reverse()
selection.each(function(){console.log(this);})
I'm not a big fan of using the sort solution (the elements are technically already sorted, and I'd also need to figure out the current order in the DOM tree to compare by).
There is no .reverse() method in D3. Note that selections are not arrays and come with their own implementation of methods to manipulate them. To sort the elements in a particular way, use .sort().

Call show on array of jQuery objects

I have a little problem concerning performance of jQuery.show.
This problem occurs in IE8 (probably also versions below, but IE8 is of my interest).
I have an array of jQuery objects, lets call it elements.
I want to show them, so i did:
for (var i = elements.length - 1; i >= 0; i--) {
elements[i].show();
}
The bottleneck seems to be the call to show. The array is already generated, so that takes no time. looping through an array should not be a problem either.
I thought of reducing this to one call to show by creating a new jQuery element containing all my elements. but I was not sure how to do this. I tried by jQuery.add.
var $elements = elements[0];
for (var i = elements.length - 1; i >= 1; i--) {
$elements = $elements.add(elements[i]);
}
$elements.show();
Now, this time it seems to be a problem with jQuery.add. Probably because it always creates a new object.
So, I thought of three different approaches that could solve my problem. Maybe you can help me with one of them:
Is there a jQuery method like add that does not return a new object, but instead adds it to the current jQuery element?
Is there an easy and fast way to create a jQuery element by an array of jQuery elements?
Is there a way to show all jQuery objects in an array in a faster way?
Answering just one of the question would probably help me out here. My problem is, that jquery always expects an array of DOM elements and not an array of jQuery elements in its methods.
Thanks a lot in advance!
-- EDIT about the contents of elements
I have a jstree that dynamically creates nodes (that is, li elements). These elements have an attribute data-id to identify them.
Now, I could always query for something like $('li[data-id=xxx]'), but this would be very slow. So instead, when li elements are created, i cache them into a dictionary like object (key is the data-id, value is the node). Out of this object, i generate my array elements. This happens very fast.
The array can have a size of up to 4000 nodes. Every jQuery Element in the array only contains one DOM-Element (li).
Edit
After reading your update, and the comments, this Very small one-liner is most likely going to be the answer:
elements.each($.fn.show);
Using the jQ each method to apply (well, internally: call is used) the show method to all elements.
The easiest, and fastest way to create a jQuery object from an array of jQuery objects would be this:
var objFromArr = $(jQarr);
I've just tested this in the console:
objFromArr = jQuery([jQuery('#wmd-input'),jQuery('#wmd-button-bar')]);
objFromArr.each(function()
{
console.log(this);//logs a jQ object
console.log(this[0]);//logs the DOMElement
});
But having said that: you say elements is an array of jQ objects, but if it's the return value of a selector ($('.someClass')) then really, it isn't: in that case, your loop is "broken":
elements = $('.someClass');
for (var i=0;i<elements.length;i++)
{
console.log(elements[i]);//logs a DOMElement, not a jQuery object
}
//It's the same as doing:
console.log(elements[0]);
//or even:
console.log($('.someClass').get(0));
But in the end, if you have an array of jQuery objects, and you want to invoke the show method on each and every one of them, I suspect this is the best take:
elements.each($.fn.show);//use the show method as callback

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