Ajax Bestiary: A Javascript Field Guide
 
Ajax Bestiary: A Javascript Field Guide
 
 

Entries Tagged as 'YUI'

Loopy Optimizations

Posted by Dave Mahon

We all know that code optimization is important, especially when processing large quantities of data. It is also common knowledge that adding layers of code to loops reduces performance. Except this maxim doesn’t always hold when it comes to JavaScript in browsers and even native methods can vary wildly in performance. In fact, in almost all cases, Underscore, jQuery and YUI outperformed any of the native methods. Interestingly, the newest implementation for native looping, forEach, consistently trumped a traditional for (var i = 0; i < 2500; i++) loop.

I set up a testing framework that looped through a normal array instantiated like so:

var data = [];
var v = {}; //This value doesn't seem to affect performance at the data size I chose
 
for (var i = 0; i &lt; loops; i++) { //loops is defined elsewhere
   data.push(v);
}

I looped through this array using the following methods:

  • for loop
  • for … in … loop
  • forEach loop (not supported in IE9 Quirks Mode)
  • Prototype 1.7: Enumerable.each
  • jQuery 1.7.1: $.each
  • Underscore 1.2.3: _.each
  • YUI 3.1.4: YUI.each

Each loop was passed the value of the array element and returned immediately, like so:

//From the native for and for ... in ... tests
(function(el){return;})(data[i]);

I eventually settled upon an array of 2500 elements and running the test 200 times to collect a reasonable number of samples. These numbers were not chosen arbitrarily. Prototype would time out on Firefox at 5000 array elements and Safari seemed to have wildly varying results on each run of the suite with fewer than 200 samples. With 200 samples, the variance in mean time between runs became a few hundredths of a millisecond, not enough to be of consequence. Disturbingly, while Prototype froze the browser with 5000 array elements and 100 samples, it had no issue with 2500 elements and 200 samples. Even so, with some tests averaging less than a hundredth of a millisecond, we will soon require much larger data sets to get meaningful results at all, which may preclude the inclusion of Prototype (and even native methods!) in future tests.

All tests were run in a freshly launched browser on an updated operating system (either MacOS 10.7.2 or Windows 7 Home Premium) running on a MacBook Pro with a 2.53GHz Intel Core 2 Duo processor and 4GB of 1067MHz DDR3 RAM. Firefox had all add-ons disabled and Internet Explorer had the Developer Tools open (to switch between Standards and Quirks mode).

So let’s look at some charts!

Mac safari
This was certainly an interesting start to the process. YUI, Underscore and jQuery all clocked in at 0.005 ms. Prototype would prove to be faster than native methods, with the exception of forEach, on all browsers. Underscore was only be outperformed on IE 9 (32-bit, Standards Mode).

Mac chrome
Chrome was exceptional as well, with the traditional for loop actually running slower than for ... in .... This behavior was also seen on Chrome for Windows and Safari for Windows.

Since all of the major browsers are clearly pre-optimized for these libraries (as they themselves wrap the native looping language structures), let’s look at just the libraries:
Loop run times, by library
Here we can begin to see that Prototype really is behind its peers in loop performance. While we are talking fractions of a millisecond, our apps are growing larger by the day and this could become a serious issue.

Run times of non-prototypical libraries by browser
Hey! It looks like Firefox really is slow. Curiously, IE 9 is significantly faster, which flies in the face of most generalized JavaScript performance metrics.

Still, something looks odd about IE:
Run times by library and version of Internet Explorer 9
Your mileage varies wildly depending on whether you choose standards or quirks mode, and not always in obvious ways. In general, 64-bit is faster, but only marginally, and most people are not using it. (You have to explicitly launch it, as it is not the default, even on 64-bit Windows). Meanwhile, quirks mode apparently embeds some performance hacks. As a note to benchmark developers, this should be evidence enough that not all IE’s are the same and we need to start breaking down by rendering mode and compilation.

So far, we’ve seen the average times and most browsers are quite acceptable. What are the worst case scenarios?

Platform

Browser

Method

Max (ms)

Mean (ms)

Windows 7

IE 9.0.8112.16421 (64-bit IE 9 Quirks)

for

93

5.29

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Standards)

forEach

81

4.04

Windows 7

IE 9.0.8112.16421 (64-bit IE 9 Quirks)

for in

81

6.27

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Standards)

for in

76

9.87

Windows 7

IE 9.0.8112.16421 (64-bit IE 9 Standards)

for in

71

4.89

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Quirks)

for in

67

5.995

MacOS 10.7.2

Firefox 9.0.1

for in

55

1.885

Windows 7

Firefox 9.01

for in

52

6.055

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Quirks)

for

49

4.66

Windows 7

IE 9.0.8112.16421 (64-bit IE 9 Standards)

for

48

4.76

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Standards)

for

39

7.845

Windows 7

Chrome 16.0.912.75 m

for in

30

1.13

Windows 7

Chrome 16.0.912.75 m

for

26

1.315

MacOS 10.7.2

Chrome 16.0.912.75

for

23

1.175

MacOS 10.7.2

Chrome 16.0.912.75

for in

22

1.085

MacOS 10.7.2

Safari 5.1.2

for in

16

1

Windows 7

Firefox 9.01

jQuery

6

0.185

MacOS 10.7.2

Safari 5.1.2

for

5

0.52

MacOS 10.7.2

Firefox 9.0.1

for

5

0.7

Those averages hid some extreme variations within Internet Explorer. Fortunately, most of these are found using native language structures, which we know better than to use.

YUI Calendar Popup from Text Input

Posted by Don Albrecht

