How to prevent HTML from loading until all server data is processed? - javascript

In my project, my JS receives information from server and then displays it on HTML. However, when I acess the page, the data is not fully loaded yet, so the entire HTML is loaded but the data is not. It forces me to wait X milliseconds to see the last thing to complete the page (the data).
I want to make all elements (divs, span, buttons, my data) load exactly when data's retrieved and ready to be shown. Also, I wanted to do this by displaying a simple waiting gif in order to make the user pacient about it, but I'm not sure how to do it.
window.onload = ()=>{
var questionPlace = document.querySelector("#question-place");
displayPrevious(data, questionPlace);
}
<head>
<script src='./scripts/index.js' type='module'></script>
</head>
<body>
<div class="flexbox-container" id="question-place"> <!-- data here --> </div>
<!-- buttons, divs, etc -->
</body>

Rather than window.onload, use $.when($.ajax()).then():
Option 1:
Create every element using document.createElement:
//window.onload = () => {
$.when($.ajax("file.txt")).then((data, textStatus, jqXHR) => {
var elements = [];
elements.push(document.createElement('div'));
});
And the only element that should be in the <body> would be your gif:
<body>
<img src="loading.gif" alt="Loading...">
</body>
Option 2:
Set every element to have display: none;:
<head>
<style>
* {
display: none;
}
</style>
</head>
<body>
<!-- other elements -->
<img src="loading.gif" alt="Loading..." onload="(event) => event.target.style.display = 'block'">
</body>
And again wait for the call to finish and set everything to block:
$.when($.ajax("file.txt")).then((data, textStatus, jqXHR) => {
$("*").css("display", "block");
});

You can hide whatever "parent" HTML element you want and unhide it on the success event for the jQuery get request.
See: Show html after completing work with ajax and jquery

Related

Run google scripts before html page load

I am creating a dashboard that is based on google scripts which pulls data from spreadsheet.
But my page loads before the JavaScript runs.
here is my code :-
document.addEventListener('DOMContentLoaded', function() {
google.script.run.withSuccessHandler(chartData).loadCdata();
google.script.run.withSuccessHandler(otherChart).loadCdata();
});
Since I will advance further and a lot more data has to be pulled from server side and I want html to only load "view" after my scripts finish
I have two questions:
1. In current scenario how can I make my html to print after my script runs.
2. how can I prevent loading data array again and again from server side. I just want to run it once and use the array data in different functions. ".loadCdata();"
this image shows only half of my chart is printed
Hide the main div and then display it after the server-side data has loaded.
<div id="main" style="display:none">
.... content
</div>
<script>
google.script.run.withSuccessHandler(function() {
document.getElementById("main").style.display = "block";
}).loadData();
</script>
To display HTML after the server script completes, start off by having the HTML hidden (e.g. display: none) and then have your chartData() function change the display attribute so it becomes visible. (You can use a Promise to make sure it happens in the correct sequence.)
Use the Web Storage API to save your array data in the browser storage.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div id="chart1" style="display:none">
<!-- Chart 1 -->
</div>
<div id="chart2" style="display:none">
<!-- Chart 2 -->
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
google.script.run.withSuccessHandler(populateCharts).loadCdata();
});
/**
* Populate the charts, make them visible, and save data to sessionStorage for later usage.
*/
function populateCharts(data) {
return new Promise((resolve, reject) => {
// Populate charts
resolve();
}).then(() => {
// Make the charts visible
document.getElementById("chart1").style.display = "block";
document.getElementById("chart2").style.display = "block";
// Save chart data to session storage
sessionStorage.setItem("chartData", JSON.stringify(data));
});
}
</script>
</body>
</html>

Load Clicked Id's Website in iframe on Click for Website in Database

