How to ignore toggling the highlight of freespace in Javascript bingo? - javascript

I'm building a "buzzword bingo" game and am having difficulty with ignoring the onClick for the freespace which should always remain highlighted. I am using Javascript to build the table for me, so applying the css isn't coming easy to me. Here is the js:
function calcRowSize(words) {
return Math.sqrt(words.length);
}
function isEndOfRow(rowSize, index) {
return Number.isInteger(index + 1 / rowSize);
}
function isStartOfRow(rowSize, index) {
return Number.isInteger(index / rowSize);
}
function isFreeSpace(wordCount, index) {
var freeSpaceIndex = Math.floor(wordCount / 2);
return freeSpaceIndex == index;
}
function insertData(words) {
var table = document.getElementById("table");
table.innerHTML=""; // Initialize the table
var tr=""; // Intitialize the table row
var rowSize = calcRowSize(words);
words.forEach((word, index) => {
// Handle 4 scenarios:
// - [start of row] start table row & insert table data
// - [end of row] insert table data & end table row
// - [is the free space] insert blank table data
// - [middle of row] insert table data
if (isStartOfRow(rowSize, index)) {
tr+= '<tr>' ;
tr+= '<td>' + word + '</td>';
} else if (isEndOfRow(rowSize, index)) {
tr+= '<td>' + word + '</td>';
tr+= '</tr>';
} else if (isFreeSpace(words.length, index)) {
tr+= '<td><img src="images/paw.svg"></td>';
} else {
tr+= '<td>' + word + '</td>';
}
// tr+= '<tr>';
// tr+= '<td>' + word + '</td>';
// tr+= '</tr>';
});
table.innerHTML += tr;
}
insertData(shuffle(words));
// Toggle highlighted cells
table.onclick = function(event) {
highlight(event.target);
};
function highlight(td) {
td.classList.toggle('highlight');
}
What is the best way to go about achieving this?

Related

Sorting table using only Javascript

I have this table in which I read the tbody contents from a JSON API and now I need to make it sortable by columns and using only javascript and no Jquery.
Any help would be appreciated
i have found this code which is exactly what i want, but i don't know how to refer to tbodies from my api
var myRequest = new XMLHttpRequest();
myRequest.open('GET', 'https://jsonplaceholder.typicode.com/todos');
myRequest.onload = function () {
var myData = JSON.parse(myRequest.responseText);
dataTable(myData);
};
myRequest.send();
function dataTable(data) {
if (data.length > 0) {
var temp = '';
data.forEach((u) => {
temp += '<tr>';
temp += "<td style='text-align: center'>" + u.userId + '</td>';
temp += "<td style='text-align: center'>" + u.id + '</td>';
temp += '<td>' + u.title + '</td>';
temp += "<td style='text-align: center'>" + u.completed + '</td></tr>';
document.getElementById('data').innerHTML = temp;
});
}
}
<table class="table_id">
<thead>
<tr>
<th>UserID</th>
<th>ID</th>
<th>Title</th>
<th>Completion</th>
</tr>
</thead>
<tbody id="data">
</tbody>
</table>
var myData, asc = {'userId':true, 'id':true, 'title':true, 'completed':true};
var myRequest = new XMLHttpRequest();
myRequest.open('GET', 'https://jsonplaceholder.typicode.com/todos');
myRequest.onload = function () {
myData = JSON.parse(myRequest.responseText);
dataTable(myData);
};
myRequest.send();
function sortTable(key){
myData.sort(function(a, b) {
if(asc[key]){
return a[key] > b[key]? 1:-1;
}
else{
return a[key] > b[key]? -1:1;;
}
});
asc[key] = !asc[key];
document.getElementById('data').innerHTML = '';
dataTable(myData);
}
function dataTable(data) {
if (data.length > 0) {
var temp = '';
data.forEach((u) => {
temp += '<tr>';
temp += "<td style='text-align: center'>" + u.userId + '</td>';
temp += "<td style='text-align: center'>" + u.id + '</td>';
temp += '<td>' + u.title + '</td>';
temp += "<td style='text-align: center'>" + u.completed + '</td></tr>';
document.getElementById('data').innerHTML = temp;
});
}
}
<table class="table_id">
<thead>
<tr>
<th onclick="sortTable('userId');">UserID</th>
<th onclick="sortTable('id');">ID</th>
<th onclick="sortTable('title');">Title</th>
<th onclick="sortTable('completed');">Completion</th>
</tr>
</thead>
<tbody id="data">
</tbody>
</table>
Here is a quick class I made.
You first load your data with dt.load(), then when someone clicks one of the headers, you can add an event that does:
elm.addEventListener("click", (e) => {
prop = e.target.textContent.trim();
dt.sort(prop);
dt.render();
})
class DataTable{
load(arr){
if(arr) this.data = arr;
}
sort(prop){
this.data.sort((a, b) => a[prop] - b[prop]);
}
render(selector="#data"){
if(data.length){
html = data.map(u => {
return [
"<tr>",
`<td style='text-align: center'>${u.userId}</td>`,
`<td style='text-align: center'>${u.id}</td>`,
`<td>${u.title}</td>`,
`<td style='text-align: center'>${u.completed}</td></tr>`
].join("");
}).join("");
document.querySelector(selector).innerHTML = html;
}
}
}
Important - are you wanting to be able to sort multiple columns at the same time or just one column at a time?
Initialize myData outside of onload first. You'll want to be able to access those results outside of onload to sort them. The actual sort function JS offers is a pretty confusing but it's really the only way to go about vanilla JS array sorting.
function sortData(col, asc = true) {
//JS sort function
myData = myData.sort((first, second) => {
//sort logic
if (first[col] == second[col]) {
return 0;
}
if (asc) {
if (first[col] > second[col]) {
return 1;
}
else {
return -1;
}
}
else {
if (first[col] > second[col]) {
return -1;
}
else {
return 1;
}
}
});
//Re-Create table
dataTable(myData);
}
EDIT:
I added in sort logic, but it's definitely possible I messed up. I can't actually test this right now and I haven't touched the sort function in years.

