Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Wednesday, February 20, 2008

YUI 2.5 Release

Lots of new and improvements on existing features. It also looks like they fixed the bug that was causing TextNodes to be treated as Arrays in the Dom.get() method.

YUI 2.5

posted by Matt Snider at 7:46 pm  

Friday, February 1, 2008

YUI DateMath on JavaScript Date Object

In the Date Functions article, I mentioned that you could apply the methods on YAHOO.util.DateMath to the Date object direclty, instead of implementing a static class. A few people wrote in and requested that I do just that, so that is what I will write about today.

For reference, please check out the DateMath class at YAHOO:

DateMath

The first step is to remove the constants from the static class and augment the Date object with them.

Example 1: Date Augmentation

YAHOO.lang.augmentObject(Date, { /** * Constant field representing Day * @property DAY * @static * @final * @type String */ DAY : “D”, /** * Constant field representing Week * @property WEEK * @static * @final * @type String */ WEEK : “W”, /** * Constant field representing Year * @property YEAR * @static * @final * @type String */ YEAR : “Y”, /** * Constant field representing Month * @property MONTH * @static * @final * @type String */ MONTH : “M”, /** * Constant field representing one day, in milliseconds * @property ONE_DAY_MS * @static * @final * @type Number */ ONE_DAY_MS : 1000*60*60*24, /** * Retrieves a JavaScript Date object representing January 1 of any given year. * @method getJan1 * @param {Number} calendarYear The calendar year for which to retrieve January 1 * @return {Date} January 1 of the calendar year specified. */ getJan1 : function(calendarYear) { return Date.getDate(calendarYear,0,1); }, /** * Returns a new JavaScript Date object, representing the given year, month and date. Time fields (hr, min, sec, ms) on the new Date object * are set to 0. The method allows Date instances to be created with the a year less than 100. “new Date(year, month, date)” implementations * set the year to 19xx if a year (xx) which is less than 100 is provided. * * NOTE:Validation on argument values is not performed. It is the caller’s responsibility to ensure * arguments are valid as per the ECMAScript-262 Date object specification for the new Date(year, month[, date]) constructor. * * @method getDate * @param {Number} y Year. * @param {Number} m Month index from 0 (Jan) to 11 (Dec). * @param {Number} d (optional) Date from 1 to 31. If not provided, defaults to 1. * @return {Date} The JavaScript date object with year, month, date set as provided. */ getDate : function(y, m, d) { var dt = null; if (YAHOO.lang.isUndefined(d)) { d = 1; } if (y >= 100) { dt = new Date(y, m, d); } else { dt = new Date(); dt.setFullYear(y); dt.setMonth(m); dt.setDate(d); dt.setHours(0,0,0,0); } return dt; } });

Most of what we have moved here are constant values, but I did move two static methods. We moved “getJan1″, because the parameter required is not a Date object, but instead a year integer and therefore, doesn’t really belong on each instance of Date. The “getDate” method is a shortcut method to retrieve a Date object from 3 integers and therefore also does not belong on “Date.prototype”.

The following methods have been transformed to interact with the current Date object instantiation instead of requiring Date as a parameter.

Example 2: Date.prototype Augmentation

