Posts Tagged ‘browsers’

Detecting browser’s activity within JavaScript

Experiment, test, analyze. Experiment again, test again, analyze again. This is the process of learning the environment, the language and the tools I work with. Taking things apart, looking inside, diving deeper and building a picture of understanding. I think JS is a language with a lot of hidden corners and this time I’ve decided to dig into timers and intervals of the JavaScript. This experiment grew into a browser-based activity monitor of JavaScript execution and I would like to share my experience about it, with you.

How it all started

As you all know, timers in JavaScript get triggered at the moment when the browser is idling. This is described very well in one of the John’s articles at http://ejohn.org/blog/how-javascript-timers-work/ : “Since all JavaScript in a browser executes on a single thread asynchronous events (such as mouse clicks and timers) are only run when there’s been an opening in the execution.”

This information gave me a pretty absurd idea: Is it possible to determine the active/idle state of the browser by using the “opening” behavior of the timers? I thought – yes. But the question is – how? If we start looping “setTimeout” with scheduled time of zero milliseconds, we could collect an interval between the timers and identify the current browser’s state ( active/idling ) based on the interval’s info. Something, like the picture below shows:

timeout works

To prove for myself that this craziness had at least a small rational kernel, I built a small prototype. I injected it into a heavy ajax-based application and I was quite happy with the results. All the results I received had a common pattern in them, indicating that the calculated interval is a reliable source for tracking the browser’s activity. I do agree, that maybe this approach can’t be used for precise profiling of an application, but I still think that it could be used to get the global picture of the browser’s execution flow for the ajax driven applications.

Path into the experiment

To quickly proceed with this experiment, I started with pretty simple code. Collect the difference between the current time and time of the previous timer call, save all the values into an array, and I have everything I need for now. In the first place the code looked like this:

function start(){
    var timer_start = (+new Date()),
          timer_end,
          stack = [];
    
    (function collect() {
        timer_end = (+new Date());
        stack.push( timer_end - timer_start );
        timer_start = timer_end;
        setTimeout( collect, 0 );
    })();

    return stack;
}

// Example of the stack array
// [ 10, 11, 10, 11, 10, 11, 14, 19, 17, 16, 15, 
//    15, 13, 13, 13, 12, 17, 13, 10, 10, 11, 10, 
//    11, 10, 11, ...]

In all the tests I’ve done so far, there was one thing bothering me. Even when the browser was idling, there were almost no zero values in an array, but two digits were continuously repeating. For example: in Firefox (mac) these were 10 and 11. You can see that also also in the example above.

It was clear to me that these two values represent a kind of “baseline” for browser’s idling state. In Mozilla Developer Network (MDN) it’s described as a timeout clamping https://developer.mozilla.org/en/DOM/window.setTimeout ( at the bottom of the page ). Summarizing: clamping is the minimum amount of time between any interval or timer. I also tested different browsers in diferent OS’s ( Windows, Linux, OSX ) and almost none of them got zero values at the moment of idling. Besides that, these clamping values varied between all the browsers.

The funny thing about the timers clamping is that this interval is not just one static number, but two numbers, repeating in turn. These two numbers I called the “baseline”. Let’s look at some of them in different browsers.

Browser “Baseline”
Firefox 3.5.11 ( osx ) 10, 11
Safari 5.0 ( osx ) 10, 11
Chrome 5.0.375 ( osx, win ) 4, 5
IE 7.0 ( win ) 15, 16
Opera ( win ) 10, 11

Table: the baseline for different browsers

Despite the fact that the MDN claims that there is always a delay between timers, this was not the case. Sometimes the interval values were lower than the clamping interval, even dropping to zero value. Digging deeper sheds some light on this weired behavior. I’ve discovered that the dropped interval happened only at the moments of non idle state, when the browser was busy with really heavy execution flow. This gave me an idea that the timers are executing in two different cases.

Case one: The browser is idling. It periodically checks for the suitable timer/interval inside the timer’s and interval’s queue. This period is exactly the clamping moment, which is described in the MDN. At the moment when the browser finds an interval or a timer to be executed – fire.

Case two: Browser is executing JS code. Periodic checks are stopped to prevent timers and intervals being executed at the moment of other code execution. This means, the browser is waiting for an “opening” now. When the execution is finished, the browser starts checking the timers’ queue, without waiting for clamping offset. It controls if the execution of the timer was not far away in the past/future from the current moment and if not the browser executes it. This case also explains why my prototype code gave as a first value – zero. Because there was nothing else to execute and browser could pick up the scheduled timeout.

