Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Friday, September 14, 2007

jQuery 1.2 Released

If you didn’t already know, jQuery is a lightweight JavaScript Framework that introduced powerful DOM querying and Function chaining. Check out their documentation for more information.

The team has added a lot in this version, rounding out the Framework’s rough edges. It is important to note that this version is not backwards compatible with previous versions and you will need to use the supplied plugin for jQuery 1.1.4 backwards compatibility.

jQuery 1.2

posted by Matt Snider at 5:59 pm  

Tuesday, September 11, 2007

Type Detection Revisited

Mikol Graves, recently commented on my Type Detection article showing a novel way to do type detection. Here is his code snippet:

function isTYPE(o) { return (o != null && typeof o == ‘object’ && o.constructor.toString() == TYPE.toString()); }

For each Object type that you care about, for example: Date, Array, Class, to name a few. You simply replace “TYPE” with the appropriate Object name. These examples would produce functions like:

function isArray(o) { return (o != null && typeof o == ‘object’ && o.constructor.toString() == Array.toString()); } function isDate(o) { return (o != null && typeof o == ‘object’ && o.constructor.toString() == Date.toString()); } function isClass(o) { return (o != null && typeof o == ‘object’ && o.constructor.toString() == Class.toString()); }

This is nice, because it gives you a way of detecting all kinds of Meta Object types that you might care about. However, you end up using the same code over and over again. Therefore, I took some time and looked around the different toolkits for various other ways that type detection was being done. I found a snippet of code that I really liked in mootools.v1.11. Here is the code:

/* Section: Core Functions */ /* Function: $defined Returns true if the passed in value/object is defined, that means is not null or undefined. Arguments: obj - object to inspect */ function $defined(obj){ return (obj != undefined); }; /* Function: $type Returns the type of object that matches the element passed in. Arguments: obj - the object to inspect. Example: >var myString = ‘hello’; >$type(myString); //returns “string” Returns: ‘element’ - if obj is a DOM element node ‘textnode’ - if obj is a DOM text node ‘whitespace’ - if obj is a DOM whitespace node ‘arguments’ - if obj is an arguments object ‘object’ - if obj is an object ’string’ - if obj is a string ‘number’ - if obj is a number ‘boolean’ - if obj is a boolean ‘function’ - if obj is a function ‘regexp’ - if obj is a regular expression ‘class’ - if obj is a Class. (created with new Class, or the extend of another class). ‘collection’ - if obj is a native htmlelements collection, such as childNodes, getElementsByTagName .. etc. false - (boolean) if the object is not defined or none of the above. */ function $type(obj){ if (!$defined(obj)) return false; if (obj.htmlElement) return ‘element’; var type = typeof obj; if (type == ‘object’ && obj.nodeName){ switch(obj.nodeType){ case 1: return ‘element’; case 3: return (/S/).test(obj.nodeValue) ? ‘textnode’ : ‘whitespace’; } } if (type == ‘object’ || type == ‘function’){ switch(obj.constructor){ case Array: return ‘array’; case RegExp: return ‘regexp’; case Class: return ‘class’; } if (typeof obj.length == ‘number’){ if (obj.item) return ‘collection’; if (obj.callee) return ‘arguments’; } } return type; };

This was a good foundation for an improvement upon my type detection Functions. The $type Function can detect nearly all of my “isType” Functions straight away and has the power to detect some other important types, such as: arguments, textnode, element, collection, and more. So far, I have only added Date in addition to the types already defined and created an additional Function “isType” which can be used to test the object against a desired type.

We lose, “isAlien” Function and whether the number is finite. However, I never use these anymore, so I do not really need them. So far I believe the benefit of using these Functions will out-weight the loss. Although, I have also found these issues: testing for ‘whitespace’ does not work with IE because IE ignores whitespaces when parsing the DOM; in Opera testing for ‘arguments’ will return ‘array’, because Arguments constructor is Array (go figure). Otherwise, it has worked flawlessly and these issues can be worked around. I put together a test page, to verify the results of the isType Function and checked variations on the most common browsers.

You can download my Type Detection JavaScript file.

posted by Matt Snider at 10:09 pm  

Tuesday, September 4, 2007

Prototype Overhauled

I was just sitting down to write an article about the differences between the Event handlers of Prototype versus YUI, and many of the other Frameworks, when I stumbled upon the new release candidate (version 1.6) of Prototype. I have to say that I am surprised and impressed. A lot I planned to discuss has changed and it seemed more appropriate to highlight the important changes found in the next release.

