selfcontained[web development]

Articles tagged with "yui" (12)

Review: Yahoo! User Interface Library 2.x Cookbook

Wednesday April 20, 2011
By Brad Harris

I've had some time to really dig in to Matt Snider's latest book, Yahoo! User Interface Library 2.x Cookbook, and have some great things to say about it. I wanted to take a different approach to reading and reviewing this book, and hopefully it proves helpful to readers. I've been working on whoopdwhoop.com in my free time a lot lately, and normally as I'm developing front-end code using YUI, I reference their online documentation (which is pretty good IMO) when I have questions. I decided to just rely on this book for the past few weeks to really see how useful it was as a reference while developing. In short, it has been a great development companion. Let me explain...

I was working on adding some DataTable functionality for a client's site (Aeris Secure), and found the chapter in Matt's book to provide great examples and explanations for getting it going relatively quickly. He lays out multiple use cases for the DataTable, as he does so with just about all of the chapters, and that wide coverage provided a great reference as I found each example had additional insight into how to use the particular component of the YUI library. I think this approach will be a great way for beginners to ramp up to using the library, as they start fairly vanilla and basic, but as you progress the more advanced use cases and features are discussed. For a developer that is more familiar with the basics, they will quickly learn to jump a few sections in to each chapter to get to the meat of what they want to learn.

That's one example of how I found the book to be helpful in practice. If you want a solid picture of how to work with YUI, this book is great.

Latest Endeavor: whoopdwhoop.com

Sunday January 23, 2011
By Brad Harris

My wife and I have been chugging away on a new endeavor for awhile, and we finally got to a point where we could launch it live. In short, it's a currency free, creative marketplace, and it's called whoopdwhoop.com. It gives "artisans", or crafty people, a place to list their creations, and hopefully, a community where they can swap their creations with others all without exchanging any currency. This is facilitated through a pretty simple "whoop" (read point) based system. As people request a creation from someone, they pay them in "whoops", and then that person can use those "whoops" to request other creations. We haven't pushed much of a marketing campaign at it yet, in hopes to gauge initial feedback before doing so, and fix or improve whatever came up. We've done a fair amount of that so far, and are pretty happy with it's current state. Needless to say, we can't speak to if it will catch on and be the start of a thriving community, we'll have to wait and see.

While I don't think the majority of my blog's reader-base would be interested in using the site itself, I wanted to make a quick post to point out how the development of it has gone, which will hopefully be of more interest to those reading.

I built the site in about 4 or 5 months of actual heads-down, after-hours work. I have a day job, so this is just something I've spent nights and weekends putting time into. It's built on Zend Framework MVC, which I absolutely love. The UI is enhanced through YUI, which is another favorite library of mine. The database is MySQL, and I'm also using Doctrine ORM.

Zend Framework and Doctrine, in my mind, are a great marriage of libraries for PHP. Zend handles everything I've needed from an MVC, with the additional benefits of providing out-of-the-box API's for things like ACL, Auth, Caching, Emails and Logging. Doctrine does a great job at providing a stable and solid ORM, and a great means of managing updates through a simple migration strategy. The best part about finding a solid framework you enjoy working with, is you eventually end up with a great set of features you've built that can be dropped in to any project, giving you quite the head-start. When I started ( which was actually over a year ago, my motivation comes in spurts), Doctrine 2 was in development, but wasn't where it is now. I like the concept they've taken with the new version, but currently I'm using their 1.x version.

YUI is being used pretty sparingly right now. I think the only modules being used currently are containers for the dialogs, buttons, and menu. I need to give a shout out to the Minify library as well, which is handling the JS/CSS minification quite nicely.

I have some follow-up posts I plan on writing to go into more detail on some of the items and techniques I used in regards to things like Caching, but until I've had more of a chance to put the site through a ringer, I'll hold off. Anyways, if you're building a new site, looking for frameworks, I highly recommend everything I mentioned above.

YUI => jQuery?

Friday November 19, 2010
By Brad Harris

Recently a question was posted on Quora, "How could YUI3 improve its image compared to jQuery, MooTools, etc.?". John Resig, of jQuery fame, gave a great answer on his thoughts to the question. Nicholas Zakas responds with another great explanation of why he doesn't think the comparison is needed. I disagree with Zakas in regards to jQuery not being sufficient for "scalable web applications". Both have great points, and are worth a read if you're actively involved with frontend engineering.

