How to embed an accurate DOM Elements Counter without Popup Box - javascript

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>

Related

Preload HTML from within Javascript file, into the DOM, but don't execute

Im creating a simple JS game, which will run in the browser and will pull the files directly from the pc. Because of this needed to make a workaround the "Cross-origin" error, which went smoothly, I put all the HTML within a JS and loaded the JS from the tag in the index.html. Everything was going smoothly so far.
You click "press any key to continue" -> but then next you click "New Game" and you get event listener error "can't set property of null". Which i don't understand how it happens, because the element is already in the "DOM" , the css could pick it up, but the event listener could not? So i tried moving all scripts on top, rearranging stuff, nothing worked. Pre-loading all HTML into the index.html, without executing it will definitely work, but how can i achieve this exactly? My Configuration atm is:
index.html (root folder)
/components/main_menu.js
/components/character_creation.js
function MainMenu()
{/*
<div id="mm_wrapper_grid">
<div id="mm_subgrid1">
</div>
<div id="mm_subgrid2">
<div id="mm_subgrid2_image"></div>
<div id="mm_new_game"><p id="mm_new_game_p" class="grow">New Game<p></div>
<div id="mm_load_game"><p id="mm_load_game_p" class="grow">Load Game</p></div>
<div id="mm_options"><p id="mm_options_p" class="grow">Options</p></div>
<div id="mm_credits"><p id="mm_credits_p" class="grow">Credits</p></div>
</div>
</div>
*/}
function CharacterCreation()
{/*
<div> Character Creation test
</div>
*/}
<div id ="game">
<div id="loading_screen">Press Any Key To Continue</div>
</div>
<script type="text/javascript">
document.getElementById("loading_screen").addEventListener("click", function() {callback("game", MainMenu)});
document.getElementById("mm_new_game_p").addEventListener("click", function() {callback("game", CharacterCreation)});
function callback(arg1, func)
{
var html = func.toString();
var htmlstart = html.indexOf('/*');
var htmlend = html.lastIndexOf('*/');
var html = html.substr(htmlstart+2, htmlend-htmlstart-2);
document.getElementById(arg1).innerHTML = html;
}
</script>
You have the problem because you are trying to add the second listener for getElementById("mm_new_game_p") when this element doesn't exist on the page. I suggest you to add the follwing line of code to make sure, that it's true:
<script type="text/javascript">
document.getElementById("loading_screen").addEventListener("click", function() {callback("game", MainMenu)});
console.log('#mm_new_game_p', document.getElementById("mm_new_game_p"));
document.getElementById("mm_new_game_p").addEventListener("click", function() {callback("game", CharacterCreation)});
...
You have to add this listener after this element will be created (after calling of MainMenu() function).
To tell the truth, I can see such storing of html templates in js functions for the first time. It's hard to support your code and I've modified it a little bit below. This is not the best way to implement it, but my goal is show you a solution based on your code. What you can see here:
all the templates for pages are in html (not in JS);
you can add listeners from html code using HTML attribute onclick - and in this case you can be sure, that element exists on the page.
If you want to add listeners from JS, than you have to create own functions for each pages which you have and after HTML template of a page will be added to #game container you will need to create event listeners for the buttons which are on the created page.
openPage("game", "loading_screen");
function openPage(parentDOMElementId, name) {
console.log('openPage:', name);
var pageHtml = document.getElementById("page_" + name).outerHTML;
document.getElementById(parentDOMElementId).innerHTML = pageHtml;
}
<div id="game"></div>
<div class="templates" style="visibility: hidden;">
<div id="page_loading_screen" onclick="openPage('game', 'main_menu')">
Press Any Key To Continue
</div>
<div id="page_main_menu">
<div id="mm_subgrid1">
</div>
<div id="mm_subgrid2">
<div id="mm_subgrid2_image"></div>
<div id="mm_new_game">
<p id="mm_new_game_p" class="grow" onclick="openPage('game', 'character_creation')">New Game
<p>
</div>
<div id="mm_load_game">
<p id="mm_load_game_p" class="grow">Load Game</p>
</div>
<div id="mm_options">
<p id="mm_options_p" class="grow">Options</p>
</div>
<div id="mm_credits">
<p id="mm_credits_p" class="grow">Credits</p>
</div>
</div>
</div>
<div id="page_character_creation">
Character Creation test
</div>
</div>

