I made a loader that uses css and javascript to play an animation. On loading the site for the first time the animation sometimes doesn't play leaving a blank white screen. I believe it has something to do with caching on the second load that makes it work. Thanks in advance.
HTML:
<section id="loading">
<div class="circle spin"></div>
<img src="src/j2.svg" alt="J2 Logo">
</section>
<link rel="stylesheet" href="css/loading.css">
<script type="text/javascript" src="scripts/loading.js"></script>
loading.css:
https://pastebin.com/E16PMTtQ
loading.js:
https://pastebin.com/1X09KatC
The websites link is https://j2.business
With a quick look at your code it looks like all code is executed when the javascript-file gets loaded. This could be a timing-issue (your javascript-file is retrieved faster than your HTML-page: the elements it wants to act on are not available yet).
With jQuery you can quickly solve that by embedding your variables and functions in this holder:
$( document ).ready(function() {
// place code here, the document is waiting
});
Because you are not using jQuery you could use this:
add the "defer" attribute.
<script type="text/javascript" src="scripts/loading.js" defer></script>
This should be enough, specs found here:
https://www.w3schools.com/tags/att_script_defer.asp
Or if you want only some functions executed when the document is loaded you could use the function which all browsers support:
(function() {
// place code here, the document is waiting
})();
Related
I want to serve a little HTML snippet that other pages can include.
The HTML content would look something like this:
<div id="coolIncludable" style="display:none"> <!--be invisible until you are finished initializing -->
<div>Cool stuff here</div>
<div>More cool stuff and so on...</div>
</div>
<script src="http://somehwere/jquery.js"></script>
<script src="http://somewhere/something.js"></script>
<script>
$(function(){$('#coolIncludable').show();});//<- actually contained in a script file, just for illustration
</script>
I'm planning to use the method detailed here: https://www.w3schools.com/howto/howto_html_include.asp to do the actual including. Let's say the page looks something like this:
<html>
<head>
</head>
<body>
<H1>Content before snippet</H1>
<div id="registerWrapper" html-include="http://somehwere/snippet.html">
No content loaded
</div>
<H1>Content after snippet</H1>
<script type="text/javascript" src="http://somehwere/html-include.js"></script>
</body>
</html>
The HTML snippet gets loaded and embedded all right, but the JavaScript that comes with it never gets executed. Is there a way to embed content including scripts that makes sure they are executed?
I don't expect to control the embedding page, so I cannot rely on it having jQuery or anything else loaded. I therefore avoided using jQuery in the embedding function and restricted myself to plain JavaScript. Loading jQuery is one of the things the <script> tags at the end of the snippets would do.
Since you are using jQuery you can use it's built in load() method to do what you want
Something like:
HTML
<div class="include" data-include="page2.html"></div>
JS
$('.include').each(function(){
const $el = $(this), url = $el.data('include');
$el.load(url)
});
Then make sure the script tag for the new content is below that content.
Simple working demo
In retrospect, my mistake is glaringly obvious:
What does the line $(function(){$('#coolIncludable').show();});
do? does it execute $('#coolIncludable').show();? No it doesn't. It registers a callback to do so that gets triggered by the 'load' event, which already has fired, and won't fire again.
On the other hand, that's really a moot point because the code never even gets executed.
Here's what I learned about dynamic loading of javascript
Injecting script tags directly does not work
script tags injected by setting element.innerHtml do not get executed
<div id="snippet">
...
</div>
<!-- neither of these will be executed -->
<script type="text/javascript">alert("stuff");</script>
<script type="text/javascript" src="http://somewhere/script.js"></script>
Creating script tags dynamically does work
What does work is dynamic tag generation the way it is described in this article: JavaScript Madness: Dynamic Script Loading
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'helper.js';
head.appendChild(script);
//At this point (or soon after) the code in helper.js will be executed
You would do that in your loading script. My loading script looks something like this:
function importJsFiles(){
const scriptFiles = ["http://somewhere/jquery.js",
"http://somewhere/stuff.js",
"http://somewhere/bootstrapSnippet.js"];
for (let i = 0; i< scriptFiles.length; i++){
importJsFile(scriptFiles[i]);
}
}
function includeSnippet(){
//See https://www.w3schools.com/howto/howto_html_include.asp
//We still have to do it without jQuery,
//because at the time this executes the injected jquery.js
//hasn't run and we do not yet have jQuery available
}
importJsFiles();
//At this point, all script tags are created, but the scripts are NOT loaded yet
includeSnippet();
//At this point, the dom is in its final shape
bootstrapSnippet(); //<- This won't work, because the script tags injected by this code won't be evaluated until after this file/function/whatever returns
//bootstrapSnippet.js
function bootstrapSnippet(){
alert("Snippet JS running")
if (window.jQuery) {
alert("JQuery is avaliable"); //<- This will fire, because the new script
// tags are evaluated in order, and we put the
// jquery.js one before the bootstrapSnippet.js one
}
//So now we CAN do this:
$('#coolIncludable').show();
}
bootstrapSnippet();
There are many more interesting ideas and details in this post that I picked the link above from. I hope someday I'll find time to explore them all.
I’m including one HTML file in another, as a way to reuse my header and navigation generation logic.
The trouble is that when I browse to pages on my site, I can see the HTML that isn’t included in the include files load first. Only then you can see the menus and banners load afterwards. I’d like everything to appear to load at the same time.
Here's the rendered HTML.
And here’s a code snippet showing you how I generate these pages:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="assets/js/jquery-2.1.3.min.js"></script>
<script>
$(function(){
$("#includeHeader").load("includes/templates/header.html");
$("#includeNavigation").load("includes/templates/navigation.html");
});
</script>
<div id="includeHeader"></div>
</head>
<body>
<div id="wrapper">
<!-- Navigation -->
<div id="includeNavigation"></div>
I’m currently working with the code to try to move any external libraries / CSS to the bottom of the page vs. in the header. But so far, that hasn’t really changed or improved anything.
You should use one of the templating languages.
If your includes are simple HTML files then you could use Handlebars or Dust - you could just copy your code and that's it, then in Javascript you would need just render these templates - see the documentation.
You could use Jade/Pug instead, but its syntax is different from the HTML, so that's not just question of copy-paste.
You are using $(handler) to load them, which is a form for $.ready(). So it waits for the document to load everything before loading your header.html and navigation.html.
Try
<head>
<script src="assets/js/jquery-2.1.3.min.js"></script>
</head>
<body>
<div id="includeHeader"></div>
<script>
$("#includeHeader").load("includes/templates/header.html");
$("#includeNavigation").load("includes/templates/navigation.html");
</script>
</body>
Your problem is that the load function does not run until the document.ready event has fired. Which is probably after your page has started rendering. To get everything to appear at the same time you could use the callback from .load to show everything. So everything is hidden,
$( "#result" ).load( "ajax/test.html", function() {
/// show your stuff
});
You will of course need to know both has loaded.
I would recommend not using javascript to render HTML from a static path and would use a server side lang instead for speed.
I think it make some level fast its not waiting for load all dom element, I am considering #includeNavigation element is under #includeHeader element
<head>
<script src="assets/js/jquery-2.1.3.min.js"></script>
</head>
<body>
<div id="includeHeader"></div>
<script>
$("#includeHeader").load("includes/templates/header.html", function(data){
console.log("header loaded");
$("#includeNavigation").load("includes/templates/navigation.html", function(data){
console.log("navigation loaded");
});
});
</script>
</body>
Using the JS loader head.js I'm having a bit of a hard time distinguishing the subtle differences between head.ready() and head.load().
head.ready('jquery.js', function(){//Do something});
VS
head.load('jquery.js', function(){//Do something});
As far as I understand both seem to load 'jquery.js' and then perform a callback when it is loaded. However, in practice I get some edge cases where head.load doesn't work as expected in Firefox making me think I am not understanding where to use head.load and where to use head.ready.
Reading the API it seems like head.load loads the content, but head.ready is an Event Listener, you can also add a callback to head.load and would work too, but head.load is the only one who can actually load the resources, head.ready not.
EDIT: An example
<html>
<head>
<script src="head.min.js"></script>
<script>
// this loads jquery asyncrounously & in parallel
head.load("jquery.min.js");
</script>
</head>
<body>
<!-- some content-->
<!-- injected via a module or an include -->
<script>
// some function that depends on jquery
head.ready("jquery.min.js", function () {
// this will only be executed once jquery has finished loading
$(".main").hide();
});
</script>
<!-- some content-->
</body>
</html>
I'm developing a web application that because of performance concerns is heavily reliant on Ajax functionality. I'm attempting to make parts of each page available while longer running modules load.
The issue is that I want to kick off the Ajax requests as soon as possible (in the head of the document). This part works fine; the issue is on rare occasion, the Ajax call will come back before the area that I want to load the Ajax data into is present on the page. This causes the data to not be loaded.
To get around the issue I started using script tags below each of my containers that resolve a JQuery promise to let the code know that the area is available.
EDIT: I want to load the data into the area as soon as it becomes available (before full document load).
The current pseudo code looks like this:
<head>
<script>
var areaAvailablePromise = new $.Deferred();
$.when(areaAvailablePromise, myAjaxFunction()).then(function(){
// load data into the element.
});
</script>
</head>
<!-- much later in the document -->
<div class="divIWantToLoadAjaxContentInto"></div>
<script>
areaAvailablePromise.resolve();
</script>
My question is: is there ANY better way to handle this situation? Every one knows that inline scripts are blocking and are bad for performance. Also, I feel that this is going to lead to cluttered code with micro-script tags all over the place.
Put your (whole) <script> tag just after the element.
HTML is parsed from top to bottom, so the element will be loaded already.
No. There really is no better way to my knowledge.
<!doctype html>
<html>
<head>
<script src="jquery.min.js"></script>
<script src="q.min.js"></script>
<script>
var elD = Q.defer();
var dataP = Q($.ajax(…));
Q.spread([elD.promise, dataP], function (el, data) {
…
}).done();
</script>
</head>
<body>
…
<div id="foo"></div>
<script>elD.resolve($("#foo"));</script>
…
</body>
</html>
you can use:
$(document).ready( handler )
(recommended)and also has contracted form:
$(handler)
exemple:
$(function(){
alert("OK");
})
read more: http://api.jquery.com/ready/
I have been puzzling with this for quite a while and can't get it to work. Here is the situation. I want a SOCIAL MEDIA bar to ONLY appear if people click some DIV. It should not be loaded unless people click the div. For Social Media I have ADD THIS, and the GOOGLE+1 icon. But I can not get them to load by such an external call. Here is the code so far:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=ISO-8859-1" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$("#socialmedia").live('click',function(){
$("#loadhere").load('html-part.html');
$.getScript('js-part.js');
});
});
</script>
</head>
<body>
<div id="socialmedia">
Show the Social Media
</div>
<div id="loadhere">
</div>
</body>
</html>
In the HTML part I have the HTML info that needs to be loaded:
html-part.html:
<!-- AddThis Button BEGIN -->
<div class="addthis_toolbox addthis_default_style ">
<a class="addthis_button_facebook_like" fb:like:layout="button_count"></a>
<a class="addthis_button_tweet"></a>
<a class="addthis_counter addthis_pill_style"></a>
</div>
<!-- AddThis Button END -->
<g:plusone size="medium" id="gg"></g:plusone>
</div>
For the JS part I am struggling. Here is what needs to be loaded:
<script type="text/javascript">var addthis_config = {"data_track_clickback":true};</script>
<script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#pubid=ID"></script>
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
I have tried to call them one by one:
$.getScript('http://s7.addthis.com/js/250/addthis_widget.js#pubid=ID');
$.getScript('https://apis.google.com/js/plusone.js');
But I guess this is a crossdomain problem...?
If I use PHP to obtain the content, and load a local PHP file, it still does not work. Before spending one more day on this... is this possible to achieve?
The problem here is that addthis code fires on dom ready event. When you load it with jQuery the dom has already been loaded so the code is not executed. The fix is to use addthis.init() method to force the code execution after you load the code. There is no cross domain problem or anything.
Note that according to addthis documentation it should be possible by just passing a get variable through the widget url like this http://s7.addthis.com/js/250/addthis_widget.js#pubid=[PROFILE ID]&domready=1 but it didn't work for me.
I would also recommend you store the html in a string variable, that way you don't have to do unnecesary requests for a little static html.
See working demo here: http://jsfiddle.net/z7zrK/3/
$("#socialmedia").click(function(){
var add_this_html =
'<div class="addthis_toolbox addthis_default_style ">'+
'<a class="addthis_button_facebook_like" fb:like:layout="button_count"></a>'+
'<a class="addthis_button_tweet"></a>'+
'<a class="addthis_counter addthis_pill_style">'+
'</a>'+
'</div>'+
'<g:plusone size="medium" id="gg"></g:plusone>';
$("#loadhere").html(add_this_html);
$.getScript('http://s7.addthis.com/js/250/addthis_widget.js#pubid=xxx',
function(){
addthis.init(); //callback function for script loading
});
$.getScript('https://apis.google.com/js/plusone.js');
});
Just used amosrivera's answer (huge kiss to you btw :) and ran into another issue :
Addthis object can only be loaded once, so when you have multiple addthis toolboxes on the same page it may only work for the first clicked toolbox.
The workaround is to do :
if (window.addthis){ window.addthis = null; }
before calling
addthis.init();
Here's what I've just done to start loading the buttons only when an article is hovered long enough :
HTML:
<article data-url="someUrl" data-title="someTitle" data-description="someDesc">
.....
<div class="sharing">
<div class="spinner"></div>
<div class="content"></div>
</div>
</article>
JS :
// Only throw AJAX call if user hovered on article for more than 800ms
// Then show the spinner while loading buttons in a hidden div
// Then replace the spinner with the loaded buttons
$(function() {
var t;
$("article").hover(function() {
var that = this;
window.clearTimeout(t);
t = window.setTimeout(function () {
sharing_div = $('.sharing', that);
add_this_html =
'<div class="addthis_toolbox addthis_default_style "> \
<a class="addthis_button_facebook_like" fb:like:layout="button_count"></a> \
<a class="addthis_button_google_plusone" g:plusone:size="medium"></a> \
</div>';
if (sharing_div.find('.content div').length == 0) {
sharing_div.find('.spinner').show();
sharing_div.find('.content').html(add_this_html);
sharing_div.find('addthis_toolbox').attr({
'addthis:url': $(that).attr('data-url'),
'addthis:title': $(that).attr('data-title'),
'addthis:description': $(that).attr('data-description'),
})
if (window.addthis){ window.addthis = null; } // Forces addthis to reload
$.getScript('http://s7.addthis.com/js/250/addthis_widget.js#pubid=xxx&async=1',
function(){
addthis.init();
setTimeout(function() {
sharing_div.find('.spinner').hide();
sharing_div.find('.content').show();
}, 2500);
});
}
}, 800);
});
});
To answer your official question, yes, I believe this is possible to achieve.
But, to further elaborate on this, I believe what you may want to try working with is the order in which your external scripts and external markup are loaded. An interesting situation we find when dealing with asynchronous actions such as these, is that they don't always complete, load, or execute in the order you would like unless you specifically say so. jQuery lets you do this through some callbacks you can pass to the getScript and load methods.
There also should not be a "cross-domain" problem with javascript files on other domains, though there certainly is when loading HTML.
I'm not sure if this will exactly solve the problem you're having, but it certainly feels like this is worth a try. You could try making sure the markup loads before the scripts do:
$(function(){
$("#socialmedia").live('click',function(){
$("#loadhere").load('html-part.html', function() {
// this waits until the "html-part.html" has finished loading...
$.getScript('js-part.js');
});
});
});
Now, we should also ask about how you are building your "js-part.js" file. (You only showed what you wanted, not what you've built.) If this is truly a JS file, you can't just use some HTML <script> tags to load other JS files. (You would instead want to continue calling getScript in this file, or use one of several other approaches to get your other JS stuff loaded, such as manually appending script elements to the document's head, or using another library, etc...)
Good luck!