Reputation: 195
I'm currently trying to figure out the way to expand my dynamically generated table with buttons. Said buttons would be showing (on click) some parts of the informations from the table in the aside element from HTML of a page in question. For example - when I click a button in first row, it's showing me name of a product in this row in the aside block next to the table. The idea is simple, the execution not so much.
Creating aside element isn't a rocket science but creating dynamic buttons that can showcase parts of a dynamic table is a bit problematic for me. Below is a full code responsible for the creation of the table.
window.onload = function(e) {
createBook("book");
}
var books = [{
"author": "Eric T. Freeman",
"title": "Head First JavaScript Programming: A Brain-Friendly Guide",
"isbn": "978-1-4493-4398-9, 9781449343989",
"publisher": "O'Reilly Media",
"editions": [{
"year": "2017",
"covercolour": "gray"
},
{
"year": "2014",
"covercolour": "blue"
}
]
},
{
"author": "David Flanagan",
"title": "JavaScript: The Definitive Guide",
"isbn": "0596805527",
"publisher": "O'Reilly Media",
"editions": [{
"year": "2016",
"covercolour": "yellow"
},
{
"year": "2011",
"covercolour": "black"
}
]
}
];
function createBook(bookid) {
var bookbox = document.getElementById(bookid);
article = document.createElement("article");
bookbox.appendChild(article);
sectionInfo = createSection("List of Books");
article.appendChild(sectionInfo);
var infoTable = createTableBook(book);
sectionInfo.appendChild(infoTable);
}
function createTableBook() {
var table = document.createElement("table");
table.classList.add("tableBasic");
var tr = document.createElement("tr");
var th1 = document.createElement("th");
var th2 = document.createElement("th");
var th3 = document.createElement("th");
var th4 = document.createElement("th");
var th5 = document.createElement("th");
var th6 = document.createElement("th");
th1.innerHTML = "Author";
th2.innerHTML = "Title";
th3.innerHTML = "ISBN";
th4.innerHTML = "Publisher";
th5.innerHTML = "Editions";
th6.innerHTML = "Showcase";
tr.appendChild(th1);
tr.appendChild(th2);
tr.appendChild(th3);
tr.appendChild(th4);
tr.appendChild(th5);
tr.appendChild(th6);
table.appendChild(tr);
for (var index in books) {
var tr = document.createElement("tr");
var td1 = document.createElement("td");
td1.innerHTML = books[index].author;
tr.appendChild(td1);
var td2 = document.createElement("td");
td2.innerHTML = books[index].title;
tr.appendChild(td2);
var td3 = document.createElement("td");
td3.innerHTML = books[index].isbn;
tr.appendChild(td3);
var td4 = document.createElement("td");
td4.innerHTML = books[index].publisher;
tr.appendChild(td4);
var td5 = document.createElement("td");
// td5.appendChild(createEditionDetails(index));
tr.appendChild(td5);
var td6 = document.createElement("button");
td6.innerHTML = "button";
tr.appendChild(td6);
table.appendChild(tr);
}
return table;
}
function buttonWork(asideID) {//function I want to use
var aside = document.getElementById(asideID);
var $row = $(this).closest("tr");
var $text = $row.find(".name").text();
aside.innerHTML += $text + '<br/>';
}
function createHeader(h, text) {
header = document.createElement("header");
h = document.createElement(h);
h.innerHTML = text;
header.appendChild(h);
return header;
}
function createSection(title) {
var section = document.createElement("section");
section.appendChild(createHeader("h3", title));
return section;
}
<section>
<article>
<aside>
<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</aside>
<section id="book">
</section>
</article>
</section>
<!--<script>
window.onload = function(e) {
createBook("book");
}
</script>-->
After some trial and error, I was able to find a solution to some of my problems but I can't find a way to reliably connect buttons to the new logic in buttonWork function. I could use some ideas for a newbie in JS.
Upvotes: 0
Views: 77
Reputation: 65806
First, your code needs to be corrected because all table content must go into a cell (th
or td
). You currently have your button
elements being appended directly to rows. But, after that correction, this is simpler than you think.
click
event handler on the table and when each
generated button is clicked, that event will bubble up to the table
and be handled there. (event delegation).closest()
and .querySelector()
methods and display it in the aside.On a side note, don't use .innerHTML
when you aren't setting/getting any content that contains HTML. There are performance and security concerns to its use. Instead, use .textContent
.
Finally, the code you are showing isn't using images or external resources, so having it all trigger on the .load
event, while functional, is not the best choice. Instead, have your code initiate as soon as the browser has finished parsing the HTML in the body
. The simplest way to make that happen is to just place your code just prior to the closing body
tag.
table {
font-size:.8em;
border:2px solid #363;
font-family:Arial, Calibri, Helvetica;
}
th, td {
border:1px solid #e0e0e0;
padding:2px;
}
<body>
<section>
<article>
<aside>
<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</aside>
<section id="book">
</section>
</article>
</section>
<!-- Placing your script here ensures that it won't run until all the HTML
above it has been parsed and the DOM is fully loaded. -->
<script>
// Object property/key names do not need to be in quotes unless they contain spaces
var books = [{
author: "Eric T. Freeman",
title: "Head First JavaScript Programming: A Brain-Friendly Guide",
isbn: "978-1-4493-4398-9, 9781449343989",
publisher: "O'Reilly Media",
editions: [{year: "2017", covercolour:"gray" },{year: "2014", covercolour:"blue"}]
},
{
author: "David Flanagan",
title: "JavaScript: The Definitive Guide",
isbn: "0596805527",
publisher: "O'Reilly Media",
editions: [{year: "2016", covercolour:"yellow"},{year:"2011", covercolour:"black"}]
}];
function createBook(bookid) {
var bookbox = document.getElementById(bookid);
article = document.createElement("article");
bookbox.appendChild(article);
sectionInfo = createSection("List of Books");
article.appendChild(sectionInfo);
var infoTable = createTableBook(book);
sectionInfo.appendChild(infoTable);
}
function createTableBook() {
var table = document.createElement("table");
table.classList.add("tableBasic");
var tr = document.createElement("tr");
var th1 = document.createElement("th");
var th2 = document.createElement("th");
var th3 = document.createElement("th");
var th4 = document.createElement("th");
var th5 = document.createElement("th");
var th6 = document.createElement("th");
th1.textContent = "Author";
th2.textContent = "Title";
th3.textContent = "ISBN";
th4.textContent = "Publisher";
th5.textContent = "Editions";
th6.textContent = "Showcase";
tr.appendChild(th1);
tr.appendChild(th2);
tr.appendChild(th3);
tr.appendChild(th4);
tr.appendChild(th5);
tr.appendChild(th6);
table.appendChild(tr);
// Books is an array, for/in loops are for objects.
// With Arrays, there are many different types of loops available, but .forEach()
// is the simplest as it does away with indexers
books.forEach(function(book){
var tr = document.createElement("tr");
var td1 = document.createElement("td");
td1.textContent = book.author;
td1.classList.add("author"); // <-- This will be used to locate the data you want to show
tr.appendChild(td1);
var td2 = document.createElement("td");
td2.textContent = book.title;
td2.classList.add("title"); // <-- This will be used to locate the data you want to show
tr.appendChild(td2);
var td3 = document.createElement("td");
td3.textContent = book.isbn;
td3.classList.add("isbn"); // <-- This will be used to locate the data you want to show
tr.appendChild(td3);
var td4 = document.createElement("td");
td4.textContent = book.publisher;
td4.classList.add("publisher"); // <-- Used to locate the data you want to show
tr.appendChild(td4);
var td5 = document.createElement("td");
// td5.appendChild(createEditionDetails(index));
td5.classList.add("edition"); // <-- This will be used to locate the data you want to show
tr.appendChild(td5);
// All table content must be contained inside of cells. You have to put your button in
// a cell and then that cell goes into the row.
var td6 = document.createElement("td");
var btn = document.createElement("button");
btn.textContent = "Details";
td6.appendChild(btn);
tr.appendChild(td6);
table.appendChild(tr);
});
return table;
}
function createHeader(h, text) {
header = document.createElement("header");
h = document.createElement(h);
h.textContent = text;
header.appendChild(h);
return header;
}
function createSection(title) {
var section = document.createElement("section");
section.appendChild(createHeader("h3", title));
return section;
}
createBook("book");
// You'll need to reference the table and the aside more than once.
// Just query for them one time and then keep referring to those variables:
let tbl = document.querySelector("table");
let side = document.querySelector("aside");
// Any buttons within the table that get clicked will also cause a click event to
// trigger for the table itself. We'll handle the details there.
tbl.addEventListener("click", function(evt){
// Set the aside's text content by navigating to the clicked button's closest
// (<tr>) and then query from there to find the cell with the desired class.
// Here, we're showing the title in the aside, but you can substitute any of the other
// book data by just referring to the class that was assigned to the cell.
side.textContent = evt.target.closest("tr").querySelector(".title").textContent;
});
</script>
</body>
Upvotes: 1
Reputation: 28563
If you want to show information on click, you could use either a button/input or a hyperlink (on your first column) to make the row/column clickable
The following piece of code illustrates how to make a button
var td1 = document.createElement('input');
td1.type = "button";
td1.className = "btn";
td1.value = books[index].author;
td1.onclick = (function() {write your function here});
td.appendChild(td1);
Using your existing code you could make a column (in this case, the first) into a button by tweaking your code to reflect that the innerHTML would be a button (see bolded code), as opposed to adding an extra column of buttons to the table.
I would recommend adding identifiers to the columns. See fiddle to illustrate what I mean (shows button being added to 'Author' column)
The most important thing will be what you write in the function. It is not clear what you want to do here, but if you want to write to another section, then get that section by calling it by it's id and then write in the values.
Hope this helps
window.onload = function(e) {
createBook("book");
}
var books = [{
"author": "Eric T. Freeman",
"title": "Head First JavaScript Programming: A Brain-Friendly Guide",
"isbn": "978-1-4493-4398-9, 9781449343989",
"publisher": "O'Reilly Media",
"editions": [{
"year": "2017",
"covercolour": "gray"
},
{
"year": "2014",
"covercolour": "blue"
}
]
},
{
"author": "David Flanagan",
"title": "JavaScript: The Definitive Guide",
"isbn": "0596805527",
"publisher": "O'Reilly Media",
"editions": [{
"year": "2016",
"covercolour": "yellow"
},
{
"year": "2011",
"covercolour": "black"
}
]
}
];
function createBook(bookid) {
var bookbox = document.getElementById(bookid);
article = document.createElement("article");
bookbox.appendChild(article);
sectionInfo = createSection("List of Books");
article.appendChild(sectionInfo);
var infoTable = createTableBook(book);
sectionInfo.appendChild(infoTable);
}
function createTableBook() {
var table = document.createElement("table");
table.classList.add("tableBasic");
var tr = document.createElement("tr");
var th1 = document.createElement("th");
var th2 = document.createElement("th");
var th3 = document.createElement("th");
var th4 = document.createElement("th");
var th5 = document.createElement("th");
var th6 = document.createElement("th");
th1.innerHTML = "Author";
th2.innerHTML = "Title";
th3.innerHTML = "ISBN";
th4.innerHTML = "Publisher";
th5.innerHTML = "Editions";
th6.innerHTML = "Showcase";
tr.appendChild(th1);
tr.appendChild(th2);
tr.appendChild(th3);
tr.appendChild(th4);
tr.appendChild(th5);
tr.appendChild(th6);
table.appendChild(tr);
for (var index in books) {
var tr = document.createElement("tr");
var td1 = document.createElement("td");
**td1.innerHTML = '<input type="button" value ="' + books[index].author + '"' +'/>';**
tr.appendChild(td1);
var td2 = document.createElement("td");
td2.innerHTML = books[index].title;
tr.appendChild(td2);
var td3 = document.createElement("td");
td3.innerHTML = books[index].isbn;
tr.appendChild(td3);
var td4 = document.createElement("td");
td4.innerHTML = books[index].publisher;
tr.appendChild(td4);
var td5 = document.createElement("td");
// td5.appendChild(createEditionDetails(index));
tr.appendChild(td5);
var td6 = document.createElement("td"); //a column reserved for buttons
// td6.appendChild(createButtonShow(index)); //I suppose it's going to be a similar index requirement as in createEditionDetails function
tr.appendChild(td6);
table.appendChild(tr);
}
return table;
}
function createHeader(h, text) {
header = document.createElement("header");
h = document.createElement(h);
h.innerHTML = text;
header.appendChild(h);
return header;
}
function createSection(title) {
var section = document.createElement("section");
section.appendChild(createHeader("h3", title));
return section;
}
<section>
<article>
<aside>
<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</aside>
<section id="book">
</section>
</article>
</section>
<!--<script>
window.onload = function(e) {
createBook("book");
}
</script>-->
Upvotes: 0