I needed a way to provide my users with a date picker that was automatically provided when a text area received focus.  I was eager to use the excellent YUI calendar as a starting point, but the provided documentation didn’t provide a solid example for this type of implementation.

Dav Glass has provided a solid example of the Calendar tied to a text input. But, his example is highly dependent on the text input having specific ids.  This doesn’t take advantage of YUI’s excellent Selector library really didn’t meet my need for a simple universal solution.

Key Requirements:

  1. Progressive Enhancement (No inline javascript)
  2. Yui based
  3. Universal implementation across all pages in a site.
  4. Support for multiple date inputs on a page.

Getting Started:

The bulk of the code used is pretty solidly Dav’s I’ve simply replaced all of the hard coded references to dynamically generated targets and moved from hard coded ID’s for the target fields to a css class.  Lastly, I’ve added a “activeCal” class to the currently active target input so that one calendar can be recycled across multiple text areas on the page.

Source:

var cal1;
var over_cal = false;
function transmogCals() {
    cal1 = new YAHOO.widget.Calendar("cal1","cal1Container");
    cal1.selectEvent.subscribe(getDate, cal1, true);
    cal1.renderEvent.subscribe(setupListeners, cal1, true);
    var pickers =  YAHOO.util.Selector.query('.date-picker'); 
for( i in pickers){
    YAHOO.util.Event.addListener(pickers[i], 'focus', showCal);
    YAHOO.util.Event.addListener(pickers[i], 'blur', hideCal);
    }
cal1.render();
}
function setupListeners() {
    YAHOO.util.Event.addListener('cal1Container', 'mouseover', overCal);
    YAHOO.util.Event.addListener('cal1Container', 'mouseout', outCal);
}
function getDate() {
        var calDate = this.getSelectedDates()[0];
        calDate = (calDate.getMonth() + 1) + '/' + calDate.getDate() + '/' + calDate.getFullYear();
        YAHOO.util.Selector.query('.activeCal')[0].value = calDate;
        over_cal = false;
        hideCal();
}
function showCal(e, targ) {
    var xy = YAHOO.util.Dom.getXY(this);
    var el = new YAHOO.util.Element(this); 
    el.addClass('activeCal');
    var date = this.value;
    if (date) {
        cal1.cfg.setProperty('selected', date);
        cal1.cfg.setProperty('pagedate', new Date(date), true);
        cal1.render();
    }
    YAHOO.util.Dom.setStyle('cal1Container', 'display', 'block');
    xy[1] = xy[1] + 20;
    YAHOO.util.Dom.setXY('cal1Container', xy);
}
function hideCal() {
    if (!over_cal) {
         var el = new YAHOO.util.Element(this); 
        el.removeClass('activeCal');
        YAHOO.util.Dom.setStyle('cal1Container', 'display', 'none');
    }
}
function overCal() {
    over_cal = true;
}
function outCal() {
    over_cal = false;
}
YAHOO.util.Event.addListener(window, 'load', transmogCals);

 

Adding it to your page

Integrating the code into the page is VERY easy.

In the header of the page add the following css includes.

<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?2.6.0/build/calendar/assets/skins/sam/calendar.css">
In the footer add the following script include and include the date-picker.js file
<script type=“text/javascript” src=“http://yui.yahooapis.com/combo?2.6.0/build/yahoo-dom-event/yahoo-dom-event.js&2.6.0/build/calendar/calendar-min.js&2.6.0/build/selector/selector-beta-min.js”></script> 
Lastly, place a class of date-picker to any text fields you want to tie to the input and add the following to your pages markup:

 

<div class='yui-skin-sam' style="position:absolute; left:-1000px;">
     <div id="cal1Container"></div>
   </div>

YUI 2.4 has landed

Posted by Don Albrecht

YUI has announced a major new release with the  immediate availability of YUI 2.4.

Key Features:

  • Selector Utility: Following in the footsteps of most other toolkits, YUI now includes a CSS Selector.  This beta component includes much of the standard CSS3 selector syntax including the proposed Selector extensions.
  • Charting: Using a hybrid Flash / Javascript model, a new charting component has been released with support for bar, line and pie charts.  Of special note is the fact that the charting utility utilizes the same data model as the data table implementation allowing hybrid chart / table interfaces.
  • Get: dynamically load scripts and nodes via the new Get tools.
  • Profiler: This combined with YUI Test will allow you to quickly and efficiently determine profiles and unit tests.  Most notably, profiler allows unit tests based on performance to be performed.
  • JSON Utility: dramatically improved JSON support.

Behind the scenes:

Incremental improvments to: Calendar, Drag & Drop & Button controls.

Dramatic enhancements & customization support added to the Rich Text Editor:

Read about the release here:

http://yuiblog.com/blog/2007/12/04/yuii-240/

Determining Position with YUI

Posted by Don Albrecht

Today we conclude our series of posts on space & dimension with an exploration of YUI’s Spacial capabilities. Many of YUI’s capabilities aren’t readily apparent from the component level documentation. One exception are the setXY & getXY functions.

  • setXY & getXY operate on the top left corner of an Element relative to the top left corner of the document.
  • A companion getXY is provided with the YUI event object to determine the location of clicks.

A look at YUI’s API’s reveals a second, powerful class for dealing with 2d space. The YUI region class is a representation of an object on a grid. Region provides the top, left, right & bottom locations in a rectangular shape. Region is not a tool for manipulating the dom, rather it is a utility class for determining the union, intersection, area and other properties of a defined rectangular area.

YUI lacks many of the capabilities for handling scrolls, widths & heights we’ve encountered in other toolkits but still provides a reasonably capable set of tools with which to handle locations within a document.