Hide column while exporting to excel from html table using javascript - javascript

I have a html table which I have to export to excel , but while doing so, I dont want some of the td elements to be exported. When I apply javascript to hide the td, the changes are being applied only to the view form and not to the the content being exported.
Need help in how to export in this case.
I have included html, css and script all in one page.
<html>
<body>
<div id="myDiv">
<table id="metrics" border="1px" cellspacing="0 px" style="border-style: solid; border-color: Black;
border-width: thin;">
<tr>
<td style= "background-color: #bfbfbf; font-size: small; color: black;">
LOB
</td>
<td>
<span class="hillbillyForm" data-displayname='LOB' style="display:none;"></span>
</td>
</tr>
</table>
<input type="button" id="btnExport" value="Export" onclick="TableToExcel('metrics');" />
</div>
</body>
Here I want to hide the td which contains span class "hillbillyForm"
The javascript That I am using is
function TableToExcel(tableid) {
var id = $('[id$="' + tableid + '"]');
var $clonedTable = $("id").clone();
$clonedTable.find('[style = "display: none"]').remove();
var strCopy = $('<div></div>').html(id.clone()).html();
window.clipboardData.setData("Text", strCopy);
var objExcel = new ActiveXObject("Excel.Application");
objExcel.visible = false; var objWorkbook = objExcel.Workbooks.Add; var objWorksheet = objWorkbook.Worksheets(1); objWorksheet.Paste; objExcel.visible = true;
}
</script>

So what I'm understanding is that you want to remove all TD's which have a direct child with the class hillbillyForm.
You can do something like this:
var form = document.getElementById(tableid),
exportForm = form.cloneNode(true),
elementsToRemove = exportForm.querySelectorAll('.hillbillyForm');
for (var i = elementsToRemove.length; i--;){
var td = elementsToRemove[i].parentElement;
if (td) td.parentElement.removeChild(td);
}
jsFiddle

Related

Multiple elements using appendChild for table

I have the following input and button
const inputNotice = document.createElement("input");
inputNotice.type = "text";
r.insertCell(26).appendChild(inputNotice.cloneNode(true));
//new button
const Noticebutton = document.createElement("button");
Noticebutton.type = "button";
Noticebutton.textContent = "Send Notice";
r.insertCell(26).appendChild(Noticebutton);
Im trying to get the input field and button to sit in 1 cell in the table, it creates these in 2 separate cells.
create a div having input and button as children and then append this as the child of the cell like this:
const div= document.createElement('div');
const inputNotice = document.createElement('input');
const Noticebutton = document.createElement("button");
div.appendChild(inputNotice);
div.appendChild(NoticeButton);
Since there is no html template provided, I have had one of my own to do the illustration.
The idea is to add both of the elements inside a container and then append that container to the cell as a child.
In the following illustration I have used a div as a container. Feel free to choose one of which that suits the needs.
Illustration
const nonWorkingRow = document.querySelector('#cell-host-non-working');
const inputNotice = document.createElement("input");
inputNotice.type = "text";
// inputNotice.style.display = 'inline block';
nonWorkingRow.insertCell(0).appendChild(inputNotice.cloneNode(true));
//new button
const Noticebutton = document.createElement("button");
Noticebutton.type = "button";
Noticebutton.textContent = "Send Notice";
// Noticebutton.style.display = 'inline block';
nonWorkingRow.insertCell(0).appendChild(Noticebutton.cloneNode(true));
const workingRow = document.querySelector('#cell-host');
const container = document.createElement('div');
container.appendChild(inputNotice);
container.appendChild(Noticebutton);
workingRow.insertCell(0).appendChild(container);
.column-bordered-table thead td {
border-left: 1px solid #c3c3c3;
border-right: 1px solid #c3c3c3;
}
.column-bordered-table td {
border-left: 1px solid #c3c3c3;
border-right: 1px solid #c3c3c3;
}
.column-bordered-table tfoot tr {
border-top: 1px solid #c3c3c3;
border-bottom: 1px solid #c3c3c3;
}
<h1>Non Working</h1>
<table id="row-host-non-working" class="column-bordered-table">
<tr id="cell-host-non-working" style="outline: thin solid">
<td>
<p>Hello</p>
</td>
</tr>
</table>
<h1>Working</h1>
<table id="row-host-working" class="column-bordered-table">
<tr id="cell-host" style="outline: thin solid">
<td>
<p>Hello</p>
</td>
</tr>
</table>
WYSIWYG => WHAT YOU SHOW IS WHAT YOU GET
Instead of inserting a new cell twice (which is the cause of your problem), do that only once and work with the reference insertCell provides:
const cell = r.insertCell(26);
const inputNotice = document.createElement("input");
inputNotice.type = "text";
const Noticebutton = document.createElement("button");
Noticebutton.type = "button";
Noticebutton.textContent = "Send Notice";
cell.append(inputNotice, Noticebutton);
Notice I'm using append here, not appendChild, because it allows to pass a number of elements to it rather than just one.