YUI 2.8 Learning the Library book review

Saturday September 4, 2010
By Brad Harris

I've had a chance to read through the latest book on YUI, titled YUI 2.8 Learning the Library. The book was written by Daniel Barreiro and Dan Wellman, and was published by Packt Publishing. For the impatient that don't want to read the whole review, and want to get right to the goods, here they are. The book has great coverage of the YUI library, including all of the popular widget like Calendar, Container, Autocomplete, DataSource, DataTable and more. If you'ren new to YUI and looking for an overage and how-to for the library, this book would serve you well. If you're an experienced YUI developer, you probably won't get a whole lot out of this book that you don't already know, or couldn't gain through reading YUI's online examples and API.

If you read through this book in it's entirety, you'll come to understand the main reason I love YUI, that it's not just a collection of widgets and utilities. This book explains the full feature set of the YUI library, and you'll realize that it's the perfect foundation to build on top of. The author's do a really great job of showing in depth examples that teach you how the components work. I particularly liked reading the chapter on DataSource and DataTable.

If the online examples provided by Yahoo! leave you wondering how things are working, this book fills in those gaps. Most of the book is targeted to beginners and intermediate developers.

"YUI 2.8: Learning the Library" Free Chapter

Friday August 13, 2010
By Brad Harris

Grab a free chapter of the latest YUI book from Packt Publishing, "YUI 2.8: Learning the Library." The free chapter covers something we all use a lot, menus. I'm checking it out now, and suggest if you use, or are thinking about using YUI, you do the same since it's free.

I've been using YUI for about 4 years now, and love it. I love the solid foundation it provides for me to build my own interfaces on top of. I love the polished UI elements it provides as well. I'm looking forward to reading this book in its entirety. Check back soon for a full review of it.

Scoping Javascript closures in loops

Friday January 23, 2009
By Brad Harris

It must have been something I ate, cause this is like the third post in 2 days I think! This is a quick one, but super handy to know if you don't already. There is semi-common problem I run into, and it has to do with scoping of closures inside of loops. Lets get straight to the code so its easier to understand what I'm talking about:

<html>
<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/utilities/utilities.js" ></script>
<script type="text/javascript">
    var values = [0,1,2,3,4,5,6,7,8,9];
    for(var idx in values) {
        //First Test - will have incorrent scoping
        YAHOO.util.Event.addListener(window, 'load', function() {
            YAHOO.util.Dom.get('wrong-scope').innerHTML += ' '+values[idx]+' ';
        });
        //Second Test - scoping will be correct
        YAHOO.util.Event.addListener(window, 'load', function(scopedValue) {
            return function() {
                YAHOO.util.Dom.get('right-scope').innerHTML += ' '+scopedValue+' ';
            }
        }(values[idx]));

    }
</script>

<body>
<div id="wrong-scope">
<h1>Wrong Scope</h1>
</div>
<div id="right-scope">
<h1>Right Scope</h1>
</div>

</body>
</html>

In this example, there is a simple array of ordered values, and then a loop over those values. For each iteration of the loop, there is an onload listener added that will dump that value into a div. You'll see the first loop always dumps 9, because the scoping is wrong when the closure executes, and the last time through the loop sets the scope of values[idx].

The second section does some unique handy-work to correct the scoping. A listener is added like before, but the closure is created in a specific fashion in order to get the scope to be the way we want at runtime. For the closure in the second section, we create a self-executing function, passing in a parameter that is the current value in our array of numbers. That function runs, and returns another function that does the appending to the div of the value. This second, inner-function is what will execute on page load. Because of the outer-function we immediately called, the variable passed into it, the current value from our array, will be available, and properly scoped for our inner-function.

scoping

This is a handy trick when you have a situation where you are looping over a collection, and are providing some type of callback/closure for each entry, but need some proper scoping.

Followup on YUI : getFirstDescendantBy()

Thursday January 22, 2009
By Brad Harris

Awhile ago I posted on an additional function for YAHOO.util.Dom called getFirstDescendantBy(). I was following the ticket submitted to the YUI Sourceforge tracker, and saw that it had been closed out, and that a new function called YAHOO.util.Dom.getElementBy() was added to fill this request. I decided to check out the newly available YUI source code on github, and noticed some nice enhancements. YAHOO.util.Dom.getElementBy(method, tag, root) is now available (not in the latest stable release yet though), and does what getFirstDescendantBy did, and in most cases its much faster. Great job to the YUI team!