I do not claim, that this is actually what is happening, but by analyzing from the outside, it appeared to me so.

Tests with simple dump tool

Well, enough of raw data. Users need a GUI and I also needed some representation of the collected data. For this reason I made a first prototype version of a dumping tool. As an input it receives the array with values and as an output it produces some “very” simple graph like the one bellow.

This graph has two sates: “activity” and “no activity” state. They are represented by high level and low level of the bar, respectively. As you’ve noticed the high bar consists of red and black areas. In this way duration and type of the activity was represented.

Let’s start with the red part. The longer the red bar is, the longer the browser stays active. It becomes red, only when the activity interval is longer than the “baseline”. At the moment when the activity goes below the baseline, it becomes a small black stripe.

Because of the visual graph, you can analyze data much faster than with the raw array. Faster analysis, more intensive tests. More conclusions. And the first conclusion which I made was that, it is almost impossible to trace activity, if it is less than the clumping interval. But still, here comes the nice part, web pages nowadays are all heavily event driven, and even a small event often executes longer than the clumping interval. Take for example a typing event, resizing a window, etc. Typing event in an text-area triggered this so well, that I could easily see this in the graph.

Image : Firefox Typing activity

Image : Chrome Typing activity

Or, scrolling. I scrolled a couple of times and I think, this is quite fascinating to see, that graph shows you this four scrolls I made.

Image : Safari scroll activity

Last activity as an example is based on resizing of the Firefox window:

Image : Firefox resize activity

Another conclusion I made was that based on the examples you can see that the timers depend not only on the JavaScript execution of the code, but also on the internal parts of the browser, like moving of the window, or opening a new tab. So, keep this in mind :)

Besides all the graphs of event driven behavior, I also came across another interesting aspect in Firefox when it was “doing nothing” and checking the idle state. Firefox when idling still has some activity peeks. I also looked at Chrome and Safari, but they are all stable as statues. These browsers showed no sign of activity at all, in idle state. First, I thought that it’s just some crazy late running timer, but when I checked the Activity Monitor of OSX I found that there are also the same small peaks of the CPU usage for Firefox processor.

Image : Firefox small idle peaks

From here, I can draw two conclusions: 1. Firefox is really doing something all the time (which is reflected in the CPU usage) or 2. Firefox just has inaccurate timers.

More ?

I could not resist and not to build some kind of runtime activity monitor.

First thing which I did was to check the response of this monitor to the activity. The fastest way was to fire up native Activity Monitor of OSX and compare the peaks of both. It was a surprise to see peaks in the browser monitor first, and only after that in OSX. :)

Image : Firefox and Activity Monitor

Because runtime monitor gives you a global overview of the activity, it was really nice to play with it in a different browsers and compare how they react on different kinds of events/execution. It gave me an instant coverage of the places where browsers spend much time and of the places where they “fly”. For example, I used the test code like this

var arr = [];
for (var i=0;i<16099;i++) {
    var div = document.createElement("div");
    arr.push( div );
}

and I got these results :

Images: Execution of test code : Firefox (win), IE (win), Chrome(win)

Another thing which I noted is the way IE behaves. Its activity always stays at "zero" level when it's idle, a really "silent" browser. Also in the image above you can see that IE gave only the activity of the JS execution, but nothing else. I assume that it has to do with the clamping interval. It has the highest interval between all the browsers, which means that the activity bellow 15ms will always stays invisible to us. Sad. At least we can track resize of the window, with ease :)

Image: Resizing IE

The source of it you can find source at github.

Epilogue

While I was busy with timers I found another interesting article about timers and intervals. I did a small experiment with that too and it appeared that the argument which Firefox passes to the timeout function is equal to the sum of the calculated interval + the baseline. It's not always the same, but in most situations it is. I did not perform any further tests in other browsers, but if you are interested feel free to fill this gap.

This experiment gave me some interesting thoughts. This monitor can actually help you to look at the application from a different angle. It can show you the way the application performs and interacts with the browser. It can show you that the clicking on a button in one browser triggers a more complicated wave of the execution than in the other browsers. It helps to see you your web application as a whole piece and not as a bunch of separated code regions.

As usually, a playground is available for everyone who is interested in it :

http://nemisj.com/src/amonjs/

