insertBefore function for arrays and/or HTMLCollections? - javascript

Does there exist a function in vanilla JavaScript or jQuery that operates similarly to Node.insertBefore(), but for arrays and/or HTMLCollections?
An example could look something like:
var list = document.getElementsByClassName("stuff");
var nodeToMove = list[0];
var otherNode = list[4];
list.insertBefore(nodeToMove, otherNode);
Basically I'm trying to perform insertBefore() without manipulating the actual DOM, as I want the changes to only be applied to the DOM under certain conditions. If those conditions are met, then I would perform insertBefore() on the actual nodes.
To clarify, I'm looking for a function that would insert an element before a target element at a given index in an array, not necessarily at a given index. Examples I've seen using splice() usually insert an element at a given index, which sometimes puts the element before the target element, and sometimes after, depending on where the element to be moved originally was in the array. I'm looking for something that would reliably put the element to be moved before the target element.

HTMLCollection does not have an insertBefore method. jQuery can apply any jQuery methods both to a single element being selected, as well as many.
https://api.jquery.com/insertBefore/

There is no single method to do this in one step, but there doesn't need to be. If you convert the collection to an Array, you can call the Array.prototype.splice() method to achieve the same result.
Here's an example:
let ary = [1,2,3,4,5];
// Swap 2 and 3
// Start at the 3rd item and remove one item (3).
// Store the removed item
let removed = ary.splice(2,1);
// Start at the second item, don't remove anything, insert the removed
// item at that position
ary.splice(1,null,removed[0]);
// Log the result
console.log(ary);
And, with that knowledge, you can create your own more easily callable function:
let ary = [1,2,3,4,5];
function insertBefore(ary, newItem, target){
ary.splice(target,null,newItem);
}
// Insert 999 before the 3rd array item
insertBefore(ary,999,2)
console.log(ary);

You need to get the index you want, then use Array.splice.
Myself I would do something like this :
const myArr = ['Aurore', 'Dimitri', 'Alban', 'Frédéric'];
const insertBeforeThis = 'Alban';
const eltToInsert = 'Laura';
const index = myArr.findIndex(name => name === insertBeforeThis);
myArr.splice(index, 0, eltToInsert);
Please feel free to try it out in your browser's console. Note i used const for my array, as it fixes the type of the variable as an array but allow me to manipulate it.
MDN: Array.prototype.findIndex()
stackoverflow: How to insert an item into an array at a specific index (JavaScript)?
Have a happy coding time!

Related

Is there a way to combine map and shift in Javascript?

I'm working with a buffer array that I am periodically checking. When I am mapping through the elements, I would like access the element using the shift method, this way I would get the next element in the array and would also remove it. Is there a way to do this in a map? Thank you!
I currently have a naive solution, which is prone to race conditions.
if (timestep) {
bufferArray.map((mvt) =>{
console.log(mvt)
});
bufferArray = [];
}
As I would like to go through the elements of the array one by one and remove the current element from the array. For this reason a simple and great solution is to use a while loop with the shift method. For example:
let arr = [0,1,2,3,4,5];
while (arr.length)
{
let current = arr.shift()
// do something with current
}

Why do getElementsByTagName() always returns an array?

Why is it that if I have only one h1 element in the document, I still have to use the index to access it?
Like the following doesn't work.
document.getElementsByTagName('h1').innerHTML = "SHUSHAN";
but if I do
document.getElementsByTagName('h1')[0].innerHTML = "SHUSHAN";
It does work.
Even though I only have one h1, why do I have to specify?
Short answer: This is so that you can have some sanity.
If you don't know whether you will get a single element or a collection of elements, you would have to write defensive, type-checking (stupid) code like this
let foo = document.getElementsByTagName('h1')
if (foo instanceof HTMLCollection)
// do something with all elements
else
// do something with just one element
It makes way more sense for the function to always return a known type, an HTMLCollection of HTMLElement objects
If you only care about getting the first element, you can use destructuring assignment
let [first] = document.getElementsByTagName('h1')
console.log(first) // outputs just the first h1
This is fine because the assignment clearly shows that it's expecting an array (or array-like) of elements but only cares about assigning an identifier to the first value
You should also be aware of the newer document.querySelector and document.querySelectorAll functions …
document.querySelector will select at most one element from the document or returnnull
document.querySelectorAll will always return an HTMLCollection, but may be empty if no elements match the selector.
Here's how I'd write your code in 2017
setTimeout($ => {
// get the element to change
let elem = document.querySelector('h1')
// update the text of the element
elem.textContent = 'SHUSHAN'
}, 3000)
<h1>wait 3 seconds ...</h1>
getElementsByTagName - the method name itself implies that it will return multiple elements - i.e. an array. The method always returns an array, with the length equal to the number of matching elements. As such you must always access the elements by the index of the element in the array.
Arrays must be accessed by index regardless of how many values it holds. Do some reading on array data types to get a better understanding of the concept.
The point is that getElementsByTagName always returns a HTMLCollection of elements, which works mostly as an array. If there is only one element in this collection, then its index is 0.
This is the reason why you must specify the index, even if there is only one element in the document.
Click here or here to see more documentation about this.

