I have a Sudoku table which I've generated using JavaScript. After generating the table, I've also attached a number entry field as well as a function to each cell. Currently, the function passes in only the very last cell id that was generated (ex. R9C9), not the cell that was recently modified. I would rather have the function get passed the current cell id which the user modified so that I can check the row, column, and current square for conflicts and not every single cell on the board. I'm trying not to use jQuery, but any help would be appreciated.
This is the code that attaches the number field, as well as the function. I believe currently the function it attaches is anonymous, which wouldn't matter as long as I could get the attached anonymous function to be associated with the current cell.
for (i = 1; i <=9; i++)
{
for (j = 1; j <= 9; j++) {
temp = document.getElementById('R'+i+'C'+j);
if (temp.innerHTML == "")
{
var temp2 = temp.appendChild(document.createElement("input"));
temp2.type = "number";
temp3 = document.getElement('R'+i+'C'+j);
temp2.onkeyup = function(){conflictChecker(temp3)};
}
}
}
This is the code for generating the table.
function makeGrid(x, y, name) {
var tableDiv = document.getElementById("gameTable");
var table = document.createElement('table');
table.id = "theTable";
table.style.width = '100px';
table.style.border = 'thick solid black';
for (var i = 1; i <= x; i++) {
var row = table.insertRow();
row.id = "Row" + i;
for (var j = 1; j <= y; j++) {
var cell = row.insertCell();
cell.id = "R" + i + "C" + j;
cell.classList.add();
cell.style.border = '1px solid';
if((i%3) == 0)
{
cell.style.borderBottom = "thick solid black";
}
if(((j-1)%3) == 0)
{
cell.style.borderLeft = "thick solid black";
}
}
}
tableDiv.appendChild(table)
The original elements of the table I add using so the user cannot modify them.
document.getElementById("R_C_").innerHTML = "someNumber";
I tried taking the assingment of the functions out of the orinal function by adding this
for (i =1; i <= 9; i++) {
for (j = 1; j <= 9; j++) {
temp = document.getElementById('R' + i + 'C' + j);
temp.onkeyup = function(){conflictChecker(temp)};
}
}
Any help would be immensely appreciated. I've tried several different types of syntax, but they don't seem to be working.
What's happening is that the javascript is not computing the value of temp3 - it's keeping it as a variable until the function is called, and then it computes the value, which will be equal to what it was during the very last iteration...
Did you try this?
temp2.onkeyup = function(){conflictChecker(this.parent)};
I solved my problem. For some reason using the onkeyup function for my event wasn't working. I switched it to onchange() and was able to get the current cell by passing in 'this'
for (i = 1; i <=9; i++)
{
for (j = 1; j <= 9; j++) {
temp = document.getElementById('R'+i+'C'+j);
if (temp.innerHTML == "")
{
var temp2 = temp.appendChild(document.createElement("input"));
temp2.type = "number";
temp2.id = 'R'+i+'C'+j+'2';
temp2.onchange = function(){conflictChecker(this)};
}
else
{
theVal = temp.innerHTML;
temp.value = theVal;
temp.id = 'R'+i+'C'+j+'2';
}
}
}
I assigned different Id's as well so that I could look up the value of the cell from conflictChecker. Probably not the most elegant solution but it works.
Related
This block of code is to create 3 arrays with the values pulled from the user's input in a popup menu in the HTML file, but the values here are needed to fill in the table below.
var arrM = new Array; var arrT = new Array; var arrA = new Array;
arrM[0] = mod0.mod.value; arrT[0] = mod0.target.value; arrA[0] = mod0.actual.value;
arrM[1] = mod1.mod.value; arrT[1] = mod1.target.value; arrA[1] = mod1.actual.value;
arrM[2] = mod2.mod.value; arrT[2] = mod2.target.value; arrA[2] = mod2.actual.value;
arrM[3] = mod3.mod.value; arrT[3] = mod3.target.value; arrA[3] = mod3.actual.value;
arrM[4] = mod4.mod.value; arrT[4] = mod4.target.value; arrA[4] = mod4.actual.value;
arrM[5] = mod5.mod.value; arrT[5] = mod5.target.value; arrA[5] = mod5.actual.value;
arrM[6] = mod6.mod.value; arrT[6] = mod6.target.value; arrA[6] = mod6.actual.value;
arrM[7] = mod7.mod.value; arrT[7] = mod7.target.value; arrA[7] = mod7.actual.value;
arrM[8] = mod8.mod.value; arrT[8] = mod8.target.value; arrA[8] = mod8.actual.value;
arrM[9] = mod9.mod.value; arrT[9] = mod9.target.value; arrA[9] = mod9.actual.value;
the code in between the block above and the block below(not shown here) is just to compute the average values and does not interact with the block below
the code below is to create a table with the same number of rows as the number of rows the user filled in the popup menu.
var tableGenerator = document.getElementById("tableGenerator");
tbl = document.createElement('table');
tbl.style.width = '500px';
tbl.style.height = '100px';
tbl.style.border = '1px solid black';
tbl.style.margin = '50px';
tbl.style.float = 'left';
if (j < 6) {
j = 6;
}
for (var a = 0; a < j+1; a++) {
var tr = tbl.insertRow();
for (var b = 0; b < 3; b++) {
if (a == j && b == 3) {
break;
} else {
var td = tr.insertCell();
td.appendChild(document.createTextNode(""));
td.style.border = '1px solid black';
if (a == 0 && b == 0) {
var newtext = document.createTextNode(Text);
var celltext = "Year " + year.value + " Semester " + semester.value;
td.appendChild(document.createTextNode(celltext));
td.setAttribute('colSpan', '3'); break;
}
//this else block below here obviously doesn't work, but this idea is there and I want something that
//works like the pseudo code below
else {
for (a = 1; a < j; a++) {
tbl[a][0] = arrM[a];
tbl[a][1] = arrT[a];
tbl[a][2] = arrA[a];
}
}
}
}
}tableGenerator.appendChild(tbl);
I am very unfamiliar with HTML/JS/CSS, is it possible for us to access cell values of a table as if it is an array? or is there any better way to do this?
In JavaScript you'll need to either create text nodes and assign the content of that node, or assign the content to the textContent, innerText or innerHTML properties to give the table cells their values.
td.textContent = 'Hello'; // This is the preferred property for text.
The help you achieve this it would be wise to structure your data in a way that you can loop over, because you're basically doing the same thing in a specific order. For example:
var data = [
arrM,
arrT,
arrA
];
This will put your arrays in another array. Now you can loop over the data array and create a table row for each array, and a table cell for each item in the nested array.
for (var i = 0; i < data.length; i++) {
// ... create table row.
for (var j = 0; j < data[i].length; j++) {
// ... create table cell and assign textContent property.
}
}
Examine the example below. It's a runnable version of the thing I've explained above. I hope it helps you out.
function createTable(headers, values) {
var table = document.createElement('table');
// Build <thead>
var tableHeader = table.createTHead();
// Create <tr> inside <thead>
var tableHeaderRow = tableHeader.insertRow();
for (var i = 0; i < headers.length; i++) {
// Create <th>
var tableHeaderCell = document.createElement('th');
// Set text of <th> to value in array.
tableHeaderCell.textContent = headers[i];
// Add <th> to <tr> inside <thead>
tableHeaderRow.appendChild(tableHeaderCell);
}
// Build <tbody>
var tableBody = table.createTBody();
for (var j = 0; j < values.length; j++) {
// Create <tr> inside <tbody>
var tableBodyRow = tableBody.insertRow();
for (var k = 0; k < values[j].length; k++) {
// Create <td> inside <tr>
var tableBodyCell = tableBodyRow.insertCell();
// Set text of <td> to value in array.
tableBodyCell.textContent = values[j][k];
}
}
// Add <table> to the <body>
document.body.appendChild(table);
}
var titles = [
'One',
'Two',
'Three'
];
var characters = [
['Batman', 'Robin', 'Batgirl'],
['Joker', 'Two-Face', 'Poison Ivy'],
['James Gordon', 'Alfred Pennyworth', 'Clayface']
];
createTable(titles, characters);
i'm bulding a simon game as a student work project in school. i bulit the "card game "Dynamically by entering cell's to a table in pure js now i would want to make the "card game " to flash in a Random Sequence so i had created a random var and add a classList to evry random but here is the problem
1) i would want to creat a random array to compare between the users array when playing and it seems that i cant do a classLiss.add() to it
2)i would want to "flash" the "cards game" that evry time it will flash once and NOT at the same time (and also at the first turn it will flashh once and at the second turn it will flash Twice {not on the same time.exc}) i did use a setTimeout function to remove classList
Here is the code for "card display" and random function:
function cards(user) {
userchioce = parseInt(user.value);
if (userchioce == 4) {
var table = document.getElementById("mytable");
document.getElementById("mytable").innerHTML = "";
for (var i = 0; i < 2; i++) {
var row = table.insertRow(0);
for (var j = 0; j < 2; j++) {
var cell = row.insertCell(-1);
}
}
var t = document.getElementById("mytable");
var idnum = 0;
counter = 0;
for (var r = 0; r < t.rows.length; r++) { //luop at length of rows
for (var c = 0; c < t.rows[r].cells.length; c++) { //luop at length of rows and cells
t.rows[r].cells[c].style.backgroundColor = colorarry[counter];
t.rows[r].cells[c].innerHTML = colorarry1[counter];
t.rows[r].cells[c].setAttribute("class", "td1");
t.rows[r].cells[c].setAttribute("id", "tdd" + idnum++);
counter++;
}
}
}
counter = 0;//end of if 4
function getrandom(rnd) {
rnd = Math.floor(Math.random() * userchioce);
var id = "tdd";
var fullid = id + rnd;
var dispaly = document.getElementById(fullid);
dispaly.classList.add("flash");
{
setTimeout(function () {
dispaly.classList.remove("flash");
}, 850);
}
}
Alright, let's clean up a little first. You are creating looping to create the cells, then looping again to modify them, you should just modify them right away.
if (userchioce == 4) {
var table = document.getElementById("mytable");
document.getElementById("mytable").innerHTML = "";
var idnum = 0;
for (var i = 0; i < 2; i++) {
var row = table.insertRow(0);
for (var j = 0; j < 2; j++) {
var cell = row.insertCell(-1);
cell.style.backgroundColor = colorarry[idnum];
cell.innerHTML = colorarry1[idnum];
cell.setAttribute("class", "td1");
cell.setAttribute("id", "tdd" + idnum++);
}
}
}
I've also removed the counter variable in favour to the idnum variable. They were both defined at 0 at the same place, and also incremented at the same pace...
You do not get to display the lights one after the other because you only do it once. There should be a place where you keep track of the previous randoms.
var moves = [];
function newTurn() {
var rnd = Math.floor(Math.random() * userchioce);
// Add the new random to the moves history.
moves.push(rnd);
//create a copy, we'll be playing with it.
var movesToShow = moves.slice();
showMove();
}
function showMove(moveList){
//Remove first value of the list of moves and use it to show.
var move = moveList.shift();
var id = "tdd";
var fullid = id + move;
var display= document.getElementById(fullid);
display.classList.add("flash");
//Wait a little before removing the hightlight.
setTimeout(function () {
display.classList.remove("flash");
if(moveList.length>0){
//There are more moves, wait just a little
setTimeout(function(){
//Display a new move.
showMove(moveList);
},100);
}
}, 850);
}
// call this to start a new turn.
newTurn();
Also, I would like to urge you to correct all the typos in your script. "dispaly","userchioce" this will make things very hard for you to follow.
How to ensure i have a dynamic increment of Alphabets in a new cell on left side, next to each cell in a row which is dynamically created based on the option chosen in Select. This newly generated alphabet will be considered as bullet points/serial number for that particular row's text box.
jsfiddle
js code
$(document).ready(function(){
var select = $("#Number_of_position"), table = $("#Positions_names");
for (var i = 1; i <= 100; i++){
select.append('<option value="'+i+'">'+i+'</option>');
}
select.change(function () {
var rows = '';
for (var i = 0; i < $(this).val(); i++) {
rows += "<tr><td><input type='text'></td></tr>";
}
table.html(rows);
});
});
html
<select id="Number_of_position">
</select> <table id="Positions_names">
</table>
This is essentially a base26 question, you can search for an implementation of this in javascript pretty easily - How to create a function that converts a Number to a Bijective Hexavigesimal?
alpha = "abcdefghijklmnopqrstuvwxyz";
function hex(a) {
// First figure out how many digits there are.
a += 1; // This line is funky
var c = 0;
var x = 1;
while (a >= x) {
c++;
a -= x;
x *= 26;
}
// Now you can do normal base conversion.
var s = "";
for (var i = 0; i < c; i++) {
s = alpha.charAt(a % 26) + s;
a = Math.floor(a/26);
}
return s;
}
So you can do
$(document).ready(function(){
var select = $("#Number_of_position"), table = $("#Positions_names");
for (var i = 1; i <= 100; i++){
select.append('<option value="'+i+'">'+i+'</option>');
}
select.change(function () {
var rows = '';
for (var i = 0; i < $(this).val(); i++) {
rows += "<tr><td>" + hex(i) + "</td><td><input type='text'></td></tr>";
}
table.html(rows);
});
});
Heres the example http://jsfiddle.net/v2ksyy7L/6/
And if you want it to be uppercase just do
hex(i).toUpperCase();
Also - this will work up to any number of rows that javascript can handle
if i have understood you correctly, that's maybe what you want:
http://jsfiddle.net/v2ksyy7L/3/
I have added an array for the alphabet:
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
and then added the output to your "render" loop:
rows += "<tr><td>" + alphabet[i] + " <input type='text'></td></tr>";
I want to add a new image in each cell of the new table and give it the same source as the old table, and then make it clickable. Firstly, I did this:
function showData() {
if (localStorage.getItem(name) !== null) {
var showme = localStorage.getItem(name);
alert("I got the table");
var newTable = document.createElement('table');
newTable.innerHTML = showme;
newTable.id = "newTable";
newNumRows = newTable.getElementsByTagName('tr').length;
newNumCells = newTable.getElementsByTagName('td').length;
newNumCols = newNumCells / newNumRows;
alert(newNumRows);
alert(newNumCells);
alert(newNumCols);
var newImages = newTable.getElementsByTagName('img');
for (var i = 0; i < newImages.length; i += 1) {
var picSource = newImages[i]['src'];
console.log(picSource);
}
function addNewImage(newNumCols) {
var newImg = new Image();
newImg.src = picSource;
col.appendChild(newImg);
newImg.onclick = function() {
alert("WOW");
};
}
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
col = row.insertCell(-1);
addNewImage(newNumCols);
}
}
var showIt = document.getElementById('holdTable');
showIt.appendChild(newTable);
}
}
This works to a certain extent, but, unfortunately, only the last image was displaying. So, I did a bit of looking around and I think it has to do with closure (apologies for any duplication), but it's a concept I am really struggling to understand. So then I tried this:
function showData() {
if (localStorage.getItem(name) !== null) {
hideTaskForm();
var showme = localStorage.getItem(name);
var oldTable = document.createElement('table');
oldTable.innerHTML = showme;
newTable = document.createElement('table');
newTable.id = "newTable";
var i, r, c, j;
newNumRows = oldTable.getElementsByTagName('tr').length;
newNumCells = oldTable.getElementsByTagName('td').length;
newNumCols = newNumCells / newNumRows;
var newTableCells = newTable.getElementsByTagName('td');
var getImages = oldTable.getElementsByTagName('img');
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
makeNodes = row.insertCell(-1);
}
}
for (var j = 0; j < newTableCells.length; j++) {
var theNodeImage = document.createElement("img");
newTableCells[j].appendChild(theNodeImage);
alert(newTableCells[j].innerHTML); //This gives me img tags
}
for (i = 0; i < getImages.length; i += 1) {
var oldSource = getImages[i]['src']; //gets the src of the images from the saved table
console.log(oldSource);
//alert(oldSource);//successfully alerts the image paths
var newPic = new Image(); //creates a new image
(function(newPic, oldSource) {
newPic.src = oldSource;
alert(newPic.src); //gives the same image paths
newTable.getElementsByTagName('img').src = newPic.src; //This doesn't work - table is blank???
})(newPic, oldSource);
}
var showIt = document.getElementById('holdTable');
showIt.appendChild(newTable);
}
}
Now, this doesn't throw any errors. However, nor does it fill the table. It does give me the source and I think I have created the new image objects to attach to the img tags in the newTableCells, but the table is showing up blank. I don't know where I am going wrong. All help really welcome.
Note: Even as a hobbyist, even I know there are probably tons of more efficient ways to do this, but I purposely did it this way to try and help me understand the logic of each step I was taking.
In your code you have:
var newImages = newTable.getElementsByTagName('img');
for (var i = 0; i < newImages.length; i += 1) {
var picSource = newImages[i]['src'];
console.log(picSource);
}
At the end of this, picSource has the value of the last image's src attribute. Then there is:
function addNewImage(newNumCols) {
var newImg = new Image();
newImg.src = picSource;
col.appendChild(newImg);
newImg.onclick = function() {
alert("WOW");
};
}
A value is passed to newNumCols but not used in the function. The value of picSource comes from the outer execution context and is not changed, so it's still the last image src from the previous for loop.
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
col = row.insertCell(-1);
addNewImage(newNumCols);
}
}
This loop just keeps calling addNewImage with a single parameter that isn't used in the function, so you get the same image over and over.
For the record, the addNewImage function does have a closure to picSource, but it also has a closure to all the variables of the outer execution contexts. This isn't the issue, though it perhaps masks the fact that you aren't setting a value for picSource on each call, so you get the left over value from the previous section of code.
You haven't provided any indication of the content of showme, so it's impossible to determine if this approach will work at all.
Note
Where you have:
var showme = localStorage.getItem(name);
alert("I got the table");
var newTable = document.createElement('table');
newTable.innerHTML = showme;
newTable.id = "newTable";
IE does not support setting the innerHTML property of table elements, though you can create an entire table as the innerHTML of some other element and set the innerHTML of a cell (tr, th). If you want to use this approach, consider:
var div = document.createElement('div');
div.innerHTML = '<table id="newTable">' + showme + '<\/table>';
var newTable = div.firstChild;
I have stucked with this for days now.
I have a JavaScript function that creates a 10x10 table with 100 images in each td elements. At the creation of these images, I add an onclick event listener to them with a parameter of their ID number. When these images are clicked, they should pop up an alert with their ID number in content. However, the alert message shows me "[object MouseEvent]" instead. I don't have an idea what causes that. I've been searching on w3schools, stackoverflow and other blogs, but not much success so far.
This is the JS code:
function orbClicked(orb) {
alert(orb);
}
function initField() {
var table = document.getElementById("gameField");
for (var i = 0; i < 10; i++) {
var tr = document.createElement("tr");
for (var j = 0; j < 10; j++) {
var td = document.createElement("td");
var orbNumber = i * 10 + j;
var orbImage = document.createElement("img");
orbImage.setAttribute("src", "images/orb_empty.png");
orbImage.setAttribute("id", "orb" + orbNumber);
orbImage.addEventListener("click", function(orbNumber) {orbClicked(orbNumber)}, false);
td.appendChild(orbImage);
tr.appendChild(td);
}
table.appendChild(tr);
}
}
Thank you in advance for your help!
function orbClicked(orb) {
alert(orb);
}
function initField() {
var table = document.getElementById("gameField");
for (var i = 0; i < 10; i++) {
var tr = document.createElement("tr");
for (var j = 0; j < 10; j++) {
var td = document.createElement("td");
var orbNumber = i * 10 + j;
var orbImage = document.createElement("img");
orbImage.setAttribute("src", "images/orb_empty.png");
orbImage.setAttribute("id", "orb" + orbNumber);
orbImage.addEventListener("click", function() {orbClicked(this.id)}, false);
td.appendChild(orbImage);
tr.appendChild(td);
}
table.appendChild(tr);
}
}
don't pass the id variable in run time function (callback), because it will not be available at run time. Just fetch the id at run time and pass , so "this.id" wil give the id of clicked image.