YAHOO.lang.augmentObject(Date.prototype, { /** * Adds the specified amount of time to the this instance. * @method add * @param {String} field The field constant to be used for performing addition. * @param {Number} amount The number of units (measured in the field constant) to add to the date. * @return {Date} The resulting Date object */ add : function(field, amount) { var d = new Date(this.getTime()); switch (field) { case Date.MONTH: var newMonth = this.getMonth() + amount; var years = 0; if (newMonth < 0) { while (newMonth < 0) { newMonth += 12; years -= 1; } } else if (newMonth > 11) { while (newMonth > 11) { newMonth -= 12; years += 1; } } d.setMonth(newMonth); d.setFullYear(this.getFullYear() + years); break; case Date.DAY: d.setDate(this.getDate() + amount); break; case Date.YEAR: d.setFullYear(this.getFullYear() + amount); break; case Date.WEEK: d.setDate(this.getDate() + (amount * 7)); break; } return d; }, /** * Subtracts the specified amount of time from the this instance. * @method subtract * @param {Number} field The this field constant to be used for performing subtraction. * @param {Number} amount The number of units (measured in the field constant) to subtract from the date. * @return {Date} The resulting Date object */ subtract : function(field, amount) { return this.add(field, (amount*-1)); }, /** * Determines whether a given date is before another date on the calendar. * @method before * @param {Date} compareTo The Date object to use for the comparison * @return {Boolean} true if the date occurs before the compared date; false if not. */ before : function(compareTo) { return (that.getTime() < compareTo.getTime()); }, /** * Determines whether a given date is after another date on the calendar. * @method after * @param {Date} compareTo The Date object to use for the comparison * @return {Boolean} true if the date occurs after the compared date; false if not. */ after : function(compareTo) { return (that.getTime() > compareTo.getTime()); }, /** * Determines whether a given date is between two other dates on the calendar. * @method between * @param {Date} dateBegin The start of the range * @param {Date} dateEnd The end of the range * @return {Boolean} true if the date occurs between the compared dates; false if not. */ between : function(dateBegin, dateEnd) { return (this.after(dateBegin) && this.before(dateEnd)); }, /** * Calculates the number of days the specified date is from January 1 of the specified calendar year. * Passing January 1 to this function would return an offset value of zero. * @method getDayOffset * @return {Number} The number of days since January 1 of the given year */ getDayOffset : function() { var beginYear = Date.getJan1(this.getFullYear()); // Find the start of the year. This will be in week 1. // Find the number of days the passed in date is away from the calendar year start return Math.ceil((this.getTime() - beginYear.getTime()) / Date.ONE_DAY_MS); }, /** * Calculates the week number for the given date. This function assumes that week 1 is the * week in which January 1 appears, regardless of whether the week consists of a full 7 days. * The calendar year can be specified to help find what a the week number would be for a given * date if the date overlaps years. For instance, a week may be considered week 1 of 2005, or * week 53 of 2004. Specifying the optional calendarYear allows one to make this distinction * easily. * @method getWeekNumber * @return {Number} The week number of the given date. */ getWeekNumber : function() { var date = this.clearTime(); var nearestThurs = new Date(date.getTime() + (4 * Date.ONE_DAY_MS) - ((date.getDay()) * Date.ONE_DAY_MS)); var jan1 = Date.getJan1(nearestThurs.getFullYear()); var dayOfYear = ((nearestThurs.getTime() - jan1.getTime()) / Date.ONE_DAY_MS) - 1; return Math.ceil((dayOfYear)/ 7); }, /** * Determines if a given week overlaps two different years. * @method isYearOverlapWeek * @return {Boolean} true if the date overlaps two different years. */ isYearOverlapWeek : function() { var nextWeek = this.add(Date.DAY, 6); return (nextWeek.getFullYear() != weekBeginDate.getFullYear()); }, /** * Determines if a given week overlaps two different months. * @method isMonthOverlapWeek * @return {Boolean} true if the date overlaps two different months. */ isMonthOverlapWeek : function() { var nextWeek = this.add(Date.DAY, 6); return (nextWeek.getMonth() != weekBeginDate.getMonth()); }, /** * Gets the first day of a month containing a given date. * @method findMonthStart * @return {Date} The JavaScript Date representing the first day of the month */ findMonthStart : function(date) { return Date.getDate(this.getFullYear(), this.getMonth(), 1); }, /** * Gets the last day of a month containing a given date. * @method findMonthEnd * @return {Date} The JavaScript Date representing the last day of the month */ findMonthEnd : function() { var start = this.findMonthStart(); var nextMonth = start.add(Date.MONTH, 1); return nextMonth.subtract(Date.DAY, 1); }, /** * Clears the time fields from a given date, effectively setting the time to 12 noon. * @method clearTime * @return {Date} The JavaScript Date cleared of all time fields */ clearTime : function() { var date = new Date(this.getTime()); date.setHours(12,0,0,0); return date; } });

Generally these functions do not modify the current date, but instead return a new instance of the Date object after a transformation has been made. So if you wanted to update the current Date instantiation, then you would need to assign it to the returned value:

Example 3: Assignment

var d = new Date(); // d is now the current time Date object d = d.findMonthStart(); // d is now the first of the month Date object // versus var date = new Date(); // date is now the current time Date object var newdate = date.findMonthStart(); // newdate is now the first of the month Date object, but date is still the current time

The other functions return boolean values and should be straight forward in meaning. I also took the liberty to simplify the code. YUI tends to be more verbose than necessary, most likely as a result of Douglas Crockfords JavaScript standards (no function chaining and always assigning a value to a variable).

I have not created a test page for this code, but it does compile and my quick function test seemed to work as expected. Please let me know if you notice anything that does not work as expected.

posted by Matt Snider at 6:26 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  

Monday, October 1, 2007

Web Development News 10.01.07

1) Dustin Diaz, writes about improving your “getXHR” Function. Using his code will create a very robust Function that finds the appropriate XHR Object, then overloads the executing Function so that you do not have to find the Object each time you call “getXHR”. Thus, removing the cost of a constant operation from your getXHR Function and improving the performance.

http://www.dustindiaz.com/faster-ajax/

2) Website-Performance.org goes live. This site is dedicated to providing good information, tools, and techniques for improving the performance of your website.

http://website-performance.org/

3) YUI is showcased by a design magazine, Smashing Magazine.