after refresh the page and add new data so newly added data is replaced with old data in the table [javascript]

here I'm working with localstorage in javascript
here is my code for enter productDetails in the table using a form. when i'm enter productDetails in the table and refresh the page the entered data is in the table because of localStorage. but my problem is that when I refresh the page and again add new data so that newly added data is replaced with data which is added before refresh the page. and I want all my data instead of replacing
let productDetails = {
};
/**
* this function is for get the value from form
*/
function getValue() {
let id = document.getElementById('productId').value;
let partNo = document.getElementById('productNo').value;
let productName = document.getElementById('productName').value;
let size = getRadioValue();
let color = getCheckBoxValue();
let description = document.getElementById('description').value;
let date = document.getElementById('date').value;
let address = document.getElementById('address').value;
let companyName = document.getElementById('companyName').value;
return {
id, partNo, productName, size, color, description, date, address, companyName
};
}
/**
* function to insert data into table
*/
function insertion() {
let value = getValue();
let letter = value.productName[0];
if (!productDetails.hasOwnProperty(letter)) {
productDetails[letter] = [];
}
let object = {
weight: value.weight, id: value.id, partNo: value.partNo, productName: value.productName, size: value.size, color: value.color, description: value.description,
companyDetails: {
date: value.date,
address: value.address,
companyName: value.companyName
}
};
JSON.parse(window.localStorage.getItem('productDetails'));
productDetails[letter].push(object);
localStorage.setItem("productDetails", JSON.stringify(productDetails));
displayData();
message("");
}
/**
* this function display the data in table
*/
function displayData() {
objectArray = Object.values(productDetails);
display(objectArray);
}
/**
* function to display table
*/
function display() {
var result = JSON.parse(window.localStorage.getItem("productDetails"));
console.log(result)
messageTable(" ");
let table = "<table border = 1 cellpadding = 10 ><th colspan=7 >Product Details</th><th colspan=7 >company Details</th><tr><th>weight</th><th>Product Id</th><th>Part No</th><th>Name</th><th>Size</th><th>Color</th><th>Description</th><th>Date</th><th>Address</th><th>Company name</th></tr>";
for (var key in result) {
for (var weight in result[key]) {
//let companyDetails = result[key][weight].companyDetails ? result[key][weight].companyDetails : { date: "", address: "", companyName: "" };
table += "<tr><td>" + key + "</td>";
table += "<td>" + result[key][weight].id + "</td>";
table += "<td>" + result[key][weight].partNo + "</td>";
table += "<td>" + result[key][weight].productName + "</td>";
table += "<td>" + result[key][weight].size + "</td>";
table += "<td>" + result[key][weight].color + "</td>";
table += "<td>" + result[key][weight].description + "</td>";
table += "<td>" + result[key][weight].companyDetails.date + "</td>";
table += "<td>" + result[key][weight].companyDetails.address + "</td>";
table += "<td>" + result[key][weight].companyDetails.companyName + "</td>";
}
} messageTable(table);
console.log(result)
}
What you need to do is add a check looking for the localstorage key for your data when the page loads, if the check is true then add the previous localstorage data to your productDetails object. This is the Example =>
window.onload = init;
var arr = [];
function init() {
if(localStorage.getItem("productDetails")) {
arr.push(JSON.parse(localStorage.getItem("productDetails")));
getValue(); /*Then Continue eg.Refer to a function*/
}
else {
getValue(); /*Do something eg.Refer to a function*/
}
}
The concept is when the page loads add a window.onload function to check whether the localStorage key "productDetails" exists. If the key exist then add/push the value stored by the key to the array arr in this example. If it does not exist then eg. Do something like => Refer to a function.