Known issues: In Linux in Firefox calibration of the baseline sometimes is not working the first time, so you should recalibrate if it behaves strangely.

IE9, Windows XP and 2014?

Today I’ve found an interesting link in my RSS reader about IE progress in open-standards niche. Personally I think it’s really good that IE team puts so much effort to make IE a faster browser, a better browser and an HTML5 compatible browser. Finally, we – web developers, will be able to concentrate on web-applications and their functionality, instead of doing different dirty tricks to allow application to work in any browser.

Still I think we should ask our-selfs, when will this happen? When will web-developers be free of “hacking browser specific defacto’s “, when will they be able to have fun with latest web technologies? Actually, it’s a rhetorical question in this note. Despite the happiness of the fact that web-world moved, I have some sad thoughts.

Even if IE9 will be in one line with other open-standard browsers, it will not make it’s debut to all Windows platforms. IE9 does not run on Windows XP and requires at least Windows Vista with SP2. What does this means to us? Well, first of all, it means that, till the time all the Windows users switch to a successor of Windows XP, we will be binded to the good old HTML4. And I’m afraid it will not happen any time soon, at least for some of us. Officially Windows XP stays in Extended support for the next four years, till 2014. Sorry for skepticism, but even if most of the users will move on to Windows Vista or Windows 7, there are organizations and people which will not make this jump.

Of course the situation is not dramatic, but it has some hidden and sad story. The percentage of AJAX driven applications growth and will grow even more. Different web-portals, CRM system and other web2.0 related applications are an entry point for thousands of people working in different organizations. As said, some of this organizations will not make a fast jump to Windows Vista/7. Meaning that web-developers will have to continue targeting IE(7,8) audience without HTML5 and other cool, fun things which are already included in IE9.

I know that Microsoft said “modern browser” needs a “modern operating system”, but it is still strange to see that other browser vendors can deal with Windows XP “non-modern operating system”, while Microsoft can’t. Can someone, please, explain?

My point of all this is : It’s all pretty cool and funky with IE9, but without being delivered to XP machines, it does not become new superior open-standard web-browser for me. Why? Cause it’s not a drop-in-replacement for IE family, but simply an extra browser to test in.

Focus, tabIndex and behavior of browsers

“Do not trust defaults”

# Prefix

Recently I had an opportunity to deal with focus behavior in browsers, with tabindex attribute and other focus related stuff. When I was doing this work I came across interesting aspects of focus implementation in different browsers. This article is exactly about all these things. Tested browsers are IE (6,7,8), Firefox (linux-3.6.3) , Chrome 4.x, Safari 4.0.4 , Chromium(5.x linux), Opera 10.5.

# Stem

Before I start, let me remind you some basics about focus, tabIndex and user interaction.

As you know tabindex is used to specify focus order of the nodes and enable focus. I say, enable focus, because there are nodes which are not focusable by default, like div, span, table, etc, but can receive focus if tabindex is applied. Element receives focus when clicked by mouse (or touched on touch screens ) or when tab key is pressed. I’ve divided this article into two parts : “Interaction by tab-key” and “Interaction by click”. There has been a lot written about tab pressing interaction, so I will keep it briefly. The main part of this article will be “focused” on “focus with mouse click”.

For testing purpose I took different tabindex values as in example below :

<div>
    <input type="text" value="tabindex is not here" />

    <div> not tabindex </div>
    
    <input type="text" tabindex="-1" value="tabindex is negative" />
    
    <div tabindex="-1"> tabindex is negative </div>
    
    <div tabindex="0"> zero or positive </div>
         
    <input type="text" tabindex="0" value="positive or zero" />

    <div tabindex="" > omitted tabindex </div>
</div>

## Tab-stops

First, let’s refer to the w3c documentation to fully understand the tabIndex meaning in the tab-press story. The most important of all in that link is the tabIndex value. Which defines if node should be included in tab-press sequence – equal or greater than zero, or discarded from this sequence – negative value. If value is omitted it has different meanings based on node type. For non focusable elements it means nothing, while for inputs it will have effect like zeroed tabindex.

All the theoretical information is repeated, time to start and test the browsers’ implementation. The result of my titanic work of that test you can see below :)

Attribute in markup Node is focused
input tabindex = “-1″ no
div tabindex = “-1″ no
div tabindex = “” no
input tabindex = “0″ yes
div tabindex = “0″ yes
div (no tabindex) no
input (no tabindex) yes

