HTML files not loading in another html file - javascript

I'm trying to load HTML inside HTML Tabs, I've three tab Report 1, Report 2 and Report 3 Based on each tab selection I would like to show the different html reports but HTML file is not getting loaded when I select the tabs - please find my code below. Am I missing anywhere here and please find my reports file here - https://github.com/mikemarsh27/jest-poc/tree/main/html-report
It would be really appreciated if someone can help me to resolve this issue. Thanks in advance!
reportMain.html
<!DOCTYPE html>
<html>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<body>
<div class="w3-container">
<h2>Reports</h2>
<div class="w3-row">
<a href="javascript:void(0)" onclick="openReport(event, 'Report1');">
<div class="w3-third tablink w3-bottombar w3-hover-light-grey w3-padding">Report 1</div>
</a>
<a href="javascript:void(0)" onclick="openReport(event, 'Report2');">
<div class="w3-third tablink w3-bottombar w3-hover-light-grey w3-padding">Report 2</div>
</a>
<a href="javascript:void(0)" onclick="openReport(event, 'Report3');">
<div class="w3-third tablink w3-bottombar w3-hover-light-grey w3-padding">Report 3</div>
</a>
</div>
<div id="Report1" class="w3-container report" style="display:none">
<h2>Report 1</h2>
<p>First Report</p>
<div w3-include-HTML="report1.html"></div>
</div>
<div id="Report2" class="w3-container report" style="display:none">
<h2>Report 2</h2>
<p>Second Report</p>
<div w3-include-HTML="report2.html"></div>
</div>
<div id="Report3" class="w3-container report" style="display:none">
<h2>Report 3</h2>
<p>Third Report</p>
<div w3-include-HTML="report3.html"></div>
</div>
</div>
<script>
function openReport(evt, reportName) {
getHtml(reportName);
var i, x, tablinks;
x = document.getElementsByClassName("report");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i < x.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" w3-border-red", "");
}
document.getElementById(reportName).style.display = "block";
evt.currentTarget.firstElementChild.className += " w3-border-red";
}
function getHtml(id) {
alert(id)
//Get the <div> element
let element = document.querySelector("#" + id)
.querySelector("div");
//Check if it's empty; we don't want to reload twice
if (element.innerHTML.trim() !== "") {
return;
}
//Get the HTML filename from the <div>
let htmlFile = element.getAttribute("w3-include-HTML");
alert(htmlFile)
//Load the HTML file into the page
element.innerHTML =
`<object type="text/html" data="${htmlFile}" ></object>`;
}
</script>
</body>
</html>

The example you provided appears to be from here. They provide additional steps that will probably make your code somewhat functional. I say somewhat because the report files you're looking to load in contain more than just HTML. Therefore, their examples may not ultimately work for you.
Here is a rough, but working solution:
Step 1: Add this function to your code
function getHtml(id){
//Get the <div> element
let element = document.querySelector("#" + id)
.querySelector("div");
//Check if it's empty; we don't want to reload twice
if (element.innerHTML.trim() !== "") {
return;
}
//Get the HTML filename from the <div>
let htmlFile = element.getAttribute("w3-include-HTML");
//Load the HTML file into the page
element.innerHTML=
`<object type="text/html" data="${htmlFile}" ></object>`;
}
Step 2: Call getHtml(...) in openReport(...)
function openReport(evt, reportName) {
getHtml(reportName);
...
}
A modified approach is provided below. In your specific circumstances it may not work, so I would stick with the first one. But for others in a similar situation, it may be more reasonable.
function getHtml(id) {
//Get the <div> element
let element = document.querySelector("#" + id)
.querySelector("div");
//Check if it's empty; we don't want to reload twice
if (element.innerHTML.trim() !== "") {
return;
}
//Get the HTML filename from the <div>
let htmlFile = element.getAttribute("w3-include-HTML");
//Get the HTML file contents
fetch(htmlFile).then(function(data) {
return data.text();
}).then(function(data) {
//Got the HTML file contents; print it to the page
element.innerHTML = data;
}).catch(function(err) {
// Report error here (e.g., console.warn(...))
});
}

