Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Saturday, January 5, 2008

Improving Extend With Super

Alright, it looks like I will need to eat my words about not needing super class support in my extend Function, see Object Extension. As many of you know, I have been working on Objects to represent XJson in JavaScript. One of the changes from my original JSONObject Model is that I now use “Core.extend” to extend a core Model object. This object has an onChange event and an update function. Here is what I have so far:

Example 1: Model.js

Core.Model.Model = function(o) { this.update(o); }; Core.Model.Model.prototype = { addChangeListener: function(fx) { var evt = new YAHOO.util.CustomEvent(’model’ + Math.random(), this, false, YAHOO.util.CustomEvent.FLAT), that = this; this.addChangeListener = function(fx) {evt.subscribe(fx, that);}; this.addChangeListener(fx); }, update: function(o) { if (! o) {throw(’Model - Invalid object passed into Update’);} this.data = o; } };

Model does little right now, but what I realized is that any Object that extends from it and overrides the update method, should first call the update method of Model. This way the passed Object is always evaluated and “this.data” is always created. In the future, I may also find other important values to attach. In order to make this call, I needed access to the super class of an extending Object.

As I used YUI as a model for my extend function, it is also a good model for how to do super classes. OOP in JS, Part 2 is a useful article as well. Here is a revamped version of extend to support super classes:

Example 2: Superclasses

var extend = function(subc, superc, overrides) { if (! superc || ! subc) { throw new Error(’Core.extend failed, please check that all dependencies are included.’); } var F = function() {}; F.prototype = superc.prototype; subc.prototype = new F(); subc.prototype.constructor = subc; subc.prototype.parent = superc.prototype; if (overrides) { for (var i in overrides) { subc.prototype[i] = overrides[i]; } } };

I have taken a very similar approach to YUI, however, there are two notable changes: 1) I use ‘parent’ as the super class reference, instead of ’superclass’; as a DOMScripter parent is a familiar naming convention and it feels more intuitive, 2) when the super class is ‘Object’ nothing is attached to the prototype of ‘Object’; I hate attaching anything to the prototype of Objects and Arrays as it messes up ‘for … in’ statements.

So, lastly, here is an example of how you call the super class from the child class:

Example 3: Calling the Super Class

Core.Model.XJsonArray = function(data) { this.update(data); }; Core.extend(Core.Model.XJsonArray, Core.Model.Model, { length: 0, … /* More to come in my Tuesday Article */ /** * Updates the object to use the passed data set * * @method update * @param data {object} xjsonarray object * @public */ update: function(data) { if (! (data && isType(data, ‘object’) && isType(data.scheme, ‘array’) && isType(data.set, ‘array’))) {throw(’XJsonArray - Invalid data passed into Update’);} this.parent.update.call(this, data.set); this.length = this.data.length; this.scheme = data.scheme; } });
posted by Matt Snider at 1:35 am  

Tuesday, December 18, 2007

Semantic HTML for a Simple 5-Star Rating System

I am going to deviate this week from the Json Object discussion, as I have not had any time to work on it. Instead, I wanted to share a technique you can use to write semantic HTML for a rating system. If you have ever used a site like Amazon.com or Yelp.com, then you are familiar with the star rating system (0 stars = worst rating, 5 stars = best rating). However, most rating systems do not do a good job when browser font-size or zoom changes, making them inaccessible. Also, most tend to use a different graphic for each rating, requiring up to 10 graphics to load. The technique I worked on this week, not only scales well, but only requires 2 graphics, and you can change the color of your ratings with simple CSS.

Step 1: Create 2 Images

First decide which size you want the image to normally be (for me this was 80px wide by 16px high); this is a 1 to 5 ratio, because I am going to use a 5 point rating system, which will play an important role for the size of each rating point symbol. Use a program like Photoshop to create an image with these dimensions and a transparent background. In a separate window create an 16 x 16 (or 1/5 of the default width you chose) transparent image and draw in the symbol you want to use for the rating point (I used black for the color of my symbol, but it is up to you). I used a star, but it doesn’t matter what you choose so long as the center is transparent and the symbol fills the dimensions. All spaces outside the symbol should be the background color of your page (this is white for my example page). Here is an example of my star:

Example 1: Star Graphics

Single star graphic

Single star graphic

The first graphic shows what “star.gif” looks like by default. The second show, the difference when a background color is applied. I choose red, but you can change it to whatever hex you prefer.

Next copy your 16×16 symbol image 5 times into the original image you created. You should have something that looks like the following:

Example 2: Rating Graphics

5 star graphic

5 star graphic

Example 2 is the first image we will need. I made the background yellow to show how easy it is to change. The second image we need is a background masking image used to cover the part of the rating inverse (if the rating is 1.5, then this will cover the other 3.5 of the symbols). The background should be the color of the site background (white for me), and the left-most pixels should all be the color of the symbols (black for me). This image should be taller and wider than the rating image, because it will need to scale as the browser does. I usually do 2x the original dimensions, which supports up to a +4 font-size. Therefore, the dimensions of my “ratingbg.gif” is 160×32px:

Example 3: Rating Background Graphics

5 star graphic

The gray border is only here to show contrast so you can see what the image looks like. The small sliver of black on the left will be the line that marks the rating position inside of the symbols. This completes all the images and HTML you will need to get the rating system to work.

Step 2: Create Styles to Control the Ratings

Next we style the image tag to support our ratings. I suggest using classes, here are the styles I used:

Example 4: Rating Styles

img.rating { background: #FC0 url(/assets/img/bg/ratingbg.gif) 5em 0 no-repeat; /* specify your color; 5 em is the 5:1 ratio; and the url is wherever the ratingbg.gif is located */ font-size: 1.6em; /* this is the height of a single symbol; mine is 16px */ height: 1em; /* this will cause the image to scale as the font-size changes, default is 16px */ width: 5em; /* this the 5 to 1 ratio that I mentioned, but could be different if your symbols aren’t symetric */ } /* higher specificity than img.rating */ html body img.r9 { background-position: 4.5em 0; } html body img.r8 { background-position: 4.0em 0; } html body img.r7 { background-position: 3.5em 0; } html body img.r6 { background-position: 3.0em 0; } html body img.r5 { background-position: 2.5em 0; } html body img.r4 { background-position: 2.0em 0; } html body img.r3 { background-position: 1.5em 0; } html body img.r2 { background-position: 1.0em 0; } html body img.r1 { background-position: 0.5em 0; } html body img.r0 { background-position: 0 0; }

Step 3: Tie it all Together

Here is a rating of 2.5 in yellow, 1 in blue, and 4.5 in green:

Example 5: 3 Star Rating Variations

2.5 in yellow rating example
1 in blue rating example
4.5 in green rating example

The image heights in this article are slightly off by a fraction, due to rounding issues with other styles inherited in this wordpress theme. I have also created a test page so you can play with the uncorrupted styles and view them in different browsers. Try to scale the font-size and see how nicely the images scale and the rating stays in the appropriate place.

posted by Matt Snider at 3:45 pm  

Wednesday, December 12, 2007

Issues With JsonArray

My goal today was to finish most of the models that I have been working on and share this with you. However, it is turning out to be a much more complicated problem than I originally thought. I want the JsonArray object to dynamically create JsonObjects (as necessary) when retrieving elements out of the array. However, the JsonObject declaration requires that you know what Object is being passed, and more importantly, what keys to expect.

For example, here is what I have for JsonArray:

Example 1: JsonArray

/** * The JsonArray class manages … * * @namespace Mint.Model * @class JsonArray * @dependencies library */ Mint.Model.JsonArray = function(data) { this.update(data); }; Mint.Model.JsonArray.prototype = { update: function(data) { var that = []; this.get = function(i) { if (! that[i]) { var o = data[i]; if (isArray(o)) { that[i] = new Mint.Model.JsonArray(o); } else if (isObject(o)) { that[i] = new Mint.Model.JsonObject(o); } else { that[i] = o; } } return that[i]; }; } });

This will work just fine if all values of the array are non-object. However, if it is an Object (most likely, it is), then the JsonObject method is instantiated. The JKEYS array will be empty, because you haven’t defined it yet and will throw errors. This has been a real thorn in my side and I have not found a good solution around the issue, except possibly in xJson.