Table: Node is focusable when performing tab-press

Tab-stop sequence in all browsers is exactly the way it’s described by W3C. Focus is placed only on nodes which have tabindex equal or greater than zero. Default nodes like input, do not need any tabindex to be included in tab-stop sequence. Though if tabindex is negative, all browsers skip this node from tab sequence. Well, it’s all clear. Nothing more to say about this subject, so let’s move to the next stage.

## To click or not to click

This test was a little bit controversial for me. From the user perspective – focused node is the node which gets outlined or selected by some other kind of visual selection ( border dotted, blue, etc). From us, developers perspective, focused node is the node which receives onfocus event and it does not matter whether focus is visible or not.

Of course, end-user is the person who will work with an application. We have to originate from his point of view, which means that visual style is everything. If node is not visually selected, it does not exists as focused element for user. That’s why my test was aimed at end-user experience – “Hey, when I click nothing happens…it’s broken” – or something like that.

Because input elements can always receive focus ( when enabled ), I did not include them in the results below:

markup attribute Firefox IE WebKit * Opera
div tabindex = “-1″ yes no yes no
div tabindex = “0″ yes yes** yes no
div tabindex = “” yes no no no
div (no tabindex) no no no no

Table: Node is focusable when clicking it

* Safari and Chrome both uses Webkit render engine and have the same results

** IE bug

That’s sorrowful. There are no identical browsers which have the same focus implementation, except Safari and Chrome (I assume only because they both use WebKit engine).

One of the first things which came to my mind, is that, it’s still not possible to rely on the browser’s default behavior. One browser will make visual style, while other will not. It could be okey, if we were working only with positive or zeroed tabindex. But it is 2010 and ajax applications are sometimes more complex than desktop’s are, it’s not possible to pretend that no one uses negative values for tabindex. So… such a big difference in outline implementation left us not a big choice. If you want to have visual accent on focused nodes, use your own CSS classes, like most of us do for the :hover elements or stop using negative tabindex at all.

Beside all of that weird stuff I’ve also noticed two strange aspects in Firefox and MS Internet Explorer.

It appears that only Firefox is the browser which shows outlined node when tabindex is presented as attribute but value is omitted. I do not know, if it was a feature or not, but keep in mind, that

node.setAttribute("tabindex","")

will make node focusable by click.

Another interesting issue is non focusable nodes in IE. It seems that nodes like div, which have tabindex zero or greater than zero do not receive focus by click. Yet, they will start receiving click focus if such node has been focused by tab-press. After node has been focused once (by tab), it will start receiving focus by click (even if you reload the page). Though, if you delete browser’s cache and open the same page again, node becomes non focusable back. Really weird… If interested – Try it yourself.

UPDATE: Tested in IE6/7 in mac (with wine) and the bug is not possible to reproduce.

## To dispatch or not to dispatch

After end-user test there is still one open item. Ajax applications are event-driven, so how does tabindex influence “onfocus” event? Does it get dispatched or do we stay unaware like usual users do? Well, check the results :

Attribute in markup Firefox IE WebKit * Opera
div tabindex = “-1″ yes yes yes yes
div tabindex = “0″ yes yes yes yes
div tabindex = “” yes no no no
div (no tabindex) no no no no

Table: Node fires onfocus event

What do we have here? It appears that even if node is not visually outlined, it still fires an onfocus event. All of the major browsers behave the same, except that Firefox keeps receiving focus with omitted tabindex value.

## Detecting focusable node through JavaScript

To say frankly, I’m a bit meticulous person, I always try to understand internal part of the subject. In situation with focusable nodes, I was wandering what information does browser expose to the JavaScript environment, depending on the tabIndex and node type (like input and div). As an challenge I decided to write code which could detect any focusable element, despite the focus visualization. Even that such functionality has not much to do with daily work, but maybe for some of you it will be useful.

Actually defining if node is focusable or not does not look difficult. Node with negative or positive value is focusable by click ( at least can receive onfocus event ). Node with positive or zero is focusable by tab-press. In theory the only left thing is to get appropriate tabindex value of the node and check if node is focusable by default. Easy… :)

At that time I knew, that getting tabindex value can be done in two different ways. First by using property node.tabIndex, described at MSDN. Or by using node.getAttribute("tabindex") function.

I used both functions to see the differences and to decide which one I need. In a result table below I grouped all browsers, except IE, due to the fact that IE gives totally other results than the rest.