Related

Browser go back to active div in previous page

I want to create a list of button where once clicked, it will shows the respective div as below. And in the div, there is a few links that user can click, and once they clicked the link and go back, it will bring them back to the previous div instead of the first default div. Codes as below.
<div class="tab">
<a class="tablinks btn" href="#m0" id="t0">Item A</a>
<a class="tablinks btn" href="#m1" id="t1">Item B</a>
<a class="tablinks btn" href="#m2" id="t2">Item C</a>
</div>
<div class="tlist">
<div id="m0" class="tdiv" style="display:block;">
LinkA</div>
<div id="m1" class="tdiv" style="display:none;">
LinkB</div>
<div id="m2" class="tdiv" style="display:none;">
LinkC</div>
</div>
I have Javascript codes that will change the display from none to block when user clicked on the Item.
document.getElementById("m0").style.display = "block";
document.getElementById("t"+i).addEventListener('click',divStyle.bind(this,"m"+i),false);
function divStyle(num) {
var i,tdiv,tablinks;
tdiv = document.getElementsByClassName("tdiv");
for (i=0;i<tdiv.length;i++) {
tdiv[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i=0;i<tablinks.length;i++) {
tablinks[i].className = tablinks[i].className.replace(" active","");
}
document.getElementById(num).style.display = "block";
Event.className += "active";
}
//print tab for Item
function printTab(itemnum) {  
for (var y = 0; y < itemnum; y++) {    
tabbtn = document.createElement("a");  
tabbtn.classList.add("tablinks", "btn", "btn-secondary");  
tabbtn.setAttribute("href", "#m" + y);  
tabbtn.setAttribute("id", "t" + y);  
if (y == 0) {   
tabbtn.classList.add("tablinks", "btn", "btn-secondary", "active");  
}  
tabtxt = document.createTextNode("");  //print Item text here 
tabbtn.appendChild(tabtxt);  
document.getElementById("tab").appendChild(tabbtn);
}
//print div for Link
function printLink(num) {
var docFrag = document.createDocumentFragment(); 
for (var i = 0; i < Object.keys(obj).length; i++) {  
moddiv = document.createElement("div");  
moddiv.setAttribute("id", "m" + num);  
moddiv.setAttribute("class", "tdiv");  
moddiv.style.display = "none";  
for (var i = 0; i < Object.keys(obj).length; i++) {   
/*do something here and put link of each item*/   
}   
  
moddiv.appendChild(docFrag);  
document.getElementById("tlist").appendChild(moddiv);  
}
The problem I have now is that when LinkC is clicked, and user then pressed Back button in the browser, browser goes back to the link of the previous specific div, for example, page.html#m2 but shows div m0. I guess this is because I already set document.getElementById("m0").style.display = "block"; by default so it will always go to div m0 but is there other way to make sure the browser will go back to the previous specific div chosen?
My google finding shows people suggesting history.back() but that means I need to create a Back button but I do not want that. I am sure this is not a complicated issue but I can't think anymore on how to solve this.
Any help is very appreciated. Thank you!
Update: I tried to use history.back() and created a button but this also is not working as it still display div m0. :(
Update #2: Tried this on Firefox and it is working though. Is there another way to make sure it can work for different browser?
Please try the bellow code :
<div class="tab">
<a class="tablinks btn active" href="#m0" id="t0">Item A</a>
<a class="tablinks btn" href="#m1" id="t1">Item B</a>
<a class="tablinks btn" href="#m2" id="t2">Item C</a>
</div>
<br>
<div class="tlist">
<div id="m0" class="tdiv" style="display:block;">
LinkA</div>
<div id="m1" class="tdiv" style="display:none;">
LinkB</div>
<div id="m2" class="tdiv" style="display:none;">
LinkC</div>
</div>
<style>
a{color:#333;text-decoration: none;background: #eee;border: 1px solid #333;border-radius:5px;padding:3px;}
.active{color:blue;background: #ccc;}
</style>
<script type="text/javascript">
var tabSelect=(url)=>{
console.log(url);
let hs = url.split('#')[1]||'m0',ts = hs.split('m').join('t');
if(hs!=''){
let tabcs = document.getElementsByClassName('tdiv');
for(let tabc of tabcs){if(tabc.id){tabc.style.display='none';}}
let tabhs = document.getElementsByClassName('tablinks');
for(let tabh of tabhs){if(tabh.id){tabh.className="tablinks btn"}}
let c = document.getElementById(hs);
if(c){c.style.display = 'block';document.getElementById(ts).className="tablinks btn active"}
}
}
window.onhashchange=(i)=>{tabSelect(i.newURL);}
window.onload=()=>{tabSelect(location.href);}
</script>
Hope you will be fine with this code.

change a div content again and again without losing previous html

I am writing a jquery function to filter products by type. It works perfectly fine but when I filter by type more than once. Html Element of product-box named addToWishlist stop working.
otherwise all products are displayed perfectly fine.
Cant figure out where is the problem.
Here is the code
//load products data in array
var productArray = [];
$("#product-items .col-4").each (function (){
productArray.push($(this)) })
$(".filter-btn").click(function(e) {
var btnId = e.target.id;
var tempArray = [];
for(var i = 0;i < productArray.length; i++){
var type = $(productArray[i]).find('.addToWishlist').data("type");
if(btnId == "fairness-soaps" && type == "Fairness")
tempArray.push(productArray[i])
if(btnId == "deep-clean-soaps" && type == "Deep-Clean")
tempArray.push(productArray[i])
if(btnId == "skin-whitening-soaps" && type == "Skin-Whitening")
tempArray.push(productArray[i])
}
$("#product-items").html(tempArray);
});
<div class="row" id="product-items">
<div class="col-4">
<a href="#">
<div class="product-box">
<div class="product-img">
<img src="images/product-img13.png" alt="">
<a type="button" class="addToWishlist" data-id="13" data-image="images/product-img13.png" data-price="$30"
data-name="Aloe Vera Soap" data-quantity="1" data-weight="50g" data-availability="In Stock" data-type="Fairness">
<i class="wishlist-icon fa fa-heart-o"></i></a>
</div>
<p class="product-name">Aloe Vera Soap</p>
<p class="product-price">$30</p>
</div>
</a>
</div>
and so on....
You're not reordering the product Elements, you're rewriting them. Even though the HTML of the products is the same, the events you attach to them is lost when you call $("#product-items").html(tempArray);. You either need to reapply the events to the "addToWishList" buttons or reorder the elements instead of writing directly to the html.
Here's a contrived example that shows how just because the HTML is the same doesn't mean the event stays:
<div id="container">
<button id="special-button">Click me</button>
</div>
<script>
$("#special-button").on("click", function(){
alert("I've Been clicked!");
});
$("#container").html(`<button id="special-button">Click me</button>`);
</script>

How to loop through div tags with same class name

On my page, I have 5 div tags named "dropdown". I want to find all "a" tags under each "dropdown" div tag. I hope I am explaining this properly but this is what I have. Can someone confirm that it is right:
var dropdownDivs = document.getElementsByClassName('dropdown');
for(i = 0; i < dropdownDivs.length;i++)
var lnks = document.getElementsByClassName('dropdown').getElementsByTagName('a');
var dropdownDivs = document.getElementsByClassName('dropdown');
var links = dropdownDivs.getElementsByTagName('a');
You do not need the for loop.
How to get elements of specific class inside a div already found in JavaScript?
One line with pure javascript
let test = document.querySelectorAll('.dropdown a');
console.log(test);
My HTML for test
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="dropdown">
<a> TOTO </a>
</div>
<div class="test">
<a> TOTOB </a>
</div>
<div class="dropdown">
<a> TOTOC </a>
</div>
<div class="dropdown">
<a> TOTOD </a>
</div>
<script type="text/javascript" src="test.js"></script>
</body>
</html>
You'll need to get the links inside the for loop:
var dropdownDivs = document.getElementsByClassName('dropdown');
var lnks = [];
for (i = 0; i < dropdownDivs.length; i++) {
lnks.push(...dropdownDivs[i].getElementsByTagName('a'));
}
lnks.forEach(function(el) {
el.style.color = "red";
});
<div class="dropdown">
link
</div>
link
<div class="dropdown">
link
</div>
<div class="dropdown">
link
</div>
link
You can shorten it to a single call, by using Document#querySelectorAll:
var lnks = document.querySelectorAll('.dropdown a');
lnks.forEach(function(el) {
el.style.color = "red";
})
<div class="dropdown">
link
</div>
link
<div class="dropdown">
link
</div>
<div class="dropdown">
link
</div>
link
Use document.querySelectorAll('.dropdown a'). Here's the MDN on querySelectorAll.
I think your for loop itself is probably correct. Your problem though may be what you are doing with it in the loop.
const divs = document.getElementsByClassName('target');
for (let i = 0; i < divs.length; i++) {
console.log(divs[i].getElementsByTagName('a')[0]);
}
<div class="target">A</div>
<div class="target">B</div>
<div class="target">C</div>
<div class="target">D</div>
<div class="target">E</div>
In your example, you're just setting them into a variable each time. If there is more to it, then that might be okay. If you're trying to collect them all into one variable, you'll want to put them in an array instead.
const divs = document.getElementsByClassName('target');
let anchors = [];
for (let i = 0; i < divs.length; i++) {
anchors.push(divs[i].getElementsByTagName('a')[0]);
}
console.log(anchors);
<div class="target">A</div>
<div class="target">B</div>
<div class="target">C</div>
<div class="target">D</div>
<div class="target">E</div>
As other people already suggested how to do it through java script, If want to go with jquery this can help.
$(".dropdown").each(function(){
$(this).find("a").each(function(){
console.log(this);
})
})

Passing variable to function on another page

I am working on a website and am planning on having it so that certain links will have a value set, this will change what container is displayed when the page loads. How would I have it so the link passes a value that would be used for the onload functions?
Here is a mockup of my HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Lunch</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="script.js"></script>
</head>
<body onload="navBar(); dateChange(); tabulate(0);">
<nav>
<ul>
<li>Appitizers</li>
<li>Breakfast</li>
<li>Lunch</li>
<li>Dinner</li>
<li>Dessert</li>
<li>Ten-Course Dinner</li>
<li>Send in your Recipes!</li>
</ul>
</nav>
<div class="main">
<div class="box">
<ul>
<li><a onclick="tabulate(this.id);" id="1">Chicken Clubhouse Sandwiches</a></li>
<li><a onclick="tabulate(this.id);" id="2">Smokey Tomato Soup</a></li>
</ul>
</div>
<div id="0" class="recipe" style="display: block;">
<div class="tabs">
<a class="tab"> </a>
</div>
<div class="page">
<p>The recipes you'll find here are ones you can use to impress guests at your next get together</p>
</div>
</div> <!--recipe card end-->
<div class="recipe" id="1">
<h1>Chicken Clubhouse Sandwiches</h1>
</div> <!--recipe card end-->
<div class="recipe" id="2">
<h1>Smokey Tomato Soup</h1>
</div> <!--recipe card end-->
</div>
</body>
</html>
And here is my tabulate function:
function tabulate(tabNum){
$('.recipe').each(function() {
if(tabNum==this.id){
this.style.display="block";
}
else{
this.style.display="none";
}
});
}
You would need to make use of the URL's GET parameters:
lunch.html?item=2
In conjunction with passing the variable into the JavaScript function:
// Set up an object for GET parameter
var $_GET = {};
// Find and extract the various GET parameters
if(document.location.toString().indexOf('?') !== -1) {
var query = document.location.toString().replace(/^.*?\?/, '').replace(/#.*$/, '').split('&');
for(var i=0, l=query.length; i<l; i++) {
var aux = decodeURIComponent(query[i]).split('=');
$_GET[aux[0]] = aux[1];
}
}
// Target a specific get parameter, given the GET parameter name
var tabNum = $_GET['item']; // Comes through as '2' in this example
// Pass the parameter into the function
function tabulate(tabNum){
$('.recipe').each(function() {
if(tabNum==this.id){
this.style.display="block";
}
else{
this.style.display="none";
}
});
}
See this post and this post for further reference.
Hope this helps! :)
I haven't tested this, but you should be able to get by with passing a GET variable via PHP into tabulate(), in a way like this:
function tabulate(tabNum){
$('.recipe').each(function() {
if(tabNum==this.id){
this.style.display="block";
}
else{
this.style.display="none";
}
});
}
window.addEventListener('DOMContentLoaded', function(evt) {
var id = <?php echo htmlspecialchars($_GET['id'], ENT_COMPAT, 'utf8'); ?>;
tabulate(id);
});

How to group node elements in a <p> tag

I was wondering if someone can help me out. The issue I'm having is the '#' and 'spaces' are being displayed individually on their own line, what I'm trying to have is a layout like this (without the quotes at the end of each line):
"# # # #"
"# # # #"
"# # # #"
The code would display four '#' each line. The length is determined by the number the user is prompt with.
Any help is greatly appreciated, thanks again.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<title>Q3 Display</title>
<style>
.resultText {
display: inline-block;
}
</style>
</head>
<body>
<div>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">Q3</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<!-- Question 3 Start -->
<div role="tabpanel" class="tab-pane tab-pane active" id="q3">
<div class="row">
<div class="col-md-12">
<pre>
Question 3 code:
</pre>
</div>
<div class="col-md-12">
<!-- button -->
<button id="q3-button" class="btn btn-default" type="button">Question Three Solution</button>
</div>
<div class="col-md-12">
<!-- result -->
<div id="result"></div>
</div>
</div>
</div>
<script>
//Question 3
//When the button is clicked, begin the function called start
$("#q3-button").on("click", function () {
start();
});
function start() {
//Sets up user prompt
var start = parseInt(prompt("How long would you like the side to be?"));
//Determine if what was entered in prompt is a number
if (isNaN(start)) {
alert("That's not a number, please retry.");
var start = prompt("Please re-enter a number.");
}
//Grabs the result div and assigns it a variable, will be used later on for result printing
var element = document.getElementById("result");
for (var i = 1; i <= start; i++) {
for (var j = 1; j <= 8; j++) {
if ((i + j) % 2 == 0) {
//Creates <p></p> element
var p1 = document.createElement("p");
//sets a class to the <p></p> element
p1.setAttribute("class", "resultText");
//Sets a variable to hold the text the <p></p> should contain
var node1 = document.createTextNode("#");
//Actually adds the text to the <p></p> element
p1.appendChild(node1);
//adds the <p></p> tag to the results div
element.appendChild(p1);
}
else {
//Creates <p></p> element
var p2 = document.createElement("p");
//p2.setAttribute("class", "resultText");
//Sets a variable to hold the text the <p></p> should contain (in this case an empty tag)
var node2 = document.createTextNode(" ");
//Actually adds the text to the <p></p> element
p2.appendChild(node2);
//adds the <p></p> tag to the results div
element.appendChild(p2);
}
}
}
}
</script>
</div>
</body>
</html>
Node.appendChild() will put the new element to the end of the list of children of the node, or move the existing element to there.
In your code, if you want to print 4 # in a line, change this line:
p1.appendChild(node1);
to
for (var i = 0; i < 4; i++ ) {
p1.appendChild(node1);
}
The reason that your code is printing out #s in separated lines is, element p1 with a pair of tags <p></p> will add space before and after the content.
Try this HTML snippet and you will get it:
<p>Text1</p>
<p>Text2</p>
EDIT
if you want to include the quotes in your output, do it like this:
var node1 = document.createTextNode('"#" "#" "#" "#"');
That is, use single quote around the double quotes and put space in the element. You don't need to repeatedly insert multiple text nodes in order to output a line of something.

Categories