Instead of taking a recursive approach to walking the graph like I had, YUI is just grabbing all the children by tag name, even if you don't supply a tag name (in this case it will use ''). This turns out to be much faster than the recursive approach for most cases. If you happen to be looking for an element in a very large dom tree structure, and that object is located early on in the tree, the new YUI approach will be slower than the recursive approach. Fortunately, when I say *"large" dom tree, I'm talking about a tree about 8 nodes deep, iterated 500-1000 times. Most of us don't work with sites displaying that much html on a single page, so its definitely not a concern in my book.

Digging in further, I noticed that the new getElementBy just delegates to YAHOO.util.Dom.getElementsBy(), which has now been improved to accept a number of additional parameters than what 2.6.0 has available. One of those is a boolean, firstOnly, which will stop after it finds the first match, and return it. It looks like there are also additional parameters for passing in an object to your apply method, and making that object the scope.

I'm excited about this change, and it means I will soon be able to use the native YUI function for what I needed. I'd suggest that anyone else that was using something such as getFirstDescendantBy() that I had shared look at switching once YUI releases the new function. Thanks again YUI.

Javascript widget approaches: Singleton vs Prototype

Tuesday December 23, 2008
By Brad Harris

Recently I've been doing some work setting up some standard javascript widgets for a web application I am working on. By widget, I'm referring to items such as javascript date pickers, tooltips, autocomplete inputs, etc. I'm building on top of YUI for this approach, but the principles I'd like to discuss are applicable to any library. YUI provides a fantastic javascript library, and a collection of widgets right out of the box. More than likely, as you add them to your application, you'll want to wrap or extend them in your own javascript implementations to get them functioning as desired. To accomplish this, I typically have taken one of two approaches, and these are the topics I'd like to cover. To provide a working example, I'll use a simple wrapper for a YUI Calendar widget that is linked to a text input, and opens by clicking a calendar icon.

image of a date picker widget

Prototype approach

This approach basically creates an instance of the javascript widget for each input field, and the javascript widget object utilizes the prototype definition so the internal functions can be defined once in memory. Below is an example of what a simple DatePicker widget that "wraps" the YUI Calendar widget, would look like:

function DatePicker(icon, field) {
    this.icon = icon;
    this.field = field;
    YAHOO.util.Event.addListener(window, 'load', this.initialize, this, true);
}
DatePicker.prototype = {

    icon : null,

    field : null,

    calendar : null,

    id : 'date-calendar',

    container : null,

    initialize : function() {
        YAHOO.util.Event.addListener(this.icon, 'click', this.click, this, true);
        this.renderContainer();
    },

    renderContainer : function() {
        this.container = document.createElement('div');
        this.container.style.display = 'none';
        document.body.appendChild(this.container);
    },

    click : function(e) {
        if(this.calendar === null) {
            this.renderCalendar();
        }
        this.calendar.show();
        this.positionCalendar();
    },

    renderCalendar : function() {
        this.calendar = new YAHOO.widget.Calendar(this.field+'-calendar', this.container, { title:'Choose a date:', close:true, navigator: true } );
        this.calendar.selectEvent.subscribe(this.populateDateField, this, true);
        this.calendar.render();
    },

    positionCalendar : function() {
        var position = YAHOO.util.Dom.getXY(this.field);
        position[1] = position[1] + 25;
        YAHOO.util.Dom.setXY(this.container, position);
    },

    populateDateField : function() {
        var date = this.calendar.getSelectedDates()[0];
        YAHOO.util.Dom.get(this.field).value = date.getMonth() + '/' + date.getDate() + '/' + date.getFullYear();
        this.calendar.hide();
    },

    hide : function() {
        if(this.calendar !== null) {
            this.calendar.hide();
        }
    }

};

The html for creating this widget is as simple as follows:

<script type="text/javascript">
    new DatePicker('date-icon', 'date-field');
</script>
<label>Date: </label>
<input type="text" name="date-field" id="date-field" />
<img src="images/calendar.png" id="date-icon" />

Some benefits to this approach are that the instance of the widget object has a direct reference to the input id and calendar icon id, and nothing has to be 'inspected' at runtime execution of the events. This leads to some cleaner code on a small level. It also has some downsides as we'll discuss below.

