How to break text in dynamically added row in my table? - javascript

I created table which's effect you can see there:
https://imgur.com/88vcLE6
The problem is that, when i have long "text info" the table is getting wider instead of text being broken and getting into new line and row geting extended(elongated).
Problem shown here:
https://imgur.com/3w5V03r
even when i added \n in text in moments I wanted it to break.
let newText = document.createTextNode('TEXT INFO AND VERY LONG TEXT INFO \n THAT SHOULD MAKE THE TABLE \n THE SAME THICKNESS BUT LONGER');
I read also about str.split() method but I do not know if it's suitable here.
Additionaly, I went through idea to create new table instead of row that would be formatted the way I want basing on:
Insert Table Inside a Row
How to append a childnode to a specific position
But it seems to be too sophisticated to use it there, but I cannot think of simpler solution here.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>...::: Multicast :::...</title>
<link rel="stylesheet" type="text/css" href="multicast.css">
<script src="js/jquery.min.js"></script>
<script src="js/jquery.sortElements.js"></script>
</head>
<body>
<?php
$provider = "Test_provider";
echo '<table id="my-table">';
echo '<tr><th colSpan = "3">INPUT ROW MULTICAST</th></tr>';
echo '<tr><th id="sort11">Sort A</th><th id="sort11">Sort B</th><th id="sort11">Sort C</th></tr>';
for($counter = 0; $counter <= 9; $counter++){
$provider = "Test_provider";
echo' <tr id ="'.$counter.'"><td><button onclick="specialFunc()">'.$provider.'</button></td><td>Row '.$counter.' Col '.$counter.'</td><td>Row '.$counter.' Col '.$counter.'</td></tr>';
}
echo '</table>';
?>
<script>
isFirst = true;
var testTable = document.getElementById("my-table"),rIndex,cIndex;
function addRow(rIndex) {
var currPos = rIndex;
let tableRef = document.getElementById("my-table");
let newRow = tableRef.insertRow(rIndex);
newRow.id = "open row"
let newCell = newRow.insertCell(0);
newCell.colSpan = 3;
let newText = document.createTextNode('TEXT INFO');
newCell.appendChild(newText);
newRowNumb = document.getElementById("open row").rowIndex;
console.log("new row addRow:" + newRowNumb);
}
function specialFunc(){
buttFlag = true;
for(var i = 2; i < testTable.rows.length; i++)
{
for(var j = 0; j < testTable.rows[i].cells.length; j++)
{
testTable.rows[i].cells[j].onclick = function()
{
rIndex = this.parentElement.rowIndex;
cIndex = this.cellIndex;
//console.log(rIndex,cIndex);
if(buttFlag==true){
if (isFirst ){
rIndex = rIndex+1;
addRow(rIndex);
console.log("new row first call :" + newRowNumb);
isFirst = false;
currPos = rIndex;
buttFlag = false;
}
else{
if(rIndex == (currPos - 1))
temp=1
else{
if(rIndex==1){rIndex=rIndex+1;}
if(typeof currPos != "undefined"){testTable.deleteRow(currPos);}
if(rIndex < currPos){rIndex=rIndex+1;}
addRow(rIndex);
console.log("new row second call and more:" + newRowNumb);
currPos = rIndex;
buttFlag = false;
}
}
}
}
};
}
};
</script>
<script>
//var table = $('table');
var table = $('#my-table');
$('#sort11,#sort12,#sort13')
.each(function(){
var th = $(this),
thIndex = th.index(),
inverse = false;
th.click(function(){
if (typeof newRowNumb != "undefined") {
console.log("del row sort func :" + newRowNumb);
document.getElementById("my-table").deleteRow(newRowNumb);
newRowNumb = void 0;
}
table.find('td').filter(function(){
return $(this).index() === thIndex;
}).sortElements(function(a, b){
return $.text([a]) > $.text([b]) ?
inverse ? -1 : 1
: inverse ? 1 : -1;
}, function(){
// parentNode is the element we want to move
return this.parentNode;
});
//newRowNumb = void 0;
currPos = void 0;
isFirst = true;
});
});
</script>
</body>
</html>