Current Website:
enter image description here
I have a website that is generated by a for loop from a call to my database using php & mysql. I have an id, names, company website, address and image. It currently displays the name, description, and image all displayed in stacked square boxes.
On click of the box, I'm trying to load an iframe of the company website that then overlays the box. I have been able to get all of the website iframes to load when I load the site, but if there are more than 5-6 rows of data, the site loads very slow because it's loading ~7 websites.
I've spent most of the day looking through jquery and iframe questions but still have not been able to get my iframes to load on click individually when you click on the box. my intention is to have the user click on the description/company box not the iframe. This will then load the iframe and have it appear over the company box where it fills/hides the content in the box completely overlaying the box content.
How do you load a website onclick that is opened within an iframe without loading all of the iframes inside a dynamically generated page.
<?php require_once('include/header.php')?>
<? require('include/navigation.php') ?>
<html>
<head>
<meta charset="utf-8">
<title>Coworking Spaces</title>
<link rel="stylesheet" type="text/css" href="<?php echo base_url('assets/css/mystyles'); ?>">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<script>
jQuery(function(){
$("iframe").each(function(){
this.tmp = this.src;
this.src = "";
})
.parent(".website")
.click(function(){
var frame = $(this).children("iframe")[0];
console.log(frame); frame.src = frame.tmp;
});
});
</script>
</script>
</script>
</head>
<body>
<div id="container">
<div id='city_header'>
<div id='city_search'>
<h1>
Kansas City
</h1>
</div>
</div>
<div id="body">
<?php for($i = 0; $i < count($cospaces); ++$i){?>
<div class="company_box" style ="background-image: url(<?php echo($cospaces[$i]['image'])?>);">
<div class="name_box">
<h3 class="space_name"><?php echo($cospaces[$i]['name'])?></h3>
</div>
<div class="description">
<p><?php echo($cospaces[$i]['description']) ?></p>
</div>
<!-- iframe wanting to load -->
<iframe id = "website" data-src="<?php echo($cospaces[$i]['website'])?>" width="200" height="200" style="background:#ffffff"></iframe>
</div>
<?php } ?>
</div>
<p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds</p>
</div>
</div>
</body>
</html>
TESTED Suggested implementation:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function($) {
$('iframe').bind('load', function() {
var childFrame = $(this).contents().find('iframe');
var childElement = childFrame.contents().find('body');
var src = $(this).attr('data-src');
childElement.on('click', function() {
childFrame.attr('src', src);
});
});
});
</script>
</head>
<body>
<iframe data-src="https://jsfiddle.net" srcdoc="<iframe id='hi' srcdoc='<body>Click me</body>'></iframe>">
</iframe>
</body>
</html>
I am not seeing where this.src is defined within the PHP generated iframes for your initial .each function call.
I am also unsure why you are calling .parent('.website'), since that would traverse upward looking for a wrapping element with class="website", where the PHP generated iframes would have no parent other than the div with id="body".
e.g your code is looking for:
<div class="website">
<iframe></iframe>
</div>
One thing to keep in mind when working with iFrames, is that their content is not available on DOMReady, so you must attach a load listener to each iFrame you want to modify the contents of.
If I understand you correctly, you simply want the src of the iframe to load when a user clicks the iframe. Have you tried something like
jQuery(function($) {
$('iframe').on('click', function(e) {
var frame = $(this);
frame.attr('src', frame.attr('data-src'));
frame.off('click'); //remove on-click event to prevent reloading on click
});
});
The iFrame target is very small, and would only trigger the click event when clicking the outer-border of the iFrame and not its content body. iFrames do not act like <div> elements or other block elements in regards to DOM Events, and mileage will vary on what you can do per browser and per version.
Unless you are attempting to find iframes and change their source within the Coworking Spaces created iframes, which is not possible using Javascript unless the child iframes reside on the same domain. See: Same Origin Policy
Otherwise you can do something similar to
jQuery(function($) {
$('iframe').bind('load', function() {
var childFrame = $(this).contents().find('iframe');
var childElement = childFrame.contents().find('body');
var src = $(this).attr('data-src');
childElement.on('click', function() {
childFrame.attr('src', src);
});
});
});
This will tell your script to wait for each master iframe to load, find its child iframe, attach an onclick event to the child iframe body to set the source to the master iframes data-src
Example: https://jsfiddle.net/Laomfx7g/
I use the srcdoc attribute to load static HTML into the iFrame to demonstrate binding to same-origin content, since I would not be able to edit the source content of an external website from jsfiddle.
Lastly element id's (specifically <iframe id="website" in your for loop) are expected to be unique, and will function wildly different in varying browsers. Some will only affect the first element with the specified id, others will affect the last, where a few will read all of the specified ids, which may or may not be intended.
EDIT - from comment clarification
jQuery(function($) {
$('.description').on('click', function() {
var frame = $(this).next('iframe');
frame.attr('src', frame.attr('data-src'));
$(this).off('click'); //remove click event
});
});
Example: https://jsfiddle.net/2x0yfpts/

I want to show a image first then I want to show the site content

Suppose I have a page named a.html and a picture x.
Now, when users go to a.html, I want to show the picture x for 3/4s then I want to show the page content.
Can anyone help me to do this?
Here is a small code that will use pure js to show a image prior to showing the content of the site. I think this is similar to what people use to show a loading image before loading the content.
<html>
<head>
<title>Image before loading content</title>
</head>
<body onload="show();">
<div id = "myDiv">
<img id = "myImage" src = "http://jimpunk.net/Loading/wp-content/uploads/loading45.gif">
</div>
<div id="content" style="display: none;">
This is a CONTENT SECTION Put your content here
</div>
<script type = "text/javascript">
function show() {
document.getElementById("myDiv").style.display="block";
setTimeout("hide()", 5000); // 5 wait, change the delay here
}
function hide() {
document.getElementById("myDiv").style.display="none";
document.getElementById("content").style.display="block";
}
</script>
</body>
This yo can put in a HTML page and you shold be able to see where i made the image and where the delay time will be happening.
Here is a working example using the above code: https://jsbin.com/pixemiwubu/edit?html,output