How to generate Dynamic button in a table row and open new page on button click

i actually having a requirement of generating dynamic table from services url and after that generating dynamic table.This is i worked it out but what i want is
How to generate a dynamic button on each table row with click event.
After generating the button how we can assign click events to the button i mean suppose in a table there are four columns like date,id number,name,location and on the clicking on the each column or related to that cell it has to redirect to a new page.
or
if a table row is clicked and there are 4 columns are there like date,id number,name,location the click event has will take date as a parameter and click event function and then it have to proceed to the next page/redirect
$('#btn_Day').click(function () {
var ex = document.getElementById("dpp_info");
var clOptions = ex.options[ex.selectedIndex].value;
var clOptions1 = ex.options[ex.selectedIndex].text;
var dt = todaydate;
var dt1 = todaydate;
$.ajax({
type: 'GET',
url: xxxxx.xxxxx.xxxxx,
data: frmDate_=" + dt + "&toDate_=" + dt1 + "",
success: function (resp) {
var Location = resp;
var tr;
for (var i = 0; i < Location.length; i++) {
tr = tr + "<tr>";
tr = tr + "<td style='height:20px' align='left'>" + Location[i].Name + "</td>";
tr = tr + "<td style='height:20px' align='left'>" + Location[i].Date + "</td>";
tr = tr + "<td style='height:20px' align='left'>" + Location[i].IdNum + "</td>";
tr = tr + "</tr>";
};
document.getElementById('Wise').innerHTML = "<table class='r'>" + "<tr><thead ><th style='height:20px'>Location</th>"
+ "<th style='height:20px'>Date</th>" + "<th style='height:20px'>Id Num</th>" + "</tr></thead>"
+ tr +
"<tr></tr>" +
"</table>";
document.getElementById('Wise').childNodes[0].nodeValue = null;
},
error: function (e) {
window.plugins.toast.showLongBottom("Please Enable your Internet connection");
}
});
});
now in the image if u see there are four columns suppose if i click on the idnumb and there records related to that particular number has to be displayed in separate page
Looking For Help!
After some more discussion on this the key was to just use the handler and pass any values using attributes. You can see the fiddle here
https://jsfiddle.net/p2fpbkuo/3/
$('.button-click').off();
$('.button-click').on('click', function () {
// navigate to new page
// console.log('button click')
// what you could do here is get the serialnumber which is an attribute on the button
var id = $(this).attr('data-id') // as long as this is unique this should always work
var filteredResults = results.filter(function (result) {
if (result.SerialNumber.toString() === id.toString()) {
return result;
}
});
var selectedRowValues = filteredResults[0];
// this will contain all the values for that row
console.log(selectedRowValues)
// var dataValue = $(this).attr('data-url'); // dont't need this any more
window.open(selectedRowValues.Url)
});

datatable append html but got refreshed?