http://www.prototypejs.org/2007/8/15/prototype-1-6-0-release-candidate

Here are the improvements that jump right out at me:

  • Events have been overhauled so you no longer need to use the ‘bindAsEventListener’ Function to scope DOM Nodes or other Objects, instead scope can be passed in the observation declaration
  • Custom Event - one of the most powerful Framework utilities is now available in Prototype
  • More use of closures to create inheritance instead of Object hashes
  • Semantic Sugar - most return objects are now wrapped with relevant Prototype Functions
  • Commitment pledge support to JavaScript Web Standards

I believe with this new release the Prototype team is making a big step forward with their framework. My only concern is that they are still attaching methods to the Object and Array pseudo types. Otherwise, they have done an excellent job on refactoring the Framework. I will provide a link to the download when the official version rolls out.

posted by Matt Snider at 6:04 pm  

Monday, August 27, 2007

5 JavaScript Frameworks

I stumbled upon this article today, while researching techniques for capturing the back button in JavaScript. This article highlights the features of 5 top-tier JavaScript frameworks:

  1. YUI
  2. Prototype
  3. Rico
  4. Qooxdoo
  5. Dojo

Justin, says Top 5, but doesn’t say what criteria he measured them by. Ignoring his ranking, these are 5 powerful Frameworks (although Rico is really an extension of the Prototype Framework). And I had not taken a look at Qooxdoo before:

Top 5 javascript frameworks

posted by Matt Snider at 2:37 pm  

Thursday, August 23, 2007

Super Simple Image Viewer

A designer friend of mine was having trouble with one of those Image Slideshow JavaScripts you download off the internet and ask for my help. I thought it would be an easy fix, but after looking at the code I realized 2 things: the code was crap and my friend knew very little about web technologies. The code was supposed to cache images using a simple ‘addPhoto’ function and then cycle through them with a previous and next anchor without requiring page refreshes. However, all it really did was modify the URL, which would require some server-side scripting.

Being a relatively nice person, and also curious to see how difficult and time-consuming it would be to write a super-simple image slideshow using YUI I said that I would write something.

My goals were as follows:

  • unobtrusive
  • support next/prev
  • support a dynamic # of sets of image files
  • super-lightweight
  • must use module pattern

About 90 minutes of work later, the result is a 2kb minimized file that only requires ‘yahoo-dom-event.js’. A page using the slideshow need only have two anchors (with ids ‘’showNext” and “showPrev”) and an image tag (with id “image”). If you want to have more than 1 set of images then create a series of anchor tags and give them each IDs. These IDs will be used to identify the data set. Lastly, to add images to the file I created a shortcut method ‘addPhoto’ which can be used as follows:

An Example with 4 Sets of Images

//addPhoto(/*anchor ID of set*/, /*path to image file*/); addPhoto(’set1′, ‘image1-1.jpg’); addPhoto(’set1′, ‘image1-2.jpg’); addPhoto(’set1′, ‘image1-3.jpg’); addPhoto(’set2′, ‘image2-1.jpg’); addPhoto(’set2′, ‘image2-2.jpg’); addPhoto(’set2′, ‘image2-3.jpg’); addPhoto(’set3′, ‘image3-1.jpg’); addPhoto(’set3′, ‘image3-2.jpg’); addPhoto(’set3′, ‘image3-3.jpg’); addPhoto(’set4′, ‘image4-1.jpg’);

I also have a live example.

Change Made on 11/15/2007

As Jak pointed out I did not do a very good job explaining how to use this tool. In order to use this, you should first include these two files:

yahoo-dom-event.js
matts_photo_viewer.js

I suggest doing this as the last elements in your body tag:

<script type=”text/javascript” src=”http://mattsnider.com/js/yahoo-dom-event.js”></script> <script type=”text/javascript” src=”http://mattsnider.com/js/matts_photo_viewer.js”></script> <script type=”text/javascript”> // replace these with the actual names of your files addPhoto(’portfolio1′, ‘images/berserk1.jpg’); addPhoto(’portfolio1′, ‘images/berserk2.jpg’); addPhoto(’portfolio1′, ‘images/berserk3.jpg’); addPhoto(’portfolio2′, ‘images/parasite1.jpg’); addPhoto(’portfolio2′, ‘images/parasite2.jpg’); addPhoto(’portfolio2′, ‘images/parasite3.jpg’); </script> </body>

