array search / for loop - javascript

I've currently got a implementation which loops through an array within a json document (returned from mongoose) and looks for specific items as below
So what's happening is i'm passing an id in the request header to express and what i need to happen is for it to grab the associated story.users.id.name from the story.users array is returned and then once it has the name send do something with all the other items in the array.
I did try to do this like below:
for (var i = 0; i < story.users.length; i++) {
if (story.users[i].id._id == req.headers.id) {
var name = story.users[i].id.name
} else {
push.apns(story.users[i].id._id, name + " started a new story");
}
}
Where it would loop through grab the name and then do something with all the other users in the array, however sometimes the else argument fires first so the name variable is undefined.
So i resorted to running two if loops after each other like below:
for (var i = 0; i < story.users.length; i++) {
if (story.users[i].id._id == req.headers.id) {
var name = story.users[i].id.name
}
};
for (var i = 0; i < story.users.length; i++) {
if (story.users[i].id._id == req.headers.id) {
} else {
push.apns(story.users[i].id._id, name + " started a new story");
}
}
But there must be a better way to the above rather than looping through an array twice?

What you do looks like the right solution (with the goal you seem to have). There's no real simple way to do only one loop.
You could make it faster and cleaner, though :
var name; // this is just cleaner than to define it in the loop
for (var i = 0; i < story.users.length; i++) {
if (story.users[i].id._id == req.headers.id) {
name = story.users[i].id.name;
break; // don't loop over the other elements
}
};
for (var i = 0; i < story.users.length; i++) {
if (story.users[i].id._id !== req.headers.id) {
push.apns(story.users[i].id._id, name + " started a new story");
}
}

Related

How to update all child IDs using plain JavaScript

I have a JavaScript function called resetIndex. It works fine but I want to reset all child IDs. How can I do this? Is there any method like firstChild and lastChild?
I'm new with JavaScript. Can anyone help?
I have following function:
function resetIndex(delId) {
for (var i = delId + 1; i < count; i++) {
var currentElement = document.getElementById(i);
currentElement.id = i - 1;
var update = currentElement.childNodes;
update.setAttribute('id', 'deleteLink(' + currentElement.id + ')');
}
count--;
}
You can use
node.children[0]
to get the first one, and
node.children[node.children.length - 1]
to get the last one.
Make sure to check if they exist, first.
To do something to all child-nodes, you can use a for-loop, like
for(let a = 0; a < node.children.length; a++) {
node.children[a].id = "my-new-id";
}

Short way to write a long series of if-else-if's?