Save content editable HTML table in multiple fields

I need to develop a HTML table where one of the table column is editable on its row and the table row is dynamic in term of the row number.
I come across a problem where when I automate the saveEdits() function, the code is not working.
Here is my code, where the 'cnt' is a dynamic numeric number. Example cnt=50
<!DOCTYPE html>
<html>
<head>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
table ,tr td{
border:1px solid #dddddd;
padding: 8px;
}
tbody {
display:block;
height:600px;
overflow:auto;
}
thead, tbody tr {
display:table;
width:100%;
table-layout:fixed;
}
thead {
width: calc( 100% - 1em )
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
<script type="text/javascript">
function saveEdits(cnt) {
//get the editable elements.
var str_out = ''
while (cnt>0){
str1 = '\'edit' + cnt + '\': document.getElementById(\'edit' + cnt + '\').innerHTML,\n'
str_out = str_out.concat(' ', str1);
cnt--;
};
var editElems= { str_out };
alert(editElems)
//save the content to local storage. Stringify object as localstorage can only support string values
localStorage.setItem('userEdits', JSON.stringify(editElems));
}
function checkEdits(){
//find out if the user has previously saved edits
var userEdits = localStorage.getItem('userEdits');
alert(userEdits) // suppose to print {"edit1":" rpeyy7<br>","edit2":" tpruiiy<br>","edit3":" opty<br>"}
if(userEdits){
userEdits = JSON.parse(userEdits);
for(var elementId in userEdits){
document.getElementById(elementId).innerHTML = userEdits[elementId];
}
}
}
</script>
</head>
<body onload="checkEdits()">
<table id="myTable">
<thead>
<tr>
<td style="background-color:#A9A9A9" > Field#1 </td>
<td style="background-color:#A9A9A9" > Field#2 </td>
<td style="background-color:#A9A9A9" > Field#3- Each Row Under field#3 is content EditableByUser </td>
</tr>
</thead>
<tbody>
// Here is the python code that loop through a diectionary content
cnt = 0
for c in sorted(data_dict.keys()) :
cnt += 1
<tr>
<td> {0} </td> //Field#1
<td> {0} </td> //Field#2
...
...
<td id="edit{0}" contenteditable="true" onKeyUp="saveEdits({0});"> {1} </td>\n'.format(cnt,comment)]
</tr>
</table>
</body>
I'm not sure where goes wrong as when I automate the saveEdits() function with 'cnt' in while loop, the above code doesn't works for me. But when I defined each row clearly like below, the data the keyed-in are properly saved to each column.
function saveEdits(cnt) {
//get the editable elements.
var editElems = {
'edit1': document.getElementById('edit1').innerHTML,
'edit2': document.getElementById('edit2').innerHTML,
'edit3': document.getElementById('edit3').innerHTML,
};
alert(editElems) //print [object Object]
//save the content to local storage. Stringify object as localstorage can only support string values
localStorage.setItem('userEdits', JSON.stringify(editElems));
}
I would be much appreciate if someone can point out my mistake. The error is very much likely on saveEdits(cnt) function but I'm not sure how to fix that cause it I define each count 1 by 1, each update that being keyed-in is actually saved properly and able to retrieve when rerun. Thanks you!

I am trying to switch values in table cells using angularjs... can i use ngbind or ngmodel or something else?

I am trying to make a table cell clickable. When the cell is clicked it will switch the contents from one cell to another. I want to make a basic chess game out of this click action by eventually using angular.element to get the clicked elements and setting the second clicked square equal to the first clicked.html(). Is this possible in AngluarJs using a MEAN somehow?
My current code looks like this but the table cell isn't changing or doing anything when I click.
app.controller('ChessCtrl' , ['$http', '$scope', '$document', function
ChessCtrl($http, $scope, $document) {
var vm = this;
vm.test1 = angular.element(document.getElementById("A1"));
vm.test2 = "";
vm.test3 = "This is a test";
$scope.click = function() {
var temp = vm.test3;
vm.test2 = temp;
vm.test3 = "";
}
}]);
<div ng-Controller="ChessCtrl">
<div class="content">
<div class="left">
<table style="width: 75%">
<tr>
<td id="A1" ><a ng-bind="vm.test3" ng-click="click()"></a></td>
<td class="grey" ng-bind="vm.test2"><a ng-bind="vm.test2" ng-click="click()"></a>
</td>
<td>
</tr>
</table>
</div>
</div>
</div>
Obviously I am missing something but I have tried adding to a DB and pulling it back out. I have tried ng-model and ng-bind for holding the variables. I am just lost on if or how I can get the td to be clickable and also switch where what is clicked displays. Thanks!
NOTE: disregard test1 in this example... I was using that earlier for testing getting the HTML out of the element.
The HTML doesn't need the <a> tag. Simply set the CSS style to cursor: pointer.
Also the ng-bind directive isn't necessary, simply bind model to HTML with double brace {{ }} expressions.
The DEMO
angular.module("app",[])
.controller('ChessCtrl' , function () {
var vm = this;
vm.test2 = "♔";
vm.test3 = "test";
vm.switch = function() {
var temp = vm.test2;
vm.test2 = vm.test3;
vm.test3 = temp;
}
});
.red { background-color: red; }
.grey { background-color: grey; }
td {
width: 20%;
cursor: pointer;
font-size: 24pt;
}
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ChessCtrl as vm">
<table>
<tr>
<td class="red" ng-click="vm.switch()">{{vm.test3}}</td>
<td class="grey" ng-click="vm.switch()">{{vm.test2}}</td>
</tr>
</table>
</body>
Okay, I try to figure out one solution that might work for you too.
I am adding code snippet have a look:
Main challange, that you are facing is, ng-bind,
have a look to this article and find the sole purpose of ng-bind
https://www.w3schools.com/angular/ng_ng-bind.asp
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<table style="width: 75%">
<tr>
<td id="td1" ><a ng-bind="link1" ng-click="clickMe()"></a></td>
<td id="td2" class="" ><a ng-bind="link2" ng-click="clickMeAgain()"></a>
</td>
<td>
</tr>
</table>
</div>
<script>
var clickMeIsClicked = false;
var clickMeAgainIsClicked = false;
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.link1 = 'Click me to show td2';
$scope.link2 = ' I always want to be visible, thanks td1';
$scope.count = 0;
$scope.myFunction = function() {
$scope.count++;
}
$scope.clickMe = function(){
if(!clickMeIsClicked){
$scope.link2 = 'Click me to show td2';
$scope.link1 = ' I always want to be visible, thanks td1';
clickMeIsClicked = true;
}
else{
$scope.link1 = 'Click me to show td2';
$scope.link2 = ' I always want to be visible, thanks td1';
clickMeIsClicked = false;
}
}
$scope.clickMeAgain = function(){
}
});
</script>
</body>
</html>