Singleton approach

The Singleton approach creates a 'singleton' wrapper object that creates ONE YUI Calendar widget that is re-used across all input fields. At runtime, the icon clicked on is used to determine which input field is in use through an extra attribute added to the icon image called 'data-field' that contains the id of the input it is linked to. This code would look as follows:

DatePickerSingleton = {

    calendar : null,

    id : 'date-calendar',

    container : 'date-calendar-container',

    activeInput : null,

    initialize : function() {
        var icons = YAHOO.util.Selector.query('.date-icon');
        YAHOO.util.Event.addListener(icons, 'click', this.click, this, true);
        this.renderContainer();
    },

    renderContainer : function() {
        var container = document.createElement('div');
        container.id = this.container;
        container.style.display = 'none';
        document.body.appendChild(container);
    },

    click : function(e) {
        this.activeInput = common.byEvent(e).getAttribute('data-field');
        if(this.calendar === null) {
            this.renderCalendar();
        }
        this.calendar.show();
        this.positionCalendar();
    },

    renderCalendar : function() {
        this.calendar = new YAHOO.widget.Calendar(this.id, this.container, { title:'Choose a date:', close:true, navigator: true } );
        this.calendar.selectEvent.subscribe(this.populateDateField, this, true);
        this.calendar.render();
    },

    positionCalendar : function() {
        var position = YAHOO.util.Dom.getXY(YAHOO.util.Dom.get(this.activeInput));
        position[1] = position[1] + 25;
        YAHOO.util.Dom.setXY(this.container, position);
    },

    populateDateField : function() {
        var date = this.calendar.getSelectedDates()[0];
        YAHOO.util.Dom.get(this.activeInput).value = date.getMonth() + '/' + date.getDate() + '/' + date.getFullYear();
        this.calendar.hide();
    },

    hide : function() {
        if(this.calendar !== null) {
            this.calendar.hide();
        }
    }

};
YAHOO.util.Event.addListener(window, 'load', DatePickerSingleton.initialize, DatePickerSingleton, true);

The html for creating this widget is as simple as follows:

<div class="code-highlight"><code>
<label>Date: </label>
<input type="text" id="date_field" />
<img src="images/calendar.png" class="date-icon" data-field="date_field" />

Results

After testing out each of these approaches using a range from 1 to 1000 inputs on a page, I noticed some interesting side effects. Both approaches load using almost the same amount of resources. You might think the Prototype approach would require more memory on page load to create each of the widgets for each input, but in reality, due to the prototype definition, the only additional memory needed for each widget is for the unique element id's stored as attributes. Each approach also uses a 'lazy loading' approach, that causes the Calendar widget to not be created until the user actually clicks on an icon. This is where the two approaches begin to differ.

The Singleton approach consumes a small amount of additional memory on the first click, as it creates the Calendar widget at this time. For subsequent clicks the memory stays the same, as the objects have already been created, and are just being re-used. A downside to this approach is that on page load, a javascript css selector query has to be executed to gather all date picker icons to set up click events for them. This 'can' be time consuming with a large number of elements (1000+).

The Prototype approach will consume additional memory for each new icon that is clicked, as there is a Calendar widget created lazily for each input at the runtime click event of the icon. From my simple tests, I saw an increase ranging from 51.2 kb to 358.4 kb for each additional widget instantiated (each new icon clicked). In contrast to the Singleton approach, on page load there is no css selector query to run in order to attach the click events, as the element ids are already in memory from the instantiation of each 'wrapper' (DatePicker) object. This saves the possibly heavy css based query, but adds an initialize function for each input to the page load, which can be time consuming as well.

Recently I have been using the Singleton approach for creating widgets where it is possible, as I believe it scales better, and avoids the problem of memory increasing as users go about using the application. This can be accentuated even further when page life cycle is long such as in the case of single page web applications. I found this little exercise interesting in my own work, and hope it is informative for some other people out there. I'd love to hear any comments regarding this from everyone out there.

Javascript getFirstDescendantBy()

Wednesday August 20, 2008
By Brad Harris

Update: A new native YUI function is in the works, and does this job better