How to do two variables in an if condition? Here I have few else ifs and I want a 100 else ifs! Is there a shorter way?
$(document).on('click', '.btn-next', function () {
var z = [];
var recipientsArray = z.sort();
var zDuplicate = [];
$('option:selected.exclude_global').each(function() {
z.push($(this).val())});
for (var i = 0; i < recipientsArray.length - 1; i++) {
if (recipientsArray[i + 1] == recipientsArray[i]) {
zDuplicate.push(recipientsArray[i]);
}else if(recipientsArray[i + 2] == recipientsArray[i]){
zDuplicate.push(recipientsArray[i]);
}else if(recipientsArray[i + 3] == recipientsArray[i]){
zDuplicate.push(recipientsArray[i]);
}else if(recipientsArray[i + 4] == recipientsArray[i]){
zDuplicate.push(recipientsArray[i]);
}
}
if(zDuplicate.length>>0){
alert("Global Filter Already Exists");
event.preventDefault();
}
});
Here I have few else ifs and I want a 100 else ifs! Is there a shorter way? I have a dynamic table with dynamic rows. when my table has 5 rows the code is working, but when I have more its not working.
What you're looking for is called a nested loop. You basically can write a loop within a loop. (As many as you want, actually. Though it can get ugly fast.)
Consider your loop structure:
for (var i = 0; i < recipientsArray.length - 1; i++) {
// check if recipientsArray[i] equals any other element
}
Well, that's just another loop:
for (var i = 0; i < recipientsArray.length - 1; i++) {
for (var j = i + 1; j < recipientsArray.length - 1; j++) {
if (recipientsArray[j] == recipientsArray[i]) {
zDuplicate.push(recipientsArray[i]);
break;
}
}
}
Note that there's probably a more efficient way of checking for duplicates. (Especially if the collection is sorted.) At the very least I've changed the logic so you're not re-comparing comparisons you've already made. (I did this by starting the inner loop at i + 1 instead of 1 as your logic does.)
I also think I've replicated your else if results by using a break statement. Since your else if logic basically means "once you find one, stop looking". That's what this break should do, or at least is intended to do, but you'll want to test that. If it doesn't (nesting can be confusing sometimes, which is why it should be done carefully) then you can probably make use of labels to achieve the same effect.
Ultimately, however you implement it, the concept is the same. You're asking how to iterate over multiple values in an array. That's what a loop is for.
I don't know that language. But data and control structures are data and control structures in any language.
Substitute your for loop by :
for (var i = 0; i < recipientsArray.length - 1; i++) {
for ( var j = i+1; j < recipientsArray.lenght-1; j++) {
if (recipientsArray[i] == recipientsArray[j]) {
zDuplicate.push(recipientsArray[i]);
break;
}
}
}
Thank you so much for the idea!
A small change to your code works like heaven!
for (var i = 0; i < recipientsArray.length - 1; i++) {
for (var j = 1; j < 100; j++) {
if (recipientsArray[i+j] == recipientsArray[i]) {
zDuplicate.push(recipientsArray[i]);
break;
}
}
}

Panels not adding to columns

What I am trying to achieve is to allocate a panel to the column with the least amount of panels in it, and if 2 of the columns have an equal amount of panels then I take the first column and insert it there. I have attempted to implement this, which I will show below however I want to first address the problem that I am having. I understand that my code may have many flaws, and so I am open to suggestion on how to make it better. so the error I am getting through firebug is
TypeError: columns[leastItems] is undefined
return columns[leastItems].id;
and here is my javascript code that I have implemented:
function DashboardAllocation() {
var columns = document.querySelectorAll('.col-md-4.column');
var noElemsInCol = new Array(columns.length);
//Get count of children in each column into array
for (var columnNumber = 0; columnNumber < columns.length; columnNumber++) {
noElemsInCol.push(countChildren(columns[columnNumber]));
}
//Compare all values to see if they are all the same or if the first column is 0
if (compareAllValues(noElemsInCol) || countChildren(columns[0] === 0)) {
//if it is then return the first columns id
return columns[0].id;
}
//Reference http://www.programmingsimplified.com/c/source-code/c-program-find-minimum-element-in-array
var leastItems = 1;
var minimum = countChildren(columns[0]);;
for (var i = 1; i < noElemsInCol.length; i++) {
if (noElemsInCol[i] < minimum) {
minimum = noElemsInCol[i];
leastItems = i + 1;
}
}
return columns[leastItems].id;
}
//Compares all the values in the array to check if they are equal
//Reference http://stackoverflow.com/questions/9973323/javascript-compare-3-values
function compareAllValues(a) {
for (var i = 0; i < a.length; i++) {
if (a[i] === null) { return false }
for (var j = 0; j < i; j++) {
if (a[j] !== a[i]) { return false }
}
}
return true;
}
function countChildren(Nodes) {
var childrenCount = 0;
for (var nodeType in Nodes.childNodes) {
//if the nodetype is an element then we will add one
if (nodeType == Node.ELEMENT_NODE) {
childrenCount++;
}
}
return childrenCount;
}
I have referenced the sources where I took code from and hope it helps to see where I am coming from and understand what I am trying to do
You are getting problem as an index leastItems of the array columns is out of range.
Currently You are getting error as in an array of [5] you are trying to fetch the sixth element, using leastItems variable
So either use change
var leastItems = 0;
OR, Use
return columns[leastItems -1 ].id;

Dynamic class not being inserted when supposed to

