Looping and finding empty array - javascript

I'm working on project in which I have to create a search engine through jQuery. Everything has been going great until I started looping through the array.
I don't know whether I'm doing it wrong, but for some reason, when I use a conditional it does not output the statement I want it to say. If I change the conditional to say whether there's something in the array output this, it does. But if the array is empty it does absolutely nothing. Why is that?
for(var i = 0, j = response.length; i < j; i++){
var searchItemRes = response[i];
if(response.length === 0){
$('' + '<ul>' +
'<li><span>Nothing found, try again</span></li>' +
'</ul>'
).appendTo(searchResults);
}
$('' + '<ul>' +
'<li><img src="" /><span> '+searchItemRes.title+'</span></li>' +
'</ul>'
).appendTo(searchResults);
}

Consider this:
// declare local variables
var str, i, item;
// build the HTML source code string
if ( response.length === 0 ) {
str = '<ul><li><span>Nothing found. Please, try again.</span></li></ul>';
} else {
str = '<ul>';
for ( i = 0; i < response.length; i += 1 ) {
item = response[i];
str += '<li><img src=""><span> ' + item.title + '</span></li>';
}
str += '</ul>';
}
// append the string to the DOM
$( searchResults ).append( str );
First off, declare the local variables at the top of the function. As you can see, my code uses 3 local variables.
Next, I doubt that you want to create one UL (list-holder) for each result. It makes more sense to have one UL element which contains all the results (which is what I've implemented in the above code).
Also, I recommend manipulating the DOM only once at the end - the live-DOM should be touched as few times as possible. Therefore, the above code builds the HTML source code string "off-DOM", and only in the end appends (the whole thing) to the DOM.

for (var i = 0, j = response.length; i < j; i++){
var searchItemRes = response[i];
if (response.length === 0) {
$('<ul><li><span>Nothing found, try again</span></li></ul>').appendTo(searchResults);
}
...
}
That condition will never be executed. If i = 0 and j = response.length and it's iterating i < j then it won't iterate at all if response.length == 0 because 0 < 0 will just break out of the loop.

How can code that triggers on response.length == 0 ever execute inside a loop that iterates response.length times?
Perhaps you meant:
if (response.length === 0) {
$('<ul><li><span>Nothing found; try again</span></li></ul>').appendTo(searchResults);
}
else {
for (var i = 0, j = response.length; i < j; i++) {
var searchItemRes = response[i];
$('<ul>' +
'<li><img src="" /><span>' + searchItemRes.title + '</span></li>' +
'</ul>'
).appendTo(searchResults);
}
}

Related

Access array values inside json object

i get this with use of xmlhttprequest then i json.parse it and then for loop through the "resonse" to populate a list.
You can see in the next picture how the array in "response" looks when i click on "[0...99].
My problem is that the for loop doesnt populate the list tag in html, but when i try to write only for albania then it works. I need help with only javascript and not jQuery. you can see my code here:
The HTML part:
<section class="country">
<h3 id="countries"><br /></h3>
<nav id="countries2">
<ul id="countrylist"></ul>
</nav>
</section>
Here is javascript part:
var jsonData = JSON.parse(xhr.responseText);
document.getElementById("countrylist").innerHTML = "";
for (var i = 0; i < jsonData.response[i].length; i++) {
document.getElementById("countrylist").innerHTML += "<li id='" + jsonData.response[i].code + "'>" + jsonData.response[i].name + "</li>";
}
Here is the javascript part that works without foor loop:
document.getElementById("countrylist").innerHTML += "<li id='" + jsonData.response[0].code + "'>" + jsonData.response[0].name + "</li>";
Your for loop is ending early. Your condition is wrong.
What you have
for (var i = 0; i < jsonData.response[i].length; i++) {
What you should have
for (var i = 0; i < jsonData.response.length; i++) {
Your condition is against the length of the first element and is ending immediately.
Looking at your for loop condition:
for (var i = 0; i < jsonData.response[i].length; i++) {
jsonData.response[i].length is not the length of the array, but the length of one array element (in this case it is 1)! So your loop is only executing once.
You want instead to loop over all the array, like so:
for (var i = 0; i < jsonData.response.length; i++) {

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.

FOR IF Loop in javascript

I have a simple question. I want to make an if statement in this code (if(i=2){str += 'test';}):
var data = response.DATA;
var str = '<ul>';
for (var I = 0; I < data.length; I++) {
str += '<li>' + data[I][1] + '</li>';
if(I=2){str += 'test';}
}
str += '</ul>';
$('#output').html(str);
}
When I do, it's placing the word 'test' not only at row 2, but on every row.
Use == or === to compare two values :
if (I===2) {str += 'test';}
The result of I=2, which changes the value of I, is 2, which evaluates as true in an if.
You have a typo in your script:
if (I=2) ...
means that I is always 2 because you're assigning 2 to it.

Need help w/ JavaScript and creating an html table from array

I've tried everything I can find via google and nothing has worked correctly. Output is just a single row with all the contents of the array listed. What I need is a way to write the contents of an array but after 3 cells, automatically start a new line. I'll post the code I've made below as well as the question. (yes this is from an assignment. :( )
//***(8) place the words in the string "tx_val" in a table with a one pixel border,
//*** with a gray backgound. Use only three cells per row. Empty cells should contain
//*** the word "null". Show the table in the span block with id="ans8"
var count = i % 3;
var nrow = "";
var out = "<table border='1' bgcolor='gray'><tr>"
for (var i=0; i<txArr.length; i++)
{
out += ("<td>" + txArr[i] + "</td>");
count++;
if (count % 3 == 0)
{
nrow += "</tr><tr>";
}
}
document.getElementById('ans8').innerHTML = out + nrow;
you need to print the tr's inside the table (annd add a </table>!):
var count = i % 3; // btw. what's this??
var nrow = "";
var out = "<table border='1' bgcolor='gray'><tr>"
for (var i=0; i<txArr.length; i++)
{
out += "<td>" + txArr[i] + "</td>";
count++;
if (count % 3 == 0)
out += "</tr><tr>";
}
out += "</table>";
document.getElementById('ans8').innerHTML = out;
Rather than try to write out the html, try manipulating the dom. It seems much more straightforward to me. Take a look at the following:
var row = table.insertRow();
msdn
mdc
var cell = row.insertCell();
msdn
mdc
var cellContent = document.createTextNode(txArr[i]);
msdn
mdc
cell.appendChild(cellContent);
msdn
mdc
For deciding when to start a new row, just use the modulus operator (%
msdn
mdc
) against i:
if (i % 3 == 0)
{
row = table.insertRow()
}
You'd end up with something like this:
var container = document.getElementById("ans8");
var t = container.appendChild(document.createElement("table"));
var row;
txArr.forEach(function (item, i)
{
if (i % 3 == 0)
{
row = t.insertRow()
}
row.insertCell().appendChild(document.createTextNode(item));
});
I'll leave a little for you to figure out - border, background color, getting the word "null" in there. It is your homework after all. :-)
Also, for older browsers you'll need to add Array.forEach in yourself.
I prefer using an array over concatination
var html = [];
html.push("<table><tr>");
var i = 0;
for (var k in txArr)
{
if(i>=3){
i=0;
html.push("</tr><tr>");
}
html.push("<td>" + txArr[k] + "</td>");
i++;
}
html.push("</tr></table>");
document.getElementById('ans8').innerHTML = html.join('');
// wrapped in function
function arrayToTable(a,cols){
var html = [];
html.push("<table><tr>");
var i = 0;
for (var k in a)
{
if(i>=cols){
i=0;
html.push("</tr><tr>");
}
html.push("<td>" + a[k] + "</td>");
i++;
}
html.push("</tr></table>");
return html.join('')
}
document.getElementById('ans8').innerHTML = arrayToTable(txArr, 3);
It might be a tad easier to accomplish with something like
buffer = "<table>";
for(var r = 0; r < 10; r++){
buffer += "<tr>";
for(var c = 0; c < 3 ; c++){
buffer += "<td>Cell: " + r + ":" + c + "</td>";
}
buffer += "</tr>";
}
buffer += "</table>";
document.getElementById("ans8").innerHTML = buffer;
That would create a table 30 rows long by 3 columns for each row.
you might be assigning values to "count" too early as you don't know what i is yet. and you are not spitting out the value of nrow anywhere... change it to out.
var count;
var nrow = "";
var out = "<table border='1' bgcolor='gray'><tr>"
for (var i=0; i<txArr.length; i++)
{
out += ("<td>" + txArr[i] + "</td>");
count++;
if (count % 3 == 0)
{
out += "</tr><tr>";
}
}
document.getElementById('ans8').innerHTML = out + nrow;
Basically I would split it up into 3 functions, for readability and maintenance. These functions would consist of creating a cell, a row, and a table. This definitely simplifies reading the code. As I have not tested it, below is an example of what I would do.
function createTableCell(value) {
return value == null? "<td>NULL</td>":"<td>" + value + "</td>";
}
function createTableRow(array) {
var returnValue = "";
for (var i = 0; i < array.length; i++) {
returnValue = returnValue + createTableCell(array[i]);
}
return "<tr>" + returnValue + "</tr>";
}
function arrayToTable(array, newRowAfterNArrayElements) {
var returnValue = "<table>";
for (var i = 0; i < array.length; i = i + newRowAfterNArrayElements) {
returnValue = returnValue + createTableRow(array.split(i, (i + newRowAfterNArrayElements) - 1));
}
return returnValue + "</table>";
}
document.getElementById("ans8").innerHTML = arrayToTable(txArr, 3);
In addition this makes your code much more dynamic and reusable. Suppose you have an array you want to split at every 4 element. Instead of hardcoding that you can simply pass a different argument.
Here's a live example of doing this with DOMBuilder, and of using the same code to generate DOM Elements and an HTML String.
http://jsfiddle.net/insin/hntxW/
Code:
var dom = DOMBuilder.elementFunctions;
function arrayToTable(a, cols) {
var rows = [];
for (var i = 0, l = a.length; i < l; i += cols) {
rows.push(a.slice(i, i + cols));
}
return dom.TABLE({border: 1, bgcolor: 'gray'},
dom.TBODY(
dom.TR.map(rows, function(cells) {
return dom.TD.map(cells);
})
)
);
}
var data = [1, 2, null, 3, null, 4, null, 5, 6];
document.body.appendChild(arrayToTable(data, 3));
document.body.appendChild(
dom.TEXTAREA({cols: 60, rows: 6},
DOMBuilder.withMode("HTML", function() {
return ""+arrayToTable(data, 3);
})
)
);
Yes, you can build from scratch...but there's a faster way. Throw a grid at it. The grid will take data in a string, array, json output, etc and turn it into a proper HTML outputted table and will allow you to extend it with sorting, paging, filtering, etc.
My personal favorite is DataTables, but there are numerous others out there.
Once you get proficient, setting one of these up literally takes 5 minutes. Save your brain power to cure world hunger, code the next facebook, etc....

Categories

Resources