Here is my JavaScript that displays a list of people and images beside them; and if the name is Jim than display also the list of products. But for some reasons the loop stops after Jim and his list:
window.onload = function append() {
var i = 0;
while (i < 4) {
console.log(i);
if (people[i] === "Jim") {
app("div", people[i]);
var arr = document.createElement("ul");
for (i = 0; i < Jim_list.length; i++) {
var tt = opp("li", Jim_list[i]);
arr.appendChild(tt);
}
document.body.appendChild(arr);
} else {
app("div", people[i]);
}
var create_i = document.createElement("img");
create_i.src = "http://tattmight.com/albums/userpics/2013y/08/25/1/178/dsfaf.jpg";
create_i.style.width = "10%";
document.body.appendChild(create_i);
document.write("<br/>");
i++;
console.log("end");
}
}();
Your nested loop uses the same counter as the outer loop. Change it to a new variable:
for (var j = 0, jlen = Jim_list.length; j < jlen; j++) {
var tt = opp("li", Jim_list[j]);
arr.appendChild(tt);
}
Related
I am brand new to JavaScript and still figuring out the way things interact, so I apologize if this is obvious. I am ultimately trying to create a sliding tile puzzle, but at the moment I need to create a 2 dimensional array that will populate my grid with values (1-8). Basically all of my information thus far has been gathered from internet searches as my other resources have proven to be pretty useless.
Here is my code that generates a grid:
function newPuzzle(r, c)
{
var table = document.createElement("table");
for (var i = 0; i < r; i++)
{
var row = document.createElement('tr');
for (var j = 0; j < c; j++)
{
var column = document.createElement('td');
if (i%2 == j%2)
{
column.className = "even";
}
else
{
column.className = "odd";
}
row.appendChild(column);
}
table.appendChild(row);
}
document.body.appendChild(table);
populateTable();
}
At the end I've called the populateTable() function (which I'm not even sure will work) and here is the code for that:
function populateTable()
{
var cell = new Array(_r);
for (var i = 0; i < _r; i++)
{
cell[i] = new Array(_c);
}
for (var i = 0; i < cell.length; ++i)
{
var entry = cell[i];
for (var j = 0; j < entry.length; ++j)
{
var gridTable = document.getElementByTagName("table");
var _cells = gridTable.rows[i].cells[j].innerHTML = "2";
//the 2 is just for testing
}
}
}
Any insight would be very appreciated.
Your code basically had two issues, when I ran it:
In your method populateTable() the variables _r and _c were not defined, so I passed them in as arguments.
The method document.getElementByTagName does not exists, it's plural document.getElementsByTagName which in turn returns an array of all <table> elements so you have to select which one you want - I opted for the first one since I assume you only have one table on your page.
Here are the changes:
function newPuzzle(r, c)
{
var table = document.createElement("table");
for (var i = 0; i < r; i++)
{
var row = document.createElement('tr');
for (var j = 0; j < c; j++)
{
var column = document.createElement('td');
if (i%2 == j%2)
{
column.className = "even";
}
else
{
column.className = "odd";
}
row.appendChild(column);
}
table.appendChild(row);
}
document.body.appendChild(table);
// here we pass _r and _c as arguments
populateTable(r,c);
}
function populateTable(_r,_c)
{
var cell = new Array(_r);
for (var i = 0; i < _r; i++)
{
cell[i] = new Array(_c);
}
for (var i = 0; i < cell.length; ++i)
{
var entry = cell[i];
for (var j = 0; j < entry.length; ++j)
{
// getElementsByTagName returns an array of all table elements
var gridTable = document.getElementsByTagName("table");
// we select the first table element with the array index [0]
var _cells = gridTable[0].rows[i].cells[j].innerHTML = "2";
//the 2 is just for testing
}
}
}
An interactive JS fiddle: https://jsfiddle.net/Ls76kk2a/2/
An optimization tip: Give your table a unique ID like this:
var table = document.createElement("table");
table.id = "mySuperCoolTable";
Then you can be sure you get the right one with:
var gridTable = document.getElementById("mySuperCoolTable");
This only returns one (or none) table because the ID must be unique.
Response to your comment:
Here's an example how to populate all elements but the last one:
function populateTable(_r,_c)
{
var cell = new Array(_r);
for (var i = 0; i < _r; i++)
{
cell[i] = new Array(_c);
for (var j = 0; j < _c; j++) {
cell[i][j] = i*_c + j;
}
}
// fix the last one
cell[_r-1][_c-1] = "X";
for (var i = 0; i < cell.length; ++i)
{
var entry = cell[i];
for (var j = 0; j < entry.length; ++j)
{
var gridTable = document.getElementsByTagName("table");
var _cells = gridTable[0].rows[i].cells[j].innerHTML = cell[i][j];
}
}
}
And here's the JS fiddle: https://jsfiddle.net/Ls76kk2a/3/
<p id="demo"></p>
<script>
//This is the email list
var emailList =["adam#yahoo.edu\n", "henry#yahoo.edu\n", "john#yahoo.edu\n", "sally#yahoo.edu\n", "adam#yahoo.edu\n", "david#yahoo.edu\n", "myhome#yahoo.edu\n", "david#yahoo.edu\n", "david#yahoo.edu\n", "hunger#yahoo.edu\n", "madison#yahoo.edu\n", ];
//I am removing #yahoo.edu
function removeAddress(list){
for (var i = 0; i < list.length; i++) {
list[i] = list[i].replace("#yahoo.edu", " ");
}
}
//Function to remove the duplicates in the list
function removeDuplicates(list)
{
var hash = {};
for (var i = 0; i < list.length; i++)
{
var array = list[i];
for (var j = 0; j < array.length; j++)
{
var val = array[j];
var hashedVal = hash[val];
if (hashedVal === undefined)
{
hash[val] = true;
}
else
{
array.splice(j, 1);
if (array.length == 0)
{
list.splice(i, 1);
}
}
}
}
}
document.getElementById("demo").innerHTML = emailList;
//Remove #yahoo.edu from the list
removeAddress(emailList);
//Sort the list
emailList.sort();
//Remove the duplicates
removeDuplicates(emailList);
//Print the list
document.getElementById("demo").innerHTML = emailList;
</script>
</body>
</html>
First of all, I'm not sure why you're traversing a 1 dimensional array with 2 loops. That's not necessary. Secondly, you're iterating through the array while also removing elements. When the element is removed, all elements after it are pushed forwards 1 index. Then i is incremented, causing you to miss an item. If you want to continue with the for loop and using .splice(), you need to manually decrement i when you remove an item. Also, you only need one loop since emailList is an array of strings.
function removeDuplicates(list)
{
var hash = {};
var newList = [];
for (var i = 0; i < list.length; i++)
{
var email = list[i];
if (hash[email] === undefined) {
hash[email] = true;
} else {
list.splice(i, 1);
i --;
}
}
}
See http://codepen.io/anon/pen/YyKJOP
In the inner for, you are looping a string, not another array.
Second, you may want to .join() the array at the end to obtain a printable string.
So essentially, you're just getting a list of user names. It could have been simplified to the following:
var emailList = ["adam#yahoo.edu\n", "henry#yahoo.edu\n", "john#yahoo.edu\n", "sally#yahoo.edu\n", "adam#yahoo.edu\n", "david#yahoo.edu\n", "myhome#yahoo.edu\n", "david#yahoo.edu\n", "david#yahoo.edu\n", "hunger#yahoo.edu\n", "madison#yahoo.edu\n"];
var usernameHash = emailList.reduce(function(usernames, email, i) {
var username = email.slice(0, email.indexOf('#'));
if(!usernames[username]) usernames[username] = true;
return usernames;
}, {});
var usernames = Object.keys(usernameHash)
document.write(usernames.join(', '));
Having an issue creating objects in JavaScript.
Trying to create a deck of playing cards which I can then display however I want. I am good with the HTML stuff to display them, just having an issue understanding what I am doing wrong in the JavaScript which is only creating undefined cards for me.
(function () {
function Card (rank, suit) {
this.rank = rank;
this.suit = suit;
};
function Deck() {
this.deck = new Array();
this.makeDeck = makeDeck;
this.shuffle = shuffle;
this.deal = deal;
}
function makeDeck() {
var ranks = new Array("A", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"J", "Q", "K");
var suits = new Array("Clubs", "Diamonds", "Hears", "Spades");
this.deck = new Array(52);
var i, j;
for (i = 0; i < suits.length; i++) {
for (j = 0; j < ranks.length; j++) {
this.deck[i*ranks.length + j] = new Card(ranks[j], suits[i]);
document.write("Card made \n");
}
}
};
function shuffle() {
var i, n, j, temp;
for (i = 0; i < n; i++) {
for (j = 0; j < this.deck.length; j++) {
k = Math.floor(Math.random() * this.deck.length);
temp = this.deck[j];
this.deck[j] = this.deck[k];
this.deck[k] = temp;
}
}
document.write("Cards Shuffled");
};
function deal() {
if (this.deck.length > 0) {
return this.deck.shift();
}
else return null;
};
var deck = new Deck();
deck.makeDeck();
deck.shuffle();
for (i = 0; i < 2; i++) {
for (j = 0; j < 5; j++) {
var Card = new Card(deck.deal);
var c = JSON.stringify(Card);
document.write(this.deck[j]);
}
}
} ());
This is the problematic line :
this.deck = new Card(ranks[j], suits[i]);
this.deck is supposed to be the array that includes all your cards, but with the above line, you're overriding it everytime with the single new card.
You have 2 options :
First option
Instead of this.deck = new Array(52), use this.deck = [] instead, initializing an empty array to this.deck.
Then use this.deck.push(new Card(ranks[j], suits[i])) to push all the combinations of the cards to your deck.
Second option
The problem with the first option is that array.push is not really efficient. Read this for more info. It wouldn't really matter for a 52-sized array, just putting this on the table for everyone's info.
Alternatively, you could use this.deck[i] = new Card(ranks[j], suits[i]) to populate your array. You could use this.deck = [] or this.deck = new Array(52) for this. Either would work.
In your "main" execution part :
var deck = new Deck();
deck.makeDeck();
deck.shuffle();
for (i = 0; i < 2; i++) {
for (j = 0; j < 5; j++) {
var Card = new Card(deck.deal);
var c = JSON.stringify(Card);
document.write(this.deck[j]);
}
}
There are several things worth noting.
Change var Card from var Card = new Card(deck.deal);, as the variable Card overrides the function Card after the first iteration.
deck.deal is a function. What you need is deck.deal's return value, therefore, you must use deck.deal()
document.write(this.deck[j]); - You should use deck.deck[j] instead, because what you need to access is the deck you initialized in var deck, and to access the actual deck of cards, you need to access the deck property of the object deck. Therefore, you need to use deck.deck[j]
I am no expert in JS but one thing that rings to me is in your for cycle the deck assignment this.deck = new Card(ranks[j], suits[i]); shouldn't it also be indexed as you create the cards as in:
for (i = 0; i < suits.length; i++) {
for (j = 0; j < ranks.length; j++) {
this.deck[ranks.length*i+j] = new Card(ranks[j], suits[i]);
}
}
Probably that is why you do not have the deck you wished to form
I have the following code in my index.html page
<body>
<script type="text/javascript" src="words.js"></script>
<script>
var words = [];
window.onload = function () {
words = getwords();
};
</script>
</body>
And in word.js file
function getwords() {
var block = [];
var keyword = ['HELLO', 'CYCLE', 'APPLE', 'albatross', 'platform', 'OPERA', 'COURT', 'HOUSE', 'NEWEST', 'AEROPLANE', 'SCIENTIST', 'CORRIDOR', 'BUTTERFLY'.
'MUSICAL', ' AUSTRALIA', 'XYLOPHONE', 'TAPESTRY', 'DREAM', 'NEEDLE', 'GIRAFFE'
];
var index = [];
for (var p = 0; p < keyword.length; p++) {
index[p] = 0;
}
for (var i = 0; i < 8; i++) {
var x = Math.floor(Math.random() * (keyword.length - 1));
for (var j = 0; j <= i; j++) {
if ((words[j] !== keyword[x]) && (index[x] !== 1)) {
block[i] = keyword[x];
index[x] = 1;
}
}
}
return block;
}
I want my getwords function to return any 8 words from keyword array everytime it is called in the onload and it should get stored in words array and those words shouldnt be repaeted next time. However my code doesn't work. May I know my mistake? Please help!
I tried
function getwords(){
var block = [], index =[];
var rem = keyword.length -1;
for(var p=0 ;p <(rem+1) ;p++)
{
index[p]=0;
}
for(var i = 0; i < rem; ++i) keys.push(i);
for(var i=0; i<8 ;i++) {
var x = Math.floor(Math.random() * rem);
while(index[x]===1)
{
x = parseInt(Math.random() * rem);
}
block.push(keyword[x]);
index[x]=1;
}
return block;
}
Still gives some same words on second call.
A small mistake has cost you this problem ...
While storing the indexes in the index array you are using index[p] = 0;
But which should be
for(var p = 0; p < keyword.length; p++) {
index[p] = p;
}
here is the Working Example
I can give you a nicer approach. Tested to be OK, have a try.
var keyword=[
'HELLO', 'CYCLE', 'APPLE', 'albatross', 'platform',
'OPERA', 'COURT', 'HOUSE', 'NEWEST', 'AEROPLANE',
'SCIENTIST', 'CORRIDOR', 'BUTTERFLY', 'MUSICAL',
'AUSTRALIA', 'XYLOPHONE', 'TAPESTRY', 'DREAM',
'NEEDLE', 'GIRAFFE'];
var keys = [];
for(var i = 0; i < keyword.length; ++i) keys.push(i);
function getwords(count){
var block = [];
// first.
// pick and remove [count] times. Becareful when keys goes empty.
while(count > 0 && keys.length > 0) {
var x = parseInt(Math.random() * keys.length);
block.push(keyword[keys[x]]);
keys[x] = keys[keys.length-1];
keys.pop();
--count;
}
return block;
}
console.log(getwords(8));
console.log(getwords(8));
console.log(getwords(8));
What you mean by "doesn't work"? What shows the console?
'BUTTERFLY'.'MUSICAL'. There's a dot instead of a comma.
Hope it helps.
I pass this list from python to javascript like this:
var string=["test_data/new_directory/ok.txt","test_data/reads_1.fq","test_data/test_ref.fa"];
I want output like this:
test_data
reads_1.fq
test_ref.fa
new_directory
ok.txt
Or also the output could be like this:
test_data
reads_1.fq
test_ref.fa
test_data/new_directory
ok.txt
I used split function to get a list with each file and directory like this:
var string=["test_data/new_directory/ok.txt","test_data/reads_1.fq","test_data/test_ref.fa"];
for(var i=0;i<string.length;i++){
var result = string[i].split('/');
console.log(result);
}
Output looks like this:
["test_data", "new_directory", "ok.txt"]
["test_data", "reads_1.fq"]
["test_data", "test_ref.fa"]
How can I convert into the format I showed above? Thanks
Sorry for being late to the party. I ran into a similar issue trying to break out a list of paths into a nested object. Here's a fiddle showing how I ended up doing it.
var list = [];
list.push("A/B/C");
list.push("A/B/D");
list.push("A/B/C");
list.push("B/D/E");
list.push("D/B/E");
list.push("A/D/C");
var data = [];
for(var i = 0 ; i< list.length; i++)
{
buildTree(list[i].split('/'),data);
}
debugger;
function buildTree(parts,treeNode) {
if(parts.length === 0)
{
return;
}
for(var i = 0 ; i < treeNode.length; i++)
{
if(parts[0] == treeNode[i].text)
{
buildTree(parts.splice(1,parts.length),treeNode[i].children);
return;
}
}
var newNode = {'text': parts[0] ,'children':[]};
treeNode.push(newNode);
buildTree(parts.splice(1,parts.length),newNode.children);
}
https://jsfiddle.net/z07q8omt/
That's certainly possible, but it requires recursion.
The first thing you'll want to do (as you've already figured out to do, in fact) is split on the slashes. We'll use map for simplicity:
paths = paths.map(function(path) { return path.split('/'); });
Now we'll want to convert this into an array of objects with name and children properties. This means we'll have to use recursion.
In this function, we'll do a first pass grouping them by their first element:
var items = [];
for(var i = 0, l = paths.length; i < l; i++) {
var path = paths[i];
var name = path[0];
var rest = path.slice(1);
var item = null;
for(var j = 0, m = items.length; j < m; j++) {
if(items[j].name === name) {
item = items[j];
break;
}
}
if(item === null) {
item = {name: name, children: []};
items.push(item);
}
if(rest.length > 0) {
item.children.push(rest);
}
}
Then we can recurse on all of these (assuming the function name we chose was structurize):
for(i = 0, l = items.length; i < l; i++) {
item = items[i];
item.children = structurize(item.children);
}
Now we've got a nice structure. We can then stringify it, again with a recursive function. Since the directory listing is just each item name followed by the indented directory contents listing, we can write that fairly easily:
function stringify(items) {
var lines = [];
for(var i = 0, l = items.length; i < l; i++) {
var item = items[i];
lines.push(item.name);
var subLines = stringify(item.children);
for(var j = 0, m = subLines.length; j < m; j++) {
lines.push(" " + subLines[j]);
}
}
return lines;
}
Then, to actually do it:
console.log(stringify(structurize(paths)).join("\n"));