Basically, I want to add a class to every list item, and each class has to be specific to a "house". So, I've created an array to store all the houses, and everything seems fine. The problem seems to be in the last for loop, where the classes are added, and their value are the ones store in the previous houseColours[] array: however, when I look in the console, the classes are not inserted.
Even more weird, if I manually insert a class in the console by doing something like this:
$('li:eq(0)').addClass(houseColours[0]);
... it works just fine. What could be the problem? Thanks.
function chart()
{
houseColours = [];
var html = "<ol start='0'>";
for (var i = 0; i < shuttle.seats.length; i++)
{
if (shuttle.seats[i] == null)
{
html += "<li>Empty Seat</li>";
}
else
{
for (var j = 0, n = PASSENGERS.length; j < n; j++)
{
if (shuttle.seats[i] == PASSENGERS[j].name)
{
var house = PASSENGERS[j].house;
break;
}
}
houseColours.push(house);
html += "<li>" + shuttle.seats[i] + ' at ' + house + "</li>";
}
}
html += "</ol>";
$("#chart").html(html);
for (var k = 0, banners = houseColours.length; k < banners; k++)
{
$('li:eq(k)').addClass(houseColours[k]);
}
}
In your selector, $('li:eq(k)') the k is part of the selector string, you should use it as a variable (outside of string), like below:
$('li:eq(' + k + ')').addClass(houseColours[k]);
It's better to use .eq method instead of :eq selector, however:
$('li').eq(k).addClass(houseColours[k]);

For loop in Javascript runs only once

Here is my code. I do not quite understand why the for loop runs only once, both inner and outer. nodeList.length and innerNodeList.length show appropriate values when I generate alert messages. I see that both i and j do not increment beyond 0. Kindly point out anything wrong with the code.
function getCategoryElements() {
var newCategoryDiv = document.getElementById("category");
var nodeList = newCategoryDiv.childNodes;
for (var i = 0; i < nodeList.length; ++i) {
var innerNodeList = nodeList[i].childNodes;
alert("innerNodeList Length" + innerNodeList.length.toString());
for (var j = 0; j < innerNodeList.length; ++j) {
if (innerNodeList[j].nodeName == "SELECT") {
alert("inside select Node value " + innerNodeList[j].nodeValue.toString());
document.getElementById("newCategories").value =
document.getElementById("newCategories").value + '<%=delimiter%>' + innerNodeList[j].nodeValue;
} else if (innerNodeList[j].nodeName == "TEXTAREA") {
document.getElementById("newCategoriesData").value =
document.getElementById("newCategoriesData").value + '<%=delimiter%>' + innerNodeList[j].nodeValue;
}
}
}
}
var newCategoryDiv, nodeList, innerNodeList, innerNode, i, j;
newCategoryDiv = document.getElementById("category");
nodeList = newCategoryDiv.childNodes;
for (i = 0; i < nodeList.length; ++i) {
innerNodeList = nodeList[i].childNodes;
alert("innerNodeList Length" + innerNodeList.length.toString());
for (j = 0; j < innerNodeList.length; ++j) {
innerNode = innerNodeList[j];
if (innerNode.nodeName === "SELECT") {
alert("inside select Node value " + innerNode.nodeValue.toString());
document.getElementById("newCategories").value += '<%=delimiter%>' + innerNode.nodeValue;
} else if (innerNode.nodeName === "TEXTAREA") {
document.getElementById("newCategoriesData").value += '<%=delimiter%>' + innerNode.nodeValue;
}
// Will this work?
alert('Does this alert appear');
}
}
I took the liberty to refactor your code and clean it up a little bit. In case you're not aware, all variables have function scope in Javascript, so no matter where you declare them within a single function, Javascript treats them as if the variable declaration is the first statement.
It appears that your code is syntactically correct, and so I think that the most logical place to look for a problem is that there could be an error occurring after the last alert function call.
In order to check this, try adding another alert function call to the end of the inner loop. If it doesn't run, you'll know this is the case.

Categories

Resources