http://feeds.feedburner.com/~r/SmashingMagazine/~3/163652967/

posted by Matt Snider at 10:37 am  

Wednesday, September 26, 2007

CSS Frameworks And Removing X-browser Variations

There is a lot of hype on the web right now around CSS Frameworks; a lot like there used to be around JavaScript Frameworks, before they became so popular. It is important to understand what they are and why they will (or will not) be helpful to you.

What is a CSS Framework

“[A CSS Framework is] a set of tools, libraries, conventions, and best practices that attempt to abstract routine tasks into generic modules that can be reused. The goal here is to allow the designer or developer to focus on tasks that are unique to a given project, rather than reinventing the wheel each time around.” [Framework For Designers, by Jeff Croft]

That is a lofty goal and I believe that most CSS Frameworks endeavor to simplify your life. However, I do not think they usually do. Where CSS Frameworks excel is normalizing styles, especially x-browser variations and typography. Where they fail (or become cumbersome) is when they try to do too much such as: every layout under the sun, rigid design, large code-bases (bloating), etc. If a Framework does too much, then you end up needing to learn what it is doing and why, and without prolific commenting CSS can quickly become confusing and you wonder why a particular property might be necessary.

Despite the downsides, I recommend using a Framework, or at least part of a Framework. The most important effect from using a Framework is reseting browser specific styles, so that 1 stylesheet can be used for all browsers, instead of 1 stylesheet for each browser (or worse, a bunch of browser specific hacks). Most commonly, the browser variations are the default ways they apply padding, margins, and/or fonts to elements.

I personally, never use a complete Framework, because I prefer to have control over my layout and typography, but I always use a CSS Framework to reset browser styles. If you are not a designer and need a quick solution, or find CSS Frameworks helpful, then you should leverage them. Here are the few that I modeled my “reset.css” stylesheet from, which I use as a foundation for all my projects (and hopefully, on this blog as soon as I get some free-time):

  • Tripoli: tries to remain simple by mostly just resetting styles, but also applies some optimal changes to typography and layout
  • YAML: very well documented, multi-column layout builder with all the bells and whistles
  • YUI : lots of layout variety and optimized for integration with the YUI JavaScript Library

Smashing Magazine also wrote a great article about this topic where they cover more details about each CSS Framework listed here, and several others.