Attribute in markup tabIndex getAttribute tabIndex ( IE ) getAttribute ( IE )
tabindex = “-1″ -1 -1 -1 -1
tabindex = “” -1 “” 0 0
tabindex = “0″ 0 0 0 0
div (no tabindex) -1 null 0 0
input (no tabindex) 0 null 0 0

Table: Different approaches in getting tabIndex value

Because of these zeros in IE column, first I will analyse “all” browsers and then I will return to IE.

When looking at the results I can mention a number of positive aspects. First of all it’s really nice that browsers respect markup and give the correct value via getAttribute function meaning that getAttribute is trustable, but in IE. The second valuable aspect is that browsers return positive or zero value if node is focusable via tab-press even if no tabindex is specified. You can see that in “input” node column, which does not have any tabindex, but still tabIndex returns 0. This indicates, that browsers even help us to identify focusable nodes.

Yet, there is one little pitfall. What first hits the eye is the tabIndex which is -1. Browsers return -1 in three different cases when querying div :

  • When tabindex is not specified
  • When tabindex is specified as -1
  • When tabindex is omitted

You may ask, why is it a pitfall, browsers return -1 to any node which is not inside tab-press sequence? Fair enough. But please do not forget, detection code should identify all focusable nodes, which includes nodes focusable by mouse click.

Gathering all information together it become clear for me that through all the good things tabIndex property is doing for developers, I still have to use both approaches.

Instead of limiting myself to the isFocusable( node ) function, I decided to write generic getTabIndex( node ) function. This function would return correct tabindex value only if node is focusable ( dispatches onfocus event). Furthermore knowing IE issue with tabIndex/tabindex, I can also include the workaround to retrieve correct tabIndex for MSIE.

For now, based on the getAttribute and tabIndex, getTabIndex will looks like this :

window.getIndex = function (node) {
    var index = node.tabIndex;
    if (isIE) {
        // later
    } else {
        if (index == -1) {
            var attr = node.getAttribute("tabindex");
            if (attr == null || (attr == '' && !isFirefox )){
                return null;
            }
        }
    }

    return index;   
}

I think the code is self explaining and I do not have to dive into the explanation. Btw, as you can see, I’ve included check for firefox (let’s respect his own small weirdness) :)

## IE tabIndex retrieval

Now, lets’ look to the Internet Explorer results. IE returns zero value in a lot of different cases. The only case when IE returns correct value is when tabIndex is specified on node. So how can we determinate if node is focusable or not?

First of all we should get real value from markup and because getAttribute(“tabindex”) is not working, it’s time to find something different. The answer hides inside “attributes” property of the node. It’s possible to query attribute of the node by using node.attributes.tabIndex which will return an AttributeNode object. Though this node in most cases has value of 0, AttributeNode also consists of “specified” property, which show the real state of markup.

Here is the short IE getTabIndexAttributeValue function based on the info :

function getTabIndexAttributeValue(node) {
        var ti = node.attributes.tabIndex;
        return ti.specified ? ti.value : null; 
}

Yet, there is another problem with IE tabIndex. As I explained above, other browsers return zero also for nodes, which are focusable by default, like input, textarea, etc. IE also does that. However it does that also for nodes which do not receive focus by default, for example for div (and even more weird for <BR/> ) :O. Solution? Take names of nodes which are focusable by default and match them with given node. These names are listed in the spcecs : a, BODY, button, frame, iframe, img, input, isIndex, object, select, textarea

Well, here is the final version of getTabIndex :

window.getIndex = function (node) {
    var index = node.tabIndex;
    if (isIE) {
        // late
        var tnode = node.attributes.tabIndex.specified;
        if (!tnode) {
            var map = { a:true, body:true, button:true, 
                frame:true, iframe:true, img:true, 
                input:true, isindex: true, object: true, 
                select: true, textarea: true
            };
            
            var nodeName = node.nodeName.toLowerCase();
            return (map[nodeName])  ? 0 : null ;
        }
    } else {
        if (index == -1) {
            var attr = node.getAttribute("tabindex");
            if (attr == null || (attr == '' && !isFirefox )){
                return null;
            }
        }
    }
    return index;   
}

# Suffix

I hope you found also some useful information in this note, like I did, when I was testing. And one of the things for me was : IMHO : If you need visually selected focused elements, do not rely on browsers’ implementation. Just get rid of the active border and use your own highlighting mechanism.

Used links :

Return top