The last script tag is where you will put in your images. The first parameter in an ‘addPhoto’ Function call should be a portfolio name. If you want only one collection of images then use the same string for all ‘addPhoto’ Function calls. The second parameter is the relative path to your image. Call ‘addPhoto’ for each image you want to have in the viewer.

In your HTML markup, you will have to use 3 ID attributes: image, showNext, showPrev. The ‘image’ ID should be applied to the IMG tag that you want the update. The ’showNext’ ID should be applied to your “next” anchor tag and the ’showPrev’ to your “previous” anchor tag.

Optionally, if you want to have multiple sets (portfolios) of images, you need to attach an event handler to some element that will call

Core.Widget.PhotoViewer.changeSet(nameOfThePortfolio);

This will be one of the portfolio names you used as the first parameter in your ‘addPhoto’ Funtion calls.

posted by Matt Snider at 6:17 pm  

Tuesday, August 21, 2007

jQuery vs. Prototype from Agile Ajax

I saw this post on one of my favorite blogs, Agile Ajax. Despite the title, it is not an analysis of jQuery versus Prototype but a discussion of the OOP design of the two Frameworks. I like Brian’s analogy of Prototype being JavaScript with training wheels and other Frameworks like programming without training wheels. Using Prototype has a tendency to make coders lazy, attaching everything to the ‘this’ operating and using event and function binding all over the place, when it is not really necessary or efficient. The Module Pattern is the most efficient pattern I have used and Brian Dillard discusses this as well at the end of his article. Enjoy:

jQuery vs. Prototype: OO JavaScript with or without training wheels

posted by Matt Snider at 5:16 pm  

Sunday, August 12, 2007

YUI 2.3 Released

YUI 2.3 came out almost 2 weeks ago and I forgot to mention it. Several old feature have been improved and revisited, and 6 new feature have been added. I am most impressed by the color picker (great extension for WYSIWYG editors and theme editors), deferred image loader (allows for low res images, followed by high res versions for faster page loading), and the improved CSS package (more layouts, better normalization and fonts). Anyway, it is better than before and there are a lot more packages to include if you like.

Ultimately, though, there is only one piece that you need on every project and that is yahoo-dom-event.js. This minimized file (36k) contains the yahoo.js, dom.js, and event.js core functionality. Using this file you will have all the DOM manipulation functions that enhance productivity and one of the best event hander packages that exists today. It also, contains CustomEvent, which is my favorite part of the YUI library.

On a side note, I had dinner with Eric Miraglia of YAHOO! about a month ago and asked for some changes to the connection manager. I tend to think of AJAX requests as another event type and would like to see it incorporated with the Event package, or as a CustomEvent. This did not happen, but there has been some improvement to the ConnectionManager allowing the Object to behave more like an Event.

posted by Matt Snider at 1:22 pm  

Saturday, August 4, 2007

Module Pattern Template

So, as most of you know, I have been swamped with work lately. However, I promised myself that I would get you all a detailed article by the end of this week, regardless of how busy I am. In the near future I want to get back into comparing the different Frameworks, however, those articles take 5-10 hours to write and I just do not have that much time today. Instead, lets discuss the Module Pattern some more. In this article, I am going to show you my template for organizing my module patterns and discuss some details and gotchas about it.

First, why use the module pattern? The module pattern is best used with objects that are instantiated once (or very few times) per page. The module pattern does not leverage the power of prototype based OOP as the Functions are not being attached directly to the prototype of the Object. Instead you are instantiating a function and creating a closure thereby enclosing a self contain Object, which is more expensive in CPU cycles and memory when called frequently. I use the module pattern for 3 reasons, when writing: widgets, managers (like an Event Manager), and business logic for pages.

Here is an example of a module pattern that I use for managing the business logic of a page, which is the business need that I use the Module Pattern for most frequently:

Template.js

