Make a div appear when clicking a link [duplicate] - javascript

The NodeList don't have a indexOf(element) method? So, how can I get the element index?

You can use Array.prototype.indexOf.call() like this
let nodes = document.getElementsByTagName('*');
Array.prototype.indexOf.call(nodes, document.body);

The NodeList object is an Array-like object. So it's possible to "convert" it into an Array using Array.prototype.slice.call()
var arr = Array.prototype.slice.call(yourNodeListObject); // Now it's an Array.
arr.indexOf(element); // The index of your element :)
On browsers that support ES6 you can also do this with Array.from()
const arr = Array.from(yourNodeListObject);
or using the spread operator ...
const arr = [...yourNodeListObject];

By iterating over the elements, and checking if it matches.
Generic code that finds the index of the element within it's parents childNodes collection.
function index(el) {
var children = el.parentNode.childNodes,
i = 0;
for (; i < children.length; i++) {
if (children[i] == el) {
return i;
}
}
return -1;
}
Usage:
// should return 4
var idx = index(document.body.childNodes[4]);
EDIT: I can't delete an accepted answer, but #kennebec's answer below is much better, which I'll quote verbatim:
You can use Array.prototype.indexOf.call() like this
let nodes = document.getElementsByTagName('*');
Array.prototype.indexOf.call(nodes, document.body);

Just add one line in your script:
NodeList.prototype.indexOf = Array.prototype.indexOf; // for IE11
Then use indexOf as usual:
var index = NodeList.indexOf(NodeElement);

Let us say you have the following line:
const list=document.querySelectAll('.some_class .someother_class');
list will be a nodelist.
So we can convert the nodelist to an array and create a new array of indexes as follows:
const indexArr= [...list].map( element => return [...list].indexOf(element) );
indexArr contains all the indexes of elements in the original list.

Related

Loop through childNodes

I'm trying to loop through childNodes like this:
var children = element.childNodes;
children.forEach(function(item){
console.log(item);
});
However, it output Uncaught TypeError: undefined is not a function due to forEach function. I also try to use children instead of childNodes but nothing changed.
Does anybody know what's going on?
The variable children is a NodeList instance and NodeLists are not true Array and therefore they do not inherit the forEach method.
Also some browsers actually support it nodeList.forEach
ES5
You can use slice from Array to convert the NodeList into a proper Array.
var array = Array.prototype.slice.call(children);
You could also simply use call to invoke forEach and pass it the NodeList as context.
[].forEach.call(children, function(child) {});
ES6
You can use the from method to convert your NodeList into an Array.
var array = Array.from(children);
Or you can also use the spread syntax ... like so
let array = [ ...children ];
A hack that can be used is NodeList.prototype.forEach = Array.prototype.forEach and you can then use forEach with any NodeList without having to convert them each time.
NodeList.prototype.forEach = Array.prototype.forEach
var children = element.childNodes;
children.forEach(function(item){
console.log(item);
});
See A comprehensive dive into NodeLists, Arrays, converting NodeLists and understanding the DOM for a good explanation and other ways to do it.
I'm very late to the party, but since element.lastChild.nextSibling === null, the following seems like the most straightforward option to me:
for(var child=element.firstChild; child!==null; child=child.nextSibling) {
console.log(child);
}
Here is how you can do it with for-in loop.
var children = element.childNodes;
for(var child in children){
console.log(children[child]);
}
const results = Array.from(myNodeList.values()).map(parser_item);
NodeList is not Array
but NodeList.values() return a Array Iterator, so can convert it to Array.
Couldn't resist to add another method, using childElementCount. It returns the number of child element nodes from a given parent, so you can loop over it.
for(var i=0, len = parent.childElementCount ; i < len; ++i){
... do something with parent.children[i]
}
Try with for loop. It gives error in forEach because it is a collection of nodes nodelist.
Or this should convert node-list to array
function toArray(obj) {
var array = [];
for (var i = 0; i < obj.length; i++) {
array[i] = obj[i];
}
return array;
}
Or you can use this
var array = Array.prototype.slice.call(obj);
Here is a functional ES6 way of iterating over a NodeList. This method uses the Array's forEach like so:
Array.prototype.forEach.call(element.childNodes, f)
Where f is the iterator function that receives a child nodes as it's first parameter and the index as the second.
If you need to iterate over NodeLists more than once you could create a small functional utility method out of this:
const forEach = f => x => Array.prototype.forEach.call(x, f);
// For example, to log all child nodes
forEach((item) => { console.log(item); })(element.childNodes)
// The functional forEach is handy as you can easily created curried functions
const logChildren = forEach((childNode) => { console.log(childNode); })
logChildren(elementA.childNodes)
logChildren(elementB.childNodes)
(You can do the same trick for map() and other Array functions.)
Try this [reverse order traversal]:
var childs = document.getElementById('parent').childNodes;
var len = childs.length;
if(len --) do {
console.log('node: ', childs[len]);
} while(len --);
OR [in order traversal]
var childs = document.getElementById('parent').childNodes;
var len = childs.length, i = -1;
if(++i < len) do {
console.log('node: ', childs[i]);
} while(++i < len);
If you do a lot of this sort of thing then it might be worth defining the function for yourself.
if (typeof NodeList.prototype.forEach == "undefined"){
NodeList.prototype.forEach = function (cb){
for (var i=0; i < this.length; i++) {
var node = this[i];
cb( node, i );
}
};
}
for (var i = 0; i < e.childNodes.length; i++) {
var id = e.childNodes[i].id;
}

Javascript: how to remove second level array by top level index?