JavaScript Save Table Rows added by User

I am making an Electron app that has tables, the user can add a table and change the content of the fields, but I want the input to be saved, and only if the user entered anything into them.
How would I do this? Do I need a database? Can it be done with cookies? I have tried to learn how to use cookies but have not found how to save an added element as well as the content.
function appendRow(id) {
var table = document.getElementById(id); // table reference
length = table.length,
row = table.insertRow(table.rows.length); // append table row
var i;
// insert table cells to the new row
for (i = 0; i < table.rows[0].cells.length; i++) {
createCell(row.insertCell(i), i, 'row');
}
}
function createCell(cell, text, style) {
var div = document.createElement('div'), // create DIV element
txt = document.createTextNode('_'); // create text node
div.appendChild(txt); // append text node to the DIV
div.setAttribute('id', style); // set DIV class attribute
div.setAttribute('idName', style); // set DIV class attribute for IE (?!)
cell.appendChild(div); // append DIV to the table cell
}
table {
text-align: center;
width: 400px;
}
tr:nth-child(even) {
background-color: #ccc;
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="test.css">
</head>
<body>
<button id="addCust" class="addSort" onclick="appendRow('custList')">add customer</button>
<table id="custListTop" contenteditable="false" style="background-color: #ccc;">
<tr>
<td style="border-top-left-radius: 5px;">Customers</td>
<td style="border-top-right-radius: 5px;">Main Location</td>
</tr>
</table>
<table id="custList" contenteditable="true">
<tr>
<td>Someone</td>
<td>something</td>
</tr>
</table>
<script src="test.js"></script>
</body>
</html>
Well how you are going to save it depends on what you want to do. If you want it to persist after your program was exited, you will need to save it on the disk or on a server somehow. You probably just want to save it into a file, though. (JSON is the most obvious choice). Otherwise, just save it into a js variable.
To get the data, I would either use a save button that reads the text of your cells, or use databinding. Later is very useful for Electron apps. You can either use a framework (like vue.js, react.js or many more) or DIY.
Former is probably easier and you will want a button to save it to the disk anyways. On the click of the button you can just go through all <tr>-elements and get their values and save them.
function save(id) {
var table = document.getElementById(id);
var trs = table.getElementsByTagName('tr'); // list of all rows
var values = []; // will be a (potentially jagged) 2D array of all values
for (var i = 0; i < trs.length; i++) {
// loop through all rows, each will be one entrie in values
var trValues = [];
var tds = trs[i].getElementsByTagName('td'); // list of all cells in this row
for (var j = 0; j < tds.length; j++) {
trValues[j] = tds[j].innerText;
// get the value of the cell (preserve newlines, if you don't want that use .textContent)
}
values[i] = trValues;
}
// save values
console.log(values);
}
function appendRow(id) {
var table = document.getElementById(id); // table reference
length = table.length,
row = table.insertRow(table.rows.length); // append table row
var i;
// insert table cells to the new row
for (i = 0; i < table.rows[0].cells.length; i++) {
createCell(row.insertCell(i), i, 'row');
}
}
function createCell(cell, text, style) {
var div = document.createElement('div'), // create DIV element
txt = document.createTextNode('_'); // create text node
div.appendChild(txt); // append text node to the DIV
div.setAttribute('id', style); // set DIV class attribute
div.setAttribute('idName', style); // set DIV class attribute for IE (?!)
cell.appendChild(div); // append DIV to the table cell
}
table {
text-align: center;
width: 400px;
}
tr:nth-child(even) {
background-color: #ccc;
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="test.css">
</head>
<body>
<button id="addCust" class="addSort" onclick="appendRow('custList')">add customer</button>
<button id="save" class="save" onclick="save('custList')">save</button>
<table id="custListTop" contenteditable="false" style="background-color: #ccc;">
<tr>
<td style="border-top-left-radius: 5px;">Customers</td>
<td style="border-top-right-radius: 5px;">Main Location</td>
</tr>
</table>
<table id="custList" contenteditable="true">
<tr>
<td>Someone</td>
<td>something</td>
</tr>
</table>
<script src="test.js"></script>
</body>
</html>

Add event listener by class, pass ID as argument in JS

I have a grid set up of days of the week by times of the day, each slot on the grid is a checkbox for my site's users to indicate availability. Since this ends up being a large number of slots, I would like for the background color of the slot to change depending on whether it is checked or not, but again due to the large number of slots I don't want to have to add an event listener for each ID. Is it possible to add a single listener for the class and pass the ID of the clicked element so only its background is changed?
You'll have to use event delegation to accomplish this, simple example
document.addEventListener('change', function(e){alert(e.target.id)});
http://jsfiddle.net/mowglisanu/cCFxQ/
Assuming that your checkboxes are the childNodes of your <td> elements, you can use this code:
var checkedList = document.getElementsByClassName('checked');
for(var i = 0; i < checkedList.length; i++) {
var current = checkedList[i],
parent = current.parentNode; //it is the td
if (current.checked) parent.style.backgroundColor = 'color';
}
Working JSFiddle
If you want it to be completely dynamic, you should add an event listener as Musa said.
document.addEventListener('change', function(e){
var current = e.target,
parent = current.parentNode;
if (current.checked) parent.style.backgroundColor = 'color';
});
here a logic that should fix ur problem.
i will suggest of using a some framework "jquery" for easy work
var checkedList = document.getElementsByClassName('checkboxes');
checkedList.addEventListener('change', function(e){
var node = e.target;
if(node.checked){
node.parentElement.style.background-color='grey';
}else{
node.parentElement.style.background-color='white';
}
});
I used the following code to solve the problem you had.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">.lw {
border: 1px solid red;
font-size: 60px;
}
tr td{
border: 1px solid red;
width: 40px;
height: 40px;
}</style>
<title>HTML5, CSS3 and JavaScript demo</title>
</head>
<body>
<!-- Start your code here -->
<div>
<table class="gameboard">
<tbody>
<tr>
<td class="slot" id="One">x</td>
<td class="slot" id="Two"></td>
<td class="slot" id="Three"></td>
</tr>
<tr>
<td class="slot" id="Four"></td>
<td class="slot" id="Five"></td>
<td class="slot" id="Six"></td>
</tr>
<tr>
<td class="slot" id="Seven"></td>
<td class="slot" id="Eight"></td>
<td class="slot" id="Nine"></td>
</tr>
</tbody></table>
</div>
<div>
<p id="titleOf" class="lw">Hello Weaver!</p>
</div>
<!-- End your code here -->
<script>/* Write JavaScript here */
var a = document.getElementById("titleText");
var b = document.getElementById("titleOf");
var c = document.getElementsByClassName("gameboard");
var piece = document.getElementsByClassName('slot');
var Gamelogic = {
checkFirst:false,
makeX: function(e){
for(var i= 0; i< piece.length - 1; i++){
if(e.path[i]){
e.path[0].innerText = "X";
e.path[0].style.backgroundColor = "green" ;
console.log(e.path);
console.log(e.path[0]);
console.log(e.path[i]);
}
break;
}
}
};
c[0].addEventListener("click", Gamelogic.makeX); // if the table is clicked
</script>
</body>

Categories