I was planning on playing with xJson separately, but since xJson defines the keys in the JsonArray definition, you can leverage them during the JsonObject instantiation. Also, this has the added benefit of being server driven, without requiring client-side awareness and could make these model objects a little more tamper resistant. I will look into xJson this week and post about it on Friday.

posted by Matt Snider at 3:03 am  

Friday, December 7, 2007

JsonObject Model Prototype

I have been doing a lot of server-side work in PHP and JAVA this past month. One of the design practices used by server-side webapp languages is the MVC (model-view-controller) framework. An MVC makes writing extensible and scalable code, much easier. In JavaScript I have seen a couple of attempts at a similar MVC framework, but most of the time it is overkill or poorly implemented. Shutterfly.com on the other-hand, has a lot of JavaScript and a fairly solid MVC implementation.

I have been toying with JavaScript MVC concepts all week and want to share what I developed to improve working with JSON objects. Keep in mind this is a work in progress and I am open to any suggestions:

Example 1: Sample Code

/** * The JsonObject class manages … * * @namespace Core.Model * @class JsonObject * @dependencies core */ Core.Model.JsonObject = function(data) { this.update(data); }; Core.Model.JsonObject.prototype = { JKEYS: [], MODEL: ‘JsonObject’, update: function(data) { var obj = {}, that = this, i = 0; // iterate through the JSON object keys for (var key in data) { var o = data[key]; if (! isType(o, ‘function’)) { // this key is not in the model if (-1 < that.JKEYS.indexOf(key)) { throw('Invalid key (' + key + ') passed into ' + that.MODEL); } obj[key] = o; that[isType(o, 'boolean')? key: 'get' + ckey] = function() {return obj[key];}; that['set' + ckey] = function(o) {return obj[key] = o;}; i += 1; } }; // the keys in the object do not match the keys in the model if (i != JKEYS.length) { throw('Invalid number of keys passed into ' + that.MODEL); } } });

This method takes a JSON object and applies getter/setter methods to that object. Each time update is called, it validates against JSKEYS, which should be an array of the expected keys. We also remove any functions that might have been attached to the ‘data’ object. You may also note that I have a special check for boolean values that does not attach the ‘get’ preface to the getter method. This is because I always preface boolean values with ‘is’ or ‘has’ (or something like that), and I want that preserved in the Function attached to the JsonObject.

Here is an example of how you might use it:

Example 2: Using JsonObject

// a JSON object, most likely returned from the server, representing a car var carJson = { make: ‘ford’, model: ‘contour’, year: ‘1996′, price: ‘$2,000′, isNew: false }; // use the extend (Object Extension) method to create a CarObject, with the appropriate JKEYS set Core.extend(Core.Model.CarObject, Core.Model.JsonObject, { JKEYS: [’make’, ‘model’, ‘year’ , ‘price’], MODEL: ‘CarObject’ }); var car = new Core.Model.CarObject(carJson);

Example 2 will create a CarObject (extended JsonObject), with the following members:

Example 3: CarObject Structure

CarObject = { // constants defined by the prototype object JKEYS: [’make’, ‘model’, ‘year’ , ‘price’], MODEL: ‘CarObject’, getMake(), setMake(), getModel(), setModel(), getYear(), setYear(), getPrice(), setPrice(), isNew(), setIsNew() }

I find it much easier to work with the JsonObjects once the getters and setters have been created, because you have defined what should be there. Plus, with the validation you can be sure that you received the correct JSON Object. Some possible improvements would be to support nested JsonObjects and JsonArrays, and setter type validation (although, this might be overkill).

There are really only 3 types of models that you might need to use in JavaScript: JSON Objects/Arrays, Query strings, and XML. Creating the Models is a good first step in building an MVC as you will need to pass these between the controller and the view, to update the view and send messages to the server. Next week, I will look into these other model types and improve this one a bit.

posted by Matt Snider at 3:35 pm  

Saturday, December 1, 2007

Object Extension

Object extension is one of the most important aspects of an OOP language. Many people believe that a prototype based OOP languages, such as JavaScript, are unable to support this classical OOP feature. Frankly, these people are wrong, and most likely have never studied a prototype based OOP. There are, in fact, two ways (if you know of more, please let me know) of extending objects in JavaScript: Member Copy and Prototype Clone.

Member Copying

This is a brute force technique and the most common method used for extending Objects. Most frameworks started using this technique, see jQuery (<= v1.2) and prototype (<=1.5) extend methods. In this technique you iterate through each member in Object A and add it to Object B. Often Object B is created when the extend Function is executed. Here is an example snippet from jQuery 1.2 extend:

Example 1: Memeber Copy as Implemented By jQuery 1.2

jQuery.extend = jQuery.fn.extend = function() { // copy reference to target object var target = arguments[0] || {}, a = 1, al = arguments.length, deep = false; // Handle a deep copy situation if ( target.constructor == Boolean ) { deep = target; target = arguments[1] || {}; } // extend jQuery itself if only one argument is passed if ( al == 1 ) { target = this; a = 0; } var prop; for ( ; a < al; a++ ) // Only deal with non-null/undefined values if ( (prop = arguments[a]) != null ) // ACTUAL COPY BEGINS HERE // Extend the base object for ( var i in prop ) { // Prevent never-ending loop if ( target == prop[i] ) continue; // Recurse if we’re merging object values if ( deep && typeof prop[i] == ‘object’ && target[i] ) jQuery.extend( target[i], prop[i] ); // Don’t bring in undefined values else if ( prop[i] != undefined ) target[i] = prop[i]; } // ACTUAL COPY ENDS HERE // Return the modified object return target; };

There is a lot going on here, because jQuery allows for deep copy (recursively copying members of the extension objects) and the simultaneous extension of multiple objects. My all-caps “ACTUAL COPY …” comments wrap the actual copy code. The “for in” statement iterates through the extension Object (prop[i]) and applies it to the extending Object (target[i]).

The benefits of the Member Copy method are that it is easily understood and makes multiple inheritance trivial. The negatives are that it is much slower than the Prototype Clone method, it is easy to accidentally override methods, and a bit of hackery is needed to do a deep extension of an Object.

It is slower because you have to iterate through every member of the extension Object and then apply each of those members to the extending Object. In the Prototype Clone method, this can be done in 3 lines of non-looping code. Accidentally overriding methods is a problem, because you might be extending Object A, which has a method ‘toString’ with Object B, which also has a method ‘toString’. However, you wanted to keep the ‘toString’ method of Object A. The Prototype Clone method only allows for single inheritance, which prevents such pit-falls.

Prototype Clone

This is my favored technique as performance is the most important aspect of my applications. The user should never have to wait for your JavaScript to execute and this method can be much faster than the Member Copy method as the operation cost is a constant time operation versus an O(n) operation. Here is an example of the Prototype Clone method from YUI:

Example 2: Prototype Clone as Implemented By YUI 2.3

/** * Utility to set up the prototype, constructor and superclass properties to * support an inheritance strategy that can chain constructors and methods. * Static members will not be inherited. * * @method extend * @static * @param {Function} subc the object to modify * @param {Function} superc the object to inherit * @param {Object} overrides additional properties/methods to add to the * subclass prototype. These will override the * matching items obtained from the superclass * if present. */ extend: function(subc, superc, overrides) { if (! superc || ! subc) { throw new Error(”YAHOO.lang.extend failed, please check that ” + “all dependencies are included.”); } var F = function() {}; F.prototype = superc.prototype; subc.prototype = new F(); subc.prototype.constructor = subc; subc.superclass = superc.prototype; if (superc.prototype.constructor == Object.prototype.constructor) { superc.prototype.constructor = superc; } if (overrides) { for (var i in overrides) { subc.prototype[i] = overrides[i]; } YAHOO.lang._IEEnumFix(subc.prototype, overrides); } },

In this method you first create an anonymous Function ‘F’ and copy the prototype of the superclass to that Function (this prevents changes to the subclass from affecting the superclass). Then instantiate ‘F’ assigning it to the prototype of the subclass. This creates memory pointers on the subclass’ prototype Object to the members attached to the prototype of the superclass. Now when you instantiate the subclass Object, it will have all members of the superclass. It is important to note that you should not be extending an Object that already has values on its prototype, but instead you should use this technique when you first create the subclass Object.

YUI also adds some additional Object pointers (constructor and superclass), which make these Objects behave more like a Classical OOP language. I disagree with this action, because you can extend the Object object, and this method will modify the prototype of Object and break future “for in” statements on all Object objects. They use these methods in detecting Object types and the inheritance model, but I have not yet been convinced of the need for this.

I do like how they allow you to pass in overrides. This is an Object whose members are applied to the subclass after the extension occurs. This allows you to extend and initialize the subclass in one statement.

I suggest a simpler function (which I use in my projects), as follows:

Example 3: Simple Prototype Clone

Core.extend = function(subc, superc, overrides) { if (! superc || ! subc) { throw new Error(”Core.extend failed, please check that all dependencies are included.”); } var F = function() {}; F.prototype = superc.prototype; subc.prototype = new F(); if (overrides) { for (var i in overrides) { subc.prototype[i] = overrides[i]; } } };

And here is an example of how you might use the extend Function:

Example 4: Using Extend

var Item= {}; var Book = {}; Core.extend(Item, Object, { toString: function() { var sb = []; for (var i in this) { if (typeof this[i] !== ‘function’) { sb.push(’&'); sb.push(i); sb.push(’='); sb.push(this[i]); } return sb.join(”); } }); Core.extend(Book, Item, { getTitle: function() { return this.title; }, setTitle: function(s) { this.title = s; } });

If you really need to know the inheritance chain, then I suggest attaching a stack to each new Object that contains the inheritance chain. That way you won’t break ‘for in’ operations of the Object object.

…………………………
Edited: March 15, 2008

I eventually, found a good use for referencing super class, and here is how I modified this method to support it:

Improving Extend With Super

posted by Matt Snider at 3:18 pm  

Tuesday, November 27, 2007

Standard Tabs

I was off last week, taking a much needed break. Of course, instead of really relaxing, I decided to play with a PHP framework that I have been tuning and instead laid the foundation for a web-based ’stuff’ management system (I have too many books and DVDs to remember what I own anymore). Anyway, this project gave me a good opportunity to build a website from the ground up, adhering to standards and accessiblity. Over the next few months, as I release parts of the project, I will be covering design/engineering topics related to this project.

Today, we will discuss the best-practices way to do a top navbar. So first, let’s state what is meant by best-practices in tab design:

  1. Scalable: both vertically and horizontally
  2. Simple, human-readable code
  3. Accessible
  4. Flexible: easy to change/update

The best HTML structure to meet this criteria is an unordered list, containing anchors that are the actual tab links. The unordered list can be easily (un)styled, is built with very little code, and is easy to change. Additionally, many screen readers will iterate through the list items. Here is some sample HTML code:

Example 1: Navigation HTML

<ul id=”nav”> <li id=”nav-home”><a href=”/”>Home</a></li> <li id=”nav-items”><a href=”/”>Items</a></li> <li id=”nav-add”><a href=”/”>Add</a></li> </ul>

The id attribute “nav” will be used to uniquely apply navigation styles to this list. If we ignore any tab background and border styles, you will need the following CSS:

Example 2: Navigation CSS

#nav { border-bottom: 1px solid #999; float: left; list-style: none; margin: 0; padding: 0; width: 100%; } #nav li { float: left; font-family: “Lucinda Grande”, sans-serif; /** change this to a font-family you like */ list-style: none; margin: 0; padding: 0; } #nav a { color: #666; display: block; float: left; font-size: 1.2em; font-weight: bold; padding: 0.6em 4em 0.6em 2em; /** This is the padding around the tab titles, modify it to fit your needs */ text-decoration: none; } #nav a:hover { color: #000; }

My page has odd padding, because I am using a variation of the slant tabs, as shown at Bulletproof Slants. The right side of the anchor tag has extra padding to accommodate the slanting background image. The tabs themselves will have a solid color when not hovering. In my variation the tabs, have a gradient when they are hovered, to pop them a bit. I am not a graphic designer, so my gradient sucks, but I believe it conveys the right idea.

Example 3: Navigation Background

#nav a { background: #CCC url(../img/nav/nav_slant.gif) no-repeat scroll right top; } #nav a:hover { background: #CCC url(../img/nav/nav_on_bg.gif) repeat-y scroll right top; }

Check out my example on my Tab Test Page;

An alternate strategy is described in Dan Cederholm’s book, Bulletproof Web Design, using two top to bottom gradient images, one fading to the non-selected color and the other fading to the selected color. Then swapping the background image when hovering.

posted by Matt Snider at 7:34 pm  

Sunday, November 11, 2007

Event Package Final

In case you have not been following the discussion so far, here are links to the other articles:

Event.js

Event Package on 11/07/07
Event Package Part 2 on 10/24//07
Event Package Part 1 on 10/18/07
X-Browser Event Handling on 09/28/07

Today, I will be walking through the Event.js, discussing the parts not previously covered. Let’s start by looking at the caching function:

Example 1: Cache Event Function

var cacheEvent = function(el, eType, fn, opt) { // ensure that opt in an object var o = opt || {}; o.capture = (o.capture || false); // wrap the function so we can control the scope and return the optional second object var wrapFn = function(e) { return fn.call(o.scope || window, e, o.data); }; // cache the listener so we can try to automatically unload var evt = [el, eType, fn, wrapFn, o]; ecache[ecache.length] = evt; return evt; };

This Function will be called any time an event is added using the ‘add’ method and accepts the same parameters as the ‘add’ method. The first part of the Function, ensures that the options exist and that the capture value is set. Capture is a required for the actual attachment of the event, but since it is false 99% of the time, we are making it optional. The ‘wrapFn’ internal Function is used to set the scope of, and pass through the data option into, the callback Function. We then create an array of the important values for the cache and push it onto the stack.

We return the cache object so that the ‘add’ Function can use ‘wrapFn’ as its callback and apply the value of capture. This creates an interesting problem when removing events using the old ‘remove’ Function, as we have attached the the ‘wrapFn’ as the callback, but code outside of this package, does not have access to the wrapping Function. That is why we use a private ‘remove’ Function, so that we can locate ‘wrapFn’ from the cache. The public ‘remove’ Function does just that:

Example 2: Public Remove Function

remove: function(el, eType, fn, fl) { var rs = that.getListeners(el, eType); Core.batch(rs, function(r) { if ((r.fn) == (fn)) { update(r); } }); },

The public remove Function first gets all the cached objects for a given element that match the event type, using the ‘getListeners’ method (discussed later). We then iterate on the results and compare the paremeter ‘fn’ with the cached non-wrapped Function. When this is true, we actually remove the event, otherwise. The update Function handles this removal:

Example 3: Removing Events and Cached Elements

var update = function(r) { remove(r.el, r.type, r.wfn, r.opt.capture); var arr = []; if (0 < r.index) { arr = ecache.slice(0, r.index); } arr.concat(ecache.slice(r.index + 1)); ecache = arr; };

First we actually remove the event with the internal ‘remove’ Fucntion (notice that the wrapped Function is used). The rest of the method slices the cached event object that we are removing out of the stack.

In order to quickly and effectively find the events attached on an Element, both internally and externally, we created the public ‘getListeners’ method. I model the data architecture after a similar Function in YUI, as I could not think of a more elegant way to return matching cache objects.

Example 4: getListeners Function

getListeners: function(el, eType) { var results = []; Core.batch(ecache, function(l, i) { if (l && l[EL] === el && (! eType || eType === l[TYPE]) ) { results.push({ el: l[EL], type: l[TYPE], fn: l[FN], wfn: l[WFN], opt: l[OPT], index: i }); } }); return results; },

We simply iterate through the cache and create special result objects each time the element, and event type when provided, match that of a cached event object. Because the results objects can be passed externally, where the position name variables (’EL’, ‘FN’, ‘TYPE’, ‘WFN’, and ‘OPT’) do not exist, we instead create objects where each member is the lowercase of the constant and is set to the comparable value. The index is added, so the event object can later be removed from the cache.

I added two other Functions that I found to be extremely useful. One is the ‘removeEvents’ Function that removes all events from a given element by leveraging the existing caching infrastructure from event removal. And a ‘removeAll’ Function that removes all events ever assigned using the ‘add’ method. This method is attached to the window unload event and helps prevent memory leaks (especially in IE6) where the memory reference to the dom element that triggers the event is not cleared, because the event is still pointing to the dom element.

Lastly, I removed as spaces from the Event name constants:

Example 5: Event Name Constants

BLUR: ‘blur’, CLICK: ‘click’, DOUBLECLICK: ‘dblclick’, KEYDOWN: ‘keydown’, KEYPRESS: ‘keypress’, KEYUP: ‘keyup’, LOAD: ‘load’, MOUSEDOWN: ‘mousedown’, MOUSEMOVE: ‘mousemove’, MOUSEOVER: ‘mouseover’, MOUSEOUT: ‘mouseout’, MOUSEUP: ‘mouseup’, SUBMIT: ’submit’, UNLOAD: ‘unload’,

I did this because there was a conflict between several events, such as the KEYUP event and the KEY_UP that actual keyboard key ‘up arrow’.

Many of the Function names have become shorter as well. I simply found that I knew when using the event package that ‘add’ meant that I was adding a listener, so I did not need the names to be longer.

Please let me know any feedback you have, especially if you have suggestions for improvement.

posted by Matt Snider at 4:46 am  

Wednesday, November 7, 2007

Event Package

I completed the event package that I have been working on (hurray).

Event.js

Basically, use Core.Util.Event.add to attach events and Core.Util.Event.remove to remove events.

I have also written a very rudimentary test page that I used to verify that event add/removal functions were all working properly with the internal cache.

Event Test

There are many improvements and there needs to be an in-depth article describing the package. However, I have to postpone the explanation until Friday’s post, when I am not so busy. Please take a look at Event.js and review it.

posted by Matt Snider at 1:12 pm  

Tuesday, September 18, 2007

Mint Launches

I have been working on Mint for the past year and am please to announce that we are out of BETA. We went live right after our presentation at the TechCrunch40 Conference this morning. If you are curious about your finances and want an effortless tool to help you manage, then Mint is for you:

Mint Homepage Screenshot

posted by Matt Snider at 12:07 pm  

Friday, September 7, 2007

Changing Pace

As many of you know the original goal of this blog was to look at the many different JavaScript Frameworks and Toolkits in order to compare: speed, size, efficiency, etc. If you follow the community, you’ll probably have realized long before me, that doing this would be a full-time job, as new Frameworks appear monthly and the existing ones are constantly: updating, improving, and refactoring their codebases. As such, I cannot keep up with all these changes and offer you the rich, up-to-date comparisons that I wanted. Therefore, I will be slightly modifying the focus of this Blog.

Instead of focusing solely on the Frameworks, I will be spending more time on the JavaScript language, with a splash of Frameworks when I find something awesome and have time to write a comprehensive article. I will also be writing about more general Web Development concepts, such as Semantic Markup and CSS. I am including this additional content because you cannot be a great JavaScript developer (at least on the web) without knowing more about web technologies (most commonly, hiding/showing or inserting content).

In the coming days I will be giving my blog a face lift and reorganizing. I have been lazy and mostly just used a default wordpress theme, but I feel that as a Web Designer and Engineer I should put a little of time into a clean and accessable design. Also, the homepage will be changing to feature work that I have done. For example, I recently completed an light-weight JavaScript Image Viewer Widget, and will be wrapping up a social *cough* networking project soon. I need to showcase the work I have done both for credibility and to earn future projects.

I also find that it is important to post on a regular basis, so from now on I will be be writing at least 2 articles a week (Tuesday and Friday). Between those articles, will be the occasional short blurb and important JavaScript news.

lastly, I’m also excite to announce that I have done all of the JavaScript work for the up-and-coming, free, web-based, financial applications http://www.mint.com. Mint is now in an invite Beta period and if you are interested in checking it out then message me here and I will email you an access code (90 of 100 left).

posted by Matt Snider at 6:37 pm  
« Previous Page

Powered by WordPress