I have a nested array in javascript. The top level has a numerical index, the second level arrays contains various data. I want to be able to remove an element from the array using the top level index.
var my_array = [];
my_array[12] = ['cheese', 'egg', 'ham'];
my_array[24] = ['balloon', 'frog'];
my_array[33] = ['chicken', 'goose'];
How do I delete my_array[24]? I have tried using splice with $.inArray but inArray returned the index as -1. I don't want to use indexOf because of it's browser limitations - also I think it will give me the same problem as inArray.
Thanks!
my_array.splice(24, 1); will remove the item at index = 24.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
Create a function:
function deleteByIndex(arr, index) {
var new_arr = [];
for (var i=0; i<arr.length; i++) {
if (arr[i] && i!=index) {
new_arr[i] = arr[i];
}
}
return new_arr;
}
FIDDLE
call it like var new_array = deleteByIndex(my_array, 24);
If want to remove frog from main array index 24 by it's known index of 1
myArray[24].splice(1,1);
If want to search for frog anywhere and remove parent.
var term='frog';
my_array=$.grep(my_array,function(element,i){
return $.inArray( term, element) !=-1;
}

which approach is best to search object in array?

I've sorted following ways to search for an object in array.
This question has been asked like countless times but I want to know which of the best from following ways. If there's another I'd like to know that too.
Using $.grep()
function is_in_array(arr,element){
var result = $.grep(arr, function(e){ return e.id == element; });
return result.length;
}
Above function returns length of array.
0 when element not present
1 when element present
length > 1 if more elements with same value present
using lookup object
var lookup = {};
for (var i = 0, len = array.length; i < len; i++) {
lookup[array[i].id] = array[i];
}
This way I don't need to traverse entire array each time. I'd just check for lookup[id] instead.
for loop in traditional way
function in_array(array, id) {
for(var i=0;i<array.length;i++) {
if(array[i].id === id) {
return true;
}
}
return false;
}
to check if element exists, i'd call in_array(arr,element).
Which approach is best ? Question seriously sounds duplicate and it is but I just want to make sure which is best from these three only.
Update
Array will contain objects like --
var arr = [];
var nameObj = {};
nameObj.label = "somename";
nameObj.id = 123;
arr.push(nameObj);
.
.
.
You could also use a combination of JSON (for comparison) and the Array.filter method:
var findvalue = JSON.stringify([somevalue]),
,found = [array].filter(
function(a){return JSON.stringify(a) === findvalue;}).length
;
// found > 0 means: findvalue found
A jsfiddle example
More about Array.filter and a shim for older browsers #MDN
You could use the built-in map() method instead of a loop:
var lookup=array.map(function(e){return e.id;});
(Not supported in IE 8)

chaining methods and selectors using jquery inside of a loop

Is it possible to generate a chain of selectors and methods inside of a loop?
For example, I have an array of elements:
array[0] = '.type1value1, .type1value2, .type1value3';
array[1] = '.type2value1, .type2value2, .type2value3';
array[2] = '.type3value1, .type3value2, .type3value3';
I somehow need to build a chain of methods using the array elements as selectors (by looping or any other possible means!) so that I would end up with the following:-
$('.type1value1, .type1value2, .type1value3').filter('.type2value1, .type2.value2, .type2value3').filter('.type3value1, .type3value2, .type3value3');
If I understand you correctly, you don't even need to do a loop:
var firstSelector = array.shift(); //returns first item in the array and removes it from the original array
var filterSelector = array.join(',');
$(firstSelector).filter(filterSelector);
Why can't you just do something like:
var $test = $(array[0]);
for (var i = 1; i < array.length; i++) {
$test = $test.filter(array[i]);
}
Looking at your example, the value of each array element is exactly the value you want to pass as the selector parameter to .filter()
use the following function to pass it an array of selectors...
function getSet(arrSet){
var elements = $(arrSet[0]);
for (var i = 1; i < arrSet.length; i++) {
elements = $(elements).filter(arrSet[i]);
}
}

How to get the index of the element in javascript?

The NodeList don't have a indexOf(element) method? So, how can I get the element index?
You can use Array.prototype.indexOf.call() like this
let nodes = document.getElementsByTagName('*');
Array.prototype.indexOf.call(nodes, document.body);
The NodeList object is an Array-like object. So it's possible to "convert" it into an Array using Array.prototype.slice.call()
var arr = Array.prototype.slice.call(yourNodeListObject); // Now it's an Array.
arr.indexOf(element); // The index of your element :)
On browsers that support ES6 you can also do this with Array.from()
const arr = Array.from(yourNodeListObject);
or using the spread operator ...
const arr = [...yourNodeListObject];
By iterating over the elements, and checking if it matches.
Generic code that finds the index of the element within it's parents childNodes collection.
function index(el) {
var children = el.parentNode.childNodes,
i = 0;
for (; i < children.length; i++) {
if (children[i] == el) {
return i;
}
}
return -1;
}
Usage:
// should return 4
var idx = index(document.body.childNodes[4]);
EDIT: I can't delete an accepted answer, but #kennebec's answer below is much better, which I'll quote verbatim:
You can use Array.prototype.indexOf.call() like this
let nodes = document.getElementsByTagName('*');
Array.prototype.indexOf.call(nodes, document.body);
Just add one line in your script:
NodeList.prototype.indexOf = Array.prototype.indexOf; // for IE11
Then use indexOf as usual:
var index = NodeList.indexOf(NodeElement);
Let us say you have the following line:
const list=document.querySelectAll('.some_class .someother_class');
list will be a nodelist.
So we can convert the nodelist to an array and create a new array of indexes as follows:
const indexArr= [...list].map( element => return [...list].indexOf(element) );
indexArr contains all the indexes of elements in the original list.

Categories

Resources