Get the last item from node list without using .length

The following command
document.querySelectorAll('#divConfirm table')[1].querySelectorAll('tr')
gives a node list with 3 tablerow (tr) elements in it. If I know the list size, I can access the last element via.item(2).
Is there a way to get the last element directly without resorting to .length first?
There's at least one way
var els = document.querySelectorAll('#divConfirm table')[1].querySelectorAll('tr');
var last = [].slice.call(els).pop();
but, the following statement
But if I do not know the length prior to running the script
makes no sense, you already have the collection of elements, so you would always know the length
var els = document.querySelectorAll('#divConfirm table')[1].querySelectorAll('tr');
var last = els[els.length - 1];
Another option as the8472's answer suggests would be
document.querySelector('#divConfirm table:nth-child(2) tr:last-child');
Since NodeList doesn't have a pop method.
Using the spread syntax in a new array, then pop() to get the last element.
This basically copy the Nodelist as a regular array, thus the pop() and other array methods become available.
console.log(
// Last elem with pop()
[...document.querySelectorAll("div")].pop()
)
console.log(
// 2nd elem
[...document.querySelectorAll("div")].slice(1)[0]
)
console.log(
// By index :) just in case
document.querySelectorAll("div")[0]
)
<div>The sun</div>
<div>is</div>
<div>shinning</div>
depending on circumstances this may work: document.querySelector('#divConfirm table tr:last-of-type')
You can transform the NodeList into an Array. Then can use array.pop(). It return the last item BUT remove it to the array!
const elementsArray = Array.from(elements);
elementsArray.pop()

How to get the last element of a json file with jquery

$.getJSON('./file-read?filename='+filename+'&parameter='+parameter, function(data) {
var firstElement = data[0][0];
var lastElement = ?
});
I try to find out the last Element in my JSON file.
My JSON File looks like this:
[[1392418800000,6.9],[1392419400000,7],[1392420000000,7.1],[1392420600000,7.2],[1392421200000,7.2]]
can anybody help me to read extract the last date(1392421200000) ?
Just pick the (length - 1)th element with this:
var lastElement = data[data.length-1][0];
Another way is to use array methods, e.g. pop which will return the last element of the array:
var lastElement = data.pop()[0];
N.B.: The first approach is the fastest way of picking the last element, however the second approach will implicitly remove the last element from data array. So if you plan to use the initial array later in your code, be sure to use either the first method or alternative solution provided by #matewka.
VisioN's answer is nice and easy. Here's another approach:
var lastElement = data.slice(-1)[0];
// output: [1392421200000,7.2]
Negative number in the slice method makes the slice count from the end of the array. I find this method more compact and simpler but the disadvantage is that it returns a smaller, 1-element array instead of the element you wanted to fetch. If you want to fetch only the timestamp you'd have to add another [0] to the end of the expression, like this:
var lastElement = data.slice(-1)[0][0];
// output: 1392421200000
You can use :
var data = " any json data";
var lastelement = data[ Object.keys(obj).sort().pop() ];
Object.keys (ES5, shimmable) returns an array of the object's keys. We then sort them and grab the last one.

Javascript removing and rearranging array elements

I have this collection of images resources where that is stored in array, the user will select an image and then the selected image will be removed from the list(also from the array) and after that The array would be rearrange. How could I perform such task? (as much as possible I do not want to use an open source library)
Sounds like you need to look up splice() method. It allows you to add and remove one to many items within an array at any index.
here's reference for it.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/splice
your question lacks a code example but you can use Array.splice(index,number) whereas index is zero based and number is how many items to remove.
images.splice(selectedIndex,1);
Simply, you can create a temporary array where you store the initial array elements you need and reassign the value of your initial array to the temporary array.
function clean_array(my_array){
var no_need_value = 'value you want to remove'
var tmpArray = new Array()
for (var i = 0; i < my_array.length; i++)
if (my_array[i] != no_need_value)
tmpArray.push(my_array[i])
my_array = tmpeArray
}

Categories

Resources