I am adding a third party comment plugin on my html pages. The plugin slows down the pageload somewhat due to the number of connections the page makes to load the comment plugin.
The comment plugin will be contained within a div.
I would like to delay the loading of the comment javascript until a visitor clicks a 'add/read comments' button/link.
The language for the page is html5. I want to preferably, if possible, keep my pages as .html
The pages are html5 and css3.
my ccs3 and html5 knowledge is average. my javascript knowledge is poor. all other languages i haven't a clue about.
I was going to have the 'add/read comments' button/link, load up a duplicate page with the third party comment plugin loaded, but felt this was a messy way of doing this, as well as adding more time (another pageload then the plugin script) for the user to wait before being able to comment.
I don't want this comment plugin loading at all, not even in the background, until the user clicks the button. The reason for this, is because I don't want the user to see any indication of the page hanging/still loading, when the page load is complete without the comment plugin visable.
I sincerely hope this makes sense for someone to follow.
Answers will be much appreciated.
Thankyou for your time.
The following is the code livefyre gave me to insert into my html..
<div id="SPLUG"> <--- that is the div i am surrounding the comment plugin in
<div id="livefyre-comments"></div>
<script type="text/javascript" src="http://zor.livefyre.com/wjs/v3.0/javascripts/livefyre.js"></script>
<script type="text/javascript">
(function () {
var articleId = fyre.conv.load.makeArticleId(null);
fyre.conv.load({}, [{
el: 'livefyre-comments',
network: "livefyre.com",
siteId: "xxxxxx",
articleId: articleId,
signed: false,
collectionMeta: {
articleId: articleId,
url: fyre.conv.load.makeCollectionUrl(),
}
}], function() {});
}());
</script>
<!-- END: Livefyre Embed -->
</div>
You can dynamically inserting external JavaScript to web pages when click on a button:
<button onclick="addScript()">Click</button>
<script type="text/javascript">
function addScript() {
var headTag = document.getElementsByTagName("head")[0];
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = 'http://code.jquery.com/jquery-1.9.1.min.js';
headTag.appendChild(newScript);
}
</script>
It's not really difficult. Defer loading of JavaScript or external stuff is now needed for faster page loads. For example, there are Facebook/twitter plugins which I wanted to load once my page is loaded so one way to do is to initialize external plugins loading in window.onload or $(window).load in case of jQuery.
In your case, in the comment button onclick event, load the JavaScript of external plugin. What we typically do is manipulate the elements using Document Object Model (DOM).
As an example, I want to load an iframe on button click:
<input type="button" id="btnComment" onclick="createframe();" style="height:50px; width:120px;" value="Click Me!" />
<div id="container"></div>
function createframe() {
var i = document.createElement("iframe");
i.src = "http://www.adilmughal.com";
i.scrolling = "auto";
i.frameborder = "0";
i.width = "90%";
i.height = "220px";
document.getElementById("container").appendChild(i);
}
What this will do is create a new iframe element with any src URL and append as container's child.
Output and code can also be viewed on http://jsfiddle.net/adilmughal/ZJZn7/
I've taken a look at the liveFire docs, and it looks like it should be easy enough to initialise it on click, rather than as the page loads.
However, liveFyre actually initialises as soon as it can - rather than playing nice and waiting for the page to be ready. This is very likely the reason it slows down your page load. Does your liveFyre code look like this?
<!-- START: LiveFyre Embed -->
<script type="text/javascript" src="http://livefyre.com/wjs/javascripts/livefyre.js"></script>
<script type="text/javascript">
fyre = LF({
site_id: xxxxx,
version: '1.0'
});
</script>
<!-- END: LiveFyre Embed -->
If it does, try changing it to:
<!-- START: LiveFyre Embed -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script type="text/javascript" src="http://livefyre.com/wjs/javascripts/livefyre.js"></script>
<script type="text/javascript">
$(function(){
fyre = LF({
site_id: xxxxx,
version: '1.0'
});
});
</script>
<!-- END: LiveFyre Embed -->
This should just make livefyre wait until the page is interactive before it tries to initialise. It may not help enough (or at all), but it's a safe and easy option to try first. If it doesn't help enough, post back, and we'll pursue your 'initialise on click' option.
--- UPDATE ---
Based on your comments with the code snippet, try this (I think the comment has been a little bit mangled - hopefully you can translate this over OK:
<script type="text/javascript" src="zor.livefyre.com/wjs/v3.0/javascripts/livefyre.js">
<script type="text/javascript">
$(function(){
var articleId = fyre.conv.load.makeArticleId(null);
fyre.conv.load({}, [{
el: 'livefyre-comments',
network: "livefyre.com",
siteId: "xxxxxx",
articleId: articleId,
signed: false,
collectionMeta: {
articleId: articleId,
url: fyre.conv.load.makeCollectionUrl()
}
}]
, function() {});
})();
</script>
Again, the idea is just to wait for the page to be interactive before trying to initialise. Let us know what happens!
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 am using Bootstrap as my template, and Laravel as my framework. As suggested within the examples, you should load your jQuery script at the bottom of the page - to speed up the loading.
Within my application, I have this function that checks if an alert exists in the session, and if so, show it:
$(document).ready(function() {
toastr.options = {
"closeButton": false
};
toastr. {
{
Session::get('flash_notification.level')
}
}('{{ Session::get('
flash_notification.message ') }}')
});
This is shown above where I load the jQuery script:
#if (Session::has('flash_notification.message'))
<script>
The above script is loaded here.
</script>
#endif
#yield('content')
</div>
<!-- Scripts -->
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
In order to get this working, I need to declare my jQuery file in the header of the template, but I know this isn't best practice. I initially thought that by using the $(document).ready() method, it would resolve this, but it doesn't.
Any help would be greatly appreciated.
It is best to put the script calls in the footer so they are loaded last. This means that any other JS you write will need to be below them. You could add your other JS to another file which is included after the jQuery load.
If you cannot, you could add it to the header and add the defer attribute to the script tag to defer it's loading.
Option 1 should be preferred though.
I have three different ways to add Twitter code for loading Twitter button that seems almost identical to me, but for some reason only two of them do work.
Here is how I define Twitter button in HTML:
Tweet
Here is a fist method that works, just embed JavaScript code in the page:
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
Here is a second way that works, put this function into a separate file and load this file on page load:
<script>
$(window).bind("load", function() {
// js/social.js just contains the same code that
// was in <script> tag in previous example
$.getScript('js/social.js', function() {});
});
</script>
But if I just include js/social.js file via tag it doesn't work:
<!-- js/social.js here has the same content as in the previous example -->
<script type="text/javascript" src="js/social.js"></script>
and image does not load.
Could you explain what it the difference between those variations?
I am using Firefox 40.0.3
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!