Recently I was working on optimizing some javascript, and found a slow area that was trying to find the first focusable input in a certain area of the page, and it was taking anywhere from 100 - 500 milliseconds, depending on the size of the DOM tree in that element. After digging into it, I noticed it was using the YAHOO.util.dom.getElementsBy() method, which basically had to walk through the whole DOM tree in this case, testing each node against the boolean method passed in. After calling that, it would then return the first, if any, element that getElementsBy returned. Obviously this was a bad approach, as after you find the first match, there is no need to go further.

I did a little research, and saw that this had come up in a thread on the YUI group. I ended up writing a small method to fill in this functionality I wanted out of YUI, called getFirstDescendantBy(rootEl, method). The function takes a root element, or string id of that element, and then a function to test each element against that has the element being tested as the only input. This function passed in should return a boolean, and is similar to the way the YUI dom function getElementsBy() works. Hopefully this will help out some people in similar situations.

function getFirstDescendantBy(rootEl, method) {
    var root = typeof rootEl === 'string' ? document.getElementById(rootEl) : rootEl;
    var firstDescendant = null;
    var children = root.childNodes;
    for(var idx in children) {
        var child = children[idx];
        if(child.nodeType === 1) {
            if(method(child)) {
                firstDescendant = child;
                break;
            }else if(child.childNodes.length > 0) {
                var recursiveResult = getFirstDescendantBy(child, method);
                if(recursiveResult !== null) {
                    firstDescendant = recursiveResult;
                    break;
                }
            }
        }
    }
    return firstDescendant;
}

Back to Firefox 2

Wednesday July 23, 2008
By Brad Harris

If you're like me, you use Firebug a lot, like, all day long. Long gone are the days of resorting to alerts. The worst I'll fall back to is using the YUI logger for IE.

I've recently been having a lot of issues using Firefox 3, and Firebug. Firefox 3 has been pretty consistent at crashing a few times throughout the day. Firebug 1.2 has recently been causing me more and more troubles, to the point where I can't get it to not stop at breakpoints that I've removed, or it stops at my breakpoint, but doesn't let me play it through or debug, or remove the breakpoint, because it doesn't show up as being registered.

I'm sure these are hiccups with the new version of Firefox 3, but it is pretty disruptive to me as I'm developing. I reverted back to Firefox 2 and an older version of Firebug until they get this sorted out, which I'm sure will be soon. For anyone looking, you can find old versions of Firefox on FileHippo, and past versions of Firebug from the normal download site.

Complex Javascript Event Handling: EventMediator

Wednesday July 16, 2008
By Brad Harris

A large enterprise sized project I work on uses YUI library extensively, and events are a huge part of the rich front end we're developing. What you start to learn quickly about UI events, is that dependencies between different events start to get very complicated very fast. When A depends on B, but B needs to wait for C and D and E to finish, but E needs to wait for F to finish, you have a complex situation on your hands. Up until recently we were able to rely mostly on just using CustomEvents in YUI to handle this for us.

Where that starts to break down is when you have one event, A, that is dependent on multiple other events, B, C, D. You now have to manually keep track of what has fired, and make sure you don't fire that A until B, C and D have all fired. With very little code, here is a simple class that can be used in conjunction with YIU CustomEvents. It will handle the 'book-keeping' of firing what you want when all the events you have designated fire.

EventMediator = {

    addActivationRecord : function(record) {
        record = record || {};
        var that = this;
        for(var idx in record.events) {
            var eventRecord = record.events[idx];
            if(eventRecord.event !== null) {
                eventRecord.fired = false;
                eventRecord.event.subscribe(function(scopedEvent) {
                    return function(e) {
                        scopedEvent.fired = true;
                        that.fireActivation(record);
                    }
                }(eventRecord));
            }
        }
    },

    fireActivation : function(record) {
        var fired = true;
        for(var idx in record.events) {
            if(record.events[idx].fired === false) {
                fired = false;
                break;
            }
        }
        if(fired === true) {
            record.activate.call(record.scope);
        }
    }

};

Using the EventMediator would look something like the following:

EventMediator.addActivationRecord({
    events : [
        { event : myObj.someYUICusomEvent },
        { event : myObj.anotherYUICusomEvent }
    ],
    activate : myObj1.myActivationCallback,
    scope : myObj1
});

It's pretty straightforward I think. You call addActivationRecord, passing in an array of objects, whose 'event' property points to a YUI CustomEvent. You also provide an activate callback method, and give it a scope in which to call the method. For my purposes so far this has worked pretty well, although I'm sure it could be built up to be much more robust. Hope it helps someone out!