Trying to understand how to eliminate or minimize render delay of different JavaScript libraries on a site.
For example, if I want to load the "instant" follow buttons from many Social Networks, they seem to block each other out of rendering and you get unpleasant pop-ins.
<div id="fb-root"></div>
<script>
(function(d, s) {
var j, h = d.getElementsByTagName(s)[0],
f = d.createDocumentFragment(),
add = function(u, i) {
if (d.getElementById(i)) {
return;
}
j = d.createElement(s);
j.src = u;
i && (j.id = i);
f.appendChild(j);
};
add('http://apis.google.com/js/plusone.js');
add('http://connect.facebook.net/en_US/all.js#xfbml=1', 'facebook-jssdk');
add('http://platform.twitter.com/widgets.js', 'twitter-wjs');
add('http://platform.linkedin.com/in.js');
add('http://assets.pinterest.com/js/pinit.js');
h.parentNode.insertBefore(f, h);
}(document, 'script'));
</script>
<div id="wrapper" style="width:100%; max-width:800px; margin-left:auto; margin-right:auto; text-align:center;">
<div id="widgetWrapper" style="width:100%; max-width:800px; background-color: #eee; padding: 10px; margin-left:auto; margin-right:auto;">
<div class="followBox">
<div class="fb-like" data-href=" " data-layout="button_count" data-action="like" data-show-faces="false" data-share="false"></div>
</div>
<div class="followBox">
<div class="g-follow" data-annotation="bubble" data-height="20" data-href=" " data-rel="author"></div>
</div>
<div class="followBox">
Follow
</div>
<div class="followBox">
<div class="g-ytsubscribe" data-channel=" " data-layout="default" data-count="default"></div>
</div>
<div class="followBox">
<iframe class="btn" frameborder="0" border="0" scrolling="no" allowtransparency="true" height="25" width="113" src="http://platform.tumblr.com/v1/follow_button.html?button_type=2&tumblelog= &color_scheme=dark"></iframe>
</div>
<div class="followBox">
<script type="IN/FollowCompany" data-id=" " data-counter="right"></script>
</div>
<div class="followBox">
<a data-pin-do="buttonFollow" href="http://www.pinterest.com/ /">Fun Paw Care</a>
</div>
</div>
</div>
What can be done about this type of render blocking from JS in general? Not specifically just social network buttons, they just provide the best example.
You have very little control over your code this way.
You're actually calling to five different sites in order to load and run their code. If only one site will be a little busy you'll end up in a delayed display on your site.
There are workarounds for this problem and you can see examples almost everywhere.
There are some solutions available:
Homemade social buttons - you create and draw your own icons and attach the external site code 'under the hood'. It may seems like a simple solution but the last time I checked, it involved editing not-so-small lines of code. Personally I'd advise this as a last resort.
One button to rule them all - You probably saw it on other pages, a small sharing button that expand into a box with all you favorite social sites. These come pre-made and are an easy solution.
Patient is virtue - you warp all your links in a hidden container and display it after all renderings are done. The user will see the buttons appear together a few seconds after the site loads.
And keep in mind that javascript has a pretty much one track mind. Even if all your code was stored locally it still would take turns to render all of it.
Related
Stumbling upon a Javascript DOM Elements Counter here and here (courtesy of lingtalfi) I want to speed up my website. Apparently the number of, the length of and the depth of DOM elements seems to have an impact on speed. I want to count the DOM overhead and show it in the HTML without a need for a keypress. This could be done 5 seconds after the page has loaded to not interfere with the speed of the website.
Method 1: Alert Popup Box
<a href="
javascript: (function()
{alert(document.getElementsByTagName('*').length);
}());
">Count DOM nodes of a page
</a>
Method 2: Just Write in HTML
<script>
(function() {
document.write(document.getElementsByTagName('*').length);
}());
</script>
On my site the first method popups 814, while the second method writes 142. Quite a difference!
My question is: Is there a way to (delay and) output the correct number of DOM elements just in HTML without the need to click on a popup to count the DOM elements?
(function () {document.write(document.getElementsByTagName('*').length); }());
body {
font-size: 5em;
font-family: "Arial";
}
I am absolutely not sure about your question!
Are you searching for something like that ?
Please keep in mind that the number in the demo may be larger than the code shows. Stack Overflow adds more elements behind the scenes.
document.addEventListener("DOMContentLoaded", () => {
setTimeout(() => {
document.querySelector('aside').textContent = document.getElementsByTagName('*').length;
}, 5000)
});
<html>
<head>
</head>
<body>
<div class="header">
<div class="pages">
<div class="page">index</div>
<div class="page">contact</div>
</div>
</div>
<div class="main-content">
<div class="section-1">
</div>
<div class="section-2">
</div>
<div class="section-3">
</div>
</div>
<footer>
</footer>
<aside></aside>
</body>
</html>
I've made a similar question in the past, but I decided to try again since I have gone in a different direction since then. (I was trying with YouTube API and wasn't getting anywhere with that)
I'm trying to build a website where different pages are shown by using a function that hides/shows different divs. One of those pages has a video from YouTube and I was trying to figure out a way to stop the video when the respective div is hidden. Right now, the video just keeps playing in the background (you can hear the sound), if you change to another page/div.
After some sleuthing on the internet (i.e. this website), I finally got a solution working which is as follows.
var stopButton = document.getElementById('fecharvideo');
stopButton.onclick = function() {
var myPlayer = document.getElementById("player");
myPlayer.setAttribute("src", " ");
};
Unfortunately, as you can probably guess. This means that after clicking on an element with the id=fecharvideo, the iframe simply disappears, meaning if you return to that div the video will no longer appear, which is not ideal.
Any similar solution to this problem that allows me to reset the video, instead of deleting it altogether?
Here's the fiddle (To test it out Open "Episódio 1", start video, Open "Episódios" through the hamburger menu, and then back to "Episódio 1"): https://jsfiddle.net/Santos1600/qu8ejwsm/20/
Solution:
html
<div id="ep1" class="ep1" style="display: none;">
<div class="video-background">
<div class="video-foreground">
<iframe id="player" src="https://www.youtube.com/embed/videoseries?list=**PLAYLISTID**&modestbranding=1&iv_load_policy=3&rel=0&showinfo=0&loop=1&autoplay=1&autohide=1&enablejsapi=1&playerapiid=ytplayer1" frameborder="0" allowfullscreen allowscriptaccess="always"></iframe>
</div>
</div>
<div class="container">
<!--Menu/Episódio 1-->
<div id="myNav2" class="overlayep">
<div class="overlay-content">
<ul>
<li>EPISÓDIOS</li>
<ul><li>POEMA MEDRICAS</li>
<li>O CÃO</li>
<li>TERAPIA À DISTÂNCIA</li>
<li>MANIA DA PERSEGUIÇÃO</li>
</ul>
<li>SOBRE</li></ul>
</div>
</div>
<div class="botaomenu" onclick="myFunction(this); toggleNav2();">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
<img src="assets/logohorizontal.png" alt="logo" class="logosmall">
</div>
</div>
js
var video1 = document.getElementById('player')
function toggleVideo(a, state) {
var iframe = a.contentWindow;
iframe.postMessage('{"event":"command","func":"' + state + '","args":""}', '*');
}
I've started developing a site at: http://joshrodg.com/isbellfilms2/
I have a WordPress plugin that generates a pricing table. I like the way the plugin works and functions for the user, but needed to tweak one thing.
The plugin has a place for a description, which I don't have, but I would like to add a video instead.
I recognize this is a WordPress website, but the issue I am having is with my scripting.
What I am trying to do is find the Vimeo URL and pass that into a player.
I found a piece of code, tweaked it a bit, but it's not quite working.
The JS I am using looks like:
<script type="text/javascript">
$(document).ready(function() {
var classSelector = document.querySelectorAll('.rpt_description');
var vimeoRegEx = /(?:http?s?:\/\/)?(?:www\.)?(?:vimeo\.com)\/?(.+)/g;
var vimeoEmbed = '<div class="embed-container"><iframe src="https://player.vimeo.com/video/$1" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></div>';
array.prototype.forEach.call(classSelector, function(el) {
if (vimeoRegEx.test(el.innerHTML)) {
el.innerHTML = el.innerHTML.replace(vimeoRegEx, vimeoEmbed);
}
});
});
</script>
The code the plugin outputs with the Vimeo URLs:
<div class="rpt_plan rpt_plan_ori rpt_plan_0 ">
<div style="text-align: center; height: 15px;" class="rpt_title rpt_title_0">The Family Yearbook Film</div>
<div class="rpt_head rpt_head_0" style="height: 250px;">
<div class="rpt_recurrence rpt_recurrence_0">(Yearly)</div>
<div class="rpt_price rpt_price_0"><span class="rpt_currency"></span>$350</div>
<div style="color:#3ac893;" class="rpt_subtitle rpt_subtitle_0">Stay up to date with your changing family for an entire year.</div>
<div class="rpt_description rpt_description_0">https://www.vimeo.com/320417542</div>
<div style="clear:both;"></div>
</div>
<div class="rpt_features rpt_features_0" style="height: 183px;">
<div style="color:black;" class="rpt_feature rpt_feature_0-0">A 3-5 min film every 3 months (4 total films)</div>
<div style="color:black;" class="rpt_feature rpt_feature_0-1">Plus one Keepsake film</div>
<div style="color:black;" class="rpt_feature rpt_feature_0-2">30% off discount on any additional films you purchase that year.</div>
<div style="color:black;" class="rpt_feature rpt_feature_0-3">Upload 30-450 clips</div>
</div>
<div style="clear:both;"></div>
<a target="_self" href="https://isbellfamilyfilms.com/#order-form" style="background:#3ac893" class="rpt_foot rpt_foot_0">Add to Cart</a>
</div>
The regex finds the URL and the JS takes the URL and passes it to the player, something just isn't quite right. I made sure that this JS executes before the plugin, but I have tried it both ways.
I'm sure I'm missing something simple, any help is appreciated.
Thanks,
Josh
Totally forgot the jQuery reference, so embarrassing! Just needed to add this line before my JS code:
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
I also had to capitalize Array
Hope this helps someone!
Josh
jQuery noob here. Sorry if the question is really simple, I haven't been exposed to much jquery, though I am trying to learn.
I am attempting to move a DOM Element from one place to another, but I seem to be running into some errors.
When I attempt to test to see if the DOM exists I get indications that the element is not in the DOM:
if (jQuery('.ls-yourlogo').length) {
alert('Found!');
} else {
alert('NOT FOUND!');
}
I am trying to move .ls-yourlogo into .ls-inner.
I have tried several different things including:
jQuery('#layerslider_1').children('img').appendTo('#layerslider_1').children('.ls-inner');
also
jQuery('.ls-yourlogo').appendTo('.ls-inner');
I do know that the .ls-yourlogo and the .ls-inner DOM elements are both created with jQuery. I'm not sure if that is what is causing the problem.
I am currently working with the Layer slider plugin for WordPress: http://codecanyon.net/item/layerslider-responsive-wordpress-slider-plugin-/1362246
<div id="slider">
<script type="text/javascript"></script>
<script type="text/javascript"></script>
<div class="ls-wp-fullwidth-container" style="height: 317px;">
<div class="ls-wp-fullwidth-helper" style="height: 317px; width: 1349px; left: 0px;">
<div id="layerslider_1" class="ls-wp-container ls-container ls-noskin" style="width: 1050px; height: 317px; margin: 0px auto; visibility: visible;">
<div class="ls-webkit-hack"></div>
<div class="ls-inner">
<div class="ls-layer ls-active">
<img class="ls-s-1">
<p ></p>
<p ></p>
</div>
<div class="ls-layer" >
<img class="ls-s-1">
</div>
<div class="ls-circle-timer"></div>
<div class="ls-loading-container"></div>
<div class="ls-thumbnail-wrapper"></div>
<div class="ls-shadow"></div>
<img class="ls-yourlogo">
</div>
</div>
Thank you for your time.
Finally found a solution for moving an element the Layer Slider DOM.
jQuery('#layerslider_1').layerSlider({
hoverPrevNext : false,
cbInit : function(element){
jQuery('.ls-yourlogo').appendTo('.ls-inner');
jQuery('.ls-thumbnail-slide > a').addClass('ls-thumbnail-style');
}
});
The ID is of your layer slider that exists on the page. Mine happened to be 1 so its #layerslider_1. The next important part is the callback cbInit, inside this function you can make your appends and what ever other markup changes you want to make to the DOM.
Hope this helps someone.
try this:
suggestion instead of you typing jQuery everytime use $ instead it makes it easier for you.
if ($('.ls-yourlogo')) {
alert('Found!');
} else {
alert('NOT FOUND!');
}
Also i would suggestion using #ids than classes because ids are lot faster to get in Jquery than classes. And Make sure you call your the script that makes .is-yourlogo class first before checking if it exits.
see this jsfiddleThe </div> tags in your html are not properly closed off, that might be contributing to part of your problem. If I close a few off and run my code, it removes the element with the class='ls-your-logo' and appends it to the <div class='ls-inner'> which ends up being the same place as it was before. Perhaps if you look at my fiddle, you can better close the div tags to how you want it to properly look
I'm attempting to load different content into a div, the refresh code I have is quite similar to this: http://jsfiddle.net/TbJQ3/6/ but is more complex, it takes padding and magin etc into account.
The difference is that in my actual code, I used .load() to feed the content into my div rather than empty() and append().
When my page first loaded, I call my resizeContainer() function to render my layout dynamically set the size of my DIVs, everything looks good. I looked at firebug and this is what I got (all the sizes are there, set by my function):
<div id="divWrapper" class="fullscreen">
<div id="divTop" class="Top " style="height: 0px;"> </div>
<div id="divContainer" class="Container round" style="width: 1024px; height: 560px;">
<div id="divContent" class="Content round" onclick="javascript: jQfn.testclick();" style="width: 701px; height: 542px;"> Content </div>
<div id="divQuery" class="Query round" onclick="javascript: jQfn.testclick();" style="width: 292.2px; height: 558px;"> Query </div>
<div id="divStatus" class="Status " onclick="javascript: jQfn.testclick();" style="width: 701px; float: left;"> Status </div>
</div>
</div>
I made a test function to basically swap the content just to test the concept out...
jQfn.testclick = function(){
if (jQ.busy == true) {
console.log('Using busy.jsp');
jQ('#divContainer').load('busy.jsp');
jQ.busy = false;
} else {
console.log('Using login.jsp');
jQ('#divContainer').load('login.jsp');
jQ.busy = true;
}
jQ(window).trigger('resize');
}
However, if i click it twice just to swap it back to the original content, my resizeContainer function won't render anything at all.
I've been hammering this problem for the past 5+ hours now, I tried to use:
empty, append
detach
calling the resize function in many different ways
calling my custom resizeContainer function in many different ways
combination of all of the above and some more
I noticed that after i loaded my content, jQuery was unable to find the divs that got reinserted anymore... which would explain why my resizeContainer function couldn't set the width and height properly... But why? I could see it on the div on the screen as well as in the firebug...
This is what I see after i swap the content, obviously the styles is not present, as my custom resizeContainer function couldn't find the div.
<div id="divWrapper" class="fullscreen">
<div id="divTop" class="Top " style="height: 0px;"> </div>
<div id="divContainer" class="Container round" style="width: 1024px; height: 560px;">
<div id="divContent" class="Content round" onclick="javascript: jQfn.testclick();"> Content </div>
<div id="divQuery" class="Query round" onclick="javascript: jQfn.testclick();"> Query </div>
<div id="divStatus" class="Status " onclick="javascript: jQfn.testclick();" style="width: 701px; float: left;"> Status </div>
</div>
</div>
The reason why I know jQuery couldn't find my divs, is because I used the following code, and it logged some empty element:
var content = jQuery('#divContent');
console.log(content);
What could be wrong? I even tried to manually detach those DIVs before loading in the new content.
Load is an Ajax method, and inserts content from external files, when using ajax methods and not the append methods you will in most cases have to use jQuery's live(); to gain access to the inserted DOM elements.
Once the content is inserted the first time with Ajax, try using detach and one of the append methods instead of Ajax to reinsert it, otherwise it will not work, as load just reinserts new DOM elements, and not the content you just detached.