implementing .hide() and .show() issue, both divs being shown, with no change onbutton click

Essentially creating a trivia game and having issues implementing jQuery .hide() and .show() functions. I've been reviewing other questions here on SO and my code looks correct, so I'm confused as to why all my divs are still visible, with no response from button clicks. I've tried to condense my code by leaving out the details the divs I'm trying to hide and show, just to focus on that current problem. I just left out the actual question data and timer function.
//Problematic functions
$( document ).ready(function(){
$("#mainbox").hide();
$("#beginning").click(function(){
$("#begin").hide();
$("#mainbox").show();
startTime();
})
Divs I'm trying to hide
<div id="begin" class="unhidden">
<h1>Trivia Game</h1>
<h2>Don't run out of time!</h2>
<p>
<button id="beginning">Start</button>
</p>
<br>
</div>
<div id = "mainbox" class="hidden">
<h2>Answer the following:</h2>
<h2 id="timer">Remaining Time: </h2>
</div>
Is it a scope / ordering issue?
You're missing a set of closing braces. You're closing your click event handler function, but not your ready function.
Here is an example of your code running with the additional closing brace. Make sure you write your code cleanly and indent properly to make these kind of typos easier to notice. Also, run you code through a validator or "linter" to make sure the code you've written is free of errors.
$(function() {
$("#mainbox").hide();
$("#beginning").on('click', function(){
$("#begin").hide();
$("#mainbox").show();
startTime();
}); // close click handler
}); // close ready
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="begin" class="unhidden">
<h1>Trivia Game</h1>
<h2>Don't run out of time!</h2>
<p>
<button id="beginning">Start</button>
</p>
</div>
<div id="mainbox" class="hidden">
<h2>Answer the following:</h2>
<h2 id="timer">Remaining Time: </h2>
</div>
Also note that you don't need $(document).ready(function() { ... }); anymore. The equivalent is simply $(function() { ... });. Additionally, you should use .on() to create event handlers.

Display a loading animation until a <div> appears?

I'm running an asynchronous 3rd party script that loads an image gallery into my page, but unfortunately their code doesn't provide me with a callback after their image gallery has finished loading.
The modal starts off like this:
<div class="modal-body">
<div class="container-fluid" id="cincopa">
</div>
</div>
After the gallery is loaded, the modal looks like this:
<div class="modal-body">
<div class="container-fluid" id="cincopa">
<div id="ze_galleria">
//gallery stuff
</div>
</div>
</div>
So I need some way to display a loading animation until #ze_galleria appears. The loading animation function I can do myself, but is there something in jQuery that will listen for when a certain DOM element is created? Once the DOM element appears, it'll run the callback to remove the animation.
Based on how that script adds the gallery/gallery items you could use the DOMSubtreeModified event and then check if that particular item were added
document.addEventListener("DOMSubtreeModified", function(e) {
if (document.querySelector("#ze_galleria")) {
// exists
}
});
Here is a DOM tree event list, where you can check other possible events that might could be used.
https://developer.mozilla.org/en-US/docs/Web/Events
Update
Make sure you take a look at the MutationObserver as well, as it has very good browser support nowadays.
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
Also, you can set an interval:
var cincopa = $('#cincopa');
var counter = 0;
var intervalCode = setInterval(function(){
if (cincopa.find('#ze_galleria').length){
clearInterval(intervalCode);
yourCallback();
}
counter++;
console.log(counter + ' seconds past till the event loaded.');
}, 1000);
I think the code is intuitive, but if there is any doubt, just ask :)
Presuming that your "3rd party library" is going to totally overwrite the contents of what ever you point it at (as your example code suggests it does). You can solve your problem simply by adding an img:
<div class="modal-body">
<div class="container-fluid" id="cincopa">
<img src="loading.gif"/>
</div>
</div>
When the library has done what it needs to do it will overwrite the contents of the div <div class="container-fluid" id="cincopa"> resulting in:
<div class="modal-body">
<div class="container-fluid" id="cincopa">
<div id="ze_galleria">
//gallery stuff
</div>
</div>
</div>
thus removing your loading image.

How to separate javascript so it is not inline but as a separate snippet

I have some code that works perfectly within the html editor within WordPress. The problem is that when switching to the visual editor it strips out the javascript. I am a novice when it comes to code, and wondering if someone can help separate the javascript so I can add it as a separate script to the wordpress page.
<div class="couponactivate">
<div class="coupon1">
<h3>Subtitle</h3>
<p>This is our Standard Coupon which gives 10% off</p>
</div>
<div class="activatebutton">
<div style="position:relative;"><a onclick="jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide()" target="_blank" href="http://www.test.com" rel="nofollow">DOJU</a>
<div onclick="window.open('http://www.test.com');jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide()" id="jcorgcr-clean-jcorgcoupon-coupon1" class="couponrevealcoupon">REVEAL COUPON</div>
</div>
<div class="expiry">Expires 31 July 2014</div>
</div>
<div style="clear:both;"></div>
</div>
Really you should add a class or ID to .activatebutton > div > div but if you want to keep the markup unchanged:
<script>
jQuery(document).ready(function() {
jQuery('.activatebutton').on('click',function() {
jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide();
});
jQuery('.activatebutton > div > div').on('click',function() {
window.open('http://www.test.com');
jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide();
});
});
</script>
Essentially what you want to do is bind to onclick from outside the HTML, rather than in the element itself. So instead of this:
<a onclick="jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide()" target="_blank" href="http://www.test.com" rel="nofollow">DOJU</a>
You might have something like this:
<a id="someLink" target="_blank" href="http://www.test.com" rel="nofollow">DOJU</a>
<script type="text/javascript">
jQuery('#someLink').click(function () {
jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide();
});
</script>
That script block can be put elsewhere on the page, or the script can be put into a separate file and a script block can just reference that file.
Note that this is a very simplified example just to demonstrate the idea of binding to an element's event from outside the element. There are lots of things to consider, and I imagine you'll find those things and learn them with practice. For example, since the page is parsed in order then that script will need to be placed after the link tag in order for it to work. If it's before the link tag, then you'd need to wrap it in the document's ready event to wait for the tags to load before trying to bind to their events. Something like this:
<script type="text/javascript">
jQuery(function () {
jQuery('#someLink').click(function () {
jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide();
});
});
</script>
<a id="someLink" target="_blank" href="http://www.test.com" rel="nofollow">DOJU</a>
If tags change over time (such as being added/removed dynamically) then there would be even more to consider in terms of binding to their events. But at its simplest, using jQuery (since you're already using it), you just identify the element and use something like the click() function on that jQuery-identified element (or set of elements) to bind to that event.
Since you are new and the question is easy I will help you. Next time you have to try first.
myscript.js:
jQuery(function() {
jQuery(".activatebutton a").on("click", function() {
jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide();
});
jQuery("#jcorgcr-clean-jcorgcoupon-coupon1").on("click", function() {
window.open('http://www.test.com');
jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide();
});
}
put this in head tag (after jquery):
<script type="text/javascript" src="myscript.js"></script>
the rest of html:
<div class="couponactivate"><div class="coupon1">
<h3>Subtitle</h3>
<p>This is our Standard Coupon which gives 10% off</p>
</div><div class="activatebutton"><div style="position:relative;"><a target="_blank" href="http://www.test.com" rel="nofollow">DOJU</a><div id="jcorgcr-clean-jcorgcoupon-coupon1" class="couponrevealcoupon" >REVEAL COUPON</div></div>
<div class="expiry">Expires 31 July 2014</div>
</div><div style="clear:both;"></div></div>
Hope this helps you
<!DOCTYPE html>
<html >
<head>
<script type="text/javascript" src="globe/script/jquery.js"></script>
<title>
Html5 All in One
</title>
</head>
<body >
<div class="couponactivate">
<div class="coupon1">
<h3>Subtitle</h3>
<p>This is our Standard Coupon which gives 10% off</p>
</div>
<div class="activatebutton">
<div style="position:relative;"><a target="_blank" href="http://www.test.com" rel="nofollow">DOJU</a>
<div id="jcorgcr-clean-jcorgcoupon-coupon1" class="couponrevealcoupon">REVEAL COUPON</div>
</div>
<div class="expiry">Expires 31 July 2014</div>
</div>
<div style="clear:both;"></div>
</div>
<script>
$(document).ready(function()
{
$(".activatebutton a").click(function(){
jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide()
})
$("#jcorgcr-clean-jcorgcoupon-coupon1").click(function(){
window.open('http://www.test.com');jQuery('#jcorgcr-clean-jcorgcoupon-coupon1').hide()
})
})
</script>
</body>
</html>

innerHTML does not work with Javascript output contents

I try to make some kind of ads rotator as follows:
<html>
<head>
<title></title>
<style>
body {
margin:0;
padding:0;
}
</style>
<script>
function fillBoard() {
s = document.getElementsByClassName('slots');
board = document.getElementById('board');
board.innerHTML = s[0].innerHTML
alert(board.innerHTML);
}
</script>
</head>
<body>
<div id="board" style="width:160px; text-align: center; margin:0">
</div>
<div class="slots" style="display:none">
<!-- THE PROBLEM IS HERE -->
<!-- Begin Hsoub Ads Ad Place code -->
<script type="text/javascript">
<!--
hsoub_adplace = 1310003403401506;
hsoub_adplace_size = '125x125';
//-->
</script>
<script src="http://ads2.hsoub.com/show.js" type="text/javascript"></script>
<!-- End Hsoub Ads Ad Place code -->
</div>
<div class="slots" style="display:none">
<img src="http://lorempixel.com/160/90/sports/1/" />
</div>
<div class="slots" style="display:none">
<img src="http://lorempixel.com/160/90/sports/2/" />
</div>
<div class="slots" style="display:none">
<img src="http://lorempixel.com/160/90/sports/3/" />
</div>
<script>
fillBoard();
</script>
</body>
</html>
In the code above:
There is a div with id board to act as a board that displays contents.
The board should be filled with data supplied from other hidden divs with class name slots using innerHTML property.
To do the above a function named fillBoard() is defined in the head section of the page and then called at the end of it just before closing </body> tag.
What is happening?
The hidden divs slots works fine with divs that contain images. However, in the first div there are a javascript code that should generates ads from an ads network which it does not work.
I expect that the javascript code of the ads network should fill its div with data, then the calling of fillBoard() will just copy its content to the board div. However, this is does not occur!
I need to know how could I overcome this issue?
A live example is found here
You can just show the desired hidden div and it's usually a better practice than copying DOM content. If you make sure to only show one of the hidden divs at a time you can show the image always in the same place.
Try this to show the first "slots" element:
s[0].style.display = 'block';
Ok so after some more digging I've found the issue, although I don't have an easy solution at the moment.
The js file show.js is generating some ad content inside of an iframe for you, which you are placing in the first 'slots' div. Simple enough. When you are setting the content of the board to the content of the first slots class, an iframe is being created in the board div but without the same content.
After some searching it seems that innerHTML of an iframe will not copy the contents of the iframe if it comes from a domain other than the page domain for security reasons.
It seems to me that the solution at this point is to either show and hide the slots divs like Zhertal suggested or you can possible find some other way to physically move the content of the slots div into board, but this may still be a violation of the same security concern. I'm going to keep digging and I'll edit this answer if I find anything more.
Reference SO posts:
Get IFrame innerHTML using JavaScript
Javascript Iframe innerHTML

Categories

Resources