How to check if DOM element is fully loaded?

I'm loading really big web page with thousands of elements.
How can I test if node has fully loaded including it self and all it child elements but I don't want to wait for whole page to be loaded.
For example lets have this page:
<html>
<head>
<script>
var cnt = 0;
var id = setInterval(function test() {
var e = document.querySelector('#content')
if (!e) return;
// how to test is "e" fully loaded ?
if (cnt == e.childNodes.length) {
clearInterval(id);
} else {
cnt = e.childNodes.length;
console.log(cnt);
}
}, 10);
</script>
</head>
<body>
<div id="content">
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div>
<!-- ... add 30k div elements -->
</div>
</body>
</html>
This will print something like this on console:
4448
9448
14448
19448
24948
30000
I think that the load event would be an more apropriate answer to your question.
It can be atached to an ellement and fires when everything is loaded including images and other resources.
some examples you can find here.
https://developer.mozilla.org/en-US/docs/Web/Events/load
https://www.w3schools.com/jsref/event_onload.asp
but if you don't care about the resources than you might want to look at this.
https://developers.google.com/speed/docs/insights/rules
say you want to alert after the div#content is loaded. if you put your javascript after div's closing tag, it will run after loading all the html prior to the script.
<div id="content">
// your content
</div>
<script type="text/javascript">
alert("finished loading until this point");
</script>

Avoid GET of all contents of the HTML DOM

Context
I have a HTML5+CSS+JS slideshow designed to be synchronized between 50 clients in a domestic LAN with one wireless router.
Problem
Since the contents of the slides (mainly pictures) may be too heavy, I want to load them dynamically for each slide (e.g. as the client clicks a "next" button), since currently the site GETs all the files for every slide from the server at the beginning when the page is loaded, overloading the router.
In this question (another approach for the same problem) an user suggested me using AJAX to get only the DOM and then loading its contents dynamically. Nevertheless, his solution doesn't work for me, as the contents are loaded before the moment I want to.
Is this AJAX based approach correct? If so, what may I be doing wrong?
My code
slideshow.html (slideshow structure)
<html>
<head>
<title>My Slideshow</title>
<script src="javascripts/slidesplayer.js"></script>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<div id="slides-containter">
<div class="slide" id="slide_1">
<!--Contents such as images, text, video and audio sources -->
</div>
<div class="slide" id="slide_2">
<!--Contents -->
</div>
<!--A bunch of slides here-->
</div>
<script>
// Here I load the slides calling a function defined in slidesplayer.js
</script>
</body>
</html>
slideshow-placeholder.html (loaded when I enter to the slideshow URL)
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="/path/to/ajaxSlidesScript.js"></script>
</head>
<body>
<h1>Hello slides!</h1>
</body>
</html>
ajaxSlidesScript.js
$(document).ready(function() {
$.ajax('/path/to/slideshow.html', {
async : false,
complete : function ajaxCallback(slidesDOM) {
// Pull out the individual slides from the slideshow HTML
$slides = $(slidesDOM.responseText).find('.slide');
// For each one ...
$slides.each(function prepareSlide() {
// Store a reference to the slide's contents
var $slideContent = $($(this).html()); // <--- GETs all the files for this slide which I want to avoid.
// Empty the contents and keep only the slide element itself
var $slideWrapper = $(this).empty();
// Attach to focus event handled by the slideware
$slideWrapper.appendTo('body').on('focus', function injectContent() {
// Put the content in — NOW external resources should be downloaded via GET and loaded, not before.
$slideWrapper.append($slideContent);
});
});
}
});
});
Update: This approach won't work, as manipulating DOM object will cause the download of the resources even if you don't insert them in the DOM. You can see what I did in this question.
Ajax is definitive the right technology for your problem but as far as I can see your problem is simple.
<script src="javascripts/slidesplayer.js"></script>
<link rel="stylesheet" href="/stylesheets/style.css">
With this piece of code it doesn't matter if you use ajax or not because you load the CSS file already and all images referenced in this CSS file are load directly at the beginning. In addition you should load all files asynchronous.
You can add <img> tags via JavaScript and load the images asynchronous...

Categories