Not sure what is wrong, for me my code has the right logic. But somehow the html didn't stay after 2nd click onward. I expect my custom html would appear after the newly added tr.
my function
function appendRow(name, position, office, age, date,salary) {
var t = $('#example').DataTable();
var node = t.row.add([
name,
position,
office,
age,
date,
salary,
]).draw().node();
var detail_row = '';
detail_row = '<h3>Custom HTML</h3>';
$(node).addClass('result-row');
node = node.outerHTML += detail_row;
$(node).hide().fadeIn('normal');
}
https://jsfiddle.net/282w8yfk/
it is happening in this way because you applied sorting on the name column, so datatable being quite smart it adds the row where it needs to be... so if you want to add that in the last remove sorting option on name column...
and here is a small code change:
$(document).ready(function() {
/* Formatting function for row details - modify as you need */
function format(d) {
console.log(d);
// `d` is the original data object for the row
return '<table cellpadding="4" cellspacing="0" border="0" style="padding-left:50px;">' +
'<tr>' +
'<td>Name:</td>' +
'<td>' + d[0] + '</td>' +
'</tr>' +
'<tr>' +
'<td>Full Name:</td>' +
'<td>' + d[4] + '</td>' +
'</tr>' +
'<tr>' +
'<td>Extra info:</td>' +
'<td>And any further details here (images etc)...</td>' +
'</tr>' +
'</table>';
}
var table = $('#example').DataTable({
"columnDefs": [{
"targets": [4],
"visible": false,
"searchable": false
}]
/* the problem is here, it won't work if I enable sorting*/
});
function appendRow() {
var t = $('#example').DataTable();
var node = t.row.add([
"James Bond",
"Spy", "55", "$9000", "James Bond Larry"
]).draw().node();
console.log(node);
$(node).addClass('result-row').hide().fadeIn('normal');
};
$('#add').click(function() {
appendRow();
});
$('#example tbody').on('click', '.result-row', function() {
var tr = $(this).closest('tr');
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
} else {
// Open this row
row.child(format(row.data())).show();
tr.addClass('shown');
}
});
});
reference 1 - sort
reference 2 - row.add

Creating html table using Javascript not working

Basically, I want the user the just change the 'height' variable to how ever many rows he wants, and then store the words which each td in the row should contain, and the code should then generate the table.
My html is just this:
<table id="newTable">
</table>
This is my Javascript:
<script type="text/javascript">
var height = 2; // user in this case would want 3 rows (height + 1)
var rowNumber = 0;
var height0 = ['HeadingOne', 'HeadingTwo']; // the words in each td in the first row
var height1 = ['firstTd of row', 'secondTd of row']; // the words in each td in the second row
var height2 = ['firstTd of other row', 'secondTd of other row']; // the words in each td in the third row
$(document).ready( function() {
createTr();
});
function createTr () {
for (var h=0; h<height + 1; h++) { // loop through 3 times, in this case (which h<3)
var theTr = "<tr id='rowNumber" + rowNumber + "'>"; // <tr id='rowNumber0'>
$('#newTable').append(theTr); // append <tr id='rowNumber0'> to the table
for (var i=0; i<window['height' + rowNumber].length; i++) {
if (i == window['height' + rowNumber].length-1) { // if i==2, then that means it is the last td in the tr, so have a </tr> at the end of it
var theTd = "<td class='row" + rowNumber + " column" + i + "'>" + window['height' + rowNumber][i] + "</td></tr>";
$('#rowNumber' + rowNumber).append(theTr); // append to the end of the Tr
} else {
var theTd = "<td class='row" + rowNumber + " column" + i + "'>" + window['height' + rowNumber][i] + "</td>";
$('#rowNumber' + rowNumber).append(theTr);
}
}
rowNumber += 1;
}
}
</script>
I did 'alert(theTr);' and 'alert(theTd);' and they looked correct. How come this code doesn't generate any table?
You should change the line
$('#rowNumber' + rowNumber).append(theTr);
into
$('#rowNumber' + rowNumber).append(theTd);
You are adding the Tr-Code again in the inner loop, but you actually wanted to add the Td-Code.
All that window["height"+rowNumber] stuff is a poor way to do it. Use an array, and pass it as a parameter to the function so you don't use global variables. And use jQuery DOM creation functions instead of appending strings.
<script type="text/javascript">
var heights = [['HeadingOne', 'HeadingTwo'], // the words in each td in the first row
['firstTd of row', 'secondTd of row'], // the words in each td in the second row
['firstTd of other row', 'secondTd of other row'] // the words in each td in the third row
];
$(document).ready( function() {
createTr(heights);
});
function createTr (heights) {
for (var h=0; h<heights.length; h++) { // loop through 3 times, in this case (which h<3)
var theTr = $("<tr>", { id: "rowNumber" + h});
for (var i=0; i<heights[h].length; i++) {
theTr.append($("<td>", { "class": "row"+h + " column"+i,
text: heights[h][i]
}));
}
$('#newTable').append(theTr); // append <tr id='rowNumber0'> to the table
}
}
</script>
JSFIDDLE

Categories

Resources