/** * Copyright (c) 2007, Matt Snider, LLC. All rights reserved. * Version: 1.0 */ /** * The PageName class manages the business logic of the PageName page * @namespace Core.Biz * @class PageName * @dependencies library */ Core.Biz.PageName = function() { // // Object namespace; private variables go here // var self = null; // internal object to reference public self // // Module dom namespace; id references to the DOM and other DOM objects go here // var dom = { }; // // Module evt namespace; event callbacks go here // var evt = { }; // // Module req namespace; AJAX request and callbacks go here // var req = { }; // // Public methods and constants // return { /** * The DOM selector class to identify example DOM elements * @property CLASS_EXAMPLE * @type String */ CLASS_EXAMPLE: ‘example’, /** * Some publicly available method */ publicDoSomething: function() { }, /** * initialize the object, put elements here that use global object elements (like static variables) */ init: function() { // initialize DOM references that are not null for (var k in dom) { if (isString(dom[k])) { dom[k] = $(dom[k]); } } self = Core.Biz.PageName; } }; }();

In this example ‘Core.Biz.PageName’ will create this object:

Core.Biz.PageName = { CLASS_EXAMPLE: String, publicDoSomething: Function, init: Function }

The object will be created when your page loads, but the internal objects that require the DOM should be put inside the ‘init’ Function and that function should be called when the document is ready (for best performance) or when window loads (if you do not use a powerful enough Event management Toolkit). Inside the closure Function, I generally create 3 namespaces (unless one is not needed), which helps me organize and manage my Object, these are: dom, evt, and req.

The ‘dom’ namespace will generally have the String IDs that I use to find elements on a page, or null, if I am going to initialize the DOM node reference through some other means in the ‘init’ Function. That namespace might look something like this:

var dom = { body: ‘projectBody’, someAnchor: ‘link1′, someOtherElem: null };

By putting this namespace first all other functions of the object can reference these elements. The ‘init’ function will automatically call document.getElementById (or equivalent depending on your Framework) on any String you defined in the namespace, so thereafter the Object members will reference DOM nodes. I would define ’someOtherElem’ in the ‘init’ Function as well, maybe by calling “dom.someOtherElem = dom.body.getElementsByTagName(’div’)[0];”.

The variable ’self’ is an internal shortcut to reference the public object. Initially ‘null’, you assign the ‘Core.Biz.PageName’ Object to it during the ‘init’ Function. Since references to ’self’ will not be evaluated until those Functions are called, it is safe to do use this Object as long as you run the ‘init’ Function first. Using ’self’ helps to prevent memory leaks or circular logic, and you do not have to worry about managing ‘this’. I also use it if I need to call an internal method that is not yet instantiated. For example you would not normally be able to access methods in the ‘req’ namespace from ‘evt’ because ‘req’ is declared after ‘evt’. However, as shown in the ‘evt’ namespace discussion below, you can circumnavigate this issue, by calling a public method on ’self’.

The ‘evt’ namespace will contain all non-trivial event callback functions for events attached to DOM nodes. These events should be attached in the ‘init’ Function after you have finished declaring your ‘dom’ namespace. If using YUI it might look something like this:

var evt = { onAnchorClicked: function(e) { var targ = YAHOO.Util.Event.element(e); CBP.publicDoSomething(); } }; … init: function() { … YAHOO.Util.Event.addListener(dom.someAnchor, ‘click’, evt.onAnchorClicked); … }

The ‘req’ namespace will contain all AJAX request and callback functions. I find this namespace helpful, because I can organize all my AJAX logic in the same place. If you do not use AJAX in your application or the Object does not manage AJAX, then omit this namespace.

The ‘init’ Function will be used to initialize elements of the Object that require the DOM. The first loop is included to do the automatic conversion of the ‘dom’ namespace ID references into DOM nodes. I then declare the ’self’ Object so that any internal references to the public Object are readily available. Thereafter, I will attach events, AJAX, and initialize other widgets used by the page. If you are using YUI I recommend the following line of code be included right after ‘Core.Biz.PageName’ is initialized to fire the ‘init’ Function as soon as the DOM is ready and before the window is completely loaded:

YAHOO.util.Event.onDOMReady(Core.Biz.PageName.init);

That about wraps things up. This is a complicated subject and if you have any questions, do not hesitate to ask. Also, I would be interested in hearing about how you organize your module pattern objects and any pointers you might have.

posted by Matt Snider at 4:26 pm  

Thursday, August 2, 2007

Ext JS 1.1 Released

The Ext team have released a new version of their Framework. I have mentioned this Framework before, because they have developed their package to support other Frameworks (such as YUI, Prototype, and Dojo). A few new features have been added, but more importantly the documentation has been greatly improved and the Framework is completely standalone, although it still supports extending other Frameworks. Find out more at Extjs.com:

Ext JS 1.1

posted by Matt Snider at 10:22 am  

Thursday, July 26, 2007

Detect when DOM Element is in viewport

I just read a good article by Dustin Diaz (formerly of YAHOO) about detecting where elements are in regards to scrolling and the viewport. It is simple and very powerful, so I thought I would share it with you. Also, I am overworked right now and have not had time to write any material of my own :(.

element-scroll-into-view

posted by Matt Snider at 3:49 pm  
« Previous PageNext Page »

Powered by WordPress