Normally, I would probably taut how much I like what YUI has done, but not this time. Although, I do really like their “reset.css”, I find the rest of the Framework to be heavy-handed, with too many options and not enough documentation. Also, the Framework includes styles for some parts of the JS Framework that I do not use. YAML, does a great job, but has a lot of options and extra features that you probably won’t leverage. Tripoli, has the simplest and most unobtrusive styles, and if I was to just to throw a Framework onto a site without modifying it, I would use this one.

In the end I just wanted a set of styles to reset browser specific formatting, and I modeled this by looking at the afore mentioned Frameworks:

/** * Copyright (c) 2007, Matt Snider, LLC. All rights reserved. * version: 1.0.0 */ /* remove default element padding */ body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td { margin: 0; padding: 0; } /* default color scheme */ html body { background: #fff; color: #000; } /* remove borders and possible underlining */ a, img, a img, iframe, form, fieldset, abbr, acronym, object, applet { border: none; font-variant: normal; } /* remove stylized font-variations */ address, caption, cite, code, dfn, em, strong, th, var, i, b { font-style: normal; font-weight: normal; } /* table and center elements should always be top left aligned */ caption, th, td, center { text-align: left; vertical-align: top; } q:before, q:after { content: ”; } /* remove cellpadding and cellspacing */ table { border-collapse: collapse; border-spacing: 0; } /* clear possible list-styles; should override in design */ ul, ol, dir, menu, li { list-style: none; } /* clear possible heading styles; should override in design */ h1, h2, h3, h4, h5, h6 { font-size: 100%; font-weight: normal; } /* prevent default browser coloring of links */ a { color: inherit; } /* reset position of sup and sub */ sup, sub { vertical-align: text-top; } /* clear form field font settings */ input, textarea, select { font-family: inherit; font-size: inherit; font-weight: inherit; }

This is available for download at http://www.mattsnider.com/assets/css/reset.css.

What does this have to do with JavaScript

JavaScript and CSS are closely linked, especially when you consider animation and all the times you have to apply a style on the fly. It is important for JavaScript developers to understand CSS and it is also important that when they apply a style to an element, that element behaves as expected in all browsers. This blog will continue to focus on JavaScript, but every couple weeks, I will write a something important about CSS so we address more complex issues and widgets involving CSS and JavaScript.

posted by Matt Snider at 12:03 am  

Friday, September 21, 2007

More on Really Simple History

So contrary to my last post, it does work in Internet Explorer. I had accidentally overwritten their blank.html file with the one used by YUI. This file is required for the IE IFRAME and contains a callback to “window.parent” (the browser window that you are using dhtmlHistory in). If the following is missing, then IE won’t work:

<script language=”JavaScript”> function pageLoaded() { window.parent.dhtmlHistory.iframeLoaded(window.location); } </script> <body onload=”pageLoaded()”></body>

I never did manage to get it working in Safari 2 or 3, so if anyone knows of a back history method that works in Safari, please leave a comment.

I have two working demos now, one uses the files provided and the other uses my cleaned up YUI version.

Standard Version

My YUI Version

What is the difference?

My version uses my favorite pattern (Module) instead of the Prototype Pattern, which reduces confusion and truly makes functions and variables private. I use compliant DOM method, “document.createElement()”, instead of “document.write”. This also eliminates the need to use “document.getElementById()”. Also, as long as you wait for the DOM to be ready, leveraging “YAHOO.util.Event.onDOMReady()”, you do not need the “window.dhtmlHistory.create()”, as everything can be done in your initialization method. Lastly, because we are leveraging YUI, I demonstrated the unobtrusive way to do this demo. You could also remove the JSON Object and replace it with something simpler that meets your needs and that will save you another 5k.

posted by Matt Snider at 7:08 pm  

Friday, September 14, 2007

CustomEvent Bubbling and Capture Phase

Caridy Mayea, a well-known contributor for YUI, blogs about his technique to simulate the JavaScript Event Object native Bubbling and Capture Phases with CustomEvents. This is a good read whether you intend to use this technique, or you simply would like to understand the event phases better. Check it out:

Bubbling Library

posted by Matt Snider at 6:06 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  

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  
Next Page »

Powered by WordPress