You can solve this issue with CSS setting max-width.
Edit: Looks like for your example it would be better to change the max-midth of tr.
td {
max-width: 200px;
min-width: 150px;
word-wrap: break-word;
}
<table border="1">
<tr>
<th>Header1</th>
<td>Value</td>
</tr>
<tr>
<th>Header</th>
<td>MMMMMMMMMMMMMMMMMMMMMMMMMMMassiveValue</td>
</tr>
</table>

You can use the CSS word-break: break-word for the respective <td> where you want the breaks. You can keep the width of the <td> as per the parent element's width.
Hoping this helps.

Related

How to remove last header from the table in Javascript

I wrote a code to load data, adding and removing appended columns. However I am not able to remove the last header (of appended column). I managed to figure out to remove the first column header. Please see testing function. Is there a way to remove one cell header or removing a column with a header? The command
tbl.removeChild(tbl.firstChild);
removes only the first header of the first column. However, the code
tbl.removeChild(tbl.lastChild);
removes all data instead last header of the last appended column. What I am missing here?
Update: I managed to remove the last header but only once, next last column is removed but the header stay. Still, I am not able to solve the glitch. The code I modified is marked
Below is the complete code,
var flag1 = false;
var file = document.getElementById('inputfile');
var txtArr = [];
if (typeof(document.getElementsByTagName("table")[0]) != "undefined") {
document.getElementsByTagName("table")[0].remove();
}
// get the reference for the body
var body = document.getElementsByTagName("body")[0];
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table"),
thead = document.createElement('thead');
var tblBody = document.createElement("tbody");
file.addEventListener('change', () => {
var fr = new FileReader();
fr.onload = function() {
// By lines
var lines = this.result.split('\n');
for (var line = 0; line < lines.length; line++) {
txtArr.push(lines[line].split(" "));
}
}
fr.readAsText(file.files[0]);
});
//console.log(flag1);
// document.getElementById('output').textContent=txtArr.join("");
//document.getElementById("output").innerHTML = txtArr[0];
// console.log(txtArr[2]);
function generate_table() {
// creating all cells
if (flag1 == false) {
th = document.createElement('th'),
th.innerHTML = "Name";
tbl.appendChild(th);
th = document.createElement('th');
th.innerHTML = "Sample1";
tbl.appendChild(th);
tbl.appendChild(thead);
tbl.appendChild(tblBody);
} //endif flag1=false
else {
th = document.createElement('th');
th.innerHTML = "Sample2";
tbl.appendChild(th);
tbl.appendChild(thead);
tbl.appendChild(tblBody);
}
for (var i = 0; i < txtArr.length - 1; i++) {
// creates a table row
var row = document.createElement("tr");
for (var j = 0; j < 2; j++) {
var cell = document.createElement("td");
var cellText = document.createTextNode(txtArr[i][j]);
cell.appendChild(cellText);
row.appendChild(cell);
tblBody.appendChild(row);
}
flag1 = true;
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 2;
tbl.setAttribute("border", "2");
}
txtArr = [];
}
/////////// testing problems here /////////////////////
function testing() {
var i;
var lastCol = tbl.rows[0].cells.length - 1,
i, j;
// delete cells with index greater then 0 (for each row)
console.log(tbl.rows.length);
//while (tbl.hasChildNodes()) {
// tbl.removeChild(tbl.lastChild); // this line does not remove the last header
//}
for (i = 0; i < tbl.rows.length; i++) {
for (j = lastCol; j > lastCol - 1; j--) {
tbl.rows[i].deleteCell(j);
}
}
tbl.removeChild(thead); // this was updated
tbl.removeChild(th); // this was updated
// tbl.removeChild(tbl.firstChild); // this code remove only the first header
}
/////////// end of testing ////////////////////////////
function appendColumn() {
var i;
th = document.createElement('th');
th.innerHTML = "Sample";
tbl.appendChild(th);
tbl.appendChild(thead);
tbl.appendChild(tblBody);
// open loop for each row and append cell
for (i = 0; i < tbl.rows.length; i++) {
createCell(tbl.rows[i].insertCell(tbl.rows[i].cells.length), i, 'col');
}
}
// create DIV element and append to the table cell
function createCell(cell, text, style) {
var div = document.createElement('div'), // create DIV element
txt = document.createTextNode(text); // create text node
div.appendChild(txt); // append text node to the DIV
div.setAttribute('class', style); // set DIV class attribute
div.setAttribute('className', style); // set DIV class attribute for IE (?!)
cell.appendChild(div); // append DIV to the table cell
}
// delete table column with index greater then 0
function deleteColumn() {
var lastCol = tbl.rows[0].cells.length - 1,
i, j;
// delete cells with index greater then 0 (for each row)
console.log(tbl.rows.length);
for (i = 0; i < tbl.rows.length; i++) {
for (j = lastCol; j > lastCol - 1; j--) {
tbl.rows[i].deleteCell(j);
}
}
}
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Read Text File</title>
</head>
<body>
<input type="file" name="inputfile" id="inputfile">
<br>
<pre id="output"></pre>
<input type="button" value="Generate a table." onclick="generate_table()">
<input type="button" value="Add column" onclick="appendColumn()">
<input type="button" value="Delete column" onclick="deleteColumn()">
<input type="button" value="testing" onclick="testing()">
<table id="table">
</body>
</html>
You can loop over the rows and delete the last cell of each one.
for(const row of tbl.rows){
row.deleteCell(-1);
}
//or
[...tbl.rows].forEach(row => row.deleteCell(-1));

