Reputation: 563
I am trying to calculate the elapsed time an element is painted onto the DOM from the start time of the script or if the specific element was even painted at all. I am inserting a background gradient to the HTML, and then using javascript to create random (clouds, which are just large periods with a text shadow) in multiple places across the screen (some negative, some positive, some within scope, some outside of scope).
Currently my code looks like this:
<html>
<head>
<style>
.container {
border: 1px solid #3b599e;
overflow: hidden;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#315d8c', endColorstr='#84aace'); /* for IE */
background: -webkit-gradient(linear, left top, left bottom, from(#315d8c), to(#84aace)); /* for webkit browsers */
background: -moz-linear-gradient(top, #315d8c, #84aace); /* for firefox 3.6+ */
}
.cloud {
color: #fff;
position: relative;
font: 100% "Times New Roman", Times, serif;
text-shadow: 0px 0px 10px #fff;
line-height: 0;
}
</style>
<script type="text/javascript">
function cloud(){
var b1 = "<div class=\"cloud\" style=\"font-size: ";
var b2 = "px; position: absolute; top: ";
document.write(b1+"300px; width: 300px; height: 300"+b2+"34px; left: 28px;\">.<\/div>");
document.write(b1+"300px; width: 300px; height: 300"+b2+"46px; left: 10px;\">.<\/div>");
document.write(b1+"300px; width: 300px; height: 300"+b2+"46px; left: 50px;\">.<\/div>");
document.write(b1+"400px; width: 400px; height: 400"+b2+"24px; left: 20px;\">.<\/div>");
}
function clouds(){
var top = ['-80','80','240','400'];
var left = -10;
var a1 = "<div style=\"position: relative; top: ";
var a2 = "px; left: ";
var a3 = "px;\"><script type=\"text/javascript\">cloud();<\/script><\/div>";
for(i=0; i<8; i++)
{
document.write(a1+top[0]+a2+left+a3);
document.write(a1+top[1]+a2+left+a3);
document.write(a1+top[2]+a2+left+a3);
document.write(a1+top[3]+a2+left+a3);
if(i==4)
{
left = -90;
top = ['0','160','320','480'];
}
else
left += 160;
}
}
</script>
</head>
<body style="margin:0;padding:0;">
<div class="container" style="width: 728px; height: 90px;">
<script>clouds();</script>
</div>
</body>
</html>
I then run this inside of an iframe, trying to detect if the visible elements are being painted first, or if they are being painted in display order (pretty much, is the ad currently being viewed, or is it out of view).
I have not found a solid technique yet that works crossbrowser to detect this. In chrome, I was able to see it work when pasting images, as the visible images got an onload event fired first (even though they were at the end of the DOM), but this wasn't the case for firefox or IE.
Upvotes: 13
Views: 786
Reputation: 24988
You should use console API for measuring timings more accurately (and avoid DIY spaghetti):
console.time("Doing stuff");
/*le code*/
console.timeEnd("Doing stuff");
This functionality is available natively in Chrome and Firefox; it can also be polyfilled on other browsers like IE but will not be as precise.
Note that using Date
is not appropriate/intended for benchmarking:
Depending on the browser and OS,
Date
's resolution can be as low as 15 milliseconds.
Date
based on system time, isn't ideal. Most systems run a daemon which regularly synchronizes the time... tweaked a few milliseconds every 15-20 minutes. At that rate about 1% of 10 second intervals measured would be inaccurate.
Update:
Hold on, are you trying to measure browser paints' timing and order? These can't be monitored through js (ok, it's possible to have a js API, but ultimately it has to be benchmarked in the browser engine, so no js polyfills).
Rule of thumb is elements will be painted in parse order, with re-paints/re-flows triggered by content styling - like backgrounds being loaded, additional css rules becoming available or content of different size being added into a table column.
Html5rocks on profiling long paint times might get you started in the right direction.
Upvotes: 3
Reputation: 9856
I'm really not sure what you're after here. You said: "(pretty much, is the ad currently being viewed, or is it out of view)." But that is a bit cryptic.. What "ad" are you talking about?
In trying to figure out what you were trying to accomplish I pretty much rewrote your script to do exactly the same as before and it does an alert
of the elapsed time as well as logs the time for each cloud in the console. It's not a good way to calculate execution time (which is what it seemed to me like you were after..).
NOTE: The only reason I rewrote everything was so I myself could make better sense of it in preparation for a response from you. Once I know exactly what you want I will edit my answer.
<style>
.container {
width: 728px;
height: 90px;
border: 1px solid #3b599e;
overflow: hidden;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#315d8c', endColorstr='#84aace'); /* for IE */
background: -webkit-gradient(linear, left top, left bottom, from(#315d8c), to(#84aace)); /* for webkit browsers */
background: -moz-linear-gradient(top, #315d8c, #84aace); /* for firefox 3.6+ */
}
.cloud {
color: #fff;
position: absolute;
font: 100% "Times New Roman", Times, serif;
text-shadow: 0px 0px 10px #fff;
line-height: 0;
}
.cloud-container {
position: relative;
}
</style>
<div class="container"></div>
<script type="text/javascript">
// for IE
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function () { };
var pxTop = ['34px', '46px', '46px', '24px'],
pxLeft = ['28px', '10px', '50px', '20px'],
size = ['300px', '300px', '300px', '400px'];
function cloud(callback) {
var df = document.createDocumentFragment(),
node;
for (var i = 0; i < 4; i++) {
node = document.createElement('div');
node.className = 'cloud';
node.style.fontSize = size[i];
node.style.width = size[i];
node.style.height = size[i];
node.style.top = pxTop[i];
node.style.left = pxLeft[i];
node.innerHTML = '.';
df.appendChild(node);
}
callback && callback();
return df;
}
function clouds(containerId, callback) {
var top = ['-80','80','240','400'],
left = -10,
container = document.querySelector(containerId);
container.appendChild(document.createTextNode("\n"));
for (i = 0; i < 8; i++) {
var div = document.createElement('div');
div.className = 'cloud-container';
div.style.top = top[0] + 'px';
div.style.left = left + 'px';
console.log('About to start making a cloud', new Date().getMilliseconds());
div.appendChild(cloud(function() {
console.log('Finished making cloud', new Date().getMilliseconds());
}));
container.appendChild(div);
container.appendChild(document.createTextNode("\n")); // newline for view source
if (i == 4) {
left = -90;
top = ['0','160','320','480'];
} else {
left += 160;
}
}
callback && callback();
}
var start = new Date().getMilliseconds();
clouds('.container', (function() {
var end = new Date().getMilliseconds(),
time = end - this;
alert('Execution time: ' + time);
}).bind(start));
</script>
Upvotes: 4