Javascript table with for

I'm new to Javascript and I have been trying a Javascript table with a for loop all the day. I want to get the value of a cell. I'm doing like an "Excel app". Please check what is wrong. I just fixed things in answers ....
var MatriXcel = ( function( window, undefined ) {
var matriz = [];
var matrizJson;
var row = 5;
var col = 6;
function getData(){
return matriz;
}
function addRow(){
var newCol = [];
for (var i=0; i < col; i++){
newCol.push("");
}
matriz.push(newCol);
this.draw();
}
function drawTable(){
var table = "<tr><th></th><th>A</th><th>B</th><th>C</th><th>D</th><th>E</th></tr>";
for (var i=0; i < matriz.length; i++){
table += "<tr>";
for (var x=0; x < matriz[i].length; x++){
if (x == 0){
table += "<th>"+(i+1)+"</th>";
}else{
table += "<td><input type='text' onkeyup='MatriXcel.save("+i+","+x+",this)' value='"+matriz[i][x]+"'></td>";
}
}
table += "</tr>";
}
document.getElementById("tabla").innerHTML = table;
}
function saveInfo(irow, xcol, content){
matriz[irow][xcol] = content.value;
}
function getMatch(){
var tabla = document.getElementById("tabla");
search= document.getElementById("word").value;
var re = new RegExp(search,"gi");
var row;
var col;
for (var i = 0; i< tabla.rows.length; i++){
row = tabla.rows[i];
for (var j; j<row.cells.length; j++){
col = row.cells[j];
if(re.test(row.textContent)){
row.style.color="rgb(239, 19, 109)";
alert(row.textContent);
}else if(re.test(col.textContent)){
col.style.color="rgb(79, 2, 133)";
}
}
}
}
function saveLocal(){
matrizJson = JSON.stringify(matriz);
console.log(matrizJson);
window.localStorage.table = matrizJson;
// matrizJson = JSON.parse(matrizJson);
// console.log(matrizJson);
}
function init(){
if(typeof window.localStorage.table === 'string'){
matriz = JSON.parse(window.localStorage.table);
this.draw();
}
}
return {
addRow : addRow,
draw : drawTable,
save : saveInfo,
get : getData,
local : saveLocal,
init : init,
search : getMatch,
};
} )( window );
if (window.localStorage.length == 0){
MatriXcel.addRow();
MatriXcel.addRow();
MatriXcel.addRow();
MatriXcel.addRow();
MatriXcel.addRow();
}else{
MatriXcel.init();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ExcelApp</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<input type="search" value="" placeholder="write here" id="word">
<input type="button" value="Search" id="trigger" onclick="MatriXcel.search()">
<table id="tabla">
</table>
</body>
<script type="text/javascript" src="script.js"></script>
</html>
It seems there is an issue with your way of checking regular expression.
For example, in place of this
if(re == row.value){
it should be
if(re.test(row.value)){
Additionally, please update the code as suggested by #Teemu in the comments
you've to check for col.textContent or col.innerHTML, not row.value

Uncaught TypeError: Cannot read property 'rowIndex' of undefined

When I click each cell it will give the column, but not the row. I believe that somehow I am unable to access the parentNode, which should be td, so that I can get the correct row number.
Here is my javascript code:
function getBoard(rows, cols)
{
var board="";// ="<table>";// id=myTableId>"; //add this
var switch1 = 0;
for (x=0; x<rows; x++)
{
board +="<tr>";
for (y=0; y<cols;y++)
{
switch1 = x%2;
if (y%2 == switch1)
board +="<td class=\"" + "td1\">" ;
else
board +="<td class=\"" + "td2\">";
}
board +="</tr>";
}
return board;
}
function setEvents()
{
var cells= document.getElementsByTagName("td");
for (var x = 0; x<cells.length; x++)
{
cells[x].onclick=function () {
var col = this.cellIndex;
var row = this.ParentNode.rowIndex;
alert (row);
var info1=document.getElementById("coordinates");
var row = this.ParentNode.rowIndex;
info1.innerHTML="\"" + row +"\"";
};
}
}
window.onload = function()
{
var divGrid = document.getElementById("myTableId");
var board = getBoard(8,8);
//divGrid.innerHTML ="debug information";
divGrid.innerHTML = board;
setEvents();
}
and here is my html:
<!DOCTYPE html>
<title> Chessboard </title>
<head>
<link rel="stylesheet" href="styles.css">
<script src="view.js"></script>
<script src="model.js"></script>
</head>
<body >
<table id="myTableId">
<div id ="gridDiv"> </div>
</table>
<div id = "coordinates"></div>
</body>
yeah parentNode was ParentNode! I guess I'll need to get use to javascripts vague answers.

Hiding columns in table JavaScript

This script stops working the moment I add a table inside a table, so how to get it worked?
I don't need any jQuery solutions, I want pure JavaScript. Here's my script found on the Internet:
<script>
function show_hide_column(col_no, do_show) {
var stl;
if (do_show) stl = 'block'
else stl = 'none';
var tbl = document.getElementById('id_of_table');
var rows = tbl.getElementsByTagName('tr');
for (var row=1; row<rows.length;row++) {
var cels = rows[row].getElementsByTagName('td')
cels[col_no].style.display=stl;
}
}
</script>
Here's my HTML:
<table id='id_of_table' border=1>
<tr><td colspan="4"><table><tr><td></td></tr></table></td></tr>
<tr><td> 2</td><td> two</td><td> deux</td><td> zwei</td></tr>
<tr><td> 3</td><td> three</td><td> trois</td><td> drei</td></tr>
<tr><td> 4</td><td> four</td><td>quattre</td><td> vier</td></tr>
<tr><td> 5</td><td> five</td><td> cinq</td><td>fünf</td></tr>
<tr><td> 6</td><td> six</td><td> six</td><td> sechs</td></tr>
</table>
And here's my Form:
<form>
Enter column no: <input type='text' name=col_no><br>
<input type='button' onClick='javascript:show_hide_column(col_no.value, true);' value='show'>
<input type='button' onClick='javascript:show_hide_column(col_no.value, false);' value='hide'>
</form>
You can leverage the col tag and then the solution is straightforward using only vanilla JavaScript. The col tag has only a few CSS attributes, but visibility is one of them:
function show_hide_column( col_no, do_show ){
const table = document.getElementById( 'id_of_table' )
const column = table.getElementsByTagName( 'col' )[col_no]
if ( column ){
column.style.visibility = do_show?"":"collapse";
}
}
const btnHide = document.getElementById( 'btnHide' )
btnHide.addEventListener( "click", () => show_hide_column( 2, false ))
const btnShow = document.getElementById( 'btnShow' )
btnShow.addEventListener( "click", () => show_hide_column( 2, true ))
<table id='id_of_table' border=1>
<col class="col1"/>
<col class="col2"/>
<col class="col3"/>
<col class="col4"/>
<tr><td colspan="4"><table><tr><td></td></tr></table></td></tr>
<tr><td> 2</td><td> two</td><td> deux</td><td> zwei</td></tr>
<tr><td> 3</td><td> three</td><td> trois</td><td> drei</td></tr>
<tr><td> 4</td><td> four</td><td>quattre</td><td> vier</td></tr>
<tr><td> 5</td><td> five</td><td> cinq</td><td>fÜnf</td></tr>
<tr><td> 6</td><td> six</td><td> six</td><td> sechs</td></tr>
</table>
<button id="btnHide">hide French</button>
<button id="btnShow">show French</button>
References:
col
visibility on quirksmode
You could use children and check their tagName to make sure they're td's. Something like this:
function show_hide_column(col_no, do_show) {
var tbl = document.getElementById('id_of_table');
var rows = tbl.getElementsByTagName('tr');
for (var row = 0; row < rows.length; row++) {
var cols = rows[row].children;
if (col_no >= 0 && col_no < cols.length) {
var cell = cols[col_no];
if (cell.tagName == 'TD') cell.style.display = do_show ? 'block' : 'none';
}
}
}
Edit: Here's a working example: http://jsfiddle.net/3DjhL/2/.
Edit:
In fact, I've just remembered the rows and cols properties, which make it even simpler. See http://jsfiddle.net/3DjhL/4/ to see it in action.
function show_hide_column(col_no, do_show) {
var rows = document.getElementById('id_of_table').rows;
for (var row = 0; row < rows.length; row++) {
var cols = rows[row].cells;
if (col_no >= 0 && col_no < cols.length) {
cols[col_no].style.display = do_show ? '' : 'none';
}
}
}
Oh, and if you think the column numbers should start at 1 (which they don't), you'll have to offset that somewhere. For example at the top of show_hide_column():
col_no = col_no - 1;
The important thing here is the selector, it could be vanilla or jquery:
document.querySelectorAll('#yourtable tbody tr td:nth-child(1)').forEach(el=>el.style.display = 'none')
From the code above, the nth-child(1) selector has a 1-based index, there you define the column you want to hide ;)
I had a situation where it would have been a very big hassle to modify every single TD value and add the appropriate class name so I could toggle it. As a result I wrote some JavaScript to do that automatically. Please see the following code.
tbl = document.getElementById("Mytable")
classes = getClasses(tbl.rows[0]);
setClasses(tbl, classes);
toggleCol("col0");
toggleCol("col1");
function getClasses(row){
var cn = 0;
var classes = new Array();
for(x=0; x < row.cells.length; x++){
var cell = row.cells[x];
var c = new Column(cell.textContent.trim(), cell.offsetLeft, cell.offsetLeft + cell.offsetWidth, x);
classes[x]= c;
}
return classes;
}
function Column(name, left, right, cols) {
this.name = name;
this.left = left;
this.right = right;
this.cols = cols;
}
function setClasses(table, classes){
var rowSpans = new Array();
for(x=0; x < table.rows.length; x++){
var row = table.rows[x];
for(y=0; y < row.cells.length; y++){
var cell = row.cells[y];
for(z=0; z < classes.length; z++){
if(cell.offsetLeft >= classes[z].left && cell.offsetLeft <= classes[z].right){
cell.className = "col" + classes[z].cols;
}
}
}
}
}
function toggleCol(name){
var cols = document.getElementsByClassName(name);
for(x=0; x < cols.length; x++){
cols[x].style.display= (cols[x].style.display == 'none') ? '' : 'none';
}
}
In my example I take a look at the first row to set the top level header (In my example I had several who had colspans). It uses the offsetLeft and offsetWidth to determine the range of the top header (which in my cases has sub headers), so that all sub-columns would toggle with its parent.
Based on these values setClasses sets the appropriate classes to all the elements.
In my example I then toggle "col0" and "col1", so they would be invisible (Running the function again would make them visible again).

Adding addEventListener to a clicked table cell to change the color

I am creating a dynamic table of three columns and multiple rows. I want to be able to click the last cells in each row and have the row be selected showing a certain color. I am trying to do this as well as make sure that if another cell is selected already it will deselect. I am having a few issues not sure exactly what to do. I can create an onclick alert message that works, however no success with the bg color. Any suggestions are helpful. Function createCell should be where this is addressed.
<html>
<br/><br/></p>
<table id="my_table" align="center" cellspacing="0" cellpadding="0" border="0">
<tr>
<td>Name</td>
<td>Age</td>
<td>Sex</td>
</tr>
</table>
<p></center></p>
<script type="text/javascript" language="javascript">
function appendRow(){
var names = ["Paul", "Mike", "Linda"];
var ages = ["16", "23", "44"];
var male_female = ["M", "M", "F"];
var tbl = document.getElementById('my_table'); // table reference
// append table row
var id;
var z=1;
for(k=0;k<names.length;k++){
var row = tbl.insertRow(tbl.rows.length);
var j = tbl.rows.length - 2;
for (var i=0;i<tbl.rows[0].cells.length;i++) {
id=z++;
var cell_text = '';
if (i == 0) {
cell_text = names[j];
} else if (i == 1) {
cell_text = ages[j];
} else if (i == 2) {
cell_text = male_female[j];
}
createCell(id, row.insertCell(i), cell_text, 'row');
}
}
}
function createCell(id, cell, text, style){
var div = document.createElement('div'); // create DIV element
var txt = document.createTextNode(text); // create text node
if(id % 3 == 0)
{
cell.setAttribute('onclick', 'alert("hello")'); //for testing purposes
cell.addEventListener("click", clickCell, false);
}
div.appendChild(txt); // append text node to the DIV
div.setAttribute('class', style); // set DIV class attribute
div.setAttribute('className', style); // set DIV class attribute for IE (?!)
cell.appendChild(div); // append DIV to the table cell
}
function clickCell()
{
if(e)
e.setAttribute("bgColor","purple");
if(e != this){
e = this;
e.setAttribute("bgColor","blue");
}else{
e = null;
}
}
</script>
<BODY onload="appendRow()">
<style>
table#my_table{border-collapse:collapse;}
table#my_table td{width:50px;height:27px;border:1px solid #D3D3D3;font-size:10pt;text-align:center;padding:0;}
.append_row{background-color:#FFD6D6;border:1px #ccc solid;}
</style>
</body>
</html>
Modify the clickCell method to:
function clickCell(e) {
// clear the background of all rows
var rows = document.getElementById('my_table').rows;
for(var i = 0; i < rows.length; i++) {
rows[i].style.backgroundColor = '';
}
// set background of clicked row
this.style.backgroundColor = 'purple';
}
See an example.
In createCell change cell.setAttribute('onclick', 'alert("hello")'); to cell.setAttribute('onclick', 'alert("hello");this.parentNode.setAttribute("bgcolor", "purple")');
Figured out that if I set the clickcell function to the following, it will clear all cells that are colored. I thought I could call "this.style.backgroundColor" to change the cell color and then clear that cell with a "row.style.backgroundColor" turns out I was wrong.
function clickCell(e) {
var tr = document.getElementById('my_table').rows;
for(i=0;i<tr.length;i++)
{
for(k=0;k<tr[i].cells.length;k++)
{
tr[i].cells[k].style.backgroundColor = "";
}
}
this.style.backgroundColor = "blue";
}

Categories