[fusion-commits] r2219 - sandbox/jxlib-3.0/lib

svn_fusion at osgeo.org svn_fusion at osgeo.org
Thu Sep 9 09:51:40 EDT 2010


Author: pagameba
Date: 2010-09-09 13:51:40 +0000 (Thu, 09 Sep 2010)
New Revision: 2219

Modified:
   sandbox/jxlib-3.0/lib/jxlib.uncompressed.js
Log:
updating jxlib 3 build with latest Jx.Grid code.

Modified: sandbox/jxlib-3.0/lib/jxlib.uncompressed.js
===================================================================
--- sandbox/jxlib-3.0/lib/jxlib.uncompressed.js	2010-09-09 13:48:33 UTC (rev 2218)
+++ sandbox/jxlib-3.0/lib/jxlib.uncompressed.js	2010-09-09 13:51:40 UTC (rev 2219)
@@ -4315,12 +4315,12 @@
 license: MIT-style license
 
 authors:
-- Guillermo Rauch
-- Thomas Aylott
-- Scott Kyle
+ - Guillermo Rauch
+ - Thomas Aylott
+ - Scott Kyle
 
 requires:
-- core:1.2.4/MooTools
+ - core:1.2.4/MooTools
 
 provides: [MooTools.More]
 
@@ -4340,11 +4340,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Events
-- /MooTools.More
+ - core:1.2.4/Events
+ - /MooTools.More
 
 provides: [MooTools.Lang]
 
@@ -4441,13 +4441,13 @@
 license: MIT-style license
 
 authors:
-- Guillermo Rauch
-- Thomas Aylott
-- Scott Kyle
+ - Guillermo Rauch
+ - Thomas Aylott
+ - Scott Kyle
 
 requires:
-- core:1.2.4/Class
-- /MooTools.More
+ - core:1.2.4/Class
+ - /MooTools.More
 
 provides: [Log]
 
@@ -4519,13 +4519,13 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element.Events
-- core:1.2.4/Request.JSON
-- /MooTools.More
-- /Log
+ - core:1.2.4/Element.Events
+ - core:1.2.4/Request.JSON
+ - /MooTools.More
+ - /Log
 
 provides: Depender
 
@@ -4848,11 +4848,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Class
-- /MooTools.More
+ - core:1.2.4/Class
+ - /MooTools.More
 
 provides: [Class.refactor]
 
@@ -4884,11 +4884,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Class
-- /MooTools.More
+ - core:1.2.4/Class
+ - /MooTools.More
 
 provides: [Class.Binds]
 
@@ -4918,12 +4918,12 @@
 license: MIT-style license.
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires: 
-- core/1.2.4/Class
-- core:1.2.4/Element
-- /MooTools.More
+ - core/1.2.4/Class
+ - core:1.2.4/Element
+ - /MooTools.More
 
 provides: [Class.Occlude]
 
@@ -4953,13 +4953,13 @@
 license: MIT-style license.
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires: 
-- core:1.2.4/Chain 
-- core:1.2.4/Element
-- core:1.2.4/Fx
-- /MooTools.More
+ - core:1.2.4/Chain
+ - core:1.2.4/Element
+ - core:1.2.4/Fx
+ - /MooTools.More
 
 provides: [Chain.Wait]
 
@@ -5012,10 +5012,10 @@
 license: MIT-style license
 
 authors:
-- Christoph Pojer
+ - Christoph Pojer
 
 requires:
-- core:1.2.4/Array
+ - core:1.2.4/Array
 
 provides: [Array.Extras]
 
@@ -5068,11 +5068,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.English.US]
 
@@ -5134,18 +5134,18 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
-- Nicholas Barthelemy - https://svn.nbarthelemy.com/date-js/
-- Harald Kirshner - mail [at] digitarald.de; http://digitarald.de
-- Scott Kyle - scott [at] appden.com; http://appden.com
+ - Aaron Newton
+ - Nicholas Barthelemy - https://svn.nbarthelemy.com/date-js/
+ - Harald Kirshner - mail [at] digitarald.de; http://digitarald.de
+ - Scott Kyle - scott [at] appden.com; http://appden.com
 
 requires:
-- core:1.2.4/Array
-- core:1.2.4/String
-- core:1.2.4/Number
-- core:1.2.4/Lang
-- core:1.2.4/Date.English.US
-- /MooTools.More
+ - core:1.2.4/Array
+ - core:1.2.4/String
+ - core:1.2.4/Number
+ - core:1.2.4/Lang
+ - core:1.2.4/Date.English.US
+ - /MooTools.More
 
 provides: [Date]
 
@@ -5606,11 +5606,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
-- Scott Kyle
+ - Aaron Newton
+ - Scott Kyle
 
 requires:
-- /Date
+ - /Date
 
 provides: [Date.Extras]
 
@@ -5726,11 +5726,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Hash.base
-- /MooTools.More
+ - core:1.2.4/Hash.base
+ - /MooTools.More
 
 provides: [Hash.Extras]
 
@@ -5775,13 +5775,13 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
-- Guillermo Rauch
+ - Aaron Newton
+ - Guillermo Rauch
 
 requires:
-- core:1.2.4/String
-- core:1.2.4/$util
-- core:1.2.4/Array
+ - core:1.2.4/String
+ - core:1.2.4/$util
+ - core:1.2.4/Array
 
 provides: [String.Extras]
 
@@ -5790,7 +5790,7 @@
 
 (function(){
   
-var special = ['À','à','Ã?','á','Â','â','Ã','ã','Ä','ä','Ã…','Ã¥','Ä‚','ă','Ä„','Ä…','Ć','ć','ÄŒ','Ä?','Ç','ç', 'ÄŽ','Ä?','Ä?','Ä‘', 'È','è','É','é','Ê','ê','Ë','ë','Äš','Ä›','Ę','Ä™', 'Äž','ÄŸ','ÃŒ','ì','Ã?','í','ÃŽ','î','Ã?','ï', 'Ĺ','ĺ','Ľ','ľ','Å?','Å‚', 'Ñ','ñ','Ň','ň','Ń','Å„','Ã’','ò','Ó','ó','Ô','ô','Õ','õ','Ö','ö','Ø','ø','Å‘','Ř','Å™','Å”','Å•','Å ','Å¡','Åž','ÅŸ','Åš','Å›', 'Ť','Å¥','Ť','Å¥','Å¢','Å£','Ù','ù','Ú','ú','Û','û','Ãœ','ü','Å®','ů', 'Ÿ','ÿ','ý','Ã?','Ž','ž','Ź','ź','Å»','ż', 'Þ','þ','Ã?','ð','ß','Å’','Å“','Æ','æ','µ'];
+var special = ['À','à','Á','á','Â','â','Ã','ã','Ä','ä','Å','å','Ă','ă','Ą','ą','Ć','ć','Č','č','Ç','ç', 'Ď','ď','Đ','đ', 'È','è','É','é','Ê','ê','Ë','ë','Ě','ě','Ę','ę', 'Ğ','ğ','Ì','ì','Í','í','Î','î','Ï','ï', 'Ĺ','ĺ','Ľ','ľ','Ł','ł', 'Ñ','ñ','Ň','ň','Ń','ń','Ò','ò','Ó','ó','Ô','ô','Õ','õ','Ö','ö','Ø','ø','ő','Ř','ř','Ŕ','ŕ','Š','š','Ş','ş','Ś','ś', 'Ť','ť','Ť','ť','Ţ','ţ','Ù','ù','Ú','ú','Û','û','Ü','ü','Ů','ů', 'Ÿ','ÿ','ý','Ý','Ž','ž','Ź','ź','Ż','ż', 'Þ','þ','Ð','ð','ß','Œ','œ','Æ','æ','µ'];
 
 var standard = ['A','a','A','a','A','a','A','a','Ae','ae','A','a','A','a','A','a','C','c','C','c','C','c','D','d','D','d', 'E','e','E','e','E','e','E','e','E','e','E','e','G','g','I','i','I','i','I','i','I','i','L','l','L','l','L','l', 'N','n','N','n','N','n', 'O','o','O','o','O','o','O','o','Oe','oe','O','o','o', 'R','r','R','r', 'S','s','S','s','S','s','T','t','T','t','T','t', 'U','u','U','u','U','u','Ue','ue','U','u','Y','y','Y','y','Z','z','Z','z','Z','z','TH','th','DH','dh','ss','OE','oe','AE','ae','u'];
 
@@ -5862,12 +5862,12 @@
 license: MIT-style license
 
 authors:
-- Sebastian Markbåge, Aaron Newton, Lennart Pilon, Valerio Proietti
+ - Sebastian Markbåge, Aaron Newton, Lennart Pilon, Valerio Proietti
 
 requires:
-- core:1.2.4/Array
-- core:1.2.4/String
-- /MooTools.More
+ - core:1.2.4/Array
+ - core:1.2.4/String
+ - /MooTools.More
 
 provides: [String.QueryString]
 
@@ -5915,12 +5915,12 @@
 license: MIT-style license
 
 authors:
-- Sebastian Markbåge
-- Aaron Newton
+ - Sebastian Markbåge
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Selectors
-- /String.QueryString
+ - core:1.2.4/Selectors
+ - /String.QueryString
 
 provides: URI
 
@@ -6071,12 +6071,12 @@
 license: MIT-style license
 
 authors:
-- Sebastian Markbåge
+ - Sebastian Markbåge
 
 
 requires:
-- /Class.refactor
-- /URI
+ - /Class.refactor
+ - /URI
 
 provides: [URI.Relative]
 
@@ -6125,11 +6125,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element
-- /MooTools.More
+ - core:1.2.4/Element
+ - /MooTools.More
 
 provides: [Element.Forms]
 
@@ -6249,11 +6249,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element
-- /MooTools.More
+ - core:1.2.4/Element
+ - /MooTools.More
 
 provides: [Elements.from]
 
@@ -6283,18 +6283,18 @@
 description: Extends the Element native object to include the delegate method for more efficient event management.
 
 credits:
-- "Event checking based on the work of Daniel Steigerwald. License: MIT-style license.	Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
+ - "Event checking based on the work of Daniel Steigerwald. License: MIT-style license.	Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"
 
 license: MIT-style license
 
 authors:
-- Aaron Newton
-- Daniel Steigerwald
+ - Aaron Newton
+ - Daniel Steigerwald
 
 requires:
-- core:1.2.4/Element.Event
-- core:1.2.4/Selectors
-- /MooTools.More
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Selectors
+ - /MooTools.More
 
 provides: [Element.Delegation]
 
@@ -6389,12 +6389,12 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element.Style
-- core:1.2.4/Element.Dimensions
-- /MooTools.More
+ - core:1.2.4/Element.Style
+ - core:1.2.4/Element.Dimensions
+ - /MooTools.More
 
 provides: [Element.Measure]
 
@@ -6534,13 +6534,13 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Dimensions
-- core:1.2.4/Element.Style
-- /MooTools.More
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Element.Dimensions
+ - core:1.2.4/Element.Style
+ - /MooTools.More
 
 provides: [Element.Pin]
 
@@ -6641,11 +6641,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element.Dimensions
-- /Element.Measure
+ - core:1.2.4/Element.Dimensions
+ - /Element.Measure
 
 provides: [Elements.Position]
 
@@ -6828,11 +6828,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element.Style
-- /MooTools.More
+ - core:1.2.4/Element.Style
+ - /MooTools.More
 
 provides: [Element.Shortcuts]
 
@@ -6884,14 +6884,14 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Style
-- core:1.2.4/Options Events
-- /Element.Position
-- /Class.Occlude
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Element.Style
+ - core:1.2.4/Options Events
+ - /Element.Position
+ - /Class.Occlude
 
 provides: [IframeShim]
 
@@ -7010,15 +7010,15 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- core:1.2.4/Element.Event
-- /Class.Binds
-- /Element.Position
-- /IframeShim
+ - core:1.2.4/Options
+ - core:1.2.4/Events
+ - core:1.2.4/Element.Event
+ - /Class.Binds
+ - /Element.Position
+ - /IframeShim
 
 provides: [Mask]
 
@@ -7203,12 +7203,12 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Fx.Tween
-- /Class.refactor
-- /Mask
+ - core:1.2.4/Fx.Tween
+ - /Class.refactor
+ - /Mask
 
 provides: [Spinner]
 
@@ -7400,15 +7400,15 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element.Event
-- core:1.2.4/Request.HTML
-- /Class.Binds
-- /Class.Occlude
-- /Spinner
-- /String.QueryString
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Request.HTML
+ - /Class.Binds
+ - /Class.Occlude
+ - /Spinner
+ - /String.QueryString
 
 provides: [Form.Request]
 
@@ -7583,12 +7583,12 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Fx.Morph
-- /Element.Shortcuts
-- /Element.Measure
+ - core:1.2.4/Fx.Morph
+ - /Element.Shortcuts
+ - /Element.Measure
 
 provides: [Fx.Reveal]
 
@@ -7824,12 +7824,12 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- /Form.Request
-- /Fx.Reveal
-- /Elements.from
+ - /Form.Request
+ - /Fx.Reveal
+ - /Elements.from
 
 provides: [Form.Request.Append]
 
@@ -7897,11 +7897,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.English]
 
@@ -7954,19 +7954,20 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- core:1.2.4/Selectors
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Style
-- core:1.2.4/JSON
-- /Lang- /Class.Binds
-- /Date Element.Forms
-- /Form.Validator.English
-- /Element.Shortcuts
+ - core:1.2.4/Options
+ - core:1.2.4/Events
+ - core:1.2.4/Selectors
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Element.Style
+ - core:1.2.4/JSON
+ - /Lang
+ - /Class.Binds
+ - /Date Element.Forms
+ - /Form.Validator.English
+ - /Element.Shortcuts
 
 provides: [Form.Validator, InputValidator, FormValidator.BaseValidators]
 
@@ -8446,10 +8447,10 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- /Form.Validator
+ - /Form.Validator
 
 provides: [Form.Validator.Inline]
 
@@ -8609,10 +8610,10 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- /Form.Validator
+ - /Form.Validator
 
 provides: [Form.Validator.Extras]
 
@@ -8830,16 +8831,16 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- core:1.2.4/Element.Event
-- /Class.Binds
-- /Class.Occlude
-- /Element.Position
-- /Element.Shortcuts
+ - core:1.2.4/Options
+ - core:1.2.4/Events
+ - core:1.2.4/Element.Event
+ - /Class.Binds
+ - /Class.Occlude
+ - /Element.Position
+ - /Element.Shortcuts
 
 provides: [OverText]
 
@@ -9054,11 +9055,11 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Fx.CSS
-- /MooTools.More
+ - core:1.2.4/Fx.CSS
+ - /MooTools.More
 
 provides: [Fx.Elements]
 
@@ -9115,11 +9116,11 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Element.Event
-- /Fx.Elements
+ - core:1.2.4/Element.Event
+ - /Fx.Elements
 
 provides: [Fx.Accordion]
 
@@ -9289,11 +9290,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Fx.Morph
-- /Element.Position
+ - core:1.2.4/Fx.Morph
+ - /Element.Position
 
 provides: [Fx.Move]
 
@@ -9353,13 +9354,13 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Fx
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Dimensions
-- /MooTools.More
+ - core:1.2.4/Fx
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Element.Dimensions
+ - /MooTools.More
 
 provides: [Fx.Scroll]
 
@@ -9500,11 +9501,11 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Fx Element.Style
-- /MooTools.More
+ - core:1.2.4/Fx Element.Style
+ - /MooTools.More
 
 provides: [Fx.Slide]
 
@@ -9656,11 +9657,11 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Selectors
-- /Fx.Scroll
+ - core:1.2.4/Selectors
+ - /Fx.Scroll
 
 provides: [Fx.SmoothScroll]
 
@@ -9714,12 +9715,12 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element.Dimensions
-- /Fx.Elements
-- /Element.Measure
+ - core:1.2.4/Element.Dimensions
+ - /Fx.Elements
+ - /Element.Measure
 
 provides: [Fx.Sort]
 
@@ -9872,19 +9873,20 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
-- Tom Occhinno
-- Jan Kassens
+ - Valerio Proietti
+ - Tom Occhinno
+ - Jan Kassens
 
 requires:
-- core:1.2.4/Events
-- core:1.2.4/Options
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Style
-- /MooTools.More
+ - core:1.2.4/Events
+ - core:1.2.4/Options
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Element.Style
+ - /MooTools.More
 
 provides: [Drag]
 
+...
 */
 
 var Drag = new Class({
@@ -10044,15 +10046,15 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
-- Tom Occhinno
-- Jan Kassens
-- Aaron Newton
-- Scott Kyle
+ - Valerio Proietti
+ - Tom Occhinno
+ - Jan Kassens
+ - Aaron Newton
+ - Scott Kyle
 
 requires:
-- core:1.2.4/Element.Dimensions
-- /Drag
+ - core:1.2.4/Element.Dimensions
+ - /Drag
 
 provides: [Drag.Move]
 
@@ -10221,14 +10223,14 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Element.Dimensions
-- /Class.Binds
-- /Drag
-- /Element.Dimensions
-- /Element.Measure
+ - core:1.2.4/Element.Dimensions
+ - /Class.Binds
+ - /Drag
+ - /Element.Dimensions
+ - /Element.Measure
 
 provides: [Slider]
 
@@ -10404,10 +10406,10 @@
 license: MIT-style license
 
 authors:
-- Tom Occhino
+ - Tom Occhino
 
 requires:
-- /Drag.Move
+ - /Drag.Move
 
 provides: [Slider]
 
@@ -10600,13 +10602,13 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
-- Guillermo Rauch
+ - Aaron Newton
+ - Guillermo Rauch
 
 requires:
-- core:1.2.4/Element
-- core:1.2.4/Request
-- /Log
+ - core:1.2.4/Element
+ - core:1.2.4/Request
+ - /Log
 
 provides: [Request.JSONP]
 
@@ -10735,12 +10737,12 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Element
-- core:1.2.4/Request
-- /Log
+ - core:1.2.4/Element
+ - core:1.2.4/Request
+ - /Log
 
 provides: [Request.Queue]
 
@@ -10941,11 +10943,11 @@
 license: MIT-style license
 
 authors:
-- Christoph Pojer
+ - Christoph Pojer
 
 requires:
-- core:1.2.4/Request
-- /MooTools.More
+ - core:1.2.4/Request
+ - /MooTools.More
 
 provides: [Request.Periodical]
 
@@ -10989,11 +10991,11 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Element.Event
-- /MooTools.More
+ - core:1.2.4/Element.Event
+ - /MooTools.More
 
 provides: [Assets]
 
@@ -11111,15 +11113,15 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Array
-- core:1.2.4/String
-- core:1.2.4/Number
-- core:1.2.4/Hash
-- core:1.2.4/Function
-- core:1.2.4/$util
+ - core:1.2.4/Array
+ - core:1.2.4/String
+ - core:1.2.4/Number
+ - core:1.2.4/Hash
+ - core:1.2.4/Function
+ - core:1.2.4/$util
 
 provides: [Color]
 
@@ -11270,11 +11272,11 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Events
-- /MooTools.More
+ - core:1.2.4/Events
+ - /MooTools.More
 
 provides: [Group]
 
@@ -11323,13 +11325,13 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
-- Aaron Newton
+ - Valerio Proietti
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Cookie
-- core:1.2.4/JSON
-- /MooTools.More
+ - core:1.2.4/Cookie
+ - core:1.2.4/JSON
+ - /MooTools.More
 
 provides: [Hash.Cookie]
 
@@ -11380,12 +11382,12 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- /Class.Occlude
+ - core:1.2.4/Options
+ - core:1.2.4/Events
+ - /Class.Occlude
 
 provides: [HtmlTable]
 
@@ -11496,12 +11498,12 @@
 license: MIT-style license
 
 authors:
-- Harald Kirschner
-- Aaron Newton
+ - Harald Kirschner
+ - Aaron Newton
 
 requires:
-- /HtmlTable
-- /Class.refactor
+ - /HtmlTable
+ - /Class.refactor
 
 provides: [HtmlTable.Zebra]
 
@@ -11545,15 +11547,15 @@
 license: MIT-style license
 
 authors:
-- Harald Kirschner
-- Aaron Newton
+ - Harald Kirschner
+ - Aaron Newton
 
 requires:
-- core:1.2.4/Hash
-- /HtmlTable
-- /Class.refactor
-- /Element.Delegation
-- /Date
+ - core:1.2.4/Hash
+ - /HtmlTable
+ - /Class.refactor
+ - /Element.Delegation
+ - /Date
 
 provides: [HtmlTable.Sort]
 
@@ -11849,15 +11851,15 @@
 license: MIT-style license
 
 authors:
-- Perrin Westrich
-- Aaron Newton
-- Scott Kyle
+ - Perrin Westrich
+ - Aaron Newton
+ - Scott Kyle
 
 requires:
-- core:1.2.4/Events
-- core:1.2.4/Options
-- core:1.2.4/Element.Event
-- /Log
+ - core:1.2.4/Events
+ - core:1.2.4/Options
+ - core:1.2.4/Element.Event
+ - /Log
 
 provides: [Keyboard]
 
@@ -12090,14 +12092,14 @@
 license: MIT-style license
 
 authors:
-- Harald Kirschner
-- Aaron Newton
+ - Harald Kirschner
+ - Aaron Newton
 
 requires:
-- /Keyboard
-- /HtmlTable
-- /Class.refactor
-- /Element.Delegation
+ - /Keyboard
+ - /HtmlTable
+ - /Class.refactor
+ - /Element.Delegation
 
 provides: [HtmlTable.Select]
 
@@ -12266,11 +12268,11 @@
 license: MIT-style license
 
 authors:
-- Perrin Westrich
+ - Perrin Westrich
 
 requires:
-- core:1.2.4/Function
-- /Keyboard.Extras
+ - core:1.2.4/Function
+ - /Keyboard.Extras
 
 provides: [Keyboard.Extras]
 
@@ -12358,13 +12360,13 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
+ - Valerio Proietti
 
 requires:
-- core:1.2.4/Events
-- core:1.2.4/Options
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Dimensions
+ - core:1.2.4/Events
+ - core:1.2.4/Options
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Element.Dimensions
 
 provides: [Scroller]
 
@@ -12453,16 +12455,16 @@
 license: MIT-style license
 
 authors:
-- Valerio Proietti
-- Christoph Pojer
+ - Valerio Proietti
+ - Christoph Pojer
 
 requires:
-- core:1.2.4/Options
-- core:1.2.4/Events
-- core:1.2.4/Element.Event
-- core:1.2.4/Element.Style
-- core:1.2.4/Element.Dimensions
-- /MooTools.More
+ - core:1.2.4/Options
+ - core:1.2.4/Events
+ - core:1.2.4/Element.Event
+ - core:1.2.4/Element.Style
+ - core:1.2.4/Element.Dimensions
+ - /MooTools.More
 
 provides: [Tips]
 
@@ -12641,11 +12643,11 @@
 license: MIT-style license
 
 authors:
-- Alfons Sanchez
+ - Alfons Sanchez
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Catalan]
 
@@ -12693,11 +12695,11 @@
 license: MIT-style license
 
 authors:
-- Jan Černý chemiX
+ - Jan Černý chemiX
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Czech]
 
@@ -12753,12 +12755,12 @@
 license: MIT-style license
 
 authors:
-- Martin Overgaard
-- Henrik Hansen
+ - Martin Overgaard
+ - Henrik Hansen
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Danish]
 
@@ -12822,11 +12824,11 @@
 license: MIT-style license
 
 authors:
-- Lennart Pilon
+ - Lennart Pilon
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Dutch]
 
@@ -12893,11 +12895,11 @@
 license: MIT-style license
 
 authors:
-- Aaron Newton
+ - Aaron Newton
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.English.GB]
 
@@ -12921,11 +12923,11 @@
 license: MIT-style license
 
 authors:
-- Kevin Valdek
+ - Kevin Valdek
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Estonian]
 
@@ -12985,14 +12987,14 @@
 license: MIT-style license
 
 authors:
-- Christoph Pojer
-- Frank Rossi
-- Ulrich Petri
-- Fabian Beiner
+ - Christoph Pojer
+ - Frank Rossi
+ - Ulrich Petri
+ - Fabian Beiner
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.German]
 
@@ -13050,12 +13052,12 @@
 
 license: MIT-style license
 
-authors: 
-- Michael van der Weg
+authors:
+ - Michael van der Weg
 
 requires:
-- /Lang
-- /Date.German
+ - /Lang
+ - /Date.German
 
 provides: [Date.German.CH]
 
@@ -13072,12 +13074,12 @@
 license: MIT-style license
 
 authors:
-- Nicolas Sorosac
-- Antoine Abt
+ - Nicolas Sorosac
+ - Antoine Abt
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.French]
 
@@ -13139,12 +13141,12 @@
 license: MIT-style license.
 
 authors:
-- Andrea Novero
-- Valerio Proietti
+ - Andrea Novero
+ - Valerio Proietti
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Italian]
 
@@ -13192,11 +13194,11 @@
 license: MIT-style license
 
 authors:
-- Espen 'Rexxars' Hovlandsdal
+ - Espen 'Rexxars' Hovlandsdal
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Norwegian]
 
@@ -13228,11 +13230,11 @@
 license: MIT-style license
 
 authors:
-- Oskar Krawczyk
+ - Oskar Krawczyk
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Polish]
 
@@ -13278,11 +13280,11 @@
 license: MIT-style license
 
 authors:
-- Fabio Miranda Costa
+ - Fabio Miranda Costa
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Portuguese.BR]
 
@@ -13344,8 +13346,8 @@
 
 MooTools.lang.set('ru-RU-unicode', 'Date', {
 
-	months: ['Январь', 'Февраль', 'Март', 'Ð?прель', 'Май', 'Июнь', 'Июль', 'Ð?вгуÑ?Ñ‚', 'СентÑ?брь', 'ОктÑ?брь', 'Ð?оÑ?брь', 'Декабрь'],
-	days: ['ВоÑ?креÑ?енье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'ПÑ?тница', 'Суббота'],
+	months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
+	days: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
 	//culture's date order: MM/DD/YYYY
 	dateOrder: ['date', 'month', 'year'],
 	AM: 'AM',
@@ -13384,17 +13386,17 @@
 	lessThanMinuteAgo: 'меньше минуты назад',
 	minuteAgo: 'минута назад',
 	minutesAgo: function (delta) { return  '{delta} ' + this.pluralize(delta, 'минута', 'минуты', 'минут') + ' назад'},
-	hourAgo: 'чаÑ? назад',
-	hoursAgo: function (delta) { return  '{delta} ' + this.pluralize(delta, 'чаÑ?', 'чаÑ?а', 'чаÑ?ов') + ' назад'},
+	hourAgo: 'час назад',
+	hoursAgo: function (delta) { return  '{delta} ' + this.pluralize(delta, 'час', 'часа', 'часов') + ' назад'},
 	dayAgo: 'вчера',
-	daysAgo: function (delta) { return '{delta} ' + this.pluralize(delta, 'день', 'днÑ?', 'дней') + ' назад' },
+	daysAgo: function (delta) { return '{delta} ' + this.pluralize(delta, 'день', 'дня', 'дней') + ' назад' },
 	lessThanMinuteUntil: 'меньше минуты назад',
 	minuteUntil: 'через минуту',
-	minutesUntil: function (delta) { return  'через {delta} ' + this.pluralize(delta, 'чаÑ?', 'чаÑ?а', 'чаÑ?ов') + ''},
-	hourUntil: 'через чаÑ?',
-	hoursUntil: function (delta) { return  'через {delta} ' + this.pluralize(delta, 'чаÑ?', 'чаÑ?а', 'чаÑ?ов') + ''},
+	minutesUntil: function (delta) { return  'через {delta} ' + this.pluralize(delta, 'час', 'часа', 'часов') + ''},
+	hourUntil: 'через час',
+	hoursUntil: function (delta) { return  'через {delta} ' + this.pluralize(delta, 'час', 'часа', 'часов') + ''},
 	dayUntil: 'завтра',
-	daysUntil: function (delta) { return 'через {delta} ' + this.pluralize(delta, 'день', 'днÑ?', 'дней') + '' }
+	daysUntil: function (delta) { return 'через {delta} ' + this.pluralize(delta, 'день', 'дня', 'дней') + '' }
 
 });/*
 ---
@@ -13406,11 +13408,11 @@
 license: MIT-style license
 
 authors:
-- Ãlfons Sanchez
+ - Ãlfons Sanchez
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Spanish]
 
@@ -13469,11 +13471,11 @@
 license: MIT-style license
 
 authors:
-- Martin Lundgren
+ - Martin Lundgren
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Swedish]
 
@@ -13523,11 +13525,11 @@
 license: MIT-style license
 
 authors:
-- Slik
+ - Slik
 
 requires:
-- /Lang
-- /Date
+ - /Lang
+ - /Date
 
 provides: [Date.Ukrainian]
 
@@ -13547,11 +13549,11 @@
 	};
 
 	MooTools.lang.set('uk-UA', 'Date', {
-			months: ['Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'ВереÑ?ень', 'Жовтень', 'ЛиÑ?топад', 'Грудень'],
-			days: ['Ð?еділÑ?', 'Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П\'Ñ?тницÑ?', 'Субота'],
+			months: ['Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень'],
+			days: ['Неділя', 'Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П\'ятниця', 'Субота'],
 			//culture's date order: DD/MM/YYYY
 			dateOrder: ['date', 'month', 'year'],
-			AM: 'до полуднÑ?',
+			AM: 'до полудня',
 			PM: 'по полудню',
 
 			shortDate: '%d/%m/%Y',
@@ -13570,15 +13572,15 @@
 			},
 			dayAgo: 'вчора',
 			daysAgo: function (delta){
-				return '{delta} ' + pluralize(delta, 'день', 'днÑ?', 'днів') + ' тому';
+				return '{delta} ' + pluralize(delta, 'день', 'дня', 'днів') + ' тому';
 			},
 			weekAgo: 'тиждень тому',
 			weeksAgo: function (delta){
 				return '{delta} ' + pluralize(delta, 'тиждень', 'тижні', 'тижнів') + ' тому';
 			},
-			monthAgo: 'міÑ?Ñ?ць тому',
+			monthAgo: 'місяць тому',
 			monthsAgo: function (delta){
-				return '{delta} ' + pluralize(delta, 'міÑ?Ñ?ць', 'міÑ?Ñ?ці', 'міÑ?Ñ?ців') + ' тому';
+				return '{delta} ' + pluralize(delta, 'місяць', 'місяці', 'місяців') + ' тому';
 			},
 			yearAgo: 'рік тому',
 			yearsAgo: function (delta){
@@ -13595,15 +13597,15 @@
 			},
 			dayUntil: 'завтра',
 			daysUntil: function (delta){
-				return 'через {delta} ' + pluralize(delta, 'день', 'днÑ?', 'днів');
+				return 'через {delta} ' + pluralize(delta, 'день', 'дня', 'днів');
 			},
 			weekUntil: 'через тиждень',
 			weeksUntil: function (delta){
 				return 'через {delta} ' + pluralize(delta, 'тиждень', 'тижні', 'тижнів');
 			},
-			monthUntil: 'через міÑ?Ñ?ць',
+			monthUntil: 'через місяць',
 			monthesUntil: function (delta){
-				return 'через {delta} ' + pluralize(delta, 'міÑ?Ñ?ць', 'міÑ?Ñ?ці', 'міÑ?Ñ?ців');
+				return 'через {delta} ' + pluralize(delta, 'місяць', 'місяці', 'місяців');
 			},
 			yearUntil: 'через рік',
 			yearsUntil: function (delta){
@@ -13621,11 +13623,11 @@
 license: MIT-style license
 
 authors:
-- Chafik Barbar
+ - Chafik Barbar
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Arabic]
 
@@ -13634,19 +13636,19 @@
 
 MooTools.lang.set('ar', 'Form.Validator', {
 	required:'هذا الحقل مطلوب.',
-	minLength:'رجاءً إدخال {minLength}  أحرÙ? على الأقل (تم إدخال {length} أحرÙ?).',
-	maxLength:'الرجاء عدم إدخال أكثر من {maxLength} أحرÙ? (تم إدخال {length} أحرÙ?).',
-	integer:'الرجاء إدخال عدد صحيح Ù?ÙŠ هذا الحقل. أي رقم ذو كسر عشري أو مئوي (مثال 1.25 ) غير مسموح.',
-	numeric:'الرجاء إدخال قيم رقمية Ù?ÙŠ هذا الحقل (مثال "1" أو "1.1" أو "-1" أو "-1.1").',
-	digits:'الرجاء أستخدام قيم رقمية وعلامات ترقيمية Ù?قط Ù?ÙŠ هذا الحقل (مثال, رقم هاتÙ? مع نقطة أو شحطة)',
-	alpha:'الرجاء أستخدام أحرÙ? Ù?قط (ا-ÙŠ) Ù?ÙŠ هذا الحقل. أي Ù?راغات أو علامات غير مسموحة.',
-	alphanum:'الرجاء أستخدام أحرÙ? Ù?قط (ا-ÙŠ) أو أرقام (0-9) Ù?قط Ù?ÙŠ هذا الحقل. أي Ù?راغات أو علامات غير مسموحة.',
+	minLength:'رجاءً إدخال {minLength}  أحرف على الأقل (تم إدخال {length} أحرف).',
+	maxLength:'الرجاء عدم إدخال أكثر من {maxLength} أحرف (تم إدخال {length} أحرف).',
+	integer:'الرجاء إدخال عدد صحيح في هذا الحقل. أي رقم ذو كسر عشري أو مئوي (مثال 1.25 ) غير مسموح.',
+	numeric:'الرجاء إدخال قيم رقمية في هذا الحقل (مثال "1" أو "1.1" أو "-1" أو "-1.1").',
+	digits:'الرجاء أستخدام قيم رقمية وعلامات ترقيمية فقط في هذا الحقل (مثال, رقم هاتف مع نقطة أو شحطة)',
+	alpha:'الرجاء أستخدام أحرف فقط (ا-ي) في هذا الحقل. أي فراغات أو علامات غير مسموحة.',
+	alphanum:'الرجاء أستخدام أحرف فقط (ا-ي) أو أرقام (0-9) فقط في هذا الحقل. أي فراغات أو علامات غير مسموحة.',
 	dateSuchAs:'الرجاء إدخال تاريخ صحيح كالتالي {date}',
 	dateInFormatMDY:'الرجاء إدخال تاريخ صحيح (مثال, 31-12-1999)',
 	email:'الرجاء إدخال بريد إلكتروني صحيح.',
 	url:'الرجاء إدخال عنوان إلكتروني صحيح مثل http://www.google.com',
 	currencyDollar:'الرجاء إدخال قيمة $ صحيحة.  مثال, 100.00$',
-	oneRequired:'الرجاء إدخال قيمة Ù?ÙŠ أحد هذه الحقول على الأقل.',
+	oneRequired:'الرجاء إدخال قيمة في أحد هذه الحقول على الأقل.',
 	errorPrefix: 'خطأ: ',
 	warningPrefix: 'تحذير: '
 }).set('ar', 'Date', {
@@ -13661,12 +13663,12 @@
 license: MIT-style license
 
 authors:
-- Miquel Hudin
-- Alfons Sanchez
+ - Miquel Hudin
+ - Alfons Sanchez
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Catalan]
 
@@ -13717,11 +13719,11 @@
 license: MIT-style license
 
 authors:
-- Jan Černý chemiX
+ - Jan Černý chemiX
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Czech]
 
@@ -13733,16 +13735,16 @@
 	required:'Tato položka je povinná.',
 	minLength:'Zadejte prosím alespoň {minLength} znaků (napsáno {length} znaků).',
 	maxLength:'Zadejte prosím méně než {maxLength} znaků (nápsáno {length} znaků).',
-	integer:'Zadejte prosím celé Ä?íslo. Desetinná Ä?ísla (napÅ™. 1.25) nejsou povolena.',
-	numeric:'Zadejte jen Ä?íselné hodnoty  (tj. "1" nebo "1.1" nebo "-1" nebo "-1.1").',
-	digits:'Zadejte prosím pouze Ä?ísla a interpunkÄ?ní znaménka(například telefonní Ä?íslo s pomlÄ?kami nebo teÄ?kami je povoleno).',
+	integer:'Zadejte prosím celé číslo. Desetinná čísla (např. 1.25) nejsou povolena.',
+	numeric:'Zadejte jen číselné hodnoty  (tj. "1" nebo "1.1" nebo "-1" nebo "-1.1").',
+	digits:'Zadejte prosím pouze čísla a interpunkční znaménka(například telefonní číslo s pomlčkami nebo tečkami je povoleno).',
 	alpha:'Zadejte prosím pouze písmena (a-z). Mezery nebo jiné znaky nejsou povoleny.',
-	alphanum:'Zadejte prosím pouze písmena (a-z) nebo Ä?íslice (0-9). Mezery nebo jiné znaky nejsou povoleny.',
+	alphanum:'Zadejte prosím pouze písmena (a-z) nebo číslice (0-9). Mezery nebo jiné znaky nejsou povoleny.',
 	dateSuchAs:'Zadejte prosím platné datum jako {date}',
 	dateInFormatMDY:'Zadejte prosím platné datum jako MM / DD / RRRR (tj. "12/31/1999")',
 	email:'Zadejte prosím platnou e-mailovou adresu. Například "fred at domain.com".',
 	url:'Zadejte prosím platnou URL adresu jako http://www.google.com.',
-	currencyDollar:'Zadejte prosím platnou Ä?ástku. Například $100.00.',
+	currencyDollar:'Zadejte prosím platnou částku. Například $100.00.',
 	oneRequired:'Zadejte prosím alespoň jednu hodnotu pro tyto položky.',
 	errorPrefix: 'Chyba: ',
 	warningPrefix: 'Upozornění: ',
@@ -13755,13 +13757,13 @@
 	reqChkByName: 'Prosím vyberte {label}.',
 	match: 'Tato položka se musí shodovat s položkou {matchName}',
 	startDate: 'datum zahájení',
-	endDate: 'datum ukonÄ?ení',
+	endDate: 'datum ukončení',
 	currendDate: 'aktuální datum',
 	afterDate: 'Datum by mělo být stejné nebo větší než {label}.',
 	beforeDate: 'Datum by mělo být stejné nebo menší než {label}.',
-	startMonth: 'Vyberte poÄ?áteÄ?ní mÄ›síc.',
+	startMonth: 'Vyberte počáteční měsíc.',
 	sameMonth: 'Tyto dva datumy musí být ve stejném měsíci - změňte jeden z nich.',
-    creditcard: 'Zadané Ä?íslo kreditní karty je neplatné. Prosím opravte ho. Bylo zadáno {length} Ä?ísel.'
+    creditcard: 'Zadané číslo kreditní karty je neplatné. Prosím opravte ho. Bylo zadáno {length} čísel.'
 
 });
 /*
@@ -13774,11 +13776,11 @@
 license: MIT-style license
 
 authors:
-- 陈桂军 - guidy <at> ixuer [dot] net
+ - 陈桂军 - guidy <at> ixuer [dot] net
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Chinese]
 
@@ -13788,14 +13790,14 @@
 /*
 In Chinese:
 ------------
-需�指出的是:
+需要指出的是:
 简体中文适用于中国大陆,
-�体中文适用于香港�澳门和�湾�。
-简体中文和�体中文在字体和语法上有很多的��之处。
+繁体中文适用于香港、澳门和台湾省。
+简体中文和繁体中文在字体和语法上有很多的不同之处。
 
-我�以确�简体中文语言包的准确性,
-但对于�体中文,我�以��用户�以准确的�解,但无法��语�符�他们的阅读习惯。
-如果您�能确认的�,�以�使用简体中文语言包,因为它是最通用的。
+我可以确保简体中文语言包的准确性,
+但对于繁体中文,我可以保证用户可以准确的理解,但无法保证语句符合他们的阅读习惯。
+如果您不能确认的话,可以只使用简体中文语言包,因为它是最通用的。
 
 In English:
 ------------
@@ -13814,17 +13816,17 @@
 MooTools.lang.set('zhs-CN', 'Form.Validator', {
 	required:'这是必填项。',
 	minLength:'请至少输入 {minLength} 个字符 (已输入 {length} 个)。',
-	maxLength:'最多�能输入 {maxLength} 个字符 (已输入 {length} 个)。',
-	integer:'请输入一个整数,�能包��数点。例如:"1", "200"。',
+	maxLength:'最多只能输入 {maxLength} 个字符 (已输入 {length} 个)。',
+	integer:'请输入一个整数,不能包含小数点。例如:"1", "200"。',
 	numeric:'请输入一个数字,例如:"1", "1.1", "-1", "-1.1"。',
-	digits:'这里�能接�数字和标点的输入,标点�以是:"(", ")", ".", ":", "-", "+", "#"和空格。',
-	alpha:'请输入 A-Z 的 26 个字�,�能包�空格或任何其他字符。',
-	alphanum:'请输入 A-Z 的 26 个字�或 0-9 的 10 个数字,�能包�空格或任何其他字符。',
-	dateSuchAs:'请输入�法的日期格�,如:{date}。',
-	dateInFormatMDY:'请输入�法的日期格�,例如:MM/DD/YYYY ("12/31/1999")。',
-	email:'请输入�法的电�信箱地�,例如:"fred at domain.com"。',
-	url:'请输入�法的 Url 地�,例如:http://www.google.com。',
-	currencyDollar:'请输入�法的货�符�,例如:¥',
+	digits:'这里只能接受数字和标点的输入,标点可以是:"(", ")", ".", ":", "-", "+", "#"和空格。',
+	alpha:'请输入 A-Z 的 26 个字母,不能包含空格或任何其他字符。',
+	alphanum:'请输入 A-Z 的 26 个字母或 0-9 的 10 个数字,不能包含空格或任何其他字符。',
+	dateSuchAs:'请输入合法的日期格式,如:{date}。',
+	dateInFormatMDY:'请输入合法的日期格式,例如:MM/DD/YYYY ("12/31/1999")。',
+	email:'请输入合法的电子信箱地址,例如:"fred at domain.com"。',
+	url:'请输入合法的 Url 地址,例如:http://www.google.com。',
+	currencyDollar:'请输入合法的货币符号,例如:¥',
 	oneRequired:'请至少选择一项。',
 	errorPrefix: '错误:',
 	warningPrefix: '警告:'
@@ -13833,19 +13835,19 @@
 // Traditional Chinese
 MooTools.lang.set('zht-CN', 'Form.Validator', {
 	required:'這是必填項。',
-	minLength:'請至少�入 {minLength} 個字符(已�入 {length} 個)。',
-	maxLength:'最多�能�入 {maxLength} 個字符(已�入 {length} 個)。',
-	integer:'請�入一個整數,�能包��數點。例如:"1", "200"。',
-	numeric:'請�入一個數字,例如:"1", "1.1", "-1", "-1.1"。',
-	digits:'這裡�能接�數字和標點的�入,標點�以是:"(", ")", ".", ":", "-", "+", "#"和空格。',
-	alpha:'請�入 A-Z 的 26 個字�,�能包�空格或任何其他字符。',
-	alphanum:'請�入 A-Z 的 26 個字�或 0-9 的 10 個數字,�能包�空格或任何其他字符。',
-	dateSuchAs:'請�入�法的日期格�,如:{date}。',
-	dateInFormatMDY:'請�入�法的日期格�,例如:MM/DD/YYYY ("12/31/1999")。',
-	email:'請�入�法的電�信箱地�,例如:"fred at domain.com"。',
-	url:'請�入�法的 Url 地�,例如:http://www.google.com。',
-	currencyYuan:'請�入�法的貨幣符號,例如:¥',
-	oneRequired:'請至少�擇一項。',
+	minLength:'請至少鍵入 {minLength} 個字符(已鍵入 {length} 個)。',
+	maxLength:'最多只能鍵入 {maxLength} 個字符(已鍵入 {length} 個)。',
+	integer:'請鍵入一個整數,不能包含小數點。例如:"1", "200"。',
+	numeric:'請鍵入一個數字,例如:"1", "1.1", "-1", "-1.1"。',
+	digits:'這裡只能接受數字和標點的鍵入,標點可以是:"(", ")", ".", ":", "-", "+", "#"和空格。',
+	alpha:'請鍵入 A-Z 的 26 個字母,不能包含空格或任何其他字符。',
+	alphanum:'請鍵入 A-Z 的 26 個字母或 0-9 的 10 個數字,不能包含空格或任何其他字符。',
+	dateSuchAs:'請鍵入合法的日期格式,如:{date}。',
+	dateInFormatMDY:'請鍵入合法的日期格式,例如:MM/DD/YYYY ("12/31/1999")。',
+	email:'請鍵入合法的電子信箱地址,例如:"fred at domain.com"。',
+	url:'請鍵入合法的 Url 地址,例如:http://www.google.com。',
+	currencyYuan:'請鍵入合法的貨幣符號,例如:¥',
+	oneRequired:'請至少選擇一項。',
 	errorPrefix: '錯誤:',
 	warningPrefix: '警告:'
 });
@@ -13872,11 +13874,11 @@
 license: MIT-style license
 
 authors:
-- Lennart Pilon
+ - Lennart Pilon
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Dutch]
 
@@ -13910,11 +13912,11 @@
 license: MIT-style license
 
 authors:
-- Kevin Valdek
+ - Kevin Valdek
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Estonian]
 
@@ -13965,13 +13967,13 @@
 license: MIT-style license
 
 authors: 
-- Frank Rossi
-- Ulrich Petri
-- Fabian Beiner
+ - Frank Rossi
+ - Ulrich Petri
+ - Fabian Beiner
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.German]
 
@@ -14023,11 +14025,11 @@
 license: MIT-style license
  
 authors:
-- Michael van der Weg
+ - Michael van der Weg
 
 requires:
-- /Lang
-- /Form.Validator.German
+ - /Lang
+ - /Form.Validator.German
 
 provides: [Form.Validator.German.CH]
 
@@ -14078,12 +14080,12 @@
 license: MIT-style license
 
 authors: 
-- Miquel Hudin
-- Nicolas Sorosac <nicolas <dot> sorosac <at> gmail <dot> com>
+ - Miquel Hudin
+ - Nicolas Sorosac <nicolas <dot> sorosac <at> gmail <dot> com>
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.French]
 
@@ -14133,12 +14135,12 @@
 license: MIT-style license
 
 authors:
-- Leonardo Laureti
-- Andrea Novero
+ - Leonardo Laureti
+ - Andrea Novero
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Italian]
 
@@ -14189,11 +14191,11 @@
 license: MIT-style license
 
 authors:
-- Espen 'Rexxars' Hovlandsdal
+ - Espen 'Rexxars' Hovlandsdal
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Norwegian]
 
@@ -14227,11 +14229,11 @@
 license: MIT-style license
 
 authors:
-- Oskar Krawczyk
+ - Oskar Krawczyk
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Polish]
 
@@ -14282,11 +14284,11 @@
 license: MIT-style license
 
 authors:
-- Miquel Hudin
+ - Miquel Hudin
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Portuguese]
 
@@ -14323,11 +14325,11 @@
 license: MIT-style license
 
 authors:
-- Fábio Miranda Costa
+ - Fábio Miranda Costa
 
 requires:
-- /Lang
-- /Form.Validator.Portuguese
+ - /Lang
+ - /Form.Validator.Portuguese
 
 provides: [Form.Validator.Portuguese.BR]
 
@@ -14379,11 +14381,11 @@
 license: MIT-style license
 
 authors:
-- Chernodarov Egor
+ - Chernodarov Egor
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Russian]
 
@@ -14391,40 +14393,40 @@
 */
 
 MooTools.lang.set('ru-RU-unicode', 'Form.Validator', {
-	required:'Это поле обÑ?зательно к заполнению.',
-	minLength:'ПожалуйÑ?та, введите хотÑ? бы {minLength} Ñ?имволов (Ð’Ñ‹ ввели {length}).',
-	maxLength:'ПожалуйÑ?та, введите не больше {maxLength} Ñ?имволов (Ð’Ñ‹ ввели {length}).',
-	integer:'ПожалуйÑ?та, введите в Ñ?то поле чиÑ?ло. Дробные чиÑ?ла (например 1.25) тут не разрешены.',
-	numeric:'ПожалуйÑ?та, введите в Ñ?то поле чиÑ?ло (например "1" или "1.1", или "-1", или "-1.1").',
-	digits:'Ð’ Ñ?том поле Ð’Ñ‹ можете иÑ?пользовать только цифры и знаки пунктуации (например, телефонный номер Ñ?о знаками дефиÑ?а или Ñ? точками).',
-	alpha:'Ð’ Ñ?том поле можно иÑ?пользовать только латинÑ?кие буквы (a-z). Пробелы и другие Ñ?имволы запрещены.',
-	alphanum:'Ð’ Ñ?том поле можно иÑ?пользовать только латинÑ?кие буквы (a-z) и цифры (0-9). Пробелы и другие Ñ?имволы запрещены.',
-	dateSuchAs:'ПожалуйÑ?та, введите корректную дату {date}',
-	dateInFormatMDY:'ПожалуйÑ?та, введите дату в формате ММ/ДД/ГГГГ (например "12/31/1999")',
-	email:'ПожалуйÑ?та, введите корректный емейл-адреÑ?. ДлÑ? примера "fred at domain.com".',
-	url:'ПожалуйÑ?та, введите правильную Ñ?Ñ?ылку вида http://www.google.com.',
-	currencyDollar:'ПожалуйÑ?та, введите Ñ?умму в долларах. Ð?апример: $100.00 .',
-	oneRequired:'ПожалуйÑ?та, выберите хоть что-нибудь в одном из Ñ?тих полей.',
+	required:'Это поле обязательно к заполнению.',
+	minLength:'Пожалуйста, введите хотя бы {minLength} символов (Вы ввели {length}).',
+	maxLength:'Пожалуйста, введите не больше {maxLength} символов (Вы ввели {length}).',
+	integer:'Пожалуйста, введите в это поле число. Дробные числа (например 1.25) тут не разрешены.',
+	numeric:'Пожалуйста, введите в это поле число (например "1" или "1.1", или "-1", или "-1.1").',
+	digits:'В этом поле Вы можете использовать только цифры и знаки пунктуации (например, телефонный номер со знаками дефиса или с точками).',
+	alpha:'В этом поле можно использовать только латинские буквы (a-z). Пробелы и другие символы запрещены.',
+	alphanum:'В этом поле можно использовать только латинские буквы (a-z) и цифры (0-9). Пробелы и другие символы запрещены.',
+	dateSuchAs:'Пожалуйста, введите корректную дату {date}',
+	dateInFormatMDY:'Пожалуйста, введите дату в формате ММ/ДД/ГГГГ (например "12/31/1999")',
+	email:'Пожалуйста, введите корректный емейл-адрес. Для примера "fred at domain.com".',
+	url:'Пожалуйста, введите правильную ссылку вида http://www.google.com.',
+	currencyDollar:'Пожалуйста, введите сумму в долларах. Например: $100.00 .',
+	oneRequired:'Пожалуйста, выберите хоть что-нибудь в одном из этих полей.',
 	errorPrefix: 'Ошибка: ',
 	warningPrefix: 'Внимание: '
 });
 
 //translation in windows-1251 codepage
 MooTools.lang.set('ru-RU', 'Form.Validator', {
-	required:'�òî ïîëå îáÿçàòåëüíî ê çàïîëíåíèþ.',
-	minLength:'�îæàëóéñòà, ââåäèòå õîòÿ áû {minLength} ñèìâîëîâ (Âû ââåëè {length}).',
-	maxLength:'�îæàëóéñòà, ââåäèòå íå áîëüøå {maxLength} ñèìâîëîâ (Âû ââåëè {length}).',
-	integer:'�îæàëóéñòà, ââåäèòå â ýòî ïîëå ÷èñëî. Äðîáíûå ÷èñëà (íàïðèìåð 1.25) òóò íå ðàçðåøåíû.',
-	numeric:'�îæàëóéñòà, ââåäèòå â ýòî ïîëå ÷èñëî (íàïðèìåð "1" èëè "1.1", èëè "-1", èëè "-1.1").',
+	required:'Ýòî ïîëå îáÿçàòåëüíî ê çàïîëíåíèþ.',
+	minLength:'Ïîæàëóéñòà, ââåäèòå õîòÿ áû {minLength} ñèìâîëîâ (Âû ââåëè {length}).',
+	maxLength:'Ïîæàëóéñòà, ââåäèòå íå áîëüøå {maxLength} ñèìâîëîâ (Âû ââåëè {length}).',
+	integer:'Ïîæàëóéñòà, ââåäèòå â ýòî ïîëå ÷èñëî. Äðîáíûå ÷èñëà (íàïðèìåð 1.25) òóò íå ðàçðåøåíû.',
+	numeric:'Ïîæàëóéñòà, ââåäèòå â ýòî ïîëå ÷èñëî (íàïðèìåð "1" èëè "1.1", èëè "-1", èëè "-1.1").',
 	digits:' ýòîì ïîëå Âû ìîæåòå èñïîëüçîâàòü òîëüêî öèôðû è çíàêè ïóíêòóàöèè (íàïðèìåð, òåëåôîííûé íîìåð ñî çíàêàìè äåôèñà èëè ñ òî÷êàìè).',
-	alpha:' ýòîì ïîëå ìîæíî èñïîëüçîâàòü òîëüêî ëàòèíñêèå áóêâû (a-z). �ðîáåëû è äðóãèå ñèìâîëû çàïðåùåíû.',
-	alphanum:' ýòîì ïîëå ìîæíî èñïîëüçîâàòü òîëüêî ëàòèíñêèå áóêâû (a-z) è öèôðû (0-9). �ðîáåëû è äðóãèå ñèìâîëû çàïðåùåíû.',
-	dateSuchAs:'�îæàëóéñòà, ââåäèòå êîððåêòíóþ äàòó {date}',
-	dateInFormatMDY:'�îæàëóéñòà, ââåäèòå äàòó â ôîðìàòå ÌÌ/ÄÄ/ÃÃÃà (íàïðèìåð "12/31/1999")',
-	email:'�îæàëóéñòà, ââåäèòå êîððåêòíûé åìåéë-àäðåñ. Äëÿ ïðèìåðà "fred at domain.com".',
-	url:'�îæàëóéñòà, ââåäèòå ïðàâèëüíóþ ññûëêó âèäà http://www.google.com.',
-	currencyDollar:'�îæàëóéñòà, ââåäèòå ñóììó â äîëëàðàõ. �àïðèìåð: $100.00 .',
-	oneRequired:'�îæàëóéñòà, âûáåðèòå õîòü ÷òî-íèáóäü â îäíîì èç ýòèõ ïîëåé.',
+	alpha:'Â ýòîì ïîëå ìîæíî èñïîëüçîâàòü òîëüêî ëàòèíñêèå áóêâû (a-z). Ïðîáåëû è äðóãèå ñèìâîëû çàïðåùåíû.',
+	alphanum:'Â ýòîì ïîëå ìîæíî èñïîëüçîâàòü òîëüêî ëàòèíñêèå áóêâû (a-z) è öèôðû (0-9). Ïðîáåëû è äðóãèå ñèìâîëû çàïðåùåíû.',
+	dateSuchAs:'Ïîæàëóéñòà, ââåäèòå êîððåêòíóþ äàòó {date}',
+	dateInFormatMDY:'Ïîæàëóéñòà, ââåäèòå äàòó â ôîðìàòå ÌÌ/ÄÄ/ÃÃÃÃ (íàïðèìåð "12/31/1999")',
+	email:'Ïîæàëóéñòà, ââåäèòå êîððåêòíûé åìåéë-àäðåñ. Äëÿ ïðèìåðà "fred at domain.com".',
+	url:'Ïîæàëóéñòà, ââåäèòå ïðàâèëüíóþ ññûëêó âèäà http://www.google.com.',
+	currencyDollar:'Ïîæàëóéñòà, ââåäèòå ñóììó â äîëëàðàõ. Íàïðèìåð: $100.00 .',
+	oneRequired:'Ïîæàëóéñòà, âûáåðèòå õîòü ÷òî-íèáóäü â îäíîì èç ýòèõ ïîëåé.',
 	errorPrefix: 'Îøèáêà: ',
 	warningPrefix: 'Âíèìàíèå: '
 });/*
@@ -14437,11 +14439,11 @@
 license: MIT-style license
 
 authors:
-- Ãlfons Sanchez
+ - Ãlfons Sanchez
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Spanish]
 
@@ -14493,11 +14495,11 @@
 license: MIT-style license
 
 authors:
-- Martin Lundgren
+ - Martin Lundgren
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Swedish]
 
@@ -14548,11 +14550,11 @@
 license: MIT-style license
 
 authors:
-- Slik
+ - Slik
 
 requires:
-- /Lang
-- /Form.Validator
+ - /Lang
+ - /Form.Validator
 
 provides: [Form.Validator.Ukrainian]
 
@@ -14561,39 +14563,75 @@
 
 MooTools.lang.set('uk-UA', 'Form.Validator', {
 	required:'Це поле повинне бути заповненим.',
-	minLength:'Введіть хоча б {minLength} Ñ?имволів (Ви ввели {length}).',
-	maxLength:'КількіÑ?Ñ‚ÑŒ Ñ?имволів не може бути більше {maxLength} (Ви ввели {length}).',
-	integer:'Введіть в це поле чиÑ?ло. Дробові чиÑ?ла (наприклад 1.25) не дозволені.',
-	numeric:'Введіть в це поле чиÑ?ло (наприклад "1" або "1.1", або "-1", або "-1.1").',
-	digits:'Ð’ цьому полі ви можете викориÑ?товувати лише цифри Ñ– знаки пунктіації (наприклад, телефонний номер з знаками дефізу або з крапками).',
-	alpha:'Ð’ цьому полі можна викориÑ?товувати лише латинÑ?ькі літери (a-z). Пробіли Ñ– інші Ñ?имволи заборонені.',
-	alphanum:'Ð’ цьому полі можна викориÑ?товувати лише латинÑ?ькі літери (a-z) Ñ– цифри (0-9). Пробіли Ñ– інші Ñ?имволи заборонені.',
+	minLength:'Введіть хоча б {minLength} символів (Ви ввели {length}).',
+	maxLength:'Кількість символів не може бути більше {maxLength} (Ви ввели {length}).',
+	integer:'Введіть в це поле число. Дробові числа (наприклад 1.25) не дозволені.',
+	numeric:'Введіть в це поле число (наприклад "1" або "1.1", або "-1", або "-1.1").',
+	digits:'В цьому полі ви можете використовувати лише цифри і знаки пунктіації (наприклад, телефонний номер з знаками дефізу або з крапками).',
+	alpha:'В цьому полі можна використовувати лише латинські літери (a-z). Пробіли і інші символи заборонені.',
+	alphanum:'В цьому полі можна використовувати лише латинські літери (a-z) і цифри (0-9). Пробіли і інші символи заборонені.',
 	dateSuchAs:'Введіть коректну дату {date}.',
 	dateInFormatMDY:'Введіть дату в форматі ММ/ДД/РРРР (наприклад "12/31/2009").',
-	email:'Введіть коректну адреÑ?у електронної пошти (наприклад "name at domain.com").',
-	url:'Введіть коректне інтернет-поÑ?иланнÑ? (наприклад http://www.google.com).',
-	currencyDollar:'Введіть Ñ?уму в доларах (наприклад "$100.00").',
+	email:'Введіть коректну адресу електронної пошти (наприклад "name at domain.com").',
+	url:'Введіть коректне інтернет-посилання (наприклад http://www.google.com).',
+	currencyDollar:'Введіть суму в доларах (наприклад "$100.00").',
 	oneRequired:'Заповніть одне з полів.',
 	errorPrefix: 'Помилка: ',
 	warningPrefix: 'Увага: '
 });
-// $Id: common.js 845 2010-04-15 18:47:08Z pagameba $
+/*
+---
+
+name: Common
+
+description: Jx namespace with methods and classes common to most Jx widgets
+
+license: MIT-style license.
+
+requires:
+ - Core/Class
+ - Core/Element
+ - Core/Browser
+ - Core/Element.Style
+ - Core/Request
+ - Core/Class.Extras
+ - More/Class.Binds
+ - Core/Array
+ - Core/Element.Event
+ - Core/Element.Dimensions
+ - More/Element.Measure
+ - More/Mootools.Lang
+ - Core/Slick.Finder
+ - Core/Slick.Parser
+
+provides: [Jx]
+
+css:
+ - license
+ - reset
+ - common
+
+images:
+ - a_pixel.png
+
+...
+ */
+// $Id: common.js 976 2010-09-02 18:57:12Z pagameba $
 /**
  * Function: $jx
  * dereferences a DOM Element to a JxLib object if possible and returns
  * a reference to the object, or null if not defined.
  */
 function $jx(id) {
+  var widget = null;
   id = document.id(id);
   if (id) {
-    var widget = id.retrieve('jxWidget');
+    widget = id.retrieve('jxWidget');
     if (!widget && id != document.body) {
-      return $jx(id.getParent());
-    } else {
-      return widget;
+      widget = $jx(id.getParent());
     }
   }
-  return null;
+  return widget;
 }
 
 /**
@@ -14604,9 +14642,9 @@
  * global variables, if you discover that it does then please report
  * it as a bug
  *
- * License: 
+ * License:
  * Copyright (c) 2008, DM Solutions Group Inc.
- * 
+ *
  * This file is licensed under an MIT style license
  */
 
@@ -14615,15 +14653,17 @@
 function() {
     if (! ("console" in window)) {
         var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
-        "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
+        "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"],
+            i;
 
         window.console = {};
-        for (var i = 0; i < names.length; ++i) {
+        for (i = 0; i < names.length; ++i) {
             window.console[names[i]] = function() {};
         }
     }
 });
 
+
 // add mutator that sets jxFamily when creating a class so we can check
 // its type
 Class.Mutators.Family = function(self, name) {
@@ -14644,18 +14684,18 @@
     if (object && object.jxFamily) {
         return object;
     }
-    var unlinked;
+    var unlinked, p, i, l;
     switch ($type(object)) {
     case 'object':
         unlinked = {};
-        for (var p in object) unlinked[p] = $unlink(object[p]);
+        for (p in object) unlinked[p] = $unlink(object[p]);
         break;
     case 'hash':
         unlinked = new Hash(object);
         break;
     case 'array':
         unlinked = [];
-        for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);
+        for (i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);
         break;
     default:
         return object;
@@ -14663,6 +14703,33 @@
     return unlinked;
 }
 
+/**
+ * Override of mootools-core 1.3's typeOf operator to prevent infinite recursion
+ * when doing typeOf on JxLib objects.
+ *
+var typeOf = this.typeOf = function(item){
+    if (item == null) return 'null';
+    if (item.jxFamily) return item.jxFamily;
+    if (item.$family) return item.$family();
+
+    if (item.nodeName){
+        if (item.nodeType == 1) return 'element';
+        if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
+    } else if (typeof item.length == 'number'){
+        if (item.callee) return 'arguments';
+        if ('item' in item) return 'collection';
+    }
+
+    return typeof item;
+};
+
+this.$type = function(object){
+    var type = typeOf(object);
+    if (type == 'elements') return 'array';
+    return (type == 'null') ? false : type;
+};
+*/
+
 /* Setup global namespace.  It is possible to set the global namespace
  * prior to including jxlib.  This would typically be required only if
  * the auto-detection of the jxlib base URL would fail.  For instance,
@@ -14679,7 +14746,7 @@
 
 /**
  * APIProperty: {String} baseURL
- * This is the URL that Jx was loaded from, it is 
+ * This is the URL that Jx was loaded from, it is
  * automatically calculated from the script tag
  * src property that included Jx.
  *
@@ -14699,11 +14766,12 @@
  */
 if (!$defined(Jx.baseURL)) {
   (function() {
-    var aScripts = document.getElementsByTagName('SCRIPT');
-    for (var i = 0; i < aScripts.length; i++) {
-      var s = aScripts[i].src;
-      var n = s.lastIndexOf('/');
-      var file = s.slice(n+1,s.length-1);
+    var aScripts = document.getElementsByTagName('SCRIPT'),
+        i, s, n, file;
+    for (i = 0; i < aScripts.length; i++) {
+      s = aScripts[i].src;
+      n = s.lastIndexOf('/');
+      file = s.slice(n+1,s.length-1);
       if (file.contains('jxlib')) {
         Jx.baseURL = s.slice(0,n);
         break;
@@ -14711,7 +14779,7 @@
     }
   })();
 }
-/** 
+/**
  * APIProperty: {Image} aPixel
  * aPixel is a single transparent pixel and is the only image we actually
  * use directly in JxLib code.  If you want to use your own transparent pixel
@@ -14737,7 +14805,7 @@
   });
 }
 
-/** 
+/**
  * APIProperty: {Boolean} isAir
  * indicates if JxLib is running in an Adobe Air environment.  This is
  * normally auto-detected but you can manually set it by declaring the Jx
@@ -14749,18 +14817,18 @@
  * (end)
  */
 if (!$defined(Jx.isAir)) {
-	(function() {
-		/**
-		 * Determine if we're running in Adobe AIR.
-		 */
-		var aScripts = document.getElementsByTagName('SCRIPT');
-		var src = aScripts[0].src;
-		if (src.contains('app:')) {
-			Jx.isAir = true;
-		} else {
-			Jx.isAir = false;
-		}
-	})();
+  (function() {
+    /**
+     * Determine if we're running in Adobe AIR.
+     */
+    var aScripts = document.getElementsByTagName('SCRIPT'),
+        src = aScripts[0].src;
+    if (src.contains('app:')) {
+      Jx.isAir = true;
+    } else {
+      Jx.isAir = false;
+    }
+  })();
 }
 
 /**
@@ -14773,16 +14841,16 @@
  * {String} language identifier, the language to set.
  */
 Jx.setLanguage = function(lang) {
-	Jx.lang = lang;
-	MooTools.lang.setLanguage(Jx.lang);
+  Jx.lang = lang;
+  MooTools.lang.setLanguage(Jx.lang);
 };
 
 /**
  * APIProperty: {String} lang
  * Checks to see if Jx.lang is already set. If not, it sets it to the default
- * 'en-US'. We will then set the Motools.lang language to this setting 
+ * 'en-US'. We will then set the Motools.lang language to this setting
  * automatically.
- * 
+ *
  * The language can be changed on the fly at anytime by calling
  * Jx.setLanguage().
  * By default all Jx.Widget subclasses will listen for the langChange event of
@@ -14791,7 +14859,7 @@
  * these changes by setting the Jx.Widget option useLang to false.
  */
 if (!$defined(Jx.lang)) {
-	Jx.lang = 'en-US';
+  Jx.lang = 'en-US';
 }
 
 Jx.setLanguage(Jx.lang);
@@ -14814,9 +14882,10 @@
  * object {Object} the object (img) to which the filter needs to be applied.
  */
 Jx.applyPNGFilter = function(o) {
-    var t = Jx.aPixel.src;
+    var t = Jx.aPixel.src, 
+        s;
     if (o.src != t) {
-        var s = o.src;
+        s = o.src;
         o.src = t;
         o.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + s + "',sizingMethod='scale')";
     }
@@ -14834,7 +14903,7 @@
 //counter for number of concurrent image loads
 /**
  * APIMethod: addToImgQueue
- * Request that an image be set to a DOM IMG element src attribute.  This puts 
+ * Request that an image be set to a DOM IMG element src attribute.  This puts
  * the image into a queue and there are private methods to manage that queue
  * and limit image loading to 2 at a time.
  *
@@ -14889,10 +14958,10 @@
 
 /**
  * APIMethod: getNumber
- * safely parse a number and return its integer value.  A NaN value 
+ * safely parse a number and return its integer value.  A NaN value
  * returns 0.  CSS size values are also parsed correctly.
  *
- * Parameters: 
+ * Parameters:
  * n - {Mixed} the string or object to parse.
  *
  * Returns:
@@ -14908,7 +14977,7 @@
  * return the dimensions of the browser client area.
  *
  * Returns:
- * {Object} an object containing a width and height property 
+ * {Object} an object containing a width and height property
  * that represent the width and height of the browser client area.
  */
 Jx.getPageDimensions = function() {
@@ -14923,14 +14992,11 @@
  * safely return the type of an object using the mootools type system
  *
  * Returns:
- * {Object} an object containing a width and height property 
+ * {Object} an object containing a width and height property
  * that represent the width and height of the browser client area.
  */
 Jx.type = function(obj) {
-    if (typeof obj == 'undefined') {
-        return false;
-    }
-    return obj.jxFamily || $type(obj);
+  return typeof obj == 'undefined' ? false : obj.jxFamily || $type(obj);
 };
 
 (function($) {
@@ -14949,26 +15015,28 @@
      * these things.
      * Ultimately, it would be nice to eliminate most or all of these and find
      * the MooTools equivalent or convince MooTools to add them.
-     * 
-     * NOTE: Many of these methods can be replaced with mootools-more's 
+     *
+     * NOTE: Many of these methods can be replaced with mootools-more's
      * Element.Measure
      */
     Element.implement({
         /**
          * APIMethod: getBoxSizing
-         * return the box sizing of an element, one of 'content-box' or 
+         * return the box sizing of an element, one of 'content-box' or
          *'border-box'.
          *
-         * Parameters: 
+         * Parameters:
          * elem - {Object} the element to get the box sizing of.
          *
          * Returns:
          * {String} the box sizing of the element.
          */
         getBoxSizing: function() {
-            var result = 'content-box';
+            var result = 'content-box',
+                cm,
+                sizing;
             if (Browser.Engine.trident || Browser.Engine.presto) {
-                var cm = document["compatMode"];
+                cm = document["compatMode"];
                 if (cm == "BackCompat" || cm == "QuirksMode") {
                     result = 'border-box';
                 } else {
@@ -14978,7 +15046,7 @@
                 if (arguments.length === 0) {
                     node = document.documentElement;
                 }
-                var sizing = this.getStyle("-moz-box-sizing");
+                sizing = this.getStyle("-moz-box-sizing");
                 if (!sizing) {
                     sizing = this.getStyle("box-sizing");
                 }
@@ -14991,7 +15059,7 @@
          * return the size of the content area of an element.  This is the
          * size of the element less margins, padding, and borders.
          *
-         * Parameters: 
+         * Parameters:
          * elem - {Object} the element to get the content size of.
          *
          * Returns:
@@ -14999,14 +15067,10 @@
          * are the size of the content area of the measured element.
          */
         getContentBoxSize: function() {
-            var w = this.offsetWidth;
-            var h = this.offsetHeight;
             var s = this.getSizes(['padding', 'border']);
-            w = w - s.padding.left - s.padding.right - s.border.left - s.border.right;
-            h = h - s.padding.bottom - s.padding.top - s.border.bottom - s.border.top;
             return {
-                width: w,
-                height: h
+                width: this.offsetWidth - s.padding.left - s.padding.right - s.border.left - s.border.right,
+                height: this.offsetHeight - s.padding.bottom - s.padding.top - s.border.bottom - s.border.top
             };
         },
         /**
@@ -15014,7 +15078,7 @@
          * return the size of the border area of an element.  This is the size
          * of the element less margins.
          *
-         * Parameters: 
+         * Parameters:
          * elem - {Object} the element to get the border sizing of.
          *
          * Returns:
@@ -15022,11 +15086,9 @@
          * are the size of the border area of the measured element.
          */
         getBorderBoxSize: function() {
-            var w = this.offsetWidth;
-            var h = this.offsetHeight;
             return {
-                width: w,
-                height: h
+                width: this.offsetWidth,
+                height: this.offsetHeight
             };
         },
 
@@ -15035,7 +15097,7 @@
          * return the size of the margin area of an element.  This is the size
          * of the element plus margins.
          *
-         * Parameters: 
+         * Parameters:
          * elem - {Object} the element to get the margin sizing of.
          *
          * Returns:
@@ -15044,11 +15106,9 @@
          */
         getMarginBoxSize: function() {
             var s = this.getSizes(['margin']);
-            var w = this.offsetWidth + s.margin.left + s.margin.right;
-            var h = this.offsetHeight + s.margin.top + s.margin.bottom;
             return {
-                width: w,
-                height: h
+                width: this.offsetWidth + s.margin.left + s.margin.right,
+                height: this.offsetHeight + s.margin.top + s.margin.bottom
             };
         },
         /**
@@ -15072,12 +15132,14 @@
         getSizes: function(which, edges) {
             which = which || ['padding', 'border', 'margin'];
             edges = edges || ['left', 'top', 'right', 'bottom'];
-            var result = {};
+            var result = {},
+                e,
+                n;
             which.each(function(style) {
                 result[style] = {};
                 edges.each(function(edge) {
-                    var e = (style == 'border') ? edge + '-width': edge;
-                    var n = this.getStyle(style + '-' + e);
+                    e = (style == 'border') ? edge + '-width': edge;
+                    n = this.getStyle(style + '-' + e);
                     result[style][edge] = n === null || isNaN(parseInt(n, 10)) ? 0: parseInt(n, 10);
                 },
                 this);
@@ -15093,36 +15155,39 @@
          * size of the element may be larger depending on padding and
          * borders.
          *
-         * Parameters: 
+         * Parameters:
          * elem - {Object} the element to set the content area of.
          * size - {Object} an object with a width and/or height property that
          * is the size to set the content area of the element to.
          */
         setContentBoxSize: function(size) {
+            var m,
+                width,
+                height;
             if (this.getBoxSizing() == 'border-box') {
-                var m = this.measure(function() {
+                m = this.measure(function() {
                     return this.getSizes(['padding', 'border']);
                 });
                 if ($defined(size.width)) {
-                    var width = size.width + m.padding.left + m.padding.right + m.border.left + m.border.right;
+                    width = size.width + m.padding.left + m.padding.right + m.border.left + m.border.right;
                     if (width < 0) {
                         width = 0;
                     }
-                    this.style.width = width + 'px';
+                    this.setStyle('width', width);
                 }
                 if ($defined(size.height)) {
-                    var height = size.height + m.padding.top + m.padding.bottom + m.border.top + m.border.bottom;
+                    height = size.height + m.padding.top + m.padding.bottom + m.border.top + m.border.bottom;
                     if (height < 0) {
                         height = 0;
                     }
-                    this.style.height = height + 'px';
+                    this.setStyle('height', height);
                 }
             } else {
                 if ($defined(size.width) && size.width >= 0) {
-                    this.style.width = size.width + 'px';
+                  this.setStyle('width', width);
                 }
                 if ($defined(size.height) && size.height >= 0) {
-                    this.style.height = size.height + 'px';
+                  this.setStyle('height', height);
                 }
             }
         },
@@ -15134,37 +15199,40 @@
          * content areaof the element may be larger depending on padding and
          * borders.
          *
-         * Parameters: 
+         * Parameters:
          * elem - {Object} the element to set the border size of.
          * size - {Object} an object with a width and/or height property that
          * is the size to set the content area of the element to.
          */
         setBorderBoxSize: function(size) {
+            var m, 
+                width, 
+                height;
             if (this.getBoxSizing() == 'content-box') {
-                var m = this.measure(function() {
+                m = this.measure(function() {
                     return this.getSizes();
                 });
 
                 if ($defined(size.width)) {
-                    var width = size.width - m.padding.left - m.padding.right - m.border.left - m.border.right - m.margin.left - m.margin.right;
+                    width = size.width - m.padding.left - m.padding.right - m.border.left - m.border.right - m.margin.left - m.margin.right;
                     if (width < 0) {
                         width = 0;
                     }
-                    this.style.width = width + 'px';
+                    this.setStyle('width', width);
                 }
                 if ($defined(size.height)) {
-                    var height = size.height - m.padding.top - m.padding.bottom - m.border.top - m.border.bottom - m.margin.top - m.margin.bottom;
+                    height = size.height - m.padding.top - m.padding.bottom - m.border.top - m.border.bottom - m.margin.top - m.margin.bottom;
                     if (height < 0) {
                         height = 0;
                     }
-                    this.style.height = height + 'px';
+                    this.setStyle('height', height);
                 }
             } else {
                 if ($defined(size.width) && size.width >= 0) {
-                    this.style.width = size.width + 'px';
+                  this.setStyle('width', width);
                 }
                 if ($defined(size.height) && size.height >= 0) {
-                    this.style.height = size.height + 'px';
+                  this.setStyle('height', height);
                 }
             }
         },
@@ -15200,8 +15268,8 @@
          * requested tag name or false if none are found.
          */
         findElement: function(type) {
-            var o = this;
-            var tagName = o.tagName;
+            var o = this,
+                tagName = o.tagName;
             while (o.tagName != type && o && o.parentNode && o.parentNode != o) {
                 o = document.id(o.parentNode);
             }
@@ -15216,7 +15284,7 @@
         /**
          * APIMethod: swap
          * swaps 2 elements of an array
-         * 
+         *
          * Parameters:
          * a - the first position to swap
          * b - the second position to swap
@@ -15229,9 +15297,25 @@
     });
 })(document.id || $);
 // End Wrapper for document.id
+/*
+---
+
+name: Jx.Styles
+
+description: A singleton object useful for dynamically creating and manipulating CSS styles
+
+license: MIT-style license.
+
+requires:
+ - Jx
+
+provides: [Jx.Styles]
+
+...
+ */
 /**
  * Class: Jx.Styles
- * Dynamic stylesheet class. Used for creating and manipulating dynamic 
+ * Dynamic stylesheet class. Used for creating and manipulating dynamic
  * stylesheets.
  *
  * TBD: should we handle the case of putting the same selector in a stylesheet
@@ -15249,7 +15333,7 @@
  * License:
  * Copyright (c) 2009, Jon Bomgardner.
  * Additional code by Paul Spencer
- * 
+ *
  * This file is licensed under an MIT style license
  *
  * Inspired by dojox.html.styles, VisitSpy by nwhite,
@@ -15275,14 +15359,15 @@
      * <CSSRule> - the requested rule
      */
     getCssRule: function(selector, styleSheetName) {
-        var ss = this.getDynamicStyleSheet(styleSheetName);
-        var rule = null;
+        var ss = this.getDynamicStyleSheet(styleSheetName),
+            rule = null,
+            i;
         if (ss.indicies) {
-            var i = ss.indicies.indexOf(selector);
+            i = ss.indicies.indexOf(selector);
             if (i == -1) {
                 rule = this.insertCssRule(selector, '', styleSheetName);
             } else {
-                if (Browser.Engine.name === 'trident') {
+                if (Browser.Engine.trident) {
                     rule = ss.sheet.rules[i];
                 } else {
                     rule = ss.sheet.cssRules[i];
@@ -15301,7 +15386,7 @@
      * declaration - <String> CSS-formatted rules to include.  May be empty,
      * in which case you may want to use the returned rule object to
      * manipulate styles
-     * styleSheetName - <String> the name of the sheet to place the rules in, 
+     * styleSheetName - <String> the name of the sheet to place the rules in,
      * or empty to put them in a default sheet.
      *
      * Returns:
@@ -15310,17 +15395,17 @@
      * properties in the same way that you would set them on a DOM object.
      */
     insertCssRule: function (selector, declaration, styleSheetName) {
-        var ss = this.getDynamicStyleSheet(styleSheetName);
-
-        var rule;
-        var text = selector + " {" + declaration + "}";
-        if (Browser.Engine.name === 'trident') {
+        var ss = this.getDynamicStyleSheet(styleSheetName),
+            rule,
+            text = selector + " {" + declaration + "}",
+            index;
+        if (Browser.Engine.trident) {
             if (declaration == '') {
                 //IE requires SOME text for the declaration. Passing '{}' will
                 //create an empty rule.
                 declaration = '{}';
             }
-            var index = ss.styleSheet.addRule(selector,declaration);
+            index = ss.styleSheet.addRule(selector,declaration);
             rule = ss.styleSheet.rules[index];
         } else {
             ss.sheet.insertRule(text, ss.indicies.length);
@@ -15342,17 +15427,18 @@
      * <Boolean> true if the rule was removed, false if it was not.
      */
     removeCssRule: function (selector, styleSheetName) {
-        var ss = this.getDynamicStyleSheet(styleSheetName);
-        var i = ss.indicies.indexOf(selector);
+        var ss = this.getDynamicStyleSheet(styleSheetName),
+            i = ss.indicies.indexOf(selector),
+            result = false;
         ss.indicies.splice(i, 1);
-        if (Browser.Engine.name === 'trident') {
+        if (Browser.Engine.trident) {
             ss.removeRule(i);
-            return true;
+            result = true;
         } else {
             ss.sheet.deleteRule(i);
-            return true;
+            result = true;
         }
-        return false;
+        return result;
     },
     /**
      * APIMethod: getDynamicStyleSheet
@@ -15362,7 +15448,7 @@
      * Parameter:
      * name - <String> the title of the stylesheet to create or obtain
      *
-     * Returns: 
+     * Returns:
      * <StyleSheet> a StyleSheet object with browser dependent capabilities.
      */
     getDynamicStyleSheet: function (name) {
@@ -15397,7 +15483,7 @@
     /**
      * APIMethod: removeStyleSheet
      * Removes a style sheet
-     * 
+     *
      * Parameters:
      * name = <String> the title of the stylesheet to remove
      */
@@ -15409,14 +15495,30 @@
     /**
      * APIMethod: isStyleSheetDefined
      * Determined if the passed in name is a defined dynamic style sheet.
-     * 
+     *
      * Parameters:
      * name = <String> the title of the stylesheet to remove
      */
     isStyleSheetDefined: function (name) {
       return this.dynamicStyleMap.has(name);
     }
-}))();// $Id: object.js 912 2010-05-21 21:33:08Z pagameba $
+}))();/*
+---
+
+name: Jx.Object
+
+description: Base class for all other object in the JxLib framework.
+
+license: MIT-style license.
+
+requires:
+ - Jx
+
+provides: [Jx.Object]
+
+...
+ */
+// $Id: object.js 976 2010-09-02 18:57:12Z pagameba $
 /**
  * Class: Jx.Object
  * Base class for all other object in the JxLib framework. This class
@@ -15434,15 +15536,15 @@
  * The basic initialization pipeline for a Jx.Object is to parse the
  * parameters provided to initialize(), separate out options from other formal
  * parameters based on the parameters property of the class, call init() and
- * initialize plugins.  
+ * initialize plugins.
  *
  * Parsing Parameters:
  * Because each sub-class no longer has an initialize method, it no longer has
- * direct access to parameters passed to the constructor.  Instead, a 
+ * direct access to parameters passed to the constructor.  Instead, a
  * sub-class is expected to provide a parameters attribute with an array of
- * parameter names in the order expected.  Jx.Object will enumerate the 
+ * parameter names in the order expected.  Jx.Object will enumerate the
  * attributes passed to its initialize method and automatically place them
- * in the options object under the appropriate key (the value from the 
+ * in the options object under the appropriate key (the value from the
  * array).  Parameters not found will not be present or will be null.
  *
  * The default parameters are a single options object which is merged with
@@ -15453,25 +15555,25 @@
  * calls the init() method, then fires the 'postInit' event.  It is expected
  * that most sub-class specific initialization will happen in the init()
  * method.  A sub-class may hook preInit and postInit events to perform tasks
- * in one of two ways. 
- * 
+ * in one of two ways.
+ *
  * First, simply send onPreInit and onPostInit functions via the options
  * object as follows (they could be standalone functions or functions of
  * another object setup using .bind())
- * 
+ *
  * (code)
  * var preInit = function () {}
  * var postInit = function () {}
- * 
+ *
  * var options = {
  *   onPreInit: preInit,
  *   onPostInit: postInit,
  *   ...other options...
  * };
- * 
+ *
  * var dialog = new Jx.Dialog(options);
  * (end)
- * 
+ *
  * The second method you can use is to override the initialize method
  *
  * (code)
@@ -15494,13 +15596,13 @@
  *   }
  * });
  * (end)
- * 
+ *
  * When the object finishes initializing itself (including the plugin
  * initialization) it will fire off the initializeDone event. You can hook
  * into this event in the same way as the events mentioned above.
  *
  * Plugins:
- * Plugins provide pieces of additional, optional, functionality. They are not 
+ * Plugins provide pieces of additional, optional, functionality. They are not
  * necessary for the proper function of an object. All plugins should be
  * located in the Jx.Plugin namespace and they should be further segregated by
  * applicable object. While all objects can support plugins, not all of them
@@ -15508,39 +15610,39 @@
  * to turn this feature on for an object you need to set the pluginNamespace
  * property of the object. The following is an example of setting the
  * property:
- * 
+ *
  * (code)
  * var MyClass = new Class({
  *   Extends: Jx.Object,
  *   pluginNamespace: 'MyClass'
  * };
  * (end)
- * 
- * The absence of this property does not mean you cannot attach a plugin to an 
+ *
+ * The absence of this property does not mean you cannot attach a plugin to an
  * object. It simply means that you can't have Jx.Object create the
  * plugin for you.
- * 
+ *
  * There are four ways to attach a plugin to an object. First, simply
  * instantiate the plugin yourself and call its attach() method (other class
  * options left out for the sake of simplicity):
- * 
+ *
  * (code)
  * var MyGrid = new Jx.Grid();
  * var APlugin = new Jx.Plugin.Grid.Selector();
  * APlugin.attach(MyGrid);
  * (end)
- * 
+ *
  * Second, you can instantiate the plugin first and pass it to the object
  * through the plugins array in the options object.
- * 
+ *
  * (code)
  * var APlugin = new Jx.Plugin.Grid.Selector();
  * var MyGrid = new Jx.Grid({plugins: [APlugin]});
  * (end)
- * 
+ *
  * The third way is to pass the information needed to instantiate the plugin
  * in the plugins array of the options object:
- * 
+ *
  * (code)
  * var MyGrid = new Jx.Grid({
  *   plugins: [{
@@ -15552,22 +15654,22 @@
  *   }]
  * });
  * (end)
- * 
+ *
  * The final way, if the plugin has no options, is to pass the name of the
  * plugin as a simple string in the plugins array.
- * 
+ *
  * (code)
  * var MyGrid = new Jx.Grid({
  *   plugins: ['Selector','Sorter']
  * });
  * (end)
- * 
+ *
  * Part of the process of initializing plugins is to call prePluginInit() and
- * postPluginInit(). These events provide you access to the object just before 
+ * postPluginInit(). These events provide you access to the object just before
  * and after the plugins are initialized and/or attached to the object using
  * methods 2 and 3 above. You can hook into these in the same way that you
- * hook into the preInit() and postInit() events.  
- * 
+ * hook into the preInit() and postInit() events.
+ *
  * Destroying Jx.Object Instances:
  * Jx.Object provides a destroy method that cleans up potential memory leaks
  * when you no longer need an object.  Sub-classes are expected to implement
@@ -15575,7 +15677,7 @@
  * sub-class.  Remember to call this.parent() when providing a cleanup()
  * method. Destroy will also fire off 2 events: preDestroy and postDestroy.
  * You can hook into these methods in the same way as the init or plugin
- * events. 
+ * events.
  *
  * The Family Attribute:
  * the Family attribute of a class is used internally by JxLib to identify Jx
@@ -15613,14 +15715,14 @@
      * options - {Object} optional parameters for creating an object.
      */
     parameters: ['options'],
-    
+
     options: {
       /**
        * Option: useLang
        * Turns on this widget's ability to react to changes in
        * the default language. Handy for changing text out on the fly.
-       * 
-       * TODO: Should this be enabled or disabled by default? 
+       *
+       * TODO: Should this be enabled or disabled by default?
        */
       useLang: true,
       /**
@@ -15629,41 +15731,43 @@
        */
       plugins: null
     },
-    
+
     bound: null,
 
     initialize: function(){
         this.plugins = new Hash();
         this.bound = {};
         //normalize arguments
-        var numArgs = arguments.length;
-        var options = {};
+        var numArgs = arguments.length,
+            options = {},
+            parameters = this.parameters,
+            numParams,
+            index;
 
         if (numArgs > 0) {
             if (numArgs === 1
                     && (Jx.type(arguments[0])==='object' || Jx.type(arguments[0])==='Hash')
-                    && this.parameters.length === 1
-                    && this.parameters[0] === 'options') {
+                    && parameters.length === 1
+                    && parameters[0] === 'options') {
                 options = arguments[0];
             } else {
-                var numParams = this.parameters.length;
-                var index;
+                numParams = parameters.length;
+                index;
                 if (numParams <= numArgs) {
                     index = numParams;
                 } else {
                     index = numArgs;
                 }
-                options = {};
                 for (var i = 0; i < index; i++) {
-                    if (this.parameters[i] === 'options') {
-                        options = $merge(options, arguments[i]);
+                    if (parameters[i] === 'options') {
+                        $extend(options, arguments[i]);
                     } else {
-                        options[this.parameters[i]] = arguments[i];
+                        options[parameters[i]] = arguments[i];
                     }
                 }
             }
         }
-        
+
         this.setOptions(options);
 
         this.bound.changeText = this.changeText.bind(this);
@@ -15685,6 +15789,7 @@
      * internal function to initialize plugins on object creation
      */
     initPlugins: function () {
+        var p;
         // pluginNamespace must be defined in order to pass plugins to the
         // object
         if ($defined(this.pluginNamespace)) {
@@ -15700,21 +15805,19 @@
                         // that is used for locating the plugins. The default
                         // namespace is 'Other' for
                         // now until we come up with a better idea
-                    	var p;
-                    	if ($defined(Jx.Plugin[this.pluginNamespace][plugin.name.capitalize()])) {
-                    		p = new Jx.Plugin[this.pluginNamespace][plugin.name.capitalize()](plugin.options);
-                    	} else {
-                    		p = new Jx.Adaptor[this.pluginNamespace][plugin.name.capitalize()](plugin.options);
-                    	}
+                      if ($defined(Jx.Plugin[this.pluginNamespace][plugin.name.capitalize()])) {
+                        p = new Jx.Plugin[this.pluginNamespace][plugin.name.capitalize()](plugin.options);
+                      } else {
+                        p = new Jx.Adaptor[this.pluginNamespace][plugin.name.capitalize()](plugin.options);
+                      }
                         p.attach(this);
                     } else if (Jx.type(plugin) === 'string') {
                         //this is a name for a plugin.
-                    	var p;
-                    	if ($defined(Jx.Plugin[this.pluginNamespace][plugin.capitalize()])) {
-                    		p = new Jx.Plugin[this.pluginNamespace][plugin.capitalize()]();
-                    	} else {
-                    		p = new Jx.Adaptor[this.pluginNamespace][plugin.capitalize()]();
-                    	}
+                      if ($defined(Jx.Plugin[this.pluginNamespace][plugin.capitalize()])) {
+                        p = new Jx.Plugin[this.pluginNamespace][plugin.capitalize()]();
+                      } else {
+                        p = new Jx.Adaptor[this.pluginNamespace][plugin.capitalize()]();
+                      }
                         p.attach(this);
                     }
                 }, this);
@@ -15739,7 +15842,7 @@
     /**
      * Method: cleanup
      * to be implemented by subclasses to do the actual work of destroying
-     * an object. 
+     * an object.
      */
     cleanup: function () {
         //detach plugins
@@ -15759,12 +15862,12 @@
      * virtual initialization method to be implemented by sub-classes
      */
     init: $empty,
-    
+
     /**
      * APIMethod: registerPlugin
      * This method is called by a plugin that has its attach method
      * called.
-     * 
+     *
      * Parameters:
      * plugin - the plugin to register with this object
      */
@@ -15777,7 +15880,7 @@
      * APIMethod: deregisterPlugin
      * his method is called by a plugin that has its detach method
      * called.
-     * 
+     *
      * Parameters:
      * plugin - the plugin to deregister.
      */
@@ -15786,12 +15889,12 @@
             this.plugins.erase(plugin.name);
         }
     },
-    
+
     /**
      * APIMethod: getPlugin
      * Allows a developer to get a reference to a plugin with only the
      * name of the plugin.
-     * 
+     *
      * Parameters:
      * name - the name of the plugin as defined in the plugin's name property
      */
@@ -15803,27 +15906,28 @@
 
     /**
      * APIMethod: getText
-     * 
-     * returns the text for a jx.widget used in a label. 
-     * 
+     *
+     * returns the text for a jx.widget used in a label.
+     *
      * Parameters:
      * val - <String> || <Function> || <Object> = { set: '', key: ''[, value: ''] } for a MooTools.lang object
      */
     getText: function(val) {
-      if (Jx.type(val) == 'string') {
-        return val;
+      var result = '';
+      if (Jx.type(val) == 'string' || Jx.type(val) == 'number') {
+        result = val;
       } else if (Jx.type(val) == 'function') {
-        return val();
+        result = val();
       } else if (Jx.type(val) == 'object' && $defined(val.set) && $defined(val.key)) {
         // COMMENT: just an idea how a localization object could be stored to the instance if needed somewhere else and options change?
         this.i18n = val;
         if($defined(val.value)) {
-          return MooTools.lang.get(val.set, val.key)[val.value];
+          result = MooTools.lang.get(val.set, val.key)[val.value];
         }else{
-          return MooTools.lang.get(val.set, val.key);
+          result = MooTools.lang.get(val.set, val.key);
         }
       }
-      return '';
+      return result;
     },
 
     /**
@@ -15837,7 +15941,22 @@
      */
     changeText : $empty
 });
+/*
+---
 
+name: Locale.English.US
+
+description: Default translations of text strings used in JX for US english (en-US)
+
+license: MIT-style license.
+
+requires:
+ - More/Lang
+
+provides: [Locale.English.US]
+
+...
+ */
 MooTools.lang.set('en-US', 'Jx', {
 	
 	'widget': {
@@ -15911,7 +16030,34 @@
     submitButton: 'Save',
     cancelButton: 'Cancel'
   }
-});// $Id: widget.js 924 2010-05-26 16:03:06Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Widget
+
+description: Base class for all widgets (visual classes) in the JxLib Framework.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+ - Locale.English.US
+
+provides: [Jx.Widget]
+
+css:
+ - chrome
+
+images:
+ - spinner_16.gif
+ - spinner_24.gif
+
+optional:
+ - More/Spinner
+
+...
+ */
+// $Id: widget.js 976 2010-09-02 18:57:12Z pagameba $
 /**
  * Class: Jx.Widget
  * Base class for all widgets (visual classes) in the JxLib Framework. This
@@ -15950,9 +16096,9 @@
  * appropriate corners of the chrome image are displayed in those locations.
  *
  * Busy States:
- * 
+ *
  * Any widget can be set as temporarily busy by calling the setBusy(true)
- * method and then as idle by calling setBusy(false).  By default, busy 
+ * method and then as idle by calling setBusy(false).  By default, busy
  * widgets display an event mask that prevents them from being clicked and
  * a spinner image with a message.  By default, there are two configurations
  * for the spinner image and message, one for 'small' widgets like buttons
@@ -15980,14 +16126,14 @@
  * contentLoadFailed - called if content can not be loaded for some reason
  * addTo - called when a widget is added to another element or widget
  * busy - called just before the busy mask is rendered/removed
- * 
+ *
  * MooTools.Lang Keys:
  * widget.busyMessage - sets the message of the waiter component when used
  */
 Jx.Widget = new Class({
     Family: "Jx.Widget",
     Extends: Jx.Object,
-    
+
     options: {
         /* Option: id
          * (optional) {String} an HTML ID to assign to the widget
@@ -16067,7 +16213,7 @@
     classes: new Hash({
         domObj: 'jxWidget'
     }),
-    
+
     /**
      * Property: busy
      * {Boolean} is the widget currently busy?  This should be considered
@@ -16134,33 +16280,35 @@
      *     useful when using the contentURL method of loading content.
      */
     loadContent: function(element) {
+        var c,
+            options = this.options,
+            timeout;
         element = document.id(element);
-        if (this.options.content) {
-            var c;
-            if (this.options.content.domObj) {
-                c = document.id(this.options.content.domObj);
+        if (options.content) {
+            if (options.content.domObj) {
+                c = document.id(options.content.domObj);
             } else {
-                c = document.id(this.options.content);
+                c = document.id(options.content);
             }
             if (c) {
-                if (this.options.content.addTo) {
-                    this.options.content.addTo(element);
+                if (options.content.addTo) {
+                    options.content.addTo(element);
                 } else {
                     element.appendChild(c);
                 }
                 this.contentIsLoaded = true;
             } else {
-                element.innerHTML = this.options.content;
+                element.innerHTML = options.content;
                 this.contentIsLoaded = true;
             }
-        } else if (this.options.contentURL) {
+        } else if (options.contentURL) {
             this.contentIsLoaded = false;
             this.req = new Request({
-                url: this.options.contentURL,
+                url: options.contentURL,
                 method:'get',
                 evalScripts:true,
                 onRequest:(function() {
-                  if(this.options.loadOnDemand) {
+                  if(options.loadOnDemand) {
                       this.setBusy(true);
                   }
                 }).bind(this),
@@ -16182,13 +16330,13 @@
             });
             this.req.send();
             if (Jx.isAir) {
-                var timeout = $defined(this.options.timeout) ? this.options.timeout : 10000;
+                timeout = $defined(options.timeout) ? options.timeout : 10000;
                 this.reqTimeout = this.checkRequest.delay(timeout, this);
             }
         } else {
             this.contentIsLoaded = true;
         }
-        if (this.options.contentId) {
+        if (options.contentId) {
             element.id = this.options.contentId;
         }
         if (this.contentIsLoaded) {
@@ -16254,12 +16402,19 @@
     position: function(element, relative, options) {
         element = document.id(element);
         relative = document.id(relative);
-        var hor = $splat(options.horizontal || ['center center']);
-        var ver = $splat(options.vertical || ['center center']);
-        var offsets = $merge({top:0,right:0,bottom:0,left:0}, options.offsets || {});
-
-        var coords = relative.getCoordinates(); //top, left, width, height
-        var page, scroll;
+        var hor = $splat(options.horizontal || ['center center']),
+            ver = $splat(options.vertical || ['center center']),
+            offsets = $merge({top:0,right:0,bottom:0,left:0}, options.offsets || {}),
+            coords = relative.getCoordinates(), //top, left, width, height,
+            page, 
+            scroll,
+            size,
+            left,
+            rigbht,
+            top,
+            bottom,
+            n,
+            parts;
         if (!document.id(element.parentNode) || element.parentNode ==  document.body) {
             page = Jx.getPageDimensions();
             scroll = document.id(document.body).getScroll();
@@ -16279,10 +16434,9 @@
             coords.left = 0;
             coords.top = 0;
         }
-        var size = element.getMarginBoxSize(); //width, height
-        var left, right, top, bottom, n;
+        size = element.getMarginBoxSize(); //width, height
         if (!hor.some(function(opt) {
-            var parts = opt.split(' ');
+            parts = opt.split(' ');
             if (parts.length != 2) {
                 return false;
             }
@@ -16351,7 +16505,7 @@
         element.setStyle('left', left);
 
         if (!ver.some(function(opt) {
-          var parts = opt.split(' ');
+          parts = opt.split(' ');
           if (parts.length != 2) {
             return false;
           }
@@ -16429,11 +16583,12 @@
      */
     makeChrome: function(element) {
         var c = new Element('div', {
-            'class':'jxChrome',
-            events: {
-                contextmenu: function(e) { e.stop(); }
-            }
-        });
+                'class':'jxChrome',
+                events: {
+                  contextmenu: function(e) { e.stop(); }
+                }
+              }),
+            src;
 
         /* add to element so we can get the background image style */
         element.adopt(c);
@@ -16449,7 +16604,7 @@
 
         /* get the chrome image from the background image of the element */
         /* the app: protocol check is for adobe air support */
-        var src = c.getStyle('backgroundImage');
+        src = c.getStyle('backgroundImage');
         if (src != null) {
           if (!(src.contains('http://') || src.contains('https://') || src.contains('file://') || src.contains('app:/'))) {
               src = null;
@@ -16527,8 +16682,8 @@
      */
     hideChrome: function() {
         if (this.chrome) {
-            if (this.shim) { 
-              this.shim.hide(); 
+            if (this.shim) {
+              this.shim.hide();
             }
             this.chrome.parentNode.removeClass('jxHasChrome');
             this.chrome.dispose();
@@ -16612,15 +16767,16 @@
      * names
      */
     processTemplate: function(template,classes,container){
-        var h = new Hash();
-        var element;
+        var h = new Hash(),
+            element,
+            el;
         if ($defined(container)){
             element = container.set('html',template);
         } else {
             element = new Element('div',{html:template});
         }
         classes.each(function(klass){
-            var el = element.getElement('.'+klass);
+            el = element.getElement('.'+klass);
             if ($defined(el)){
                 h.set(klass,el);
             }
@@ -16714,7 +16870,7 @@
         }, this);
         return elements;
     },
-    
+
     /**
      * APIMethod: isBusy
      * indicate if the widget is currently busy or not
@@ -16725,29 +16881,42 @@
     isBusy: function() {
       return this.busy;
     },
-    
+
     /**
      * APIMethod: setBusy
      * set the busy state of the widget
      *
      * Parameters:
-     * busy - {Boolean} true to set the widget as busy, false to set it as
-     *    idle.
+     * busy         - {Boolean} true to set the widget as busy, false to set it as idle.
+     * message      - {String||Jx Localized Object} (Optional) set a custom message directly
+     *                next to the loading icon. Default is {set:'Jx',key:'widget',value:'busyMessage'}
+     * forceMessage - {Boolean} force displaying a message for larger areas than 60px of height
      */
-    setBusy: function(state) {
+    setBusy: function(state, message, forceMessage) {
       if (this.busy == state) {
         return;
       }
+      var options = this.options,
+          z,
+          size,
+          opts,
+          domObj = this.domObj;
+      message = $defined(message) ? message : {
+        set:'Jx',
+        key:'widget',
+        value:'busyMessage'
+      };
+      forceMessage = $defined(forceMessage) ? forceMessage : false;
       this.busy = state;
-      this.fireEvent('busy', this.busy);
-      if (this.busy) {
-        if (this.options.busyClass) {
-          this.domObj.addClass(this.options.busyClass);
+      this.fireEvent('busy', state);
+      if (state) {
+        if (options.busyClass) {
+          domObj.addClass(options.busyClass);
         }
-        if (this.options.busyMask && this.domObj.spin) {
+        if (options.busyMask && domObj.spin) {
           /* put the spinner above the element in the z-index */
-          var z = Jx.getNumber(this.domObj.getStyle('z-index'));
-          var opts = {
+          z = Jx.getNumber(domObj.getStyle('z-index'));
+          opts = {
             style: {
               'z-index': z+1
             }
@@ -16755,38 +16924,35 @@
           /* switch to the small size if the element is less than
            * 60 pixels high
            */
-          var size = this.domObj.getBorderBoxSize();
-          if (size.height < 60) {
+          size = domObj.getBorderBoxSize();
+          if (size.height < 60 || forceMessage) {
             opts['class'] = 'jxSpinner jxSpinnerSmall';
             opts.img = null;
             opts.message = new Element('p',{
               'class':'jxSpinnerMessage',
-              html: '<span class="jxSpinnerImage"></span>'+this.getText({set:'Jx',key:'widget',value:'busyMessage'})
+              html: '<span class="jxSpinnerImage"></span>'+this.getText(message)
             });
           }
-          opts = $merge(this.options.busyMask, opts);
-          
-          this.domObj.get('spinner', opts).show(!this.options.busyMask.fx);
-  		
+          opts = $merge(options.busyMask, opts);
+          domObj.get('spinner', opts).show(!options.busyMask.fx);
         }
       } else {
-        if (this.options.busyClass) {
-          this.domObj.removeClass(this.options.busyClass);
+        if (options.busyClass) {
+          domObj.removeClass(options.busyClass);
         }
-        if (this.options.busyMask && this.domObj.unspin) {
-          this.domObj.get('spinner').hide(!this.options.busyMask.fx);
-    	
+        if (options.busyMask && this.domObj.unspin) {
+          domObj.get('spinner').hide(!options.busyMask.fx);
         }
       }
     },
-    
+
     /**
      * APIMethod: changeText
      * This method should be overridden by subclasses. It should be used
      * to change any language specific default text that is used by the widget.
-     * 
+     *
      * Parameters:
-     * lang - {string} the language being changed to or that had it's data set of 
+     * lang - {string} the language being changed to or that had it's data set of
      *    translations changed.
      */
     changeText: function (lang) {
@@ -16797,7 +16963,7 @@
             this.setBusy(true);
         }
     },
-    
+
     /**
      * APIMethod: stack
      * stack this widget in the z-index of the DOM relative to other stacked
@@ -16809,10 +16975,9 @@
      * is typically this.domObj unless the method has been overloaded.
      */
     stack: function(el) {
-      el = el || document.id(this);
-      Jx.Stack.stack(el);
+      Jx.Stack.stack(el || document.id(this));
     },
-    
+
     /**
      * APIMethod: unstack
      * remove this widget from the stack.
@@ -16823,8 +16988,7 @@
      * is typically this.domObj unless the method has been overloaded.
      */
     unstack: function(el) {
-      el = el || document.id(this);
-      Jx.Stack.unstack(el);
+      Jx.Stack.unstack(el = el || document.id(this));
     }
 });
 
@@ -16858,7 +17022,23 @@
             }
         }
     });
-}// $Id: selection.js 927 2010-05-27 13:32:00Z pagameba $
+}/*
+---
+
+name: Jx.Selection
+
+description: A class to manage selection across multiple list objects
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+
+provides: [Jx.Selection]
+
+...
+ */
+// $Id: selection.js 976 2010-09-02 18:57:12Z pagameba $
 /**
  * Class: Jx.Selection
  *
@@ -16981,25 +17161,27 @@
      * item - {DOMElement} a DOM element or an element ID.
      */
     select: function (item) {
+        var options = this.options,
+            selection = this.selection;
         item = document.id(item);
-        if (this.options.selectMode === 'multiple') {
-            if (this.selection.contains(item)) {
+        if (options.selectMode === 'multiple') {
+            if (selection.contains(item)) {
                 this.unselect(item);
             } else {
-                document.id(item).addClass(this.options.selectClass);
-                this.selection.push(item);
-                this.fireEvent(this.options.eventToFire.select, item);
+                document.id(item).addClass(options.selectClass);
+                selection.push(item);
+                this.fireEvent(options.eventToFire.select, item);
             }
-        } else if (this.options.selectMode == 'single') {
+        } else if (options.selectMode == 'single') {
             if (!this.selection.contains(item)) {
-                document.id(item).addClass(this.options.selectClass);
-                this.selection.push(item);
-                if (this.selection.length > 1) {
-                    this.unselect(this.selection[0]);
+                document.id(item).addClass(options.selectClass);
+                selection.push(item);
+                if (selection.length > 1) {
+                    this.unselect(selection[0]);
                 }
-                this.fireEvent(this.options.eventToFire.select, item);
+                this.fireEvent(options.eventToFire.select, item);
             } else {
-                if (this.options.selectToggle) {
+                if (options.selectToggle) {
                   this.unselect(item);
                 }
             }
@@ -17015,11 +17197,13 @@
      * item - {DOMElement} a DOM element or an element ID.
      */
     unselect: function (item) {
-        if (this.selection.contains(item) &&
-            this.selection.length > this.options.minimumSelection) {
-            document.id(item).removeClass(this.options.selectClass);
-            this.selection.erase(item);
-            this.fireEvent(this.options.eventToFire.unselect, [item, this]);
+        var selection = this.selection,
+            options = this.options;
+        if (selection.contains(item) &&
+            selection.length > options.minimumSelection) {
+            document.id(item).removeClass(options.selectClass);
+            selection.erase(item);
+            this.fireEvent(options.eventToFire.unselect, [item, this]);
         }
     },
 
@@ -17048,7 +17232,24 @@
     isSelected: function(item) {
         return this.selection.contains(item);
     }
-});// $Id: list.js 927 2010-05-27 13:32:00Z pagameba $
+});/*
+---
+
+name: Jx.List
+
+description: A class that is used to manage lists of DOM elements
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+ - Jx.Selection
+
+provides: [Jx.List]
+
+...
+ */
+// $Id: list.js 976 2010-09-02 18:57:12Z pagameba $
 /**
  * Class: Jx.List
  *
@@ -17170,37 +17371,38 @@
         this.container = document.id(this.options.container);
         this.container.store('jxList', this);
 
-        var target = this;
-        var isEnabled = function(el) {
-            var item = el.retrieve('jxListTargetItem') || el;
-            return !item.hasClass('jxDisabled');
-        };
-        var isSelectable = function(el) {
-            var item = el.retrieve('jxListTargetItem') || el;
-            return !item.hasClass('jxUnselectable');
-        };
+        var target = this,
+            options = this.options,
+            isEnabled = function(el) {
+                var item = el.retrieve('jxListTargetItem') || el;
+                return !item.hasClass('jxDisabled');
+            },
+            isSelectable = function(el) {
+                var item = el.retrieve('jxListTargetItem') || el;
+                return !item.hasClass('jxUnselectable');
+            };
         this.bound = $merge(this.bound, {
             mousedown: function() {
                 if (isEnabled(this)) {
-                    this.addClass(target.options.pressClass);
+                    this.addClass(options.pressClass);
                     target.fireEvent('mousedown', this, target);
                 }
             },
             mouseup: function() {
                 if (isEnabled(this)) {
-                    this.removeClass(target.options.pressClass);
+                    this.removeClass(options.pressClass);
                     target.fireEvent('mouseup', this, target);
                 }
             },
             mouseenter: function() {
                 if (isEnabled(this)) {
-                    this.addClass(target.options.hoverClass);
+                    this.addClass(options.hoverClass);
                     target.fireEvent('mouseenter', this, target);
                 }
             },
             mouseleave: function() {
                 if (isEnabled(this)) {
-                    this.removeClass(target.options.hoverClass);
+                    this.removeClass(options.hoverClass);
                     target.fireEvent('mouseleave', this, target);
                 }
             },
@@ -17220,6 +17422,7 @@
                     isSelectable(this)) {
                     target.selection.select(this, target);
                 }
+                target.fireEvent('click', this, target);
             },
             select: function(item) {
                 if (isEnabled(item)) {
@@ -17237,22 +17440,22 @@
               var cm = this.retrieve('jxContextMenu');
               if (cm) {
                 cm.show(e);
-                this.removeClass(target.options.pressClass);
+                this.removeClass(options.pressClass);
               }
               e.stop();
             }
         });
 
-        if (this.options.selection) {
-            this.setSelection(this.options.selection);
-            this.options.select = true;
-        } else if (this.options.select) {
-            this.selection = new Jx.Selection(this.options);
+        if (options.selection) {
+            this.setSelection(options.selection);
+            options.select = true;
+        } else if (options.select) {
+            this.selection = new Jx.Selection(options);
             this.ownsSelection = true;
         }
 
-        if ($defined(this.options.items)) {
-            this.add(this.options.items);
+        if ($defined(options.items)) {
+            this.add(options.items);
         }
     },
 
@@ -17270,16 +17473,17 @@
         }
         this.setSelection(null);
         this.container.eliminate('jxList');
-        this.bound.mousedown=null;
-        this.bound.mouseup=null;
-        this.bound.mouseenter=null;
-        this.bound.mouseleave=null;
-        this.bound.keydown=null;
-        this.bound.keyup=null;
-        this.bound.click=null;
-        this.bound.select=null;
-        this.bound.unselect=null;
-        this.bound.contextmenu=null;
+        var bound = this.bound;
+        bound.mousedown=null;
+        bound.mouseup=null;
+        bound.mouseenter=null;
+        bound.mouseleave=null;
+        bound.keydown=null;
+        bound.keyup=null;
+        bound.click=null;
+        bound.select=null;
+        bound.unselect=null;
+        bound.contextmenu=null;
         this.parent();
     },
 
@@ -17304,45 +17508,48 @@
             return;
         }
         /* the element being wrapped */
-        var el = document.id(item);
-        var target = el.retrieve('jxListTarget') || el;
+        var el = document.id(item),
+            target = el.retrieve('jxListTarget') || el,
+            bound = this.bound,
+            options = this.options,
+            container = this.container;
         if (target) {
             target.store('jxListTargetItem', el);
             target.addEvents({
               contextmenu: this.bound.contextmenu
             });
-            if (this.options.press && this.options.pressClass) {
+            if (options.press && options.pressClass) {
                 target.addEvents({
-                    mousedown: this.bound.mousedown,
-                    mouseup: this.bound.mouseup,
-                    keyup: this.bound.keyup,
-                    keydown: this.bound.keydown
+                    mousedown: bound.mousedown,
+                    mouseup: bound.mouseup,
+                    keyup: bound.keyup,
+                    keydown: bound.keydown
                 });
             }
-            if (this.options.hover && this.options.hoverClass) {
+            if (options.hover && options.hoverClass) {
                 target.addEvents({
-                    mouseenter: this.bound.mouseenter,
-                    mouseleave: this.bound.mouseleave
+                    mouseenter: bound.mouseenter,
+                    mouseleave: bound.mouseleave
                 });
             }
             if (this.selection) {
                 target.addEvents({
-                    click: this.bound.click
+                    click: bound.click
                 });
             }
             if ($defined(position)) {
                 if ($type(position) == 'number') {
-                    if (position < this.container.childNodes.length) {
-                        el.inject(this.container.childNodes[position],'before');
+                    if (position < container.childNodes.length) {
+                        el.inject(container.childNodes[position],'before');
                     } else {
-                        el.inject(this.container, 'bottom');
+                        el.inject(container, 'bottom');
                     }
-                } else if (this.container.hasChild(position)) {
+                } else if (container.hasChild(position)) {
                     el.inject(position,'after');
                 }
                 this.fireEvent('add', item, this);
             } else {
-                el.inject(this.container, 'bottom');
+                el.inject(container, 'bottom');
                 this.fireEvent('add', item, this);
             }
             if (this.selection) {
@@ -17363,11 +17570,12 @@
      * of this list.
      */
     remove: function(item) {
-        var el = document.id(item);
+        var el = document.id(item),
+            target;
         if (el && this.container.hasChild(el)) {
             this.unselect(el, true);
             el.dispose();
-            var target = el.retrieve('jxListTarget') || el;
+            target = el.retrieve('jxListTarget') || el;
             target.removeEvents(this.bound);
             this.fireEvent('remove', item, this);
             return item;
@@ -17491,26 +17699,43 @@
      * {<Jx.Selection>} the selection object, or null to remove it.
      */
     setSelection: function(selection) {
-        if (this.selection == selection) return;
+        var sel = this.selection;
+        if (sel == selection) return;
 
-        if (this.selection) {
-            this.selection.removeEvents(this.bound);
+        if (sel) {
+            sel.removeEvents(this.bound);
             if (this.ownsSelection) {
-                this.selection.destroy();
+                sel.destroy();
                 this.ownsSelection = false;
             }
         }
 
         this.selection = selection;
-        if (this.selection) {
-            this.selection.addEvents({
+        if (selection) {
+            selection.addEvents({
                 select: this.bound.select,
                 unselect: this.bound.unselect
             });
         }
     }
 
-});/**
+});/*
+---
+
+name: Jx.Stack
+
+description: A singleton object for managing a global z-index stack for widgets that need to order themselves in the z-index of the page relative to other such widgets.
+
+license: MIT-style license.
+
+requires:
+ - Jx
+
+provides: [Jx.Stack]
+
+...
+ */
+/**
  * Class: Jx.Stack
  * Manage the zIndex of widgets
  *
@@ -17521,7 +17746,7 @@
  *
  * License:
  * Copyright (c) 2010 Paul Spencer
- * 
+ *
  * This file is licensed under an MIT style license
  */
 Jx.Stack = new(new Class({
@@ -17530,20 +17755,20 @@
    * {Array} the elements in the stack
    */
   els: [],
-  
+
   /**
    * Property: base
    * {Integer} the base z-index value of the first element in the stack
    */
   base: 1000,
-  
+
   /**
    * Property: increment
    * {Integer} the amount to increment the z-index between elements of the
    * stack
    */
   increment: 100,
-  
+
   /**
    * APIMethod: stack
    * push an element onto the stack and set its z-index appropriately
@@ -17566,12 +17791,13 @@
    * el - {DOMElement} the DOM element to pull off the stack
    */
   unstack: function(el) {
-    if (this.els.contains(el)) {
+    var elements = this.els;
+    if (elements.contains(el)) {
       el.setStyle('z-index', '');
-      var idx = this.els.indexOf(el);
-      this.els.erase(el);
-      for (var i=idx; i<this.els.length; i++) {
-        this.setZIndex(this.els[i], i);
+      var idx = elements.indexOf(el);
+      elements.erase(el);
+      for (var i=idx; i<elements.length; i++) {
+        this.setZIndex(elements[i], i);
       }
     }
   },
@@ -17590,8 +17816,23 @@
       document.id(obj).setStyle('z-index', this.base + (idx*this.increment));
     }
   }
-  
-}))();MooTools.lang.set('de-DE', 'Date', {
+
+}))();/*
+name: Locale.German
+
+description: Default translations of text strings used in JX for German (Germany) (de-DE)
+
+license: MIT-style license.
+
+requires:
+ - More/Lang
+
+provides: [Locale.German]
+
+...
+ */
+
+MooTools.lang.set('de-DE', 'Date', {
   // need to overwrite 'M&auml;rz' to 'März' for jx.select fields
   months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']
 });
@@ -17669,7 +17910,23 @@
     submitButton: 'Speichern',
     cancelButton: 'Abbrechen'
   }
-});MooTools.lang.set('ru-RU-unicode', 'Jx', {
+});/*
+---
+
+name: Locale.Russian
+
+description: Default translations of text strings used in JX for Russia (Russia) (ru-RU)
+
+license: MIT-style license.
+
+requires:
+ - More/Lang
+
+provides: [Locale.Russian]
+
+...
+ */
+MooTools.lang.set('ru-RU-unicode', 'Jx', {
 	
 	'widget': {
 		busyMessage: 'Обработка...'
@@ -17678,7 +17935,7 @@
 		alphaLabel: 'alpha (%)'
 	},
 	notice: {
-		closeTip: 'закрыть Ñ?то Ñ?ообщение'
+		closeTip: 'закрыть это сообщение'
 	},
 	progressbar: {
 		messageText: 'Загрузка...',
@@ -17692,7 +17949,7 @@
 	},
 	'formatter.boolean': {
 		'true': 'Да',
-		'false': 'Ð?ет'
+		'false': 'Нет'
 	},
 	'formatter.currency': {
 		sign: 'Ñ€.'
@@ -17702,10 +17959,10 @@
     thousandsSeparator: ' '
 	},
 	splitter: {
-		barToolTip: 'потÑ?ни, чтобы изменить размер'
+		barToolTip: 'потяни, чтобы изменить размер'
 	},
 	panelset: {
-		barToolTip: 'потÑ?ни, чтобы изменить размер'
+		barToolTip: 'потяни, чтобы изменить размер'
 	},
 	panel: {
 		collapseTooltip: 'Свернуть/Развернуть Панель',
@@ -17713,14 +17970,14 @@
     expandLabel: 'Развернуть',
     maximizeTooltip: 'Увеличить Панель',
     maximizeLabel: 'Увеличить',
-    restoreTooltip: 'ВоÑ?Ñ?тановить Панель',
-    restoreLabel: 'ВоÑ?Ñ?тановить',
+    restoreTooltip: 'Восстановить Панель',
+    restoreLabel: 'Восстановить',
     closeTooltip: 'Закрыть Панель',
     closeLabel: 'Закрыть'
 	},
 	confirm: {
 		affirmativeLabel: 'Да',
-    negativeLabel: 'Ð?ет'
+    negativeLabel: 'Нет'
 	},
 	dialog: {
 		resizeToolTip: 'Изменить размер'
@@ -17736,32 +17993,48 @@
 		buttonText: 'Загрузка файла'
 	},
 	'plugin.resize': {
-	  tooltip: 'ПотÑ?ни, чтобы изменить, двойной щелчок длÑ? авто размера.'
+	  tooltip: 'Потяни, чтобы изменить, двойной щелчок для авто размера.'
 	},
   'plugin.editor': {
     submitButton: 'Сохранить',
     cancelButton: 'Отмена'
   }
-});// $Id: record.js 834 2010-04-05 18:17:01Z jonlb at comcast.net $
+});/*
+---
+
+name: Jx.Record
+
+description: The basic record implementation. A store uses records to handle and manipulate data.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+
+provides: [Jx.Record]
+
+...
+ */
+// $Id: record.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Record
- * 
+ *
  * Extends: <Jx.Object>
- * 
+ *
  * This class is used as a representation (or container) for a single row
- * of data in a <Jx.Store>. It is not usually directly instantiated by the 
+ * of data in a <Jx.Store>. It is not usually directly instantiated by the
  * developer but rather by the store itself.
  *
- * License: 
+ * License:
  * Copyright (c) 2009, Jon Bomgardner.
- * 
+ *
  * This file is licensed under an MIT style license
  */
 Jx.Record = new Class({
-    
+
     Extends: Jx.Object,
     Family: 'Jx.Record',
-    
+
     options: {
         /**
          * Option: separator
@@ -17769,7 +18042,7 @@
          * constructor (<Jx.Compare>) - defaults to '.'
          */
         separator : '.',
-        
+
         primaryKey: null
     },
     /**
@@ -17779,9 +18052,9 @@
     data: null,
     /**
      * Property: state
-     * used to determine the state of this record. When not null (meaning no 
+     * used to determine the state of this record. When not null (meaning no
      * changes were made) this should be one of
-     * 
+     *
      * - Jx.Record.UPDATE
      * - Jx.Record.DELETE
      * - Jx.Record.INSERT
@@ -17792,7 +18065,7 @@
      * Holds a reference to the columns for this record. These are usually
      * passed to the record from the store. This should be an array of objects
      * where the objects represent the columns. The object should take the form:
-     * 
+     *
      * (code)
      * {
      *     name: <column name>,
@@ -17800,37 +18073,37 @@
      *     ..additional options required by the record implementation...
      * }
      * (end)
-     * 
-     * The type of the column should be one of alphanumeric, numeric, date, 
+     *
+     * The type of the column should be one of alphanumeric, numeric, date,
      * boolean, or currency.
      */
     columns: null,
-    
+
     parameters: ['store', 'columns', 'data', 'options'],
-    
+
     init: function () {
         this.parent();
         if ($defined(this.options.columns)) {
             this.columns = this.options.columns;
         }
-        
+
         if ($defined(this.options.data)) {
             this.processData(this.options.data);
         } else {
             this.data = new Hash();
         }
-        
+
         if ($defined(this.options.store)) {
             this.store = this.options.store;
         }
-            
+
     },
     /**
      * APIMethod: get
      * returns the value of the requested column. Can be programmed to handle
      * pseudo-columns (such as the primaryKey column implemented in this base
      * record).
-     * 
+     *
      * Parameters:
      * column - the string, index, or object of the requested column
      */
@@ -17851,37 +18124,38 @@
     },
     /**
      * APIMethod: set
-     * Sets a given value into the requested column. 
-     * 
+     * Sets a given value into the requested column.
+     *
      *  Parameters:
      *  column - the object, index, or string name of the target column
      *  data - the data to add to the column
      */
     set: function (column, data) {
-        var type = Jx.type(column);
+        var type = Jx.type(column),
+            oldValue;
         if (type !== 'object') {
             column = this.resolveCol(column);
         }
-        
+
         if (!$defined(this.data)) {
             this.data = new Hash();
         }
-        
-        var oldValue = this.get(column);
+
+        oldValue = this.get(column);
         this.data.set(column.name, data);
         this.state = Jx.Record.UPDATE;
         return [column.name, oldValue, data];
         //this.store.fireEvent('storeColumnChanged', [this, column.name, oldValue, data]);
-            
+
     },
     /**
      * APIMethod: equals
      * Compares the value of a particular column with a given value
-     * 
+     *
      * Parameters:
      * column - the column to compare with (either column name or index)
      * value - the value to compare to.
-     * 
+     *
      * Returns:
      * True | False depending on the outcome of the comparison.
      */
@@ -17905,26 +18179,26 @@
     },
     /**
      * Method: processData
-     * This method takes the data passed in and puts it into the form the 
+     * This method takes the data passed in and puts it into the form the
      * record needs it in. This default implementation does nothing but
      * assign the data to the data property but it can be overridden in
      * subclasses to massge the data in any way needed.
-     * 
+     *
      * Parameters:
      * data - the data to process
      */
     processData: function (data) {
         this.data = $H(data);
     },
-    
+
     /**
-     * Method: resolveCol 
+     * Method: resolveCol
      * Determines which column is being asked for and returns it.
-     * 
-     * Parameters: 
+     *
+     * Parameters:
      * col - a number referencing a column in the store
-     * 
-     * Returns: 
+     *
+     * Returns:
      * the column object referred to
      */
     resolveCol : function (col) {
@@ -17951,34 +18225,51 @@
 
 Jx.Record.UPDATE = 1;
 Jx.Record.DELETE = 2;
-Jx.Record.INSERT = 3;// $Id: store.js 898 2010-05-10 04:08:44Z jonlb at comcast.net $
+Jx.Record.INSERT = 3;/*
+---
+
+name: Jx.Store
+
+description: An implementation of a basic data store.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+ - Jx.Record
+
+provides: [Jx.Store]
+
+...
+ */
+// $Id: store.js 972 2010-08-25 17:56:46Z pagameba $
 /**
- * Class: Jx.Store 
- * 
+ * Class: Jx.Store
+ *
  * Extends: <Jx.Object>
- * 
+ *
  * This class is the  store. It keeps track of data. It
  * allows adding, deleting, iterating, sorting etc...
- * 
- * For the most part the store is pretty "dumb" meaning it 
+ *
+ * For the most part the store is pretty "dumb" meaning it
  * starts with very limited functionality. Actually, it can't
  * even load data by itself. Instead, it needs to have protocols,
  * strategies, and a record class passed to it that it can use.
- * 
+ *
  * Example:
  * (code)
  * (end)
  *
- * License: 
+ * License:
  * Copyright (c) 2009, Jon Bomgardner.
- * 
+ *
  * This file is licensed under an MIT style license
  */
 Jx.Store = new Class({
-    
+
     Family: 'Jx.Store',
     Extends: Jx.Object,
-    
+
     options: {
         /**
          * Option: id
@@ -17987,16 +18278,16 @@
         id : null,
         /**
          * Option: columns
-         * an array listing the columns of the store in order of their 
-         * appearance in the data object formatted as an object 
-         *      {name: 'column name', type: 'column type'} 
-         * where type can be one of alphanumeric, numeric, date, boolean, 
+         * an array listing the columns of the store in order of their
+         * appearance in the data object formatted as an object
+         *      {name: 'column name', type: 'column type'}
+         * where type can be one of alphanumeric, numeric, date, boolean,
          * or currency.
          */
-        columns : [], 
+        columns : [],
         /**
          * Option: protocol
-         * The protocol to use for communication in this store. The store 
+         * The protocol to use for communication in this store. The store
          * itself doesn't actually use it but it is accessed by the strategies
          * to do their work. This option is required and the store won't work
          * without it.
@@ -18006,8 +18297,8 @@
          * Option: strategies
          * This is an array of instantiated strategy objects that will work
          * on this store. They provide many services such as loading data,
-         * paging data, saving, and sorting (and anything else you may need 
-         * can be written). If none are passed in it will use the default 
+         * paging data, saving, and sorting (and anything else you may need
+         * can be written). If none are passed in it will use the default
          * Jx.Store.Strategy.Full
          */
         strategies: null,
@@ -18027,7 +18318,7 @@
             primaryKey: null
         }
     },
-    
+
     /**
      * Property: data
      * Holds the data for this store
@@ -18054,27 +18345,27 @@
      * Used to determine if the store is completely initialized.
      */
     ready: false,
-    
+
     /**
      * Method: init
      * initialize the store, should be called by sub-classes
      */
     init: function () {
         this.parent();
-        
+
         if ($defined(this.options.id)) {
             this.id = this.options.id;
-        } 
-        
+        }
+
         if (!$defined(this.options.protocol)) {
             this.ready = false;
             return;
         } else {
             this.protocol = this.options.protocol;
         }
-        
+
         this.strategies = new Hash();
-        
+
         if ($defined(this.options.strategies)) {
             this.options.strategies.each(function(strategy){
                 this.addStrategy(strategy);
@@ -18083,16 +18374,16 @@
             var strategy = new Jx.Store.Strategy.Full();
             this.addStrategy(strategy);
         }
-        
+
         if ($defined(this.options.record)) {
             this.record = this.options.record;
         } else {
             this.record = Jx.Record;
         }
-        
-        
+
+
     },
-    
+
     /**
      * Method: cleanup
      * avoid memory leaks when a store is destroyed, should be called
@@ -18110,7 +18401,7 @@
     /**
      * APIMethod: getStrategy
      * returns the named strategy if it is present, null otherwise.
-     * 
+     *
      * Parameters:
      * name - the name of the strategy we're looking for
      */
@@ -18122,9 +18413,9 @@
     },
     /**
      * APIMethod: addStrategy
-     * Allows the addition of strategies after store initialization. Handy to 
+     * Allows the addition of strategies after store initialization. Handy to
      * have if some other class needs a strategy that is not present.
-     * 
+     *
      * Parameters:
      * strategy - the strategy to add to the store
      */
@@ -18137,7 +18428,7 @@
      * APIMethod: load
      * used to load the store. It simply fires an event that the strategies
      * are listening for.
-     * 
+     *
      * Parameters:
      * params - a hash of parameters passed to the strategy for determining
      *     what records to load.
@@ -18154,12 +18445,12 @@
             this.data.empty();
         }
     },
-    
+
     /**
-     * APIMethod: hasNext 
+     * APIMethod: hasNext
      * Determines if there are more records past the current
      * one.
-     * 
+     *
      * Returns: true | false (Null if there's a problem)
      */
     hasNext : function () {
@@ -18170,10 +18461,10 @@
     },
 
     /**
-     * APIMethod: hasPrevious 
+     * APIMethod: hasPrevious
      * Determines if there are records before the current
      * one.
-     * 
+     *
      * Returns: true | false
      */
     hasPrevious : function () {
@@ -18184,10 +18475,10 @@
     },
 
     /**
-     * APIMethod: valid 
+     * APIMethod: valid
      * Tells us if the current index has any data (i.e. that the
      * index is valid).
-     * 
+     *
      * Returns: true | false
      */
     valid : function () {
@@ -18195,9 +18486,9 @@
     },
 
     /**
-     * APIMethod: next 
+     * APIMethod: next
      * Moves the store to the next record
-     * 
+     *
      * Returns: nothing | null if error
      */
     next : function () {
@@ -18214,11 +18505,11 @@
     },
 
     /**
-     * APIMethod: previous 
+     * APIMethod: previous
      * moves the store to the previous record
-     * 
+     *
      * Returns: nothing | null if error
-     * 
+     *
      */
     previous : function () {
         if ($defined(this.data)) {
@@ -18234,11 +18525,11 @@
     },
 
     /**
-     * APIMethod: first 
+     * APIMethod: first
      * Moves the store to the first record
-     * 
+     *
      * Returns: nothing | null if error
-     * 
+     *
      */
     first : function () {
         if ($defined(this.data)) {
@@ -18251,9 +18542,9 @@
     },
 
     /**
-     * APIMethod: last 
+     * APIMethod: last
      * Moves to the last record in the store
-     * 
+     *
      * Returns: nothing | null if error
      */
     last : function () {
@@ -18267,9 +18558,9 @@
     },
 
     /**
-     * APIMethod: count 
+     * APIMethod: count
      * Returns the number of records in the store
-     * 
+     *
      * Returns: an integer indicating the number of records in the store or null
      * if there's an error
      */
@@ -18281,9 +18572,9 @@
     },
 
     /**
-     * APIMethod: getPosition 
+     * APIMethod: getPosition
      * Tells us where we are in the store
-     * 
+     *
      * Returns: an integer indicating the position in the store or null if
      * there's an error
      */
@@ -18295,12 +18586,12 @@
     },
 
     /**
-     * APIMethod: moveTo 
+     * APIMethod: moveTo
      * Moves the index to a specific record in the store
-     * 
-     * Parameters: 
+     *
+     * Parameters:
      * index - the record to move to
-     * 
+     *
      * Returns: true - if successful false - if not successful null - on error
      */
     moveTo : function (index) {
@@ -18316,9 +18607,9 @@
     },
     /**
      * APIMethod: each
-     * allows iteration through the store's records. 
+     * allows iteration through the store's records.
      * NOTE: this function is untested
-     * 
+     *
      * Parameters:
      * fn - the function to execute for each record
      * bind - the scope of the function
@@ -18339,10 +18630,10 @@
     /**
      * APIMethod: get
      * gets the data for the specified column
-     * 
+     *
      * Parameters:
-     * column - indicator of the column to set. Either a string (the name of 
-     *          the column) or an integer (the index of the column in the 
+     * column - indicator of the column to set. Either a string (the name of
+     *          the column) or an integer (the index of the column in the
      *          record).
      * index - the index of the record in the internal array. Optional.
      *          defaults to the current index.
@@ -18356,10 +18647,10 @@
     /**
      * APIMethod: set
      * Sets the passed data for a particular column on the indicated record.
-     * 
+     *
      * Parameters:
-     * column - indicator of the column to set. Either a string (the name of 
-     *          the column) or an integer (the index of the column in the 
+     * column - indicator of the column to set. Either a string (the name of
+     *          the column) or an integer (the index of the column in the
      *          record).
      * data - the data to set in the column of the record
      * index - the index of the record in the internal array. Optional.
@@ -18386,11 +18677,11 @@
     /**
      * APIMethod: addRecord
      * Adds given data to the end of the current store.
-     * 
+     *
      * Parameters:
      * data - The data to use in creating a record. This should be in whatever
      *        form Jx.Store.Record, or the current subclass, needs it in.
-     * position - whether the record is added to the 'top' or 'bottom' of the 
+     * position - whether the record is added to the 'top' or 'bottom' of the
      *      store.
      * insert - flag whether this is an "insert"
      */
@@ -18398,13 +18689,11 @@
         if (!$defined(this.data)) {
             this.data = [];
         }
-        
+
         position = $defined(position)? position : 'bottom';
-        
-        var record;
-        if (data instanceof Jx.Record) {
-            record = data;
-        } else {
+
+        var record = data;
+        if (!(data instanceof Jx.Record)) {
             record = new (this.record)(this, this.options.columns, data, this.options.recordOptions);
         }
         if (insert) {
@@ -18424,15 +18713,15 @@
     /**
      * APIMethod: addRecords
      * Used to add multiple records to the store at one time.
-     * 
+     *
      * Parameters:
      * data - an array of data to add.
      * position - 'top' or 'bottom'. Indicates whether to add at the top or
      * the bottom of the store
      */
     addRecords: function (data, position) {
-        var def = $defined(data);
-        var type = Jx.type(data);
+        var def = $defined(data),
+            type = Jx.type(data);
         if (def && type === 'array') {
             this.fireEvent('storeBeginAddRecords', this);
             //if position is top, reverse the array or we'll add them in the
@@ -18448,11 +18737,11 @@
         }
         return false;
     },
-    
+
     /**
      * APIMethod: getRecord
      * Returns the record at the given index or the current store index
-     * 
+     *
      * Parameters:
      * index - the index from which to return the record. Optional. Defaults
      * to the current store index
@@ -18461,14 +18750,14 @@
         if (!$defined(index)) {
             index = this.index;
         }
-        
-        if (Jx.type(index) === 'number') {        
+
+        if (Jx.type(index) === 'number') {
             if ($defined(this.data) && $defined(this.data[index])) {
                 return this.data[index];
             }
         } else {
-            //Not sure what the point of this part is. It compares the 
-            //record to the index directly as if we passed in the record which 
+            //Not sure what the point of this part is. It compares the
+            //record to the index directly as if we passed in the record which
             //means we already have the record... huh???
             var r;
             this.data.each(function(record){
@@ -18484,10 +18773,10 @@
      * APIMethod: replaceRecord
      * Replaces the record at an existing index with a new record containing
      * the passed in data.
-     * 
+     *
      * Parameters:
      * data - the data to use in creating the new record
-     * index - the index at which to place the new record. Optional. 
+     * index - the index at which to place the new record. Optional.
      *          defaults to the current store index.
      */
     replace: function(data, index) {
@@ -18495,22 +18784,22 @@
             if (!$defined(index)) {
                 index = this.index;
             }
-            var record = new this.record(this.options.columns,data);
-            var oldRecord = this.data[index];
+            var record = new this.record(this.options.columns,data),
+            oldRecord = this.data[index];
             this.data[index] = record;
             this.fireEvent('storeRecordReplaced', [oldRecord, record]);
             return true;
-        } 
+        }
         return false;
     },
     /**
      * APIMethod: deleteRecord
      * Marks a record for deletion and removes it from the regular array of
-     * records. It adds it to a special holding array so it can be disposed 
+     * records. It adds it to a special holding array so it can be disposed
      * of later.
-     * 
+     *
      * Parameters:
-     * index - the index at which to place the new record. Optional. 
+     * index - the index at which to place the new record. Optional.
      *          defaults to the current store index.
      */
     deleteRecord: function(index) {
@@ -18526,12 +18815,12 @@
             this.deleted = [];
         }
         this.deleted.push(record);
-        this.fireEvent('storeRecordDeleted', [record, this]);
+        this.fireEvent('storeRecordDeleted', [this, record]);
     },
     /**
      * APIMethod: insertRecord
      * Shortcut to addRecord which facilitates marking a record as inserted.
-     * 
+     *
      * Parameters:
      * data - the data to use in creating this inserted record. Should be in
      *          whatever form the current implementation of Jx.Record needs
@@ -18541,7 +18830,7 @@
     insertRecord: function (data, position) {
         this.addRecord(data, position, true);
     },
-    
+
     /**
      * APIMethod: getColumns
      * Allows retrieving the columns array
@@ -18549,13 +18838,13 @@
     getColumns: function () {
         return this.options.columns;
     },
-    
+
     /**
      * APIMethod: findByColumn
      * Used to find a specific record by the value in a specific column. This
      * is particularly useful for finding records by a unique id column. The
      * search will stop on the first instance of the value
-     * 
+     *
      * Parameters:
      * column - the name (or index) of the column to search by
      * value - the value to look for
@@ -18585,8 +18874,8 @@
      * APIMethod: removeRecord
      * removes (but does not mark for deletion) a record at the given index
      * or the current store index if none is passed in.
-     * 
-     * Parameters: 
+     *
+     * Parameters:
      * index - Optional. The store index of the record to remove.
      */
     removeRecord: function (index) {
@@ -18598,8 +18887,8 @@
     },
     /**
      * APIMethod: removeRecords
-     * Used to remove multiple contiguous records from a store. 
-     * 
+     * Used to remove multiple contiguous records from a store.
+     *
      * Parameters:
      * first - where to start removing records (zero-based)
      * last - where to stop removing records (zero-based, inclusive)
@@ -18610,63 +18899,82 @@
         }
         this.fireEvent('storeMultipleRecordsRemoved', [this, first, last]);
     },
-    
+
     /**
-	 * APIMethod: parseTemplate
-	 * parses the provided template to determine which store columns are
-	 * required to complete it.
-	 *
-	 * Parameters:
-	 * template - the template to parse
-	 */
-	parseTemplate: function (template) {
-	    //we parse the template based on the columns in the data store looking
-	    //for the pattern {column-name}. If it's in there we add it to the
-	    //array of ones to look fo
-	    var arr = [];
-	    this.options.columns.each(function (col) {
-	        var s = '{' + col.name + '}';
-	        if (template.contains(s)) {
-	            arr.push(col.name);
-	        }
-	    }, this);
-	    return arr;
-	},
-	
-	/**
-	 * APIMethod: fillTemplate
-	 * Actually does the work of getting the data from the store
-	 * and creating a single item based on the provided template
-	 * 
-	 * Parameters: 
-	 * index - the index of the data in the store to use in populating the
-	 *          template.
-	 * template - the template to fill
-	 * columnsNeeded - the array of columns needed by this template. should be 
-	 * 			obtained by calling parseTemplate().
+   * APIMethod: parseTemplate
+   * parses the provided template to determine which store columns are
+   * required to complete it.
+   *
+   * Parameters:
+   * template - the template to parse
+   */
+  parseTemplate: function (template) {
+      //we parse the template based on the columns in the data store looking
+      //for the pattern {column-name}. If it's in there we add it to the
+      //array of ones to look fo
+      var arr = [],
+          s;
+      this.options.columns.each(function (col) {
+          s = '{' + col.name + '}';
+          if (template.contains(s)) {
+              arr.push(col.name);
+          }
+      }, this);
+      return arr;
+  },
+
+  /**
+   * APIMethod: fillTemplate
+   * Actually does the work of getting the data from the store
+   * and creating a single item based on the provided template
+   *
+   * Parameters:
+   * index - the index of the data in the store to use in populating the
+   *          template.
+   * template - the template to fill
+   * columnsNeeded - the array of columns needed by this template. should be
+   *      obtained by calling parseTemplate().
      * obj - an object with some prefilled keys to use in substituting.
      *      Ones that are also in the store will be overwritten.
-	 */
-	fillTemplate: function (index, template, columnsNeeded, obj) {
-        var record = null;
-		if ($defined(index)) {
-            if (index instanceof Jx.Record) {
-                record = index;
-            } else {
-                record = this.getRecord(index);
-            }
+   */
+  fillTemplate: function (index, template, columnsNeeded, obj) {
+      var record = null,
+          itemObj;
+      if ($defined(index)) {
+          if (index instanceof Jx.Record) {
+              record = index;
+          } else {
+              record = this.getRecord(index);
+          }
         } else {
             record = this.getRecord(this.index);
         }
-		
-	    //create the item
-	    var itemObj = $defined(obj) ? obj : {};
-	    columnsNeeded.each(function (col) {
-	        itemObj[col] = record.get(col);
-	    }, this);
-	    return template.substitute(itemObj);
-	}
-});// $Id: compare.js 855 2010-04-20 06:04:53Z jonlb at comcast.net $
+
+      //create the item
+      itemObj = $defined(obj) ? obj : {};
+      columnsNeeded.each(function (col) {
+          itemObj[col] = record.get(col);
+      }, this);
+      return template.substitute(itemObj);
+  }
+});/*
+---
+
+name: Jx.Compare
+
+description: Class that provides functions for comparing various data types. Used by the Jx.Sort class and it's descendants
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+ - More/Date.Extras
+
+provides: [Jx.Compare]
+
+...
+ */
+// $Id: compare.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Compare
  *
@@ -18779,8 +19087,8 @@
      * b - another date value
      */
     date: function (a, b) {
-        var x = new Date().parse(a);
-        var y = new Date().parse(b);
+        var x = new Date().parse(a),
+            y = new Date().parse(b);
         return (x < y) ? -1 : (x > y) ? 1 : 0;
     },
     /**
@@ -18795,9 +19103,27 @@
         return (a === true && b === false) ? -1 : (a === b) ? 0 : 1;
     }
 
-});// $Id: sort.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Sort
+
+description: Base class for the sort algorithm implementations
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+ - Jx.Compare
+
+provides: [Jx.Sort]
+
+...
+ */
+// $Id: sort.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
- * Class: Jx.Sort Base class for all of the sorting algorithm classes.
+ * Class: Jx.Sort
+ * Base class for all of the sorting algorithm classes.
  *
  * Extends: <Jx.Object>
  *
@@ -18933,7 +19259,23 @@
         this.comparator = fn;
     }
 });
-// $Id: mergesort.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Sort.Mergesort
+
+description: An implementation of the merge sort algorithm
+
+license: MIT-style license.
+
+requires:
+ - Jx.Sort
+
+provides: [Jx.Sort.Mergesort]
+
+...
+ */
+// $Id: mergesort.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * class: Jx.Sort.Mergesort
  *
@@ -18986,12 +19328,13 @@
             return arr;
         }
 
-        var middle = (arr.length) / 2;
-        var left = arr.slice(0, middle);
-        var right = arr.slice(middle);
+        var middle = (arr.length) / 2,
+            left = arr.slice(0, middle),
+            right = arr.slice(middle),
+            result;
         left = this.mergeSort(left);
         right = this.mergeSort(right);
-        var result = this.merge(left, right);
+        result = this.merge(left, right);
         return result;
     },
 
@@ -19030,7 +19373,23 @@
     }
 
 });
-// $Id: heapsort.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Sort.Heapsort
+
+description: An implementation of the heap sort algorithm
+
+license: MIT-style license.
+
+requires:
+ - Jx.Sort
+
+provides: [Jx.Sort.Heapsort]
+
+...
+ */
+// $Id: heapsort.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Sort.Heapsort
  *
@@ -19064,7 +19423,8 @@
     sort : function () {
         this.fireEvent('start');
 
-        var count = this.data.length;
+        var count = this.data.length,
+            end;
 
         if (count === 1) {
             return this.data;
@@ -19073,7 +19433,7 @@
         if (count > 2) {
             this.heapify(count);
 
-            var end = count - 1;
+            end = count - 1;
             while (end > 1) {
                 this.data.swap(end, 0);
                 end = end - 1;
@@ -19113,10 +19473,11 @@
      * sort range
      */
     siftDown : function (start, end) {
-        var root = start;
+        var root = start,
+            child;
 
         while (root * 2 <= end) {
-            var child = root * 2;
+            child = root * 2;
             if ((child + 1 < end) && (this.comparator((this.data[child]).get(this.col),
                             (this.data[child + 1]).get(this.col)) < 0)) {
                 child = child + 1;
@@ -19132,7 +19493,23 @@
     }
 
 });
-// $Id: quicksort.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Sort.Quicksort
+
+description: An implementation of the quick sort algorithm.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Sort
+
+provides: [Jx.Sort.Quicksort]
+
+...
+ */
+// $Id: quicksort.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Sort.Quicksort
  *
@@ -19208,10 +19585,10 @@
      */
     partition : function (left, right) {
         this.findMedianOfMedians(left, right);
-        var pivotIndex = left;
-        var pivotValue = (this.data[pivotIndex]).get(this.col);
-        var index = left;
-        var i;
+        var pivotIndex = left,
+            pivotValue = (this.data[pivotIndex]).get(this.col),
+            index = left,
+            i;
 
         this.data.swap(pivotIndex, right);
         for (i = left; i < right; i++) {
@@ -19239,12 +19616,14 @@
             return this.data[left];
         }
 
-        var i;
-        var shift = 1;
+        var i,
+            shift = 1,
+            endIndex,
+            medianIndex;
         while (shift <= (right - left)) {
             for (i = left; i <= right; i += shift * 5) {
-                var endIndex = (i + shift * 5 - 1 < right) ? i + shift * 5 - 1 : right;
-                var medianIndex = this.findMedianIndex(i, endIndex,
+                endIndex = (i + shift * 5 - 1 < right) ? i + shift * 5 - 1 : right;
+                medianIndex = this.findMedianIndex(i, endIndex,
                         shift);
 
                 this.data.swap(i, medianIndex);
@@ -19263,17 +19642,22 @@
      * right - the right hand, or upper, bound of the sort
      */
     findMedianIndex : function (left, right, shift) {
-        var groups = Math.round((right - left) / shift + 1);
-        var k = Math.round(left + groups / 2 * shift);
+        var groups = Math.round((right - left) / shift + 1),
+            k = Math.round(left + groups / 2 * shift),
+            i,
+            minIndex,
+            v,
+            minValue,
+            j;
         if (k > this.data.length - 1) {
             k = this.data.length - 1;
         }
-        for (var i = left; i < k; i += shift) {
-            var minIndex = i;
-            var v = this.data[minIndex];
-            var minValue = v.get(this.col);
+        for (i = left; i < k; i += shift) {
+            minIndex = i;
+            v = this.data[minIndex];
+            minValue = v.get(this.col);
 
-            for (var j = i; j <= right; j += shift) {
+            for (j = i; j <= right; j += shift) {
                 if (this.comparator((this.data[j]).get(this.col),
                         minValue) < 0) {
                     minIndex = j;
@@ -19286,7 +19670,23 @@
         return k;
     }
 });
-// $Id: nativesort.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Sort.Nativesort
+
+description: An implementation of the Javascript native sorting with the Jx.Sort interface
+
+license: MIT-style license.
+
+requires:
+ - Jx.Sort
+
+provides: [Jx.Sort.Nativesort]
+
+...
+ */
+// $Id: nativesort.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Sort.Nativesort
  *
@@ -19331,7 +19731,23 @@
     }
 
 });
-// $Id: response.js 898 2010-05-10 04:08:44Z jonlb at comcast.net $
+/*
+---
+
+name: Jx.Store.Response
+
+description: The object used to return response information to strategies.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store
+
+provides: [Jx.Store.Response]
+
+...
+ */
+// $Id: response.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Store.Response
  * 
@@ -19398,48 +19814,64 @@
 Jx.Store.Response.WAITING = 2;
 Jx.Store.Response.SUCCESS = 1;
 Jx.Store.Response.FAILURE = 0;
-// $Id: protocol.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Store.Protocol
+
+description: Base class for all store protocols.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Response
+
+provides: [Jx.Store.Protocol]
+
+...
+ */
+// $Id: protocol.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Store.Protocol
- * 
+ *
  * Extends: <Jx.Object>
- * 
+ *
  * Base class for all protocols. Protocols are used for communication, primarily,
  * in Jx.Store. It may be possible to adapt them to be used in other places but
  * that is not their intended function.
  *
- * License: 
+ * License:
  * Copyright (c) 2009, Jon Bomgardner.
- * 
+ *
  * This file is licensed under an MIT style license
  */
 Jx.Store.Protocol = new Class({
-    
+
     Extends: Jx.Object,
     Family: 'Jx.Store.Protocol',
-    
+
     parser: null,
-    
+
     options: {},
-    
+
     init: function () {
         this.parent();
-        
+
         if ($defined(this.options.parser)) {
             this.parser = this.options.parser;
         }
     },
-    
+
     cleanup: function () {
         this.parser = null;
         this.parent();
     },
-    
+
     /**
      * APIMethod: read
      * Supports reading data from a location. Abstract method that subclasses
      * should implement.
-     * 
+     *
      * Parameters:
      * options - optional options for configuring the request
      */
@@ -19448,7 +19880,7 @@
      * APIMethod: insert
      * Supports inserting data from a location. Abstract method that subclasses
      * should implement.
-     * 
+     *
      * Parameters:
      * data - the data to use in creating the record in the form of one or more
      *        Jx.Store.Record instances
@@ -19459,7 +19891,7 @@
      * APIMethod: update
      * Supports updating data at a location. Abstract method that subclasses
      * should implement.
-     * 
+     *
      * Parameters:
      * data - the data to update (one or more Jx.Store.Record objects)
      * options - optional options for configuring the request
@@ -19469,7 +19901,7 @@
      * APIMethod: delete
      * Supports deleting data from a location. Abstract method that subclasses
      * should implement.
-     * 
+     *
      * Parameters:
      * data - the data to update (one or more Jx.Store.Record objects)
      * options - optional options for configuring the request
@@ -19481,7 +19913,23 @@
      * that subclasses should implement.
      */
     abort: $empty
-});// $Id: protocol.local.js 834 2010-04-05 18:17:01Z jonlb at comcast.net $
+});/*
+---
+
+name: Jx.Store.Protocol.Local
+
+description: Store protocol used to load data that is already present in a page as an object.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Protocol
+
+provides: [Jx.Store.Protocol.Local]
+
+...
+ */
+// $Id: protocol.local.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Store.Protocol.Local
  * 
@@ -19527,27 +19975,31 @@
      * options - options to use in processing the request.
      */
     read: function (options) {
-        var resp = new Jx.Store.Response();
+        var resp = new Jx.Store.Response(),
+            page = options.data.page,
+            itemsPerPage = options.data.itemsPerPage,
+            start,
+            end,
+            data = this.data;
+
         resp.requestType = 'read';
         resp.requestParams = arguments;
         
-        var page = options.data.page;
-        var itemsPerPage = options.data.itemsPerPage;
         
-        if ($defined(this.data)) {
+        if ($defined(data)) {
             if (page <= 1 && itemsPerPage === -1) {
                 //send them all
-                resp.data = this.data;
-                resp.meta = { count: this.data.length };
+                resp.data = data;
+                resp.meta = { count: data.length };
             } else {
-                var start = (page - 1) * itemsPerPage;
-                var end = start + itemsPerPage;
-                resp.data = this.data.slice(start, end);
+                start = (page - 1) * itemsPerPage;
+                end = start + itemsPerPage;
+                resp.data = data.slice(start, end);
                 resp.meta = { 
                     page: page, 
                     itemsPerPage: itemsPerPage,
-                    totalItems: this.data.length,
-                    totalPages: Math.ceil(this.data.length/itemsPerPage)
+                    totalItems: data.length,
+                    totalPages: Math.ceil(data.length/itemsPerPage)
                 };
             }
             resp.code = Jx.Store.Response.SUCCESS;
@@ -19567,24 +20019,40 @@
      * - commit
      * - abort
      */
-});// $Id: protocol.ajax.js 898 2010-05-10 04:08:44Z jonlb at comcast.net $
+});/*
+---
+
+name: Jx.Store.Protocol.Ajax
+
+description: Store protocol used to load data from a remote data source via Ajax.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Protocol
+
+provides: [Jx.Store.Protocol.Ajax]
+
+...
+ */
+// $Id: protocol.ajax.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Store.Protocol.Ajax
- * 
+ *
  * Extends: <Jx.Store.Protocol>
- * 
+ *
  * This protocol is used to send and receive data via AJAX. It also has the
  * capability to use a REST-style API.
  *
- * License: 
+ * License:
  * Copyright (c) 2009, Jon Bomgardner.
- * 
+ *
  * This file is licensed under an MIT style license
  */
 Jx.Store.Protocol.Ajax = new Class({
-    
+
     Extends: Jx.Store.Protocol,
-    
+
     options: {
         /**
          * Option: requestOptions
@@ -19601,7 +20069,7 @@
         rest: false,
         /**
          * Option: urls
-         * This is a hash of the urls to use for each method. If the rest 
+         * This is a hash of the urls to use for each method. If the rest
          * option is set to true the only one needed will be the urls.rest.
          * These can be overridden if needed by passing an options object into
          * the various methods with the appropriate urls.
@@ -19614,57 +20082,57 @@
             'delete': null
         }
     },
-    
+
     init: function() {
         this.parent();
     },
     /**
      * APIMethod: read
      * Send a read request via AJAX
-     * 
+     *
      * Parameters:
      * options - the options to pass to the request.
      */
     read: function (options) {
-        var resp = new Jx.Store.Response();
+        var resp = new Jx.Store.Response(),
+            temp = {},
+            opts,
+            req;
         resp.requestType = 'read';
         resp.requestParams = arguments;
-        
-        var req = new Request({
-            onSuccess: this.handleResponse.bind(this, resp)
-        });
-        
-        resp.request = req;
-        var temp = {};
+
+
+        // set up options
         if (this.options.rest) {
             temp.url = this.options.urls.rest;
         } else {
             temp.url = this.options.urls.read;
         }
-        
-        //set up options
-        var opts = $merge(this.options.requestOptions, temp, options);
-        
-        req.send(opts);
-        
+
+        opts = $merge(this.options.requestOptions, temp, options);
+        opts.onSuccess = this.handleResponse.bind(this,resp);
+
+        req = new Request(opts);
+        resp.request = req;
+        req.send();
+
         resp.code = Jx.Store.Response.WAITING;
-        
+
         return resp;
-        
+
     },
     /**
      * Method: handleResponse
      * Called as an event handler for a returning request. Parses the request's
      * response into the actual response object.
-     * 
-     * Parameters: 
+     *
+     * Parameters:
      * response - the response related to teh returning request.
      */
     handleResponse: function (response) {
-        var req = response.request;
-        var str = req.xhr.responseText;
-        
-        var data = this.parser.parse(str);
+        var req = response.request,
+            str = req.xhr.responseText,
+            data = this.parser.parse(str);
         if ($defined(data)) {
             if ($defined(data.success) && data.success) {
                 if ($defined(data.data)) {
@@ -19686,7 +20154,7 @@
     /**
      * APIMethod: insert
      * Takes a Jx.Record instance and saves it
-     * 
+     *
      * Parameters:
      * record - a Jx.Store.Record or array of them
      * options - options to pass to the request
@@ -19703,7 +20171,7 @@
     /**
      * APIMethod: update
      * Takes a Jx.Record and updates it via AJAX
-     * 
+     *
      * Parameters:
      * record - a Jx.Record instance
      * options - Options to pass to the request
@@ -19721,7 +20189,7 @@
     /**
      * APIMethod: delete
      * Takes a Jx.Record and deletes it via AJAX
-     * 
+     *
      * Parameters:
      * record - a Jx.Record instance
      * options - Options to pass to the request
@@ -19739,50 +20207,67 @@
     /**
      * APIMethod: abort
      * aborts the request related to the passed in response.
-     * 
+     *
      * Parameters:
      * response - the response with the request to abort
      */
     abort: function (response) {
         response.request.cancel();
-        
+
     },
     /**
      * Method: run
      * called by update, delete, and insert methods that actually does the work
      * of kicking off the request.
-     * 
+     *
      * Parameters:
      * record - The Jx.Record to work with
      * options - Options to pass to the request
      * method - The name of the method calling this function
      */
     run: function (record, options, method) {
+        var resp = new Jx.Store.Response(),
+            opts,
+            req;
         
-        this.options.requestOptions.data = {
-            data: this.parser.encode(record)
-        };
-        
-        var resp = new Jx.Store.Response();
+        this.options.requestOptions.data = $merge(this.options.requestOptions.data, {
+          data: this.parser.encode(record)
+        });
+
         resp.requestType = method;
         resp.requestParams = [record, options, method];
-        
-        var req = new Request({
-            onSuccess: this.handleResponse.bind(this, resp)
-        });
-        
+
         //set up options
-        var opts = $merge(this.options.requestOptions, options);
-        
-        req.send(opts);
-        
+        opts = $merge(this.options.requestOptions, options);
+        opts.onSuccess = this.handleResponse.bind(this,resp);
+
+        req = new Request(opts);
+        resp.request = req;
+        req.send();
+
         resp.code = Jx.Store.Response.WAITING;
-        resp.request = req;
-        
+
         return resp;
     }
-    
-});// $Id: strategy.js 776 2010-03-22 14:35:16Z pagameba $
+
+});/*
+---
+
+name: Jx.Store.Strategy
+
+description: Base class for all store strategies.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store
+
+provides: [Jx.Store.Strategy]
+
+
+...
+ */
+// $Id: strategy.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Store.Strategy
  * 
@@ -19852,7 +20337,23 @@
         }
         return false;
     }
-});// $Id: strategy.full.js 912 2010-05-21 21:33:08Z pagameba $
+});/*
+---
+
+name: Jx.Store.Strategy.Full
+
+description: Strategy for loading the full data set from a source.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Strategy
+
+provides: [Jx.Store.Strategy.Full]
+
+...
+ */
+// $Id: strategy.full.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Store.Strategy.Full
  * 
@@ -19963,7 +20464,24 @@
             this.store.options.recordOptions.primaryKey = meta.primaryKey;
         }
     }
-});// $Id: strategy.paginate.js 912 2010-05-21 21:33:08Z pagameba $
+});/*
+---
+
+name: Jx.Store.Strategy.Paginate
+
+description: Strategy for loading data in pages and moving between them. This strategy makes sure the store only contains the current page's data.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Strategy
+
+provides: [Jx.Store.Strategy.Paginate]
+
+
+...
+ */
+// $Id: strategy.paginate.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Store.Strategy.Paginate
  * 
@@ -20252,7 +20770,23 @@
     getTotalCount: function () {
         return this.totalItems;
     }
-});/**
+});/*
+---
+
+name: Jx.Store.Strategy.Progressive
+
+description: Strategy based on Strategy.Paginate but loads data progressively without removing old or curent data from the store.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Strategy.Paginate
+
+provides: [Jx.Store.Strategy.Progressive]
+
+...
+ */
+/**
  * Class: Jx.Store.Strategy.Progressive
  *
  * Extends: <Jx.Store.Strategy.Paginate>
@@ -20405,7 +20939,23 @@
             this.load($merge(this.params, params));
         }
     }
-});// $Id: strategy.save.js 912 2010-05-21 21:33:08Z pagameba $
+});/*
+---
+
+name: Jx.Store.Strategy.Save
+
+description: Strategy used for saving data back to a source. Can be called manually or setup to automatically save on every change.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Strategy
+
+provides: [Jx.Store.Strategy.Save]
+
+...
+ */
+// $Id: strategy.save.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Store.Strategy.Save 
  * 
@@ -20455,9 +21005,10 @@
      * initialize this strategy
      */
     init: function () {
+        this.bound.save = this.saveRecord.bind(this);
+        this.bound.update = this.updateRecord.bind(this);
+        this.bound.completed = this.onComplete.bind(this);
         this.parent();
-        this.bound.saveRecord = this.saveRecord.bind(this);
-        this.bound.onComplete = this.onComplete.bind(this);
     },
     
     /**
@@ -20470,7 +21021,7 @@
             this.periodicalId = this.save.periodical(this.options.autoSave, this);
         } else if (this.options.autoSave) {
             this.store.addEvent('storeRecordAdded', this.bound.save);
-            this.store.addEvent('storeColumnChanged', this.bound.save);
+            this.store.addEvent('storeColumnChanged', this.bound.update);
             this.store.addEvent('storeRecordDeleted', this.bound.save);
         }
         
@@ -20486,16 +21037,33 @@
             $clear(this.periodicalId);
         } else if (this.options.autoSave) {
             this.store.removeEvent('storeRecordAdded', this.bound.save);
-            this.store.removeEvent('storeColumnChanged', this.bound.save);
+            this.store.removeEvent('storeColumnChanged', this.bound.update);
             this.store.removeEvent('storeRecordDeleted', this.bound.save);
         }
         
     },
     
     /**
+     * APIMethod: updateRecord
+     * called by event handlers when store data is updated
+     *
+     * Parameters:
+     * index - {Integer} the row that was affected
+     * column - {String} the column that was affected
+     * oldValue - {Mixed} the previous value
+     * newValue - {Mixed} the new value
+     */
+    updateRecord: function(index, column, oldValue, newValue) {
+      var resp = this.saveRecord(this.store, this.store.getRecord(index));
+      // no response if updating or record state not set
+      if (resp) {
+        resp.index = index;
+      }
+    },
+    /**
      * APIMethod: saveRecord
-     * Called by event handlers when store data is changed, updated, or
-     * deleted. If deleted, the record will be removed from the deleted array.
+     * Called by event handlers when a store record is added, or deleted. 
+     * If deleted, the record will be removed from the deleted array.
      * 
      * Parameters:
      * record - The Jx.Record instance that was changed
@@ -20574,12 +21142,16 @@
             if (response.requestType === 'delete') {
                 this.store.deleted.erase(record);
             } else { 
-                if (response.requestType === 'insert') {
+                if (response.requestType === 'insert' || response.requestType == 'update') {
                     if ($defined(response.data)) {
                         this.updating = true;
                         $H(response.data).each(function (val, key) {
-                            record.set(key, val);
-                        }, this);
+                            var d = record.set(key, val);
+                            if (d[1] != val && $defined(response.index)) {
+                              d.unshift(response.index);
+                              record.store.fireEvent('storeColumnChanged', d);
+                            }
+                        });
                         this.updating = false;
                     }
                 }
@@ -20596,7 +21168,24 @@
             });
         }
     }
-});// $Id: strategy.sort.js 912 2010-05-21 21:33:08Z pagameba $
+});/*
+---
+
+name: Jx.Store.Strategy.Sort
+
+description: Strategy used for sorting results in a store after they are loaded.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Strategy
+ - Jx.Sort.Mergesort
+ - Jx.Compare
+
+provides: [Jx.Store.Strategy.Sort]
+...
+ */
+// $Id: strategy.sort.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Store.Strategy.Sort
  * 
@@ -20859,7 +21448,23 @@
         }
         return col;   
     }
-});// $Id: parser.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Store.Parser
+
+description: Base class for all data parsers. Parsers are used by protocols to get data received or sent in the proper formats.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store
+
+provides: [Jx.Store.Parser]
+
+...
+ */
+// $Id: parser.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Store.Parser
  * 
@@ -20896,27 +21501,44 @@
      * object - an object to encode
      */
     encode: $empty
-});// $Id: parser.json.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Store.Parser.JSON
+
+description: Parser for reading and writting JSON formatted data.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Store.Parser
+ - Core/JSON
+
+provides: [Jx.Store.Parser.JSON]
+
+...
+ */
+// $Id: parser.json.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Store.Parser.JSON
- * 
+ *
  * Extends: <Jx.Store.Parser>
- * 
+ *
  * A Parser that handles encoding and decoding JSON strings
  *
- * License: 
+ * License:
  * Copyright (c) 2009, Jon Bomgardner.
- * 
+ *
  * This file is licensed under an MIT style license
  */
 Jx.Store.Parser.JSON = new Class({
-    
+
     Extends: Jx.Store.Parser,
-    
+
     options: {
         /**
          * Option: secure
-         * Whether to use secure decoding. When using secure decoding the 
+         * Whether to use secure decoding. When using secure decoding the
          * parser will return null if any invalid JSON characters are in the
          * passed in string. Defaults to false.
          */
@@ -20925,25 +21547,25 @@
     /**
      * APIMethod: parse
      * Turns a string into a JSON object if possible.
-     * 
+     *
      * Parameters:
      * data - the string representation of the data we're parsing
      */
     parse: function (data) {
         var type = Jx.type(data);
-        
+
         if (type === 'string') {
             return JSON.decode(data, this.options.secure);
         }
         //otherwise just return the data object
         return data;
     },
-    
+
     /**
      * APIMethod: encode
      * Takes an object and turns it into JSON.
-     * 
-     * Parameters: 
+     *
+     * Parameters:
      * object - the object to encode
      */
     encode: function (object) {
@@ -20953,10 +21575,35 @@
         } else {
             data = object;
         }
-            
+
         return JSON.encode(data);
     }
-});// $Id: button.js 912 2010-05-21 21:33:08Z pagameba $
+});/*
+---
+
+name: Jx.Button
+
+description: Jx.Button creates a clickable element that can be added to a web page.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+
+optional:
+ - Core/Drag
+
+provides: [Jx.Button]
+
+css:
+ - button
+
+images:
+ - button.png
+
+...
+ */
+// $Id: button.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Button
  *
@@ -21077,6 +21724,10 @@
          * Default is javascript:void(0) and use onClick.
          */
         href: 'javascript:void(0);',
+        /* Option: target
+         * for buttons that have an href, allow setting the target
+         */
+        target: '',
         /* Option: template
          * the HTML structure of the button.  As a minimum, there must be a
          * containing element with a class of jxButtonContainer and an
@@ -21105,50 +21756,51 @@
      */
     render: function() {
         this.parent();
-
+        var options = this.options,
+            hasFocus,
+            mouseDown;
         /* is the button toggle-able? */
-        if (this.options.toggle) {
-            this.domObj.addClass(this.options.toggleClass);
+        if (options.toggle) {
+            this.domObj.addClass(options.toggleClass);
         }
 
         // the clickable part of the button
         if (this.domA) {
-            var hasFocus;
-            var mouseDown;
             this.domA.set({
-                href: this.options.href,
-                title: this.getText(this.options.tooltip),
-                alt: this.getText(this.options.tooltip)
+                target: options.target,
+                href: options.href,
+                title: this.getText(options.tooltip),
+                alt: this.getText(options.tooltip)
             });
             this.domA.addEvents({
                 click: this.clicked.bindWithEvent(this),
                 drag: (function(e) {e.stop();}).bindWithEvent(this),
                 mousedown: (function(e) {
-                    this.domA.addClass(this.options.pressedClass);
+                    this.domA.addClass(options.pressedClass);
                     hasFocus = true;
                     mouseDown = true;
                     this.focus();
                 }).bindWithEvent(this),
                 mouseup: (function(e) {
-                    this.domA.removeClass(this.options.pressedClass);
+                    this.domA.removeClass(options.pressedClass);
                     mouseDown = false;
                 }).bindWithEvent(this),
                 mouseleave: (function(e) {
-                    this.domA.removeClass(this.options.pressedClass);
+                    this.domA.removeClass(options.pressedClass);
                 }).bindWithEvent(this),
                 mouseenter: (function(e) {
                     if (hasFocus && mouseDown) {
-                        this.domA.addClass(this.options.pressedClass);
+                        this.domA.addClass(options.pressedClass);
                     }
                 }).bindWithEvent(this),
                 keydown: (function(e) {
                     if (e.key == 'enter') {
-                        this.domA.addClass(this.options.pressedClass);
+                        this.domA.addClass(options.pressedClass);
                     }
                 }).bindWithEvent(this),
                 keyup: (function(e) {
                     if (e.key == 'enter') {
-                        this.domA.removeClass(this.options.pressedClass);
+                        this.domA.removeClass(options.pressedClass);
                     }
                 }).bindWithEvent(this),
                 blur: function() { hasFocus = false; }
@@ -21162,16 +21814,16 @@
         }
 
         if (this.domImg) {
-            if (this.options.image || !this.options.label) {
+            if (options.image || !options.label) {
                 this.domImg.set({
-                    title: this.getText(this.options.tooltip),
-                    alt: this.getText(this.options.tooltip)
+                    title: this.getText(options.tooltip),
+                    alt: this.getText(options.tooltip)
                 });
-                if (this.options.image && this.options.image.indexOf(Jx.aPixel.src) == -1) {
-                    this.domImg.setStyle('backgroundImage',"url("+this.options.image+")");
+                if (options.image && options.image.indexOf(Jx.aPixel.src) == -1) {
+                    this.domImg.setStyle('backgroundImage',"url("+options.image+")");
                 }
-                if (this.options.imageClass) {
-                    this.domImg.addClass(this.options.imageClass);
+                if (options.imageClass) {
+                    this.domImg.addClass(options.imageClass);
                 }
             } else {
                 //remove the image if we don't need it
@@ -21180,24 +21832,24 @@
         }
 
         if (this.domLabel) {
-            if (this.options.label || this.domA.hasClass('jxDiscloser')) {
-                this.setLabel(this.options.label);
+            if (options.label || this.domA.hasClass('jxDiscloser')) {
+                this.setLabel(options.label);
             } else {
                 //this.domLabel.removeClass('jx'+this.type+'Label');
                 this.domLabel.setStyle('display','none');
             }
         }
 
-        if (this.options.id) {
-            this.domObj.set('id', this.options.id);
+        if (options.id) {
+            this.domObj.set('id', options.id);
         }
 
         //update the enabled state
-        this.setEnabled(this.options.enabled);
+        this.setEnabled(options.enabled);
 
         //update the active state if necessary
-        if (this.options.active) {
-            this.options.active = false;
+        if (options.active) {
+            options.active = false;
             this.setActive(true);
         }
     },
@@ -21210,9 +21862,10 @@
      * evt - {Event} the user click event
      */
     clicked : function(evt) {
-        if (this.options.enabled && !this.isBusy()) {
-            if (this.options.toggle) {
-                this.setActive(!this.options.active);
+        var options = this.options;
+        if (options.enabled && !this.isBusy()) {
+            if (options.toggle) {
+                this.setActive(!options.active);
             } else {
                 this.fireEvent('click', {obj: this, event: evt});
             }
@@ -21239,7 +21892,7 @@
      */
     setEnabled: function(enabled) {
         this.options.enabled = enabled;
-        if (this.options.enabled) {
+        if (enabled) {
             this.domObj.removeClass('jxDisabled');
         } else {
             this.domObj.addClass('jxDisabled');
@@ -21264,16 +21917,17 @@
      * active - {Boolean} the new active state of the button
      */
     setActive: function(active) {
-        if (this.options.enabled && !this.isBusy()) {
-          if (this.options.active == active) {
+        var options = this.options;
+        if (options.enabled && !this.isBusy()) {
+          if (options.active == active) {
               return;
           }
-          this.options.active = active;
+          options.active = active;
           if (this.domA) {
-              if (this.options.active) {
-                  this.domA.addClass(this.options.activeClass);
+              if (options.active) {
+                  this.domA.addClass(options.activeClass);
               } else {
-                  this.domA.removeClass(this.options.activeClass);
+                  this.domA.removeClass(options.activeClass);
               }
           }
           this.fireEvent(active ? 'down':'up', this);
@@ -21290,7 +21944,7 @@
         this.options.image = path;
         if (this.domImg) {
             this.domImg.setStyle('backgroundImage',
-                                 "url("+this.options.image+")");
+                                 "url("+path+")");
             this.domImg.setStyle('display', path ? null : 'none');
         }
     },
@@ -21373,20 +22027,40 @@
         this.setTooltip(this.options.tooltip);
     }
 });
-// $Id: flyout.js 924 2010-05-26 16:03:06Z conrad.barthelmes $
+/*
+---
+
+name: Jx.Button.Flyout
+
+description: Flyout buttons expose a panel when the user clicks the button.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Button
+
+provides: [Jx.Button.Flyout]
+
+images:
+ - flyout_chrome.png
+ - emblems.png
+
+...
+ */
+// $Id: flyout.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Button.Flyout
  *
  * Extends: <Jx.Button>
  *
  * Flyout buttons expose a panel when the user clicks the button.  The
- * panel can have arbitrary content.  You must provide any necessary 
+ * panel can have arbitrary content.  You must provide any necessary
  * code to hook up elements in the panel to your application.
  *
  * When the panel is opened, the 'open' event is fired.  When the panel is
  * closed, the 'close' event is fired.  You can register functions to handle
  * these events in the options passed to the constructor (onOpen, onClose).
- * 
+ *
  * The user can close the flyout panel by clicking the button again, by
  * clicking anywhere outside the panel and other buttons, or by pressing the
  * 'esc' key.
@@ -21424,9 +22098,9 @@
  * open - this event is triggered when the flyout is opened.
  * close - this event is triggered when the flyout is closed.
  *
- * License: 
+ * License:
  * Copyright (c) 2008, DM Solutions Group Inc.
- * 
+ *
  * This file is licensed under an MIT style license
  */
 Jx.Button.Flyout = new Class({
@@ -21457,7 +22131,7 @@
          */
         positionElement: null
     },
-    
+
     /**
      * Property: contentClasses
      * the classes array for processing the contentTemplate
@@ -21466,7 +22140,7 @@
         contentContainer: 'jxFlyout',
         content: 'jxFlyoutContent'
     }),
-    
+
     /**
      * Property: content
      * the HTML element that contains the flyout content
@@ -21474,22 +22148,27 @@
     content: null,
     /**
      * Method: render
-     * construct a new instance of a flyout button.  
+     * construct a new instance of a flyout button.
      */
     render: function() {
+        var options = this.options;
         if (!Jx.Button.Flyout.Stack) {
             Jx.Button.Flyout.Stack = [];
         }
         this.parent();
-        this.processElements(this.options.contentTemplate, this.contentClasses);
-        
-        if (this.options.contentClass) {
-            this.content.addClass(this.options.contentClass);
+        this.processElements(options.contentTemplate, this.contentClasses);
+
+        if (options.contentClass) {
+            this.content.addClass(options.contentClass);
         }
-        
+
         this.content.store('jxFlyout', this);
-        if(!this.options.loadOnDemand || this.options.active) {
+        if(!options.loadOnDemand || options.active) {
           this.loadContent(this.content);
+        }else{
+          this.addEvent('contentLoaded', function(ev) {
+            this.show(ev);
+          }.bind(this));
         }
     },
     cleanup: function() {
@@ -21507,69 +22186,89 @@
      *
      * Parameters:
      * e - {Event} the user event
-     */ 
+     */
     clicked: function(e) {
-        if (!this.options.enabled) {
+        var options = this.options;
+        if (!options.enabled) {
             return;
         }
-        if(this.options.loadOnDemand || !this.options.cacheContent) {
+        if (this.contentIsLoaded && options.cacheContent) {
+          this.show(e);
+        // load on demand or reload content if caching is disabled
+        } else if (options.loadOnDemand || !options.cacheContent) {
           this.loadContent(this.content);
+        } else {
+          this.show(e);
         }
-        /* find out what we are contained by if we don't already know */
-        if (!this.owner) {
-            this.owner = document.body;
+    },
+   /**
+    * Private Method: show
+    * Shows the Flyout after the content is loaded asynchronously
+    *
+    * Parameters:
+    * e - {Event} - the user or contentLoaded event
+    */
+    show: function(e) {
+        var node,
+            flyout,
+            owner = this.owner,
+            stack = Jx.Button.Flyout.Stack,
+            options = this.options;
+       /* find out what we are contained by if we don't already know */
+        if (!owner) {
+            this.owner = owner = document.body;
             var node = document.id(this.domObj.parentNode);
-            while (node != document.body && this.owner == document.body) {
+            while (node != document.body && owner == document.body) {
                 var flyout = node.retrieve('jxFlyout');
                 if (flyout) {
-                    this.owner = flyout;
+                    this.owner = owner = flyout;
                     break;
                 } else {
                     node = document.id(node.parentNode);
                 }
             }
         }
-        if (Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1] == this) {
+        if (stack[stack.length - 1] == this) {
             this.hide();
             return;
-        } else if (this.owner != document.body) {
+        } else if (owner != document.body) {
             /* if we are part of another flyout, close any open flyouts
              * inside the parent and register this as the current flyout
              */
-            if (this.owner.currentFlyout == this) {
+            if (owner.currentFlyout == this) {
                 /* if the flyout to close is this flyout,
                  * hide this and return */
                 this.hide();
                 return;
-            } else if (this.owner.currentFlyout) {
-                this.owner.currentFlyout.hide();
+            } else if (owner.currentFlyout) {
+                owner.currentFlyout.hide();
             }
-            this.owner.currentFlyout = this;                
+            owner.currentFlyout = this;
         } else {
             /* if we are at the top level, close the entire stack before
              * we open
              */
-            while (Jx.Button.Flyout.Stack.length) {
-                Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1].hide();
+            while (stack.length) {
+                stack[stack.length - 1].hide();
             }
         }
         // now we go on the stack.
-        Jx.Button.Flyout.Stack.push(this);
+        stack.push(this);
         this.fireEvent('beforeOpen');
 
-        this.options.active = true;
-        this.domA.addClass(this.options.activeClass);
+        options.active = true;
+        this.domA.addClass(options.activeClass);
         this.contentContainer.setStyle('visibility','hidden');
         document.id(document.body).adopt(this.contentContainer);
         this.content.getChildren().each(function(child) {
-            if (child.resize) { 
-                child.resize(); 
+            if (child.resize) {
+                child.resize();
             }
         });
         this.showChrome(this.contentContainer);
-        
-        var rel = this.options.positionElement || this.domObj;
-        var pos = $merge(this.options.position, {
+
+        var rel = options.positionElement || this.domObj;
+        var pos = $merge(options.position, {
           offsets: this.chromeOffsets
         });
         this.position(this.contentContainer, rel, pos);
@@ -21578,7 +22277,7 @@
          * there is some horrible peekaboo bug in IE 6
          */
         this.contentContainer.setContentBoxSize(document.id(this.content).getMarginBoxSize());
-        
+
         this.stack(this.contentContainer);
         this.contentContainer.setStyle('visibility','');
 
@@ -21586,30 +22285,31 @@
         document.addEvent('click', this.clickHandler);
         this.fireEvent('open', this);
     },
+
     /**
      * APIMethod: hide
      * Closes the flyout if open
      */
     hide: function() {
         if (this.owner != document.body) {
-            this.owner.currentFlyout = null;            
+            this.owner.currentFlyout = null;
         }
         Jx.Button.Flyout.Stack.pop();
         this.setActive(false);
         this.contentContainer.dispose();
         this.unstack(this.contentContainer);
-        document.removeEvent('keydown', this.keypressHandler);    
+        document.removeEvent('keydown', this.keypressHandler);
         document.removeEvent('click', this.clickHandler);
         this.fireEvent('close', this);
     },
     /**
      * Method: clickHandler
-     * hide flyout if the user clicks outside of the flyout 
+     * hide flyout if the user clicks outside of the flyout
      */
     clickHandler: function(e) {
         e = new Event(e);
-        var elm = document.id(e.target);
-        var flyout = Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1];
+        var elm = document.id(e.target),
+            flyout = Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1];
         if (!elm.descendantOf(flyout.content) &&
             !elm.descendantOf(flyout.domObj)) {
             flyout.hide();
@@ -21617,7 +22317,7 @@
     },
     /**
      * Method: keypressHandler
-     * hide flyout if the user presses the ESC key 
+     * hide flyout if the user presses the ESC key
      */
     keypressHandler: function(e) {
         e = new Event(e);
@@ -21625,7 +22325,29 @@
             Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1].hide();
         }
     }
-});// $Id: colorpalette.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.ColorPalette
+
+description: A Jx.ColorPalette presents a user interface for selecting colors.  This is typically combined with a Jx.Button.Color which embeds the color palette in a flyout.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+
+provides: [Jx.ColorPalette]
+
+css:
+ - color
+
+images:
+ - grid.png
+
+...
+ */
+// $Id: colorpalette.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.ColorPalette
  *
@@ -21952,7 +22674,24 @@
     }
 });
 
-// $Id: color.js 912 2010-05-21 21:33:08Z pagameba $
+/*
+---
+
+name: Jx.Button.Color
+
+description:
+
+license: MIT-style license.
+
+requires:
+ - Jx.Button.Flyout
+ - Jx.ColorPalette
+
+provides: [Jx.Button.Color]
+
+...
+ */
+// $Id: color.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Button.Color
  *
@@ -22062,23 +22801,24 @@
      * override <Jx.Button.Flyout> to use a singleton color palette.
      */
     clicked: function() {
-        if (Jx.Button.Color.ColorPalette.currentButton) {
-            Jx.Button.Color.ColorPalette.currentButton.hide();
+        var cp = Jx.Button.Color.ColorPalette;
+        if (cp.currentButton) {
+            cp.currentButton.hide();
         }
-        Jx.Button.Color.ColorPalette.currentButton = this;
-        Jx.Button.Color.ColorPalette.addEvent('change', this.bound.changed);
-        Jx.Button.Color.ColorPalette.addEvent('click', this.bound.hide);
-        this.content.appendChild(Jx.Button.Color.ColorPalette.domObj);
-        Jx.Button.Color.ColorPalette.domObj.setStyle('display', 'block');
+        cp.currentButton = this;
+        cp.addEvent('change', this.bound.changed);
+        cp.addEvent('click', this.bound.hide);
+        this.content.appendChild(cp.domObj);
+        cp.domObj.setStyle('display', 'block');
         Jx.Button.Flyout.prototype.clicked.apply(this, arguments);
         /* setting these before causes an update problem when clicking on
          * a second color button when another one is open - the color
          * wasn't updating properly
          */
 
-        Jx.Button.Color.ColorPalette.options.color = this.options.color;
-        Jx.Button.Color.ColorPalette.options.alpha = this.options.alpha/100;
-        Jx.Button.Color.ColorPalette.updateSelected();
+        cp.options.color = this.options.color;
+        cp.options.alpha = this.options.alpha/100;
+        cp.updateSelected();
 },
 
     /**
@@ -22086,11 +22826,12 @@
      * hide the color panel
      */
     hide: function() {
+        var cp = Jx.Button.Color.ColorPalette;
         this.setActive(false);
-        Jx.Button.Color.ColorPalette.removeEvent('change', this.bound.changed);
-        Jx.Button.Color.ColorPalette.removeEvent('click', this.bound.hide);
+        cp.removeEvent('change', this.bound.changed);
+        cp.removeEvent('click', this.bound.hide);
         Jx.Button.Flyout.prototype.hide.apply(this, arguments);
-        Jx.Button.Color.ColorPalette.currentButton = null;
+        cp.currentButton = null;
     },
 
     /**
@@ -22158,7 +22899,30 @@
         this.swatch.setStyles(styles);
     }
 });
-// $Id: menu.js 932 2010-05-28 14:02:48Z pagameba $
+/*
+---
+
+name: Jx.Menu
+
+description: A main menu as opposed to a sub menu that lives inside the menu.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Button
+ - Jx.List
+
+provides: [Jx.Menu]
+
+css:
+ - menu
+
+images:
+ - flyout_chrome.png
+ - emblems.png
+...
+ */
+// $Id: menu.js 966 2010-07-20 13:31:16Z pagameba $
 /**
  * Class: Jx.Menu
  *
@@ -22251,8 +23015,7 @@
             Jx.Menu.Menus = [];
         }
 
-        
-        this.contentContainer.addEvent('contextmenu', this.bound.stop);
+        this.contentClone = this.contentContainer.clone();
         this.list = new Jx.List(this.subDomObj, {
             onRemove: this.bound.remove
         });
@@ -22280,6 +23043,9 @@
         }
     },
     cleanup: function() {
+      if (this.hideTimer) {
+        window.clearTimeout(this.hideTimer);
+      }
       this.list.removeEvent('remove', this.bound.remove);
       this.list.destroy();
       this.list = null;
@@ -22303,6 +23069,7 @@
       this.contentContainer.removeEvent('contextmenu', this.bound.stop);
       this.subDomObj.destroy();
       this.contentContainer.destroy();
+      this.contentClone.destroy();
       this.bound.remove = null;
       this.bound.show = null;
       this.bound.stop = null;
@@ -22383,18 +23150,18 @@
      * e - {Event} the mouse event
      */
     onMouseEnter: function(e) {
-        if (this.hideTimer) {
-          $clear(this.hideTimer);
-          this.hideTimer = null;
-        }
-        if (Jx.Menu.Menus[0] && Jx.Menu.Menus[0] != this) {
-            this.show.delay(1,this);
-        } else if (this.options.exposeOnHover) {
-          if (Jx.Menu.Menus[0] && Jx.Menu.Menus[0] == this) {
-            Jx.Menu.Menus[0] = null;
-          }
+      if (this.hideTimer) {
+        window.clearTimeout(this.hideTimer);
+        this.hideTimer = null;
+      }
+      if (Jx.Menu.Menus[0] && Jx.Menu.Menus[0] != this) {
           this.show.delay(1,this);
+      } else if (this.options.exposeOnHover) {
+        if (Jx.Menu.Menus[0] && Jx.Menu.Menus[0] == this) {
+          Jx.Menu.Menus[0] = null;
         }
+        this.show.delay(1,this);
+      }
     },
     /**
      * Method: onMouseLeave
@@ -22473,6 +23240,9 @@
         if (this.button && this.button.domA) {
             this.button.domA.removeClass(this.button.options.activeClass);
         }
+        if (this.hideTimer) {
+          window.clearTimeout(this.hideTimer);
+        }
         this.list.each(function(item){item.retrieve('jxMenuItem').hide(e);});
         document.removeEvent('mousedown', this.bound.hide);
         document.removeEvent('keydown', this.bound.keypress);
@@ -22502,21 +23272,21 @@
                 return;
             }
         }
+        if (this.hideTimer) {
+          window.clearTimeout(this.hideTimer);
+        }
+
+        this.subDomObj.dispose();
+        this.contentContainer.destroy();
+        this.contentContainer = this.contentClone.clone();
+        this.contentContainer.empty().adopt(this.subDomObj);
+        this.contentContainer.addEvent('contextmenu', this.bound.stop);
         this.contentContainer.setStyle('display','none');
         document.id(document.body).adopt(this.contentContainer);
         this.contentContainer.setStyles({
             visibility: 'hidden',
             display: 'block'
         });
-
-        /* we have to size the container for IE to render the chrome correctly
-         * but just in the menu/sub menu case - there is some horrible 
-         * peekaboo bug in IE related to ULs that we just couldn't figure out
-         */
-         this.contentContainer.setStyles({
-           width: null,
-           height: null
-         });
         this.contentContainer.setContentBoxSize(this.subDomObj.getMarginBoxSize());
         this.showChrome(this.contentContainer);
 
@@ -22545,6 +23315,9 @@
      * obj- {<Jx.SubMenu>} the sub menu that just became visible
      */
     setVisibleItem: function(obj) {
+        if (this.hideTimer) {
+          window.clearTimeout(this.hideTimer);
+        }
         if (this.visibleItem != obj) {
             if (this.visibleItem && this.visibleItem.hide) {
                 this.visibleItem.hide();
@@ -22670,8 +23443,198 @@
     }
 });
 
-// $Id: set.js 932 2010-05-28 14:02:48Z pagameba $
+/*
+---
+
+name: Jx.Menu.Item
+
+description: A menu item is a single entry in a menu.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Menu
+
+provides: [Jx.Menu.Item]
+
+images:
+ - menuitem.png
+...
+ */
+// $Id: menu.item.js 967 2010-07-20 13:31:44Z pagameba $
 /**
+ * Class: Jx.Menu.Item
+ *
+ * Extends: <Jx.Button>
+ *
+ * A menu item is a single entry in a menu.  It is typically composed of
+ * a label and an optional icon.  Selecting the menu item emits an event.
+ *
+ * Jx.Menu.Item is represented by a <Jx.Button> with type MenuItem and the
+ * associated CSS changes noted in <Jx.Button>.  The container of a MenuItem
+ * is an 'li' element.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Events:
+ * click - fired when the menu item is clicked.
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Menu.Item = new Class({
+    Family: 'Jx.Menu.Item',
+    Extends: Jx.Button,
+    // Binds: ['onMouseOver'],
+    /**
+     * Property: owner
+     * {<Jx.SubMenu> or <Jx.Menu>} the menu that contains the menu item.
+     */
+    owner: null,
+    options: {
+        //image: null,
+        label: '&nbsp;',
+        toggleClass: 'jxMenuItemToggle',
+        pressedClass: 'jxMenuItemPressed',
+        activeClass: 'jxMenuItemActive',
+        /* Option: template
+         * the HTML structure of the button.  As a minimum, there must be a
+         * containing element with a class of jxMenuItemContainer and an
+         * internal element with a class of jxMenuItem.  jxMenuItemIcon and
+         * jxMenuItemLabel are used if present to put the image and label into
+         * the button.
+         */
+        template: '<li class="jxMenuItemContainer"><a class="jxMenuItem"><span class="jxMenuItemContent"><img class="jxMenuItemIcon" src="'+Jx.aPixel.src+'"><span class="jxMenuItemLabel"></span></span></a></li>'
+    },
+    classes: new Hash({
+        domObj:'jxMenuItemContainer',
+        domA: 'jxMenuItem',
+        domImg: 'jxMenuItemIcon',
+        domLabel: 'jxMenuItemLabel'
+    }),
+    init: function() {
+      this.bound.mouseover = this.onMouseOver.bind(this);
+      this.parent();
+    },
+    /**
+     * APIMethod: render
+     * Create a new instance of Jx.Menu.Item
+     */
+    render: function() {
+        if (!this.options.image) {
+            this.options.image = Jx.aPixel.src;
+        }
+        this.parent();
+        if (this.options.image && this.options.image != Jx.aPixel.src) {
+            this.domObj.removeClass(this.options.toggleClass);
+        }
+        if (this.options.target) {
+          this.domA.set('target', this.options.target);
+        }
+        this.domObj.addEvent('mouseover', this.bound.mouseover);
+        this.domObj.store('jxMenuItem', this);
+    },
+    cleanup: function() {
+      this.domObj.eliminate('jxMenuItem');
+      this.domObj.removeEvent('mouseover', this.bound.mouseover);
+      this.bound.mouseover = null;
+      this.owner = null;
+      this.parent();
+    },
+    /**
+     * Method: setOwner
+     * Set the owner of this menu item
+     *
+     * Parameters:
+     * obj - {Object} the new owner
+     */
+    setOwner: function(obj) {
+        this.owner = obj;
+    },
+    /**
+     * Method: hide
+     * Hide the menu item.
+     */
+    hide: function() {this.blur.delay(1,this);},
+    /**
+     * Method: show
+     * Show the menu item
+     */
+    show: $empty,
+    /**
+     * Method: clicked
+     * Handle the user clicking on the menu item, overriding the <Jx.Button::clicked>
+     * method to facilitate menu tracking
+     *
+     * Parameters:
+     * obj - {Object} an object containing an event property that was the user
+     * event.
+     */
+    clicked: function(obj) {
+        var href = this.options.href && this.options.href.indexOf('javascript:') != 0;
+        if (this.options.enabled) {
+          if (!href) {
+            if (this.options.toggle) {
+                this.setActive.delay(1,this,!this.options.active);
+            }
+            this.fireEvent.delay(1, this, ['click', {obj: this}]);
+            this.blur();
+          }
+          if (this.owner && this.owner.deactivate) {
+              this.owner.deactivate.delay(1, this.owner, obj.event);
+          }
+        }
+        return href ? true : false;
+    },
+    /**
+     * Method: onmouseover
+     * handle the mouse moving over the menu item
+     */
+    onMouseOver: function(e) {
+        e.stop();
+        if (this.owner && this.owner.setVisibleItem) {
+            this.owner.setVisibleItem(this);
+        }
+        return false;
+    },
+    
+    /**
+     * APIMethod: changeText
+     *
+     * updates the label of the menu item on langChange Event for
+     * Internationalization
+     */
+    changeText: function(lang) {
+        this.parent();
+        if (this.owner && this.owner.deactivate) {
+            this.owner.deactivate();
+        }
+    }
+});
+
+/*
+---
+
+name: Jx.ButtonSet
+
+description: A ButtonSet manages a set of Jx.Button instances by ensuring that only one of the buttons is active.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+
+provides: [Jx.ButtonSet]
+
+
+...
+ */
+// $Id: set.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
+/**
  * Class: Jx.ButtonSet
  *
  * Extends: <Jx.Object>
@@ -22803,7 +23766,29 @@
         this.setActiveButton(button);
         this.fireEvent('change', this);
     }
-});// $Id: multi.js 932 2010-05-28 14:02:48Z pagameba $
+});/*
+---
+
+name: Jx.Button.Multi
+
+description: Multi buttons are used to contain multiple buttons in a drop down list where only one button is actually visible and clickable in the interface.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Button
+ - Jx.Menu
+ - Jx.ButtonSet
+
+provides: [Jx.Button.Multi]
+
+images:
+ - button_multi.png
+ - button_multi_disclose.png
+
+...
+ */
+// $Id: multi.js 977 2010-09-02 18:57:42Z pagameba $
 /**
  * Class: Jx.Button.Multi
  *
@@ -22916,7 +23901,7 @@
         if (this.domDisclose) {
             var button = this;
             var hasFocus;
-            
+
             this.bound.disclose = {
               click: function(e) {
                   if (this.list.count() === 0) {
@@ -23015,52 +24000,54 @@
         }
     },
     cleanup: function() {
+      var self = this,
+          bound = this.bound;
       // clean up the discloser
-      if (this.domDisclose) {
-        this.domDisclose.removeEvents({
-          click: this.bound.disclose.click,
-          mouseenter: this.bound.disclose.mouseenter,
-          mouseleave: this.bound.disclose.mouseleave,
-          mousedown: this.bound.disclose.mousedown,
-          mouseup: this.bound.disclose.mouseup,
-          keydown: this.bound.disclose.keydown,
-          keyup: this.bound.disclose.keyup,
-          blur: this.bound.disclose.blur
+      if (self.domDisclose) {
+        self.domDisclose.removeEvents({
+          click: bound.disclose.click,
+          mouseenter: bound.disclose.mouseenter,
+          mouseleave: bound.disclose.mouseleave,
+          mousedown: bound.disclose.mousedown,
+          mouseup: bound.disclose.mouseup,
+          keydown: bound.disclose.keydown,
+          keyup: bound.disclose.keyup,
+          blur: bound.disclose.blur
         });
       }
-      
+
       // clean up the button set
-      this.buttonSet.destroy();
-      this.buttonSet = null;
-      
+      self.buttonSet.destroy();
+      self.buttonSet = null;
+
       // clean up the buttons array
-      this.buttons.each(function(b){
+      self.buttons.each(function(b){
         b.removeEvents();
-        this.menu.remove(b.multiButton);
+        self.menu.remove(b.multiButton);
         b.multiButton.destroy();
         b.multiButton = null;
         b.destroy();
-      },this);
-      this.buttons.empty();
-      this.buttons = null;
-      
+      });
+      self.buttons.empty();
+      self.buttons = null;
+
       // clean up the menu object
-      this.menu.removeEvents({
-        'show': this.bound.show,
-        'hide': this.bound.hide
+      self.menu.removeEvents({
+        'show': bound.show,
+        'hide': bound.hide
       });
       // unset the menu button because it references this object
-      this.menu.button = null;
-      this.menu.destroy();
-      this.menu = null;
-      
+      self.menu.button = null;
+      self.menu.destroy();
+      self.menu = null;
+
       // clean up binds and call parent to finish
-      this.bound.show = null;
-      this.bound.hide = null;
-      this.bound.clicked = null;
-      this.bound.disclose = null;
-      this.activeButton = null;
-      this.parent();
+      self.bound.show = null;
+      self.bound.hide = null;
+      self.bound.clicked = null;
+      self.bound.disclose = null;
+      self.activeButton = null;
+      self.parent();
     },
     /**
      * APIMethod: add
@@ -23074,14 +24061,17 @@
      */
     add: function() {
         $A(arguments).flatten().each(function(theButton){
+          var f,
+              opts,
+              button;
             if (!theButton instanceof Jx.Button) {
                 return;
             }
             theButton.domA.addClass('jxDiscloser');
             theButton.setLabel(theButton.options.label);
             this.buttons.push(theButton);
-            var f = this.setButton.bind(this, theButton);
-            var opts = {
+            f = this.setButton.bind(this, theButton);
+            opts = {
                 image: theButton.options.image,
                 imageClass: theButton.options.imageClass,
                 label: theButton.options.label || '&nbsp;',
@@ -23093,7 +24083,7 @@
             if (!opts.image || opts.image.indexOf('a_pixel') != -1) {
                 delete opts.image;
             }
-            var button = new Jx.Menu.Item(opts);
+            button = new Jx.Menu.Item(opts);
             this.buttonSet.add(button);
             this.menu.add(button);
             theButton.multiButton = button;
@@ -23179,156 +24169,27 @@
         this.setActiveButton(button);
         button.clicked();
     }
-});// $Id: menu.item.js 934 2010-05-28 15:12:44Z pagameba $
-/**
- * Class: Jx.Menu.Item
- *
- * Extends: <Jx.Button>
- *
- * A menu item is a single entry in a menu.  It is typically composed of
- * a label and an optional icon.  Selecting the menu item emits an event.
- *
- * Jx.Menu.Item is represented by a <Jx.Button> with type MenuItem and the
- * associated CSS changes noted in <Jx.Button>.  The container of a MenuItem
- * is an 'li' element.
- *
- * Example:
- * (code)
- * (end)
- *
- * Events:
- * click - fired when the menu item is clicked.
- *
- * License:
- * Copyright (c) 2008, DM Solutions Group Inc.
- *
- * This file is licensed under an MIT style license
+});/*
+---
+
+name: Jx.Layout
+
+description: Jx.Layout is used to provide more flexible layout options for applications
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+
+
+provides: [Jx.Layout]
+
+css:
+ - layout
+
+...
  */
-Jx.Menu.Item = new Class({
-    Family: 'Jx.Menu.Item',
-    Extends: Jx.Button,
-    // Binds: ['onMouseOver'],
-    /**
-     * Property: owner
-     * {<Jx.SubMenu> or <Jx.Menu>} the menu that contains the menu item.
-     */
-    owner: null,
-    options: {
-        //image: null,
-        label: '&nbsp;',
-        toggleClass: 'jxMenuItemToggle',
-        pressedClass: 'jxMenuItemPressed',
-        activeClass: 'jxMenuItemActive',
-        /* Option: template
-         * the HTML structure of the button.  As a minimum, there must be a
-         * containing element with a class of jxMenuItemContainer and an
-         * internal element with a class of jxMenuItem.  jxMenuItemIcon and
-         * jxMenuItemLabel are used if present to put the image and label into
-         * the button.
-         */
-        template: '<li class="jxMenuItemContainer"><a class="jxMenuItem"><span class="jxMenuItemContent"><img class="jxMenuItemIcon" src="'+Jx.aPixel.src+'"><span class="jxMenuItemLabel"></span></span></a></li>'
-    },
-    classes: new Hash({
-        domObj:'jxMenuItemContainer',
-        domA: 'jxMenuItem',
-        domImg: 'jxMenuItemIcon',
-        domLabel: 'jxMenuItemLabel'
-    }),
-    init: function() {
-      this.bound.mouseover = this.onMouseOver.bind(this);
-      this.parent();
-    },
-    /**
-     * APIMethod: render
-     * Create a new instance of Jx.Menu.Item
-     */
-    render: function() {
-        if (!this.options.image) {
-            this.options.image = Jx.aPixel.src;
-        }
-        this.parent();
-        if (this.options.image && this.options.image != Jx.aPixel.src) {
-            this.domObj.removeClass(this.options.toggleClass);
-        }
-        this.domObj.addEvent('mouseover', this.bound.mouseover);
-        this.domObj.store('jxMenuItem', this);
-    },
-    cleanup: function() {
-      this.domObj.eliminate('jxMenuItem');
-      this.domObj.removeEvent('mouseover', this.bound.mouseover);
-      this.bound.mouseover = null;
-      this.owner = null;
-      this.parent();
-    },
-    /**
-     * Method: setOwner
-     * Set the owner of this menu item
-     *
-     * Parameters:
-     * obj - {Object} the new owner
-     */
-    setOwner: function(obj) {
-        this.owner = obj;
-    },
-    /**
-     * Method: hide
-     * Hide the menu item.
-     */
-    hide: function() {this.blur.delay(1,this);},
-    /**
-     * Method: show
-     * Show the menu item
-     */
-    show: $empty,
-    /**
-     * Method: clicked
-     * Handle the user clicking on the menu item, overriding the <Jx.Button::clicked>
-     * method to facilitate menu tracking
-     *
-     * Parameters:
-     * obj - {Object} an object containing an event property that was the user
-     * event.
-     */
-    clicked: function(obj) {
-        if (this.options.enabled) {
-            if (this.options.toggle) {
-                this.setActive.delay(1,this,!this.options.active);
-            }
-            this.fireEvent.delay(1, this, ['click', {obj: this}]);
-            this.blur();
-            if (this.owner && this.owner.deactivate) {
-                this.owner.deactivate.delay(1, this.owner, obj.event);
-            }
-        }
-        return false;
-    },
-    /**
-     * Method: onmouseover
-     * handle the mouse moving over the menu item
-     */
-    onMouseOver: function(e) {
-        e.stop();
-        if (this.owner && this.owner.setVisibleItem) {
-            this.owner.setVisibleItem(this);
-        }
-        return false;
-    },
-    
-    /**
-     * APIMethod: changeText
-     *
-     * updates the label of the menu item on langChange Event for
-     * Internationalization
-     */
-    changeText: function(lang) {
-        this.parent();
-        if (this.owner && this.owner.deactivate) {
-            this.owner.deactivate();
-        }
-    }
-});
-
-// $Id: layout.js 718 2010-03-02 16:22:06Z pagameba $
+// $Id: layout.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Layout
  *
@@ -23760,7 +24621,29 @@
 
         this.fireEvent('sizeChange',this);
     }
-});// $Id: toolbar.js 857 2010-04-20 12:12:11Z pagameba $
+});/*
+---
+
+name: Jx.Toolbar
+
+description: A toolbar is a container object that contains other objects such as buttons.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+ - Jx.List
+
+provides: [Jx.Toolbar]
+
+css:
+ - toolbar
+
+images:
+ - toolbar.png
+...
+ */
+// $Id: toolbar.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Toolbar
  *
@@ -24065,7 +24948,30 @@
       this.update();
     }
 });
-// $Id: container.js 926 2010-05-27 12:56:21Z pagameba $
+/*
+---
+
+name: Jx.Toolbar.Container
+
+description: A toolbar container contains toolbars.  This has an optional dependency on Fx.Tween that, if included, will allow toolbars that contain more elements than can be displayed to be smoothly scrolled left and right.  Without this optional dependency, the toolbar will jump in fixed increments rather than smoothly scrolling.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Toolbar
+ - Jx.Button
+
+optional:
+ - Core/Fx.Tween
+
+provides: [Jx.Toolbar.Container]
+
+images:
+ - emblems.png
+
+...
+ */
+// $Id: container.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Toolbar.Container
  *
@@ -24162,16 +25068,7 @@
             this.domObj.grab(this.controls);
             this.domObj.addEvent('sizeChange', this.update);
         }
-        // make sure that align is valid
-        if (!["left","center","right"].contains(this.options.align)) {
-          this.options.align = 'left';
-        }
-        // align the toolbar appropriately
-        this.domObj.addClass('jxToolbarAlign' + this.options.align.capitalize());
-        
-        // scrolling is only available if it is left aligned.
-        this.options.scroll = this.options.align == 'left' &&
-                              this.options.scroll;
+
         if (!['center', 'right'].contains(this.options.align) && this.options.scroll) {
             this.processElements(this.options.scrollerTemplate, this.classes);
             this.domObj.grab(this.scroller, 'top');
@@ -24578,7 +25475,23 @@
         return np;
     }
 
-});// $Id: toolbar.item.js 626 2009-11-20 13:22:22Z pagameba $
+});/*
+---
+
+name: Jx.Toolbar.Item
+
+description: A helper class to provide a container for something to go into a Jx.Toolbar.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Toolbar
+
+provides: [Jx.Toolbar.Item]
+
+...
+ */
+// $Id: toolbar.item.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Toolbar.Item
  *
@@ -24608,7 +25521,7 @@
         domObj: 'jxToolItem'
     }),
 
-    parameters: ['jxThing'],
+    parameters: ['jxThing', 'options'],
 
     /**
      * APIMethod: render
@@ -24621,7 +25534,34 @@
             this.domObj.adopt(el);
         }
     }
-});// $Id: panel.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Panel
+
+description: A panel is a fundamental container object that has a content area and optional toolbars around the content area.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+ - Jx.Menu.Item
+ - Jx.Layout
+ - Jx.Toolbar.Container
+ - Jx.Toolbar.Item
+
+provides: [Jx.Panel]
+
+css:
+ - panel
+
+images:
+ - panel_controls.png
+ - panelbar.png
+
+...
+ */
+// $Id: panel.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Panel
  *
@@ -24892,7 +25832,9 @@
         new Jx.Layout(this.contentContainer);
         new Jx.Layout(this.content);
 
-        this.loadContent(this.content);
+        if(this.shouldLoadContent()) {
+          this.loadContent(this.content);
+        }
 
         this.toggleCollapse(this.options.closed);
 
@@ -25167,8 +26109,41 @@
       // TODO: is this the right method to call?
       // if toolbars left/right are used and localized, they may change their size..
       this.layoutContent();
+    },
+
+    /**
+     * Method to be able to allow loadingOnDemand in subclasses but not here
+     */
+    shouldLoadContent: function() {
+      return true;
     }
-});// $Id: dialog.js 894 2010-05-07 09:10:29Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Dialog
+
+description: A Jx.Panel that implements a floating dialog.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Panel
+
+optional:
+ - More/Drag
+
+provides: [Jx.Dialog]
+
+css:
+ - dialog
+
+images:
+ - dialog_chrome.png
+ - dialog_resize.png
+
+...
+ */
+// $Id: dialog.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Dialog
  *
@@ -25285,6 +26260,16 @@
          * moveable by the user or not.  Default is true.
          */
         move: true,
+        /*
+         * Option: limit
+         * (optional) {Object} || false
+         * passed to the Drag instance of this dialog to limit the movement
+         * {Object} must have x&y coordinates with a range, like {x:[0,500],y:[0,500]}.
+         * Set an id or a reference of a DOM Element (ie 'document', 'myContainerWithId', 
+         * $('myContainer'), $('domID').getParent()) to use these dimensions
+         * as boundaries. Default is false.
+         */
+        limit : false,
         /* Option: close
          * (optional) {Boolean} determines whether the dialog is
          * closeable by the user or not.  Default is true.
@@ -25370,18 +26355,45 @@
         /* the dialog is moveable by its title bar */
         if (this.options.move && typeof Drag != 'undefined') {
             this.title.addClass('jxDialogMoveable');
+
+            this.options.limit = this.setDragLimit(this.options.limit);
+            // local reference to use Drag instance variables inside onDrag()
+            var self = this;
+            // COMMENT: any reason why the drag instance isn't referenced to the dialog?
             new Drag(this.domObj, {
                 handle: this.title,
+                limit: this.options.limit,
                 onBeforeStart: (function(){
                     this.stack();
                 }).bind(this),
-                onStart: (function() {
-                    if (!this.options.modal && this.options.parent.mask) {
-                      this.options.parent.mask(this.options.eventMaskOptions);
+                onStart: function() {
+                    if (!self.options.modal && self.options.parent.mask) {
+                      self.options.parent.mask(self.options.eventMaskOptions);
                     }
-                    this.contentContainer.setStyle('visibility','hidden');
-                    this.chrome.addClass('jxChromeDrag');
-                }).bind(this),
+                    self.contentContainer.setStyle('visibility','hidden');
+                    self.chrome.addClass('jxChromeDrag');
+                    if(self.options.limit) {
+                      var coords = self.options.limitOrig.getCoordinates();
+                      for(var i in coords) {
+                        window.console ? console.log(i, coords[i]) : false;
+                      }
+                      this.options.limit = self.setDragLimit(self.options.limitOrig);
+                    }
+                }, // COMMENT: removed bind(this) for setting the limit to the drag instance
+                onDrag: function() {
+                  if(this.options.limit) {
+                    // find out if the right border of the dragged element is out of range
+                    if(this.value.now.x+self.options.width >= this.options.limit.x[1]) {
+                      this.value.now.x = this.options.limit.x[1] - self.options.width;
+                      this.element.setStyle('left',this.value.now.x);
+                    }
+                    // find out if the bottom border of the dragged element is out of range
+                    if(this.value.now.y+self.options.height >= this.options.limit.y[1]) {
+                      this.value.now.y = this.options.limit.y[1] - self.options.height;
+                      this.element.setStyle('top',this.value.now.y);
+                    }
+                  }
+                },
                 onComplete: (function() {
                     if (!this.options.modal && this.options.parent.unmask) {
                       this.options.parent.unmask();
@@ -25679,6 +26691,7 @@
         if (url) {
             this.options.contentURL = url;
             this.options.content = null;  //force Url loading
+            this.setBusy();
             this.loadContent(this.content);
             this.addEvent('contentLoaded', this.openOnLoaded);
         } else {
@@ -25697,6 +26710,11 @@
         if (!this.isOpening) {
             this.isOpening = true;
         }
+        // COMMENT: this works only for onDemand -> NOT for cacheContent = false..
+        // for this loading an URL everytime, use this.openURL(url) 
+        if(!this.contentIsLoaded && this.options.loadOnDemand) {
+          this.loadContent(this.content);
+        }
         if (this.contentIsLoaded) {
             this.removeEvent('contentLoaded', this.openOnLoaded);
             this.show();
@@ -25786,10 +26804,78 @@
         }
       }
       return this.keyboardEvents;
+    },
+
+    /**
+     * Method: setDragLimit
+     * calculates the drag-dimensions of an given element to drag
+     *
+     * Parameters:
+     * - reference {Object} (optional) the element|elementId|object to set the limits
+     */
+    setDragLimit : function(reference) {
+      if($defined(reference)) this.options.limit = reference;
+      
+      // check drag limit if it is an container or string for an element and use dimensions
+      var limitType = this.options.limit != null ? Jx.type(this.options.limit) : false;
+      if(this.options.limit && limitType != 'object') {
+        var coords = false;
+        switch(limitType) {
+          case 'string':
+            if(document.id(this.options.limit)) {
+              coords = document.id(this.options.limit).getCoordinates();
+            }
+            break;
+          case 'element':
+          case 'document':
+          case 'window':
+            coords = this.options.limit.getCoordinates();
+            break;
+        }
+        if(coords) {
+          this.options.limitOrig = this.options.limit;
+          this.options.limit = {
+            x : [coords.left, coords.right],
+            y : [coords.top, coords.bottom]
+          }
+        }else{
+          this.options.limit = false;
+        }
+      }
+      return this.options.limit;
+    },
+
+    /**
+     * gets called by parent class Jx.Panel and decides whether to load content or not
+     */
+    shouldLoadContent: function() {
+      return !this.options.loadOnDemand;
     }
 });
 
-// $Id: splitter.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+/*
+---
+
+name: Jx.Splitter
+
+description: A Jx.Splitter creates two or more containers within a parent container and provides user control over the size of the containers.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Layout
+
+optional:
+ - More/Drag
+
+provides: [Jx.Splitter]
+
+css:
+ - splitter
+
+...
+ */
+// $Id: splitter.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Splitter
  *
@@ -26537,7 +27623,24 @@
     		document.id(bar).set('title', this.getText({set:'Jx',key:'splitter',value:'barToolTip'}));
     	},this);	
     }
-});// $Id: panelset.js 895 2010-05-07 19:05:19Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.PanelSet
+
+description: A panel set manages a set of panels within a DOM element.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Splitter
+ - Jx.Panel
+
+provides: [Jx.PanelSet]
+
+...
+ */
+// $Id: panelset.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.PanelSet
  *
@@ -26771,7 +27874,28 @@
       this.parent();
       //barTooltip is handled by the splitter's createText() function
     }
-});// $Id: message.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Dialog.Message
+
+description: A subclass of jx.Dialog for displaying messages w/a single OK button.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Dialog
+ - Jx.Button
+ - Jx.Toolbar.Item
+
+provides: [Jx.Dialog.Message]
+
+css:
+ - message
+
+...
+ */
+// $Id: message.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Dialog.Message
  *
@@ -26906,7 +28030,28 @@
       }
     }
 });
-// $Id: confirm.js 895 2010-05-07 19:05:19Z conrad.barthelmes $
+/*
+---
+
+name: Jx.Dialog.Confirm
+
+description: A subclass of Jx.dialog for asking a yes/no type question of the user.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Dialog
+ - Jx.Button
+ - Jx.Toolbar.Item
+
+provides: [Jx.Dialog.Confirm]
+
+css:
+ - confirm
+
+...
+ */
+// $Id: confirm.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Dialog.Confirm
  *
@@ -27028,7 +28173,26 @@
       }
     }
 
-});// $Id: tooltip.js 835 2010-04-07 22:59:37Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Tooltip
+
+description: These are very simple tooltips that are designed to be instantiated in javascript and directly attached to the object that they are the tip for.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+
+provides: [Jx.Tooltip]
+
+css:
+ - tooltip
+
+...
+ */
+// $Id: tooltip.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Tooltip
  *
@@ -27206,7 +28370,23 @@
         this.destroy();
     }
 });
-// $Id: fieldset.js 867 2010-04-23 15:54:04Z conrad.barthelmes $
+/*
+---
+
+name: Jx.Fieldset
+
+description: Used to create fieldsets in Forms
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+
+provides: [Jx.Fieldset]
+
+...
+ */
+// $Id: fieldset.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Fieldset
  *
@@ -27346,7 +28526,28 @@
     }
     
 });
-// $Id: form.js 901 2010-05-10 19:33:28Z jonlb at comcast.net $
+/*
+---
+
+name: Jx.Form
+
+description: Represents a HTML Form
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+ - More/String.QueryString
+ - More/Form.Validator
+
+provides: [Jx.Form]
+
+css:
+ - form
+
+...
+ */
+// $Id: form.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Form
  *
@@ -27610,7 +28811,25 @@
       });
     }
 });
-// $Id: field.js 912 2010-05-21 21:33:08Z pagameba $
+/*
+---
+
+name: Jx.Field
+
+description: Base class for all inputs
+
+license: MIT-style license.
+
+requires:
+ - Jx.Fieldset
+ - Jx.Form
+
+provides: [Jx.Field]
+
+
+...
+ */
+// $Id: field.js 969 2010-08-20 12:14:54Z pagameba $
 /**
  * Class: Jx.Field
  *
@@ -27640,7 +28859,9 @@
     options : {
         /**
          * Option: id
-         * The ID of the field.
+         * The ID assigned to the container of the Jx.Field element, this is
+         * not the id of the input element (which is internally computed to be
+         * unique)
          */
         id : null,
         /**
@@ -27757,7 +28978,7 @@
     tag : null,
     /**
      * Property: id
-     * The name of this field.
+     * A computed, unique id attached to the input element of this field.
      */
     id : null,
     /**
@@ -27790,8 +29011,7 @@
         this.options.template = this.options.template.substitute({name:name});
         this.parent();
 
-        this.id = ($defined(this.options.id)) ? this.options.id : this
-                .generateId();
+        this.id = this.generateId();
         this.name = this.options.name;
 
         if ($defined(this.type)) {
@@ -28005,7 +29225,26 @@
     }
 
 });
-// $Id: text.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Field.Text
+
+description: Represents a text input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field
+
+optional:
+ - More/OverText
+
+provides: [Jx.Field.Text]
+
+...
+ */
+// $Id: text.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Field.Text
  *
@@ -28062,7 +29301,26 @@
 
     }
 
-});// $Id: prompt.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Dialog.Prompt
+
+description: A subclass of Jx.dialog for prompting the user for text input.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Dialog
+ - Jx.Button
+ - Jx.Toolbar.Item
+ - Jx.Field.Text
+
+provides: [Jx.Dialog.Prompt]
+
+...
+ */
+// $Id: prompt.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Dialog.Prompt
  *
@@ -28209,7 +29467,25 @@
 
 
 });
-// $Id: dataview.js 912 2010-05-21 21:33:08Z pagameba $
+/*
+---
+
+name: Jx.Panel.DataView
+
+description: A panel used for displaying records from a store in a list-style interface rather than a grid.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Panel
+ - Jx.Store
+ - Jx.List
+
+provides: [Jx.Panel.DataView]
+
+...
+ */
+// $Id: dataview.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Panel.DataView
  *
@@ -28472,7 +29748,24 @@
         }, options));
     }
 });
-// $Id: group.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Panel.DataView.Group
+
+description: A subclass of Dataview that can display records in groups.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Panel.DataView
+ - Jx.Selection
+
+provides: [Jx.Panel.DataView.Group]
+
+...
+ */
+// $Id: group.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Panel.DataView.Group
  *
@@ -28635,7 +29928,23 @@
     }
 
 });
-// $Id: listitem.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.ListItem
+
+description: Represents a single item in a listview.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+
+provides: [Jx.ListItem]
+
+...
+ */
+// $Id: listitem.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.ListItem
  *
@@ -28675,7 +29984,29 @@
     enable: function(state) {
 
     }
-});// $Id: listview.js 898 2010-05-10 04:08:44Z jonlb at comcast.net $
+});/*
+---
+
+name: Jx.ListView
+
+description: A widget that displays items in a list format.
+
+license: MIT-style license.
+
+requires:
+ - Jx.List
+ - Jx.ListItem
+
+provides: [Jx.ListView]
+
+css:
+ - list
+
+images:
+ - listitem.png
+...
+ */
+// $Id: listview.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.ListView
  *
@@ -28755,7 +30086,23 @@
         this.list.empty();
         return this;
     }
-});// $Id: hidden.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Field.Hidden
+
+description: Represents a hidden input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field
+
+provides: [Jx.Field.Hidden]
+
+...
+ */
+// $Id: hidden.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Field.Hidden
  *
@@ -28794,6 +30141,30 @@
 
 
 
+/*
+---
+
+name: Jx.Field.File
+
+description: Represents a file input w/upload and progress tracking capabilities (requires APC for progress)
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field.Text
+ - Jx.Button
+ - Core/Request.JSON
+ - Jx.Field.Hidden
+ - Jx.Form
+
+provides: [Jx.Field.File]
+
+css:
+ - file
+
+
+...
+ */
 /**
  * Class: Jx.Field.File
  *
@@ -28914,13 +30285,20 @@
         //create the iframe
         //we use the same iFrame for each so we don't have to recreate it each time
         this.setupIframe = true;
-        this.iframe = new IFrame(null, {
-            styles: {
-                'display':'none',
-                'visibility':'hidden'
-            },
-            name : this.generateId()
+        this.iframe = new Element('iframe', {
+          name: this.generateId(),
+          styles: {
+            'display':'none',
+            'visibility':'hidden'
+          }
         });
+        // this.iframe = new IFrame(null, {
+        //     styles: {
+        //         'display':'none',
+        //         'visibility':'hidden'
+        //     },
+        //     name : this.generateId()
+        // });
         this.iframe.inject(document.body);
         this.iframe.addEvent('load', this.processIFrameUpload.bind(this));
 
@@ -29145,7 +30523,12 @@
         //the body text should be a JSON structure
         //get the body
         if (!this.setupIframe) {
-            var iframeBody = this.iframe.contentDocument.defaultView.document.body.innerHTML;
+            if (this.iframe.contentDocument  && this.iframe.contentDocument.defaultView) {
+              var iframeBody = this.iframe.contentDocument.defaultView.document.body.innerHTML;
+            } else {
+              // seems to be needed for ie7
+              var iframeBody = this.iframe.contentWindow.document.body.innerHTML;
+            }
 
             var data = JSON.decode(iframeBody);
             if ($defined(data.success) && data.success) {
@@ -29207,7 +30590,29 @@
     		this.browseButton.setLabel( this.getText({set:'Jx',key:'file',value:'browseLabel'}) );
     	}
     }
-});
+});/*
+---
+
+name: Jx.Progressbar
+
+description: A css-based progress bar.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+ - Core/Fx.Tween
+
+provides: [Jx.Progressbar]
+
+css:
+ - progressbar
+
+images:
+ - progressbar.png
+
+...
+ */
 /**
  * Class: Jx.Progressbar
  *
@@ -29402,7 +30807,34 @@
         //progress text will update on next update.
     }
     
-});// $Id: upload.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Panel.FileUpload
+
+description: A panel subclass that is designed to be a multiple file upload panel with a queue listing.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Panel
+ - Jx.ListView
+ - Jx.Field.File
+ - Jx.Progressbar
+ - Jx.Button
+ - Jx.Toolbar.Item
+ - Jx.Tooltip
+
+provides: [Jx.Panel.FileUpload]
+
+css:
+ - upload
+
+images:
+ - icons.png
+...
+ */
+// $Id: upload.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Panel.FileUpload
  *
@@ -29689,7 +31121,23 @@
       }
     }
 });
-// $Id: column.js 920 2010-05-25 18:39:55Z conrad.barthelmes $
+/*
+---
+
+name: Jx.Column
+
+description: A representation of a single grid column
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+
+provides: [Jx.Column]
+
+...
+ */
+// $Id: column.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Column
  *
@@ -29708,33 +31156,34 @@
  */
 Jx.Column = new Class({
 
-	Family: 'Jx.Column',
+    Family: 'Jx.Column',
     Extends: Jx.Widget,
 
     options: {
         /**
          * Option: renderMode
-         * The mode to use in rendering this column to determine its width. 
+         * The mode to use in rendering this column to determine its width.
          * Valid options include
-         * 
-         * fit - auto calculates the width for the best fit to the text. This 
-         * 			is the default.
-         * fixed - uses the value passed in the width option, doesn't 
-         * 			auto calculate.
-         * expand - uses the value in the width option as a minimum width and 
-         * 			allows this column to expand and take up any leftover space. 
-         * 			NOTE: there can be only 1 expand column in a grid. The 
-         * 			Jx.Columns object will only take the first column with this 
-         * 			option as the expanding column. All remaining columns marked 
-         * 			"expand" will be treated as "fixed".
+         *
+         * fit - auto calculates the width for the best fit to the text. This
+         *      is the default.
+         * fixed - uses the value passed in the width option, doesn't
+         *      auto calculate.
+         * expand - uses the value in the width option as a minimum width and
+         *      allows this column to expand and take up any leftover space.
+         *      NOTE: there can be only 1 expand column in a grid. The
+         *      Jx.Columns object will only take the first column with this
+         *      option as the expanding column. All remaining columns marked
+         *      "expand" will be treated as "fixed".
          */
-        renderMode: 'fit',
+        renderMode: 'fixed',
         /**
          * Option: width
          * Determines the width of the column when using 'fixed' rendering mode
          * or acts as a minimum width when using 'expand' mode.
          */
-        width: null,
+        width: 100,
+
         /**
          * Option: isEditable
          * allows/disallows editing of the column contents
@@ -29760,6 +31209,7 @@
          * The name given to this column
          */
         name: '',
+
         /**
          * Option: template
          */
@@ -29777,9 +31227,9 @@
          */
         renderer: null
     },
-    
+
     classes: $H({
-    	domObj: 'jxGridCellContent'
+      domObj: 'jxGridCellContent'
     }),
     /**
      * Property: model
@@ -29830,20 +31280,21 @@
         }
 
         this.options.renderer.setColumn(this);
+    },
 
-        this.sortImg = new Element('img', {
-            src: Jx.aPixel.src
-        });
+    getTemplate: function(idx) {
+      return "<span class='jxGridCellContent' title='{col"+idx+"}'>{col"+idx+"}</span>";
+    },
 
-    },
-    	
     /**
      * APIMethod: getHeaderHTML
      */
     getHeaderHTML : function () {
-    	if (this.isSortable()) {
-    		this.sortImg.inject(this.domObj);	
-    	}
+      if (this.isSortable()) {
+        new Element('img', {
+            src: Jx.aPixel.src
+        }).inject(this.domObj);
+      }
       return this.domObj;
     },
 
@@ -29852,9 +31303,9 @@
 
         var delta = this.cellWidth - this.width;
         if (!asCellWidth) {
-    	    this.width = parseInt(newWidth,10);
-    	    this.cellWidth = this.width + delta;
-    	    this.options.width = newWidth;
+          this.width = parseInt(newWidth,10);
+          this.cellWidth = this.width + delta;
+          this.options.width = newWidth;
         } else {
             this.width = parseInt(newWidth,10) - delta;
             this.cellWidth = newWidth;
@@ -29867,15 +31318,15 @@
           this.cellRule.style.width = parseInt(this.cellWidth,10) + "px";
       }
     },
-    
+
     getWidth: function () {
-    	return this.width;
+      return this.width;
     },
-    
+
     getCellWidth: function() {
       return this.cellWidth;
     },
-    
+
     /**
      * APIMethod: calculateWidth
      * returns the width of the column.
@@ -29885,14 +31336,14 @@
      */
     calculateWidth : function (rowHeader) {
         //if this gets called then we assume that we want to calculate the width
-    	rowHeader = $defined(rowHeader) ? rowHeader : false;
+      rowHeader = $defined(rowHeader) ? rowHeader : false;
         var maxWidth;
         var maxCellWidth;
-        
-        var model = this.grid.getModel();
+
+        var model = this.grid.getStore();
         model.first();
-        if ((this.options.renderMode == 'fixed' || 
-             this.options.renderMode == 'expand') && 
+        if ((this.options.renderMode == 'fixed' ||
+             this.options.renderMode == 'expand') &&
             model.valid) {
           var t = new Element('span', {
             'class': 'jxGridCellContent',
@@ -29933,7 +31384,7 @@
             }
 
             //check the column header as well (unless this is the row header)
-            if (!(this.grid.row.useHeaders() && 
+            if (!(this.grid.row.useHeaders() &&
                 this.options.name === this.grid.row.getRowHeaderColumn())) {
                 klass = 'jxGridColHead';
                 if (this.isEditable()) {
@@ -29954,7 +31405,7 @@
                 }
             }
         }
-        
+
         this.width = maxWidth;
         this.cellWidth = maxCellWidth;
         model.moveTo(oldPos);
@@ -29968,8 +31419,8 @@
      * text - the text to measure
      * klass - a string indicating and extra classes to add so that
      *          css classes can be taken into account.
-     * rowHeader - 
-     * row - 
+     * rowHeader -
+     * row -
      */
     measure : function (text, klass, rowHeader, row) {
         var d = new Element('span', {
@@ -29981,7 +31432,7 @@
             'visibility' : 'hidden',
             'width' : 'auto'
         });
-        
+
         d.inject(document.body, 'bottom');
         var s = d.measure(function () {
             //if not rowHeader, get size of innner span
@@ -30045,7 +31496,24 @@
         return document.id(this.options.renderer);
     }
 
-});// $Id: columns.js 886 2010-04-29 23:07:02Z jonlb at comcast.net $
+});/*
+---
+
+name: Jx.Columns
+
+description: A container for defining and holding individual columns
+
+license: MIT-style license.
+
+requires:
+ - Jx.Column
+ - Jx.Object
+
+provides: [Jx.Columns]
+
+...
+ */
+// $Id: columns.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Columns
  *
@@ -30089,6 +31557,8 @@
      * an array holding the actual instantiated column objects
      */
     columns : [],
+    
+    rowTemplate: null,
 
     parameters: ['options','grid'],
     /**
@@ -30118,12 +31588,40 @@
                 this.columns.push(new Jx.Column(col,this.grid));
             }
             var c = this.columns[this.columns.length - 1 ];
-            if (c.options.renderMode === 'expand') {
-                this.hasExpandable = true;
-            }
-
         }, this);
+        
+        this.buildTemplates();
     },
+    
+    addColumns: function(columns) {
+      this.columns.extend(columns);
+      this.buildTemplates();
+    },
+    
+    buildTemplates: function() {
+      var rowTemplate = '',
+          hasExpandable = false,
+          grid = this.grid,
+          row = grid.row,
+          rhc = grid.row.useHeaders() ? this.getByName(row.options.headerColumn) : null,
+          colTemplate;
+      
+      this.columns.each(function(col, idx) {
+        var colTemplate = '';
+        if (!col.isHidden() && col != rhc) {
+          hasExpandable |= col.options.renderMode == 'expand';
+          if (!col.options.renderer || !col.options.renderer.domInsert) {
+            colTemplate = col.getTemplate(idx);
+          }
+          rowTemplate += "<td class='jxGridCell jxGridCol"+idx+" jxGridCol"+col.options.name+"'>" + colTemplate + "</td>";
+        }
+      });
+      if (!hasExpandable) {
+        rowTemplate += "<td><span class='jxGridCellUnattached'></span></td>";
+      }
+      this.rowTemplate = rowTemplate;
+      this.hasExpandable = hasExpandable;
+    },
     /**
      * APIMethod: getHeaderHeight
      * returns the height of the column header row
@@ -30210,101 +31708,73 @@
      * Parameters:
      * row - the row to add the headers to.
      */
-    getHeaders : function (list) {
-        var r = this.grid.row.useHeaders();
-        var hf = this.grid.row.getRowHeaderColumn();
-        this.columns.each(function (col, idx) {
-            if (r && hf === col.options.name) {
-                //do nothing
-            } else if (!col.isHidden()) {
-                var th = new Element('th', {
-                    'class' : 'jxGridColHead jxGridCol'+idx
-                });
-                th.adopt(col.getHeaderHTML());
-                // th.setStyle('width', col.getWidth());
-                th.addClass('jxColHead-' + col.name);
-                //add other styles for different attributes
-                if (col.isEditable()) {
-                    th.addClass('jxColEditable');
-                }
-                if (col.isResizable()) {
-                    th.addClass('jxColResizable');
-                }
-                if (col.isSortable()) {
-                    th.addClass('jxColSortable');
-                }
-                list.add(th);
-                th.store('jxCellData', {
-                   column: col,
-                   colHeader: true,
-                   index: idx
-                });
-            }
-        }, this);
-        return list;
+    getHeaders : function (tr) {
+      var grid = this.grid,
+          row = grid.row,
+          rhc = grid.row.useHeaders() ? this.getByName(row.options.headerColumn) : null;
+      if (this.useHeaders()) {
+        this.columns.each(function(col, idx) {
+          if (!col.isHidden() && col != rhc) {
+            var classes = ['jxGridColHead', 'jxGridCol'+idx, 'jxGridCol'+col.options.name];
+            if (col.isEditable()) { classes.push('jxColEditable'); }
+            if (col.isResizable()) { classes.push('jxColResizable'); }
+            if (col.isSortable()) { classes.push('jxColSortable'); }
+            var th = new Element('th', {
+              'class': classes.join(' '),
+            });
+            th.store('jxCellData', {
+              column: col,
+              colHeader: true,
+              index: idx
+            });
+            th.adopt(col.getHeaderHTML());
+            th.inject(tr);
+          }
+        });
+        if (!this.hasExpandable) {
+          new Element('th', {
+            'class': 'jxGridColHead jxGridCellUnattached'
+          }).inject(tr);
+        }
+      }
     },
-    /**
-     * APIMethod: getColumnCells
-     * Appends the cells from each column for a specific row
-     *
-     * Parameters:
-     * list - the Jx.List instance to add the cells to.
-     */
-    getColumnCells : function (list) {
-        var r = this.grid.row;
-        var f = r.getRowHeaderColumn();
-        var h = r.useHeaders();
-        this.columns.each(function (col, idx) {
-            if (h && col.name !== f && !col.isHidden()) {
-                list.add(this.getColumnCell(col, idx));
-            } else if (!h && !col.isHidden()) {
-                list.add(this.getColumnCell(col, idx));
+    
+    getRow: function(tr, record) {
+      var data = {},
+          grid = this.grid,
+          store = grid.store,
+          row = grid.row,
+          rhc = grid.row.useHeaders() ? this.getByName(row.options.headerColumn) : null,
+          domInserts = [];
+      var i = 0;
+      this.columns.each(function(column, index) {
+        if (!column.isHidden() && column != rhc) {
+          if (column.options.renderer && column.options.renderer.domInsert) {
+            domInserts.push({column: column, index: i});
+          } else {
+            var renderer = column.options.renderer;
+            var formatter = renderer.options.formatter;
+            var text = '';
+            if (renderer.options.textTemplate) {
+              text = store.fillTemplate(null, renderer.options.textTemplate, renderer.columnsNeeded);
+            } else {
+              text = record.data.get(column.name);
             }
-        }, this);
-        if (!this.hasExpandable) {
-            list.add(new Element('td',{
-                'class': 'jxGridCellUnattached'
-            }));
+            if (formatter) {
+              text = formatter.format(text);
+            }
+            data['col'+index] = text;
+          }
+          i++;
         }
+      });
+      tr.set('html', this.rowTemplate.substitute(data));
+      domInserts.each(function(obj) {
+        var td = tr.childNodes[obj.index];
+        td.adopt(obj.column.getHTML());
+      });
     },
-    /**
-     * APIMethod: getColumnCell
-     * Returns the cell (td) for a particular column.
-     *
-     * Paremeters:
-     * col - the column to get a cell for.
-     */
-    getColumnCell : function (col, idx) {
 
-        var td = new Element('td', {
-            'class' : 'jxGridCell'
-        });
-        td.adopt(col.getHTML());
-        td.addClass('jxCol-' + col.name);
-        td.addClass('jxGridCol'+idx);
-        //add other styles for different attributes
-        if (col.isEditable()) {
-            td.addClass('jxColEditable');
-        }
-        if (col.isResizable()) {
-            td.addClass('jxColResizable');
-        }
-        if (col.isSortable()) {
-            td.addClass('jxColSortable');
-        }
-        if (!col.isAttached()) {
-            td.addClass('jxGridCellUnattached');
-        }
-
-        td.store('jxCellData',{
-            col: col,
-            index: idx, //This is the position of the column
-            row: this.grid.model.getPosition()
-        });
-
-        return td;
-    },
-    
     calculateWidths: function () {
       //to calculate widths we loop through each column
       var expand = null;
@@ -30313,9 +31783,9 @@
       this.columns.each(function(col,idx){
         //are we checking the rowheader?
         var rowHeader = false;
-        if (col.name == this.grid.row.options.headerColumn) {
-          rowHeader = true;
-        }
+        // if (col.name == this.grid.row.options.headerColumn) {
+        //   rowHeader = true;
+        // }
         //if it's fixed, set the width to the passed in width
         if (col.options.renderMode == 'fixed') {
           col.calculateWidth(); //col.setWidth(col.options.width);
@@ -30332,7 +31802,7 @@
             col.calculateWidth(rowHeader);
           }
         }
-        if (!col.isHidden() && !(col.name == this.grid.row.options.headerColumn)) {
+        if (!col.isHidden() /* && !(col.name == this.grid.row.options.headerColumn) */) {
             totalWidth += Jx.getNumber(col.getCellWidth());
             if (rowHeader) {
                 rowHeaderWidth = col.getWidth();
@@ -30342,7 +31812,7 @@
       
       // width of the container
       //var containerWidth = this.grid.gridObj.getContentBoxSize();
-      var gridSize = this.grid.gridObj.getContentBoxSize();
+      var gridSize = this.grid.contentContainer.getContentBoxSize();
       if (gridSize.width > totalWidth) {
         //now figure the expand column
         if ($defined(expand)) {
@@ -30368,27 +31838,28 @@
           }
         }
       } //else {
-      this.grid.gridTable.setContentBoxSize({'width': totalWidth});
-      this.grid.colTable.setContentBoxSize({'width': totalWidth});
+      this.grid.gridObj.setContentBoxSize({'width': totalWidth});
+      this.grid.colObj.setContentBoxSize({'width': totalWidth});
       // }
     },
 
     createRules: function(styleSheet, scope) {
-        this.columns.each(function(col, idx) {
-            var selector = scope+' .jxGridCol'+idx
-            var dec = '';
-            if (col.options.renderMode === 'fixed' || col.options.renderMode === 'expand') {
-              //set the white-space to 'normal !important'
-              dec = 'white-space: normal !important';
-            }
-            col.cellRule = Jx.Styles.insertCssRule(selector, dec, styleSheet);
-            col.cellRule.style.width = col.getCellWidth() + "px";
+      var autoRowHeight = this.grid.row.options.rowHeight == 'auto';
+      this.columns.each(function(col, idx) {
+        var selector = scope+' .jxGridCol'+idx
+        var dec = '';
+        if (autoRowHeight) {
+          //set the white-space to 'normal !important'
+          dec = 'white-space: normal !important';
+        }
+        col.cellRule = Jx.Styles.insertCssRule(selector, dec, styleSheet);
+        col.cellRule.style.width = col.getCellWidth() + "px";
 
-            var selector = scope+" .jxGridCol" + idx + " .jxGridCellContent";
-            col.rule = Jx.Styles.insertCssRule(selector, dec, styleSheet);
-            col.rule.style.width = col.getWidth() + "px";
+        var selector = scope+" .jxGridCol" + idx + " .jxGridCellContent";
+        col.rule = Jx.Styles.insertCssRule(selector, dec, styleSheet);
+        col.rule.style.width = col.getWidth() + "px";
 
-        }, this);
+      }, this);
     },
 
     updateRule: function(column) {
@@ -30448,7 +31919,23 @@
     }
 
 });
-// $Id: row.js 887 2010-04-30 12:46:38Z pagameba $
+/*
+---
+
+name: Jx.Row
+
+description: Holds information related to display of rows in the grid.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+
+provides: [Jx.Row]
+
+...
+ */
+// $Id: row.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Row
  *
@@ -30466,7 +31953,7 @@
  */
 Jx.Row = new Class({
 
-	Family: 'Jx.Row',
+  Family: 'Jx.Row',
     Extends : Jx.Object,
 
     options : {
@@ -30500,12 +31987,12 @@
          * Option: headerWidth
          * The width of the row header. Make it null or 'auto' to auto-calculate
          */
-        headerWidth : 20,
+        headerWidth : 40,
         /**
          * Option: headerColumn
          * The name of the column in the model to use as the header
          */
-        headerColumn : 'id'
+        headerColumn : null
     },
     /**
      * Property: grid
@@ -30540,52 +32027,43 @@
      * APIMethod: getGridRowElement
      * Used to create the TR for the main grid row
      */
-    getGridRowElement : function (row) {
-
-        var tr = new Element('tr');
-        //tr.setStyle('height', this.getHeight());
-        if (this.options.alternateRowColors) {
-            tr.className = (this.grid.getModel().getPosition() % 2) ? this.options.rowClasses.even
-                    : this.options.rowClasses.odd;
-        } else {
-            tr.className = this.options.rowClasses.all;
-        }
-        tr.store('jxRowData', {row: row});
-        tr.addClass('jxGridRow'+row);
+    getGridRowElement : function (row, text) {
+        var o = this.options,
+            rc = o.rowClasses,
+            c = o.alternateRowColors ?(row % 2 ? rc.even : rc.odd) : rc.all,
+            tr = new Element('tr', {
+              'class' : 'jxGridRow'+row+' '+ c,
+              html: text || ''
+            });
         return tr;
     },
     /**
      * Method: getRowHeaderCell
      * creates the TH for the row's header
      */
-    getRowHeaderCell : function () {
-        //get and set text for element
-        var model = this.grid.getModel();
-        var th = new Element('th', {
-            'class' : 'jxGridRowHead'
-        });
-        var col = this.grid.columns.getByName(this.options.headerColumn);
-        var el = col.getHTML();
-        el.inject(th);
-        th.store('jxCellData',{
-        	row: model.getPosition(),
-        	rowHeader: true
-        });
-        return th;
-
+    getRowHeaderCell : function (text) {
+      text = text ? '<span class="jxGridCellContent">'+text + '</span>' : '';
+      return new Element('th', {
+        'class' : 'jxGridRowHead',
+        html: text
+      });
     },
     /**
      * APIMethod: getRowHeaderWidth
      * determines the row header's width.
      */
     getRowHeaderWidth : function () {
-        //this can be drawn from the column for the
-        //header field
-    	var col = this.grid.columns.getByName(this.options.headerColumn);
-    	if (!$defined(col.getWidth())) {
-    		col.calculateWidth(true);
-    	}
-        return col.getWidth();
+      var col, width;
+      if (this.options.headerColumn) {
+        col = this.grid.columns.getByName(this.options.headerColumn);
+        if (!$defined(col.getWidth())) {
+          col.calculateWidth(true);
+        }
+        width = col.getWidth();
+      } else {
+        width = this.options.headerWidth;
+      }
+      return width;
     },
 
     /**
@@ -30593,66 +32071,78 @@
      * determines and returns the height of a row
      */
     getHeight : function (row) {
-        //this should eventually compute a height, however, we would need
-        //a fixed width to do so reliably. For right now, we use a fixed height
-        //for all rows.
-    	if ((!$defined(this.options.rowHeight) || this.options.rowHeight === 'auto') && $defined(this.heights[row])) {
-    		return this.heights[row];
-    	} else if (Jx.type(this.options.rowHeight === 'number')) {
-    		return this.options.rowHeight;
-    	}
+      //this should eventually compute a height, however, we would need
+      //a fixed width to do so reliably. For right now, we use a fixed height
+      //for all rows.
+      if ((!$defined(this.options.rowHeight) || this.options.rowHeight === 'auto') && $defined(this.heights[row])) {
+        return this.heights[row];
+      } else if (Jx.type(this.options.rowHeight === 'number')) {
+        return this.options.rowHeight;
+      }
     },
     calculateHeights : function () {
-    	//grab all rows in the grid body
-      document.id(this.grid.gridTableBody).getChildren().each(function(row){
-        row = document.id(row);
-        var data = row.retrieve('jxRowData');
-        var s = row.getContentBoxSize();
-        this.heights[data.row] = s.height;
-      },this);
-      document.id(this.grid.rowTableHead).getChildren().each(function(row){
-        row = document.id(row);
-        var data = row.retrieve('jxRowData');
-        if (data) {
+      if (this.options.rowHeight === 'auto' || !$defined(this.options.rowHeight)) {
+        //grab all rows in the grid body
+        document.id(this.grid.gridTableBody).getChildren().each(function(row){
+          row = document.id(row);
+          var data = row.retrieve('jxRowData');
           var s = row.getContentBoxSize();
-          this.heights[data.row] = Math.max(this.heights[data.row],s.height);
-          if (Browser.Engine.webkit) {
-              //for some reason webkit (Safari and Chrome)
-              this.heights[data.row] -= 1;
+          this.heights[data.row] = s.height;
+        },this);
+        document.id(this.grid.rowTableHead).getChildren().each(function(row){
+          row = document.id(row);
+          var data = row.retrieve('jxRowData');
+          if (data) {
+            var s = row.getContentBoxSize();
+            this.heights[data.row] = Math.max(this.heights[data.row],s.height);
+            if (Browser.Engine.webkit) {
+                //for some reason webkit (Safari and Chrome)
+                this.heights[data.row] -= 1;
+            }
           }
-        }
-      },this);
-    	
+        },this);
+      } else {
+        document.id(this.grid.rowTableHead).getChildren().each(function(row,idx){
+          this.heights[idx] = this.options.rowHeight
+        }, this);
+      }
     },
-    
+
     createRules: function(styleSheet, scope) {
+      if (this.options.rowHeight === 'auto' || !$defined(this.options.rowHeight)) {
         this.grid.gridTableBody.getChildren().each(function(row, idx) {
-            var selector = scope+' .jxGridRow'+idx + ', ' + scope + ' .jxGridRow'+idx+' .jxGridCellContent';
-            var rule = Jx.Styles.insertCssRule(selector, '', styleSheet);
+            var height = this.getHeight(idx),
+                selector = scope+' .jxGridRow'+idx + ', ' + scope + ' .jxGridRow'+idx+' .jxGridCellContent',
+                rule = Jx.Styles.insertCssRule(selector, '', styleSheet);
             this.rules.set('jxGridRow'+idx, rule);
-            rule.style.height = this.heights[idx] + "px";
+            rule.style.height = height + "px";
 
             if (Browser.Engine.webkit) {
                 selector += " th";
                 var thRule = Jx.Styles.insertCssRule(selector, '', styleSheet);
-                thRule.style.height = this.heights[idx] + "px";
-                
+                thRule.style.height = height + "px";
+
                 this.rules.set('th_jxGridRow'+idx, thRule);
             }
 
         }, this);
+      } else {
+        var rule = Jx.Styles.insertCssRule('.jxGridCellContent', '', styleSheet);
+        rule.style.height = this.options.rowHeight + 'px';
+      }
     },
-    
-    updateRules: function() {
-      this.grid.gridTableBody.getChildren().each(function(row, idx) {
-        var h = this.heights[idx] + "px";
-        this.rules.get('jxGridRow'+idx).style.height = h;
-        if (Browser.Engine.webkit) {
-          this.rules.get('th_jxGridRow'+idx).style.height = h;
-        }
-      }, this);
-    },
-    
+
+    // TODO: appears to be unused?
+    // updateRules: function() {
+    //   this.grid.gridTableBody.getChildren().each(function(row, idx) {
+    //     var h = this.heights[idx] + "px";
+    //     this.rules.get('jxGridRow'+idx).style.height = h;
+    //     if (Browser.Engine.webkit) {
+    //       this.rules.get('th_jxGridRow'+idx).style.height = h;
+    //     }
+    //   }, this);
+    // },
+
     /**
      * APIMethod: useHeaders
      * determines and returns whether row headers should be used
@@ -30687,7 +32177,23 @@
         return this.options.headerColumn;
     }
 });
-// $Id: plugin.js 822 2010-03-31 11:28:31Z conrad.barthelmes $
+/*
+---
+
+name: Jx.Plugin
+
+description: Base class for all plugins
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+
+provides: [Jx.Plugin]
+
+...
+ */
+// $Id: plugin.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Plugin
  *
@@ -30744,7 +32250,23 @@
             this.setBusy(true);
         }
     }
-});// $Id: plugin.grid.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Plugin.Grid
+
+description: Namespace for grid plugins
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin
+
+provides: [Jx.Plugin.Grid]
+
+...
+ */
+// $Id: plugin.grid.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Plugin.Grid
  * Grid plugin namespace
@@ -30755,7 +32277,37 @@
  *
  * This file is licensed under an MIT style license
  */
-Jx.Plugin.Grid = {};// $Id: grid.js 897 2010-05-07 20:03:33Z conrad.barthelmes $
+Jx.Plugin.Grid = {};/*
+---
+
+name: Jx.Grid
+
+description: A tabular control that has fixed scrolling headers on the rows and columns like a spreadsheet.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+ - Jx.Styles
+ - Jx.Layout
+ - Jx.Columns
+ - Jx.Row
+ - Jx.Plugin.Grid
+ - Jx.Store
+ - Jx.List
+
+provides: [Jx.Grid]
+
+css:
+ - grid
+
+images:
+ - table_col.png
+ - table_row.png
+
+...
+ */
+// $Id: grid.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Grid
  *
@@ -30785,7 +32337,7 @@
  * Events:
  * gridCellEnter(cell, list) - called when the mouse enters a cell
  * gridCellLeave(cell, list) - called when the mouse leaves a cell
- * gridCellSelect(cell) - called when a cell is clicked
+ * gridCellClick(cell) - called when a cell is clicked
  * gridMouseLeave() - called when the mouse leaves the grid at any point.
  *
  *
@@ -30796,581 +32348,706 @@
  * This file is licensed under an MIT style license
  */
 Jx.Grid = new Class({
+  Family : 'Jx.Grid',
+  Extends: Jx.Widget,
+  Binds: ['storeLoaded', 'clickColumnHeader', 'moveColumnHeader', 'clickRowHeader', 'moveRowHeader', 'clickCell', 'moveCell', 'leaveGrid', 'resize', 'drawStore', 'scroll', 'addRow', 'removeRow', 'removeRows', 'updateRow'],
 
-    Family : 'Jx.Grid',
-    Extends : Jx.Widget,
-
-    Binds: ['modelChanged','render','addRow','removeRow','removeRows',
-            'onSelect', 'onUnselect','onMouseEnter','onMouseLeave'],
-    
-    options : {
-        /**
-         * Option: parent
-         * the HTML element to create the grid inside. The grid will resize
-         * to fill the domObj.
-         */
-        parent : null,
-
-        /**
-         * Options: columns
-         * an object consisting of a columns array that defines the individuals
-         * columns as well as containing any options for Jx.Grid.Columns or
-         * a Jx.Grid.Columns object itself.
-         */
-        columns : {
-            columns : []
-        },
-
-        /**
-         * Option: row
-         * Either a Jx.Grid.Row object or a json object defining options for
-         * the class
-         */
-        row : null,
-
-        /**
-         * Option: plugins
-         * an array containing Jx.Grid.Plugin subclasses or an object
-         * that indicates the name of a predefined plugin and its options.
-         */
-        plugins : [],
-
-        /**
-         * Option: model
-         * An instance of Jx.Store
-         */
-        model : null,
-
-        deferRender: true
-
-    },
+  /**
+   * Property: pluginNamespace
+   * the required variable for plugins
+   */
+  pluginNamespace: 'Grid',
+  
+  options: {
     /**
-     * Property: model
-     * holds a reference to the <Jx.Store> that is the model for this
-     * grid
+     * Option: parent
+     * the HTML element to create the grid inside. The grid will resize
+     * to fill the domObj.
      */
-    model : null,
+    parent: null,
+    
+    template: "<div class='jxWidget'><div class='jxGridContainer jxGridRowCol'></div><div class='jxGridContainer jxGridColumnsContainer'><table class='jxGridTable jxGridHeader jxGridColumns'><thead class='jxGridColumnHead'></thead></table></div><div class='jxGridContainer jxGridHeader jxGridRowContainer'><table class='jxGridTable jxGridRows'><thead class='jxGridRowBody'></thead></table></div><div class='jxGridContainer jxGridContentContainer'><table class='jxGridTable jxGridContent'><tbody class='jxGridTableBody'></tbody></table></div></div>",
+    
     /**
-     * Property: columns
-     * holds a reference to the columns object
+     * Options: columns
+     * an object consisting of a columns array that defines the individuals
+     * columns as well as containing any options for Jx.Grid.Columns or
+     * a Jx.Grid.Columns object itself.
      */
-    columns : null,
+    columns: null,
+    
     /**
-     * Property: row
-     * Holds a reference to the row object
+     * Option: row
+     * Either a Jx.Grid.Row object or a json object defining options for
+     * the class
      */
     row : null,
-    /**
-     * Property: styleSheet
-     * the name of the dynamic style sheet to use for manipulating styles
-     */
-    styleSheet: 'JxGridStyles',
-    /**
-     * Property: pluginNamespace
-     * the required variable for plugins
-     */
-    pluginNamespace: 'Grid',
-    /**
-     * Property: selection
-     * holds the Jx.Selection instance used by the cell lists
-     */
-    selection: null,
-    /**
-     * Property: lists
-     * An array of Jx.List instances, one per row. All of them use the same
-     * Jx.Selection instance
-     */
-    lists: [],
 
     /**
-     * Constructor: Jx.Grid
+     * Option: store
+     * An instance of Jx.Store
      */
-    init : function () {
-        this.uniqueId = this.generateId('jxGrid_');
-        
-        var opts;
-        if ($defined(this.options.model)
-                && this.options.model instanceof Jx.Store) {
-            this.model = this.options.model;
-            this.model.addEvent('storeColumnChanged', this.modelChanged);
-            this.model.addEvent('storeSortFinished', this.render);
-            this.model.addEvent('storeRecordAdded', this.addRow);
-            this.model.addEvent('storeRecordRemoved', this.removeRow);
-            this.model.addEvent('storeMultipleRecordsRemoved', this.removeRows);
-        }
+    store: null
+  },
+   
+  classes: $H({
+    domObj: 'jxWidget',
+    columnContainer: 'jxGridColumnsContainer',
+    colObj: 'jxGridColumns',
+    colTableBody: 'jxGridColumnHead',
+    rowContainer: 'jxGridRowContainer',
+    rowObj: 'jxGridRows',
+    rowColContainer: 'jxGridRowCol',
+    rowTableBody: 'jxGridRowBody',
+    contentContainer: 'jxGridContentContainer',
+    gridObj: 'jxGridContent',
+    gridTableBody: 'jxGridTableBody'
+  }),
+  
+  /**
+   * Property: columns
+   * holds a reference to the columns object
+   */
+  columns: null,
+  
+  /**
+   * Property: row
+   * Holds a reference to the row object
+   */
+  row: null,
+  
+  parameters: ['store', 'options'],
+  
+  /**
+   * Property: model
+   * holds a reference to the <Jx.Store> that is the model for this
+   * grid
+   */
+  store: null,
+  
+  /**
+   * Property: styleSheet
+   * the name of the dynamic style sheet to use for manipulating styles
+   */
+  styleSheet: 'JxGridStyles',
+  
+  /**
+   * Property: hooks
+   * a {Hash} of event names for tracking which events have actually been attached
+   * to the grid.
+   */
+  hooks: null,
+  
+  /**
+   * Property: uniqueId
+   * an auto-generated id that is assigned as a class name to the grid's
+   * container for scoping generated CSS rules to just this grid
+   */
+  uniqueId: null,
+  
+  /**
+   * Constructor: Jx.Grid
+   */
+  init: function() {
+    this.uniqueId = this.generateId('jxGrid_');
+    this.store = this.options.store;
+    var options = this.options,
+        opts;
 
-        if ($defined(this.options.columns)) {
-            if (this.options.columns instanceof Jx.Columns) {
-                this.columns = this.options.columns;
-            } else if (Jx.type(this.options.columns) === 'object') {
-                opts = this.options.columns;
-                opts.grid = this;
-                this.columns = new Jx.Columns(opts);
-            }
-        }
+    if ($defined(options.row)) {
+      if (options.row instanceof Jx.Row) {
+        this.row = options.row;
+        this.row.grid = this;
+      } else if (Jx.type(options.row) == 'object') {
+        this.row = new Jx.Row($extend({grid: this}, options.row));
+      }
+    } else {
+      this.row = new Jx.Row({grid: this});
+    }
 
-        //check for row
-        if ($defined(this.options.row)) {
-            if (this.options.row instanceof Jx.Row) {
-                this.row = this.options.row;
-            } else if (Jx.type(this.options.row) === "object") {
-                opts = this.options.row;
-                opts.grid = this;
-                this.row = new Jx.Row(opts);
-            }
-        } else {
-            this.row = new Jx.Row({grid: this});
+    if ($defined(options.columns)) {
+        if (options.columns instanceof Jx.Columns) {
+            this.columns = options.columns;
+            this.columns.grid = this;
+        } else if (Jx.type(options.columns) === 'object') {
+            this.columns = new Jx.Columns($extend({grid:this}, options.columns));
         }
+    } else {
+      this.columns = new Jx.Columns({grid: this});
+    }
+    
+    this.hooks = $H({
+      'gridScroll': false,
+      'gridColumnEnter': false,
+      'gridColumnLeave': false,
+      'gridColumnClick': false,
+      'gridRowEnter': false,
+      'gridRowLeave': false,
+      'gridRowClick': false,
+      'gridCellClick': false,
+      'gridCellEnter': false,
+      'gridCellLeave': false,
+      'gridMouseLeave': false
+    });
+    
+    if (options.parent) {
+      this.addTo(options.parent)
+    }
+    
+    this.parent();
+  },
+  
+  wantEvent: function(eventName) {
+    console.log('wantEvent ' + eventName);
+    var hook = this.hooks.get(eventName);
+    if (hook === false) {
+      console.log('hooking event ' + eventName);
+      switch(eventName) {
+        case 'gridColumnEnter':
+        case 'gridColumnLeave':
+          this.colObj.addEvent('mousemove', this.moveColumnHeader);
+          this.hooks.set({
+            'gridColumnEnter': true,
+            'gridColumnLeave': true
+          });
+          break;
+        case 'gridColumnClick':
+          this.colObj.addEvent('click', this.clickColumnHeader);
+          this.hooks.set({
+            'gridColumnClick': true
+          });
+          break;
+        case 'gridRowEnter':
+        case 'gridRowLeave':
+          this.rowObj.addEvent('mousemove', this.moveRowHeader);
+          this.hooks.set({
+            'gridRowEnter': true,
+            'gridRowLeave': true
+          });
+          break;
+        case 'gridRowClick':
+          this.rowObj.addEvent('click', this.clickRowHeader);
+          this.hooks.set({
+            'gridRowClick': true
+          });
+          break;
+        case 'gridCellEnter':
+        case 'gridCellLeave':
+          this.gridObj.addEvent('mousemove', this.moveCell);
+          this.hooks.set({
+            'gridCellEnter': true,
+            'gridCellLeave': true
+          });
+          break;
+        case 'gridCellClick':
+          this.gridObj.addEvent('click', this.clickCell);
+          this.hooks.set('gridCellClick', true);
+          break;
+        case 'gridMouseLeave':
+          this.rowObj.addEvent('mouseleave', this.leaveGrid);
+          this.colObj.addEvent('mouseleave', this.leaveGrid);
+          this.gridObj.addEvent('mouseleave', this.leaveGrid);
+          this.hooks.set('gridMouseLeave', true);
+          break;
+        case 'gridScroll':
+          this.contentContainer.addEvent('scroll', this.scroll);
+        default:
+          break;
+      }
+    } else {
+      console.log('event is already hooked');
+    }
+  },
+  
+  /**
+   * Method: scroll
+   * handle the grid scrolling by updating the position of the headers
+   */
+  scroll : function () {
+      this.columnContainer.scrollLeft = this.contentContainer.scrollLeft;
+      this.rowContainer.scrollTop = this.contentContainer.scrollTop;
+  },
+  
+  /**
+   * APIMethod: render
+   * Create the grid for the current model
+   */
+  render: function() {
+    this.parent();
+    var store = this.store;
+    
+    this.domObj.addClass(this.uniqueId);
+    new Jx.Layout(this.domObj, {
+      onSizeChange: this.resize
+    });
+    
+    if (store instanceof Jx.Store) {
+      store.addEvent('storeDataLoaded', this.storeLoaded);
+      store.addEvent('storeSortFinished', this.drawStore);
+      store.addEvent('storeRecordAdded', this.addRow);
+      store.addEvent('storeColumnChanged', this.updateRow);
+      store.addEvent('storeRecordRemoved', this.removeRow);
+      store.addEvent('storeMultipleRecordsRemoved', this.removeRows);
+      if (this.store.loaded) {
+        this.storeLoaded();
+      }
+    }
+    if (!this.columns.useHeaders()) {
+      this.columnContainer.dispose();
+    } else {
+      this.wantEvent('gridScroll');
+    }
+    
+    if (!this.row.useHeaders()) {
+      this.rowContainer.dispose();
+    } else {
+      this.wantEvent('gridScroll');
+    }
 
-        //initialize the grid
-        this.domObj = new Element('div', {'class':this.uniqueId});
-        var l = new Jx.Layout(this.domObj, {
-            onSizeChange : this.resize.bind(this)
-        });
-        
-        //we need to know if the mouse leaves the grid so we can turn off prelighters and the such
-        this.domObj.addEvent('mouseleave',function(){
-            this.fireEvent('gridMouseLeave');
-        }.bind(this));
+    this.contentContainer.setStyle('overflow', 'auto');
+    
+    // very hacky!
+    this.hooks.each(function(value, key) {
+      if (value) {
+        this.hooks.set(key, false);
+        this.wantEvent(key);
+      }
+    }, this);
+  },
+  
+  /**
+   * APIMethod: resize
+   * resize the grid to fit inside its container.  This involves knowing something
+   * about the model it is displaying (the height of the column header and the
+   * width of the row header) so nothing happens if no model is set
+   */
+  resize: function() {
+    var p = this.domObj.getParent(),
+        parentSize = p.getSize(),
+        colHeaderHeight = 0,
+        rowHeaderWidth = 0;
+    
+    if (this.columns.useHeaders()) {
+      colHeaderHeight = this.columns.getHeaderHeight();
+    }
+    
+    if (this.row.useHeaders()) {
+      rowHeaderWidth = this.row.getRowHeaderWidth();
+    }
+    
+    this.rowColContainer.setBorderBoxSize({
+        width : rowHeaderWidth,
+        height : colHeaderHeight
+    });
+    
+    
+    this.columnContainer.setStyles({
+      top: 0,
+      left: rowHeaderWidth
+    }).setBorderBoxSize({
+      width: parentSize.x - rowHeaderWidth,
+      height: colHeaderHeight
+    });
 
-        if (this.options.parent) {
-            this.addTo(this.options.parent);
-        }
+    this.rowContainer.setStyles({
+      top: colHeaderHeight,
+      left: 0
+    }).setBorderBoxSize({
+      width: rowHeaderWidth,
+      height: parentSize.y - colHeaderHeight
+    });
 
-        //top left corner
-        this.rowColObj = new Element('div', {
-            'class' : 'jxGridContainer'
-        });
-
-        //holds the column headers
-        this.colObj = new Element('div', {
-            'class' : 'jxGridContainer'
-        });
-        this.colTable = new Element('table', {
-            'class' : 'jxGridTable jxGridHeader'
-        });
-        this.colTableBody = new Element('thead');
-        this.colTable.appendChild(this.colTableBody);
-        this.colObj.appendChild(this.colTable);
-
-        //hold the row headers
-        this.rowObj = new Element('div', {
-            'class' : 'jxGridContainer jxGridHeader'
-        });
-        this.rowTable = new Element('table', {
-            'class' : 'jxGridTable'
-        });
-        this.rowTableHead = new Element('thead');
-        this.rowTable.appendChild(this.rowTableHead);
-        this.rowObj.appendChild(this.rowTable);
-
-        //The actual body of the grid
-        this.gridObj = new Element('div', {
-            'class' : 'jxGridContainer',
-            styles : {
-                overflow : 'auto'
+    this.contentContainer.setStyles({
+      top: colHeaderHeight,
+      left: rowHeaderWidth
+    }).setBorderBoxSize({
+      width: parentSize.x - rowHeaderWidth,
+      height: parentSize.y - colHeaderHeight
+    });
+  },
+  
+  /**
+   * APIMethod: setStore
+   * set the store for the grid to display.  If a store is attached to the grid
+   * it is removed and the new store is displayed.
+   *
+   * Parameters:
+   * store - {Object} the store to use for this grid
+   */
+  setStore: function(store) {
+    if (store instanceof Jx.Store) {
+      this.store = store;
+      this.render();
+      this.domObj.resize();
+    } else {
+      this.destroyGrid();
+    }
+  },
+  
+  /**
+   * APIMethod: getStore
+   * gets the store set for this grid.
+   */
+  getStore: function() { 
+    return this.store 
+  },
+  
+  storeLoaded: function(store, response) {
+    var store = this.store,
+        template = '',
+        tr,
+        columns = [],
+        useRowHeaders = this.row.useHeaders();
+    this.fireEvent('beginCreateGrid');
+    
+    this.gridObj.getElement('tbody').empty();
+    
+    // todo consider moving whole thing into Jx.Columns ??
+    store.options.columns.each(function(col, index) {
+      // if (useRowHeaders && 
+      //     $defined(response.meta) && 
+      //     $defined(response.meta.rowHeaderColumn) && 
+      //     col.name == response.meta.rowHeaderColumn) {
+      //   this.row.options.headerColumn = col.name;
+      //   useRowHeaders = false; // just skip this step, we aren't really turning them off
+      // }
+      if (!this.columns.getByName(col.name)) {
+        var renderer = new Jx.Grid.Renderer.Text();
+        if ($defined(col.renderer)) {
+          if ($type(col.renderer) == 'string') {
+            if (Jx.Grid.Renderer[col.renderer.capitalize()]) {
+              renderer = new Jx.Grid.Renderer[col.renderer.capitalize()]();
             }
-        });
-        this.gridTable = new Element('table', {
-            'class' : 'jxGridTable jxGridContent'
-        });
-        this.gridTableBody = new Element('tbody');
-        this.gridTable.appendChild(this.gridTableBody);
-        this.gridObj.appendChild(this.gridTable);
-
-        var target = this;
-
-        this.domObj.appendChild(this.rowColObj);
-        this.domObj.appendChild(this.rowObj);
-        this.domObj.appendChild(this.colObj);
-        this.domObj.appendChild(this.gridObj);
-
-        this.gridObj.addEvent('scroll', this.onScroll.bind(this));
-
-        //setup the selection
-        this.selection = new Jx.Selection();
-        this.selection.addEvents({
-            select: this.onSelect,
-            unselect: this.onUnselect
-        });
-        this.parent();
-
-        this.domObj.store('grid', this);
-    },
-
-    /**
-     * Method: onScroll
-     * handle the grid scrolling by updating the position of the headers
-     */
-    onScroll : function () {
-        this.colObj.scrollLeft = this.gridObj.scrollLeft;
-        this.rowObj.scrollTop = this.gridObj.scrollTop;
-    },
-
-
-    /**
-     * APIMethod: resize
-     * resize the grid to fit inside its container.  This involves knowing something
-     * about the model it is displaying (the height of the column header and the
-     * width of the row header) so nothing happens if no model is set
-     */
-    resize : function () {
-        if (!this.model) {
-            return;
+          } else if ($type(col.renderer) == 'object' && 
+                     $defined(col.renderer.type) && 
+                     Jx.Grid.Renderer[col.renderer.type.capitalize()]) {
+            renderer = new Jx.Grid.Renderer[col.renderer.type.capitalize()](col.renderer);
+          }
         }
-
-        var colHeight = this.columns.useHeaders() ? this.columns
-                .getHeaderHeight() : 1;
-        var rowWidth = this.row.useHeaders() ? this.row
-                .getRowHeaderWidth() : 1;
-
-        var size = this.domObj.getContentBoxSize();
-
-
-        
-        /* -1 because of the right/bottom borders */
-        this.rowColObj.setStyles({
-            width : rowWidth - 1,
-            height : colHeight - 1
+        var format = $defined(col.format) ? col.format : null;
+        if (format) {
+          if ($type(format) == 'string' && 
+              $defined(Jx.Formatter[format.capitalize()])) {
+            renderer.options.formatter = new Jx.Formatter[format.capitalize()]();
+          } else if ($type(format) == 'object' && 
+                     $defined(format.type) && 
+                     $defined(Jx.Formatter[format.type.capitalize()])) {
+             renderer.options.formatter = new Jx.Formatter[format.type.capitalize()](format);
+          }
+        }
+        var template = "<span class='jxGridCellContent'>"+ ($defined(col.label) ? col.label : col.name).capitalize() + "</span>";
+        var column = new Jx.Column({
+          grid: this,
+          template: template,
+          renderMode: $defined(col.renderMode) ? col.renderMode : $defined(col.width) ? 'fixed' : 'fit',
+          width: $defined(col.width) ? col.width : null,
+          isEditable: $defined(col.editable) ? col.editable : false,
+          isSortable: $defined(col.sortable) ? col.sortable : false,
+          isResizable: $defined(col.resizable) ? col.resizable : false,
+          isHidden: $defined(col.hidden) ? col.hidden : false,
+          name: col.name || '',
+          renderer: renderer 
         });
-        this.rowObj.setStyles({
-            top : colHeight,
-            left : 0,
-            width : rowWidth - 1,
-            height : size.height - colHeight - 1
-        });
-
-        this.colObj.setStyles({
-            top : 0,
-            left : rowWidth,
-            width : size.width - rowWidth - 1,
-            height : colHeight - 1
-        });
-
-        this.gridObj.setStyles({
-            top : colHeight,
-            left : rowWidth,
-            width : size.width - rowWidth - 1,
-            height : size.height - colHeight - 1
-        });
-
-    },
-
-    resizeRowsCols: function (mode) {
-        mode = $defined(mode) ? mode : 'all';
-
-        if (mode === 'all' || mode === 'columns') {
-            Jx.Styles.removeStyleSheet(this.styleSheet + "Columns");
-            Jx.Styles.enableStyleSheet(this.styleSheet + "Columns");
-            this.columns.calculateWidths();
-            this.columns.createRules(this.styleSheet + "Columns", "."+this.uniqueId);
+        columns.push(column);
+      }
+    }, this);
+    this.columns.addColumns(columns);
+    if (this.columns.useHeaders()) {
+      tr = new Element('tr'),
+      this.columns.getHeaders(tr);
+      this.colObj.getElement('thead').empty().adopt(tr);
+    }
+    this.columns.calculateWidths();
+    this.columns.createRules(this.styleSheet+'Columns', '.'+this.uniqueId);
+    this.fireEvent('doneCreateGrid')
+    this.drawStore();
+  },
+  
+  /**
+   * APIMethod: addRow
+   * Adds a row to the table. Can add to either the beginning or the end 
+   * based on passed flag
+   */
+  addRow: function (store, record, position) {
+    if (this.store.loaded) {
+      if (position === 'bottom') {
+        this.store.last();
+      } else {
+        this.store.first();
+      }
+      this.drawRow(record, this.store.index, position)
+    }
+  },
+  
+  updateRow: function(index, column, oldvalue, newvalue) {
+    var record = this.store.getRecord(index);
+    this.drawRow(record, index, 'replace');
+  },
+  
+  removeRow: function (store, index) {
+    this.gridObj.deleteRow(index);
+    this.rowObj.deleteRow(index);
+  },
+  
+  removeRows: function (store, first, last) {
+    for (var i = first; i <= last; i++) {
+        this.removeRow(store, first);
+    }
+  },
+  
+  setColumnWidth: function(column, width) {
+    if (column) {
+      column.width = width;
+      if (column.rule) {
+        column.rule.style.width = width + 'px';
+      }
+      if (column.cellRule) {
+        column.cellRule.style.width = width + 'px';
+      }
+    }
+  },
+  
+  /**
+   * Method: drawStore
+   * clears the grid and redraws the store.  Does not draw the column headers,
+   * that is handled by the render() method
+   */
+  drawStore: function() {
+    console.profile();
+    this.domObj.resize();
+    this.gridTableBody.empty();
+    if (this.row.useHeaders()) {
+      this.rowTableBody.empty();
+    }
+    this.store.each(function(record,index) {
+      this.drawRow(record, index);
+    }, this);
+    console.profileEnd();
+  },
+  
+  /**
+   * Method: drawRow
+   * this method does the heavy lifting of drawing a single record into the grid
+   *
+   * Parameters:
+   * record - {Jx.Record} the record to render
+   * index - {Integer} the row index of the record in the store
+   * position - {String} 'top' or 'bottom' (default 'bottom') position to put
+   *     the new row in the grid.
+   */
+  drawRow: function(record, index, position) {
+    var columns = this.columns,
+        body = this.gridTableBody,
+        row = this.row,
+        rowHeaders = row.useHeaders(),
+        autoRowHeight = row.options.rowHeight == 'auto',
+        rowBody = this.rowTableBody,
+        rowHeaderColumn,
+        rowHeaderColumnIndex,
+        renderer,
+        formatter, 
+        getData,
+        tr,
+        th,
+        text = index + 1;
+    if (!$defined(position) || !['top','bottom','replace'].contains(position)) {
+      position = 'bottom';
+    }
+    tr = row.getGridRowElement(index, '');
+    columns.getRow(tr, record);
+    if (position == 'replace' && index < body.childNodes.length) {
+      tr.inject(body.childNodes[index], 'after');
+      body.childNodes[index].dispose();
+    } else {
+      tr.inject(body, position);
+    }
+    if (rowHeaders) {
+      if (row.options.headerColumn) {
+        rowHeaderColumn = columns.getByName(row.options.headerColumn);
+        renderer = rowHeaderColumn.options.renderer;
+        if (!renderer.domInsert) {
+          formatter = rowHeaderColumn.options.formatter;
+          rowHeaderColumnIndex = columns.columns.indexOf(rowHeaderColumn);
+          getData = function(record) {
+            var data = {},
+                text = '';
+            if (renderer.options.textTemplate) {
+              text = store.fillTemplate(null, renderer.options.textTemplate, renderer.columnsNeeded);
+            } else {
+              text = record.data.get(rowHeaderColumn.name);
+            }
+            data['col'+rowHeaderColumnIndex] = text;
+            return data;
+          };
+          text = rowHeaderColumn.getTemplate(rowHeaderColumnIndex).substitute(getData(record));
+        } else {
+          text = '';
         }
-        
-        if (mode === 'all' || mode === 'rows') {
-            Jx.Styles.removeStyleSheet(this.styleSheet + "Rows");
-            Jx.Styles.enableStyleSheet(this.styleSheet + "Rows");
-            this.row.calculateHeights();
-            this.row.createRules(this.styleSheet + "Rows", "."+this.uniqueId);
+      }
+      th = row.getRowHeaderCell(text);
+      if (row.options.headerColumn && renderer.domInsert) {
+        th.adopt(rowHeaderColumn.getHTML());
+      };
+      if (autoRowHeight) {
+        th.setStyle('height', tr.childNodes[0].getContentBoxSize().height);
+      }
+      var rh = new Element('tr').adopt(th);
+      if (position == 'replace' && index < rowBody.childNodes.length) {
+        rh.inject(rowBody.childNodes[index], 'after');
+        rowBody.childNodes[index].dispose();
+      } else {
+        rh.inject(rowBody, position);
+      }
+    }
+  },
+  
+  clickColumnHeader: function(e) {
+    var target = e.target;
+    if (target.getParent('thead')) {
+      target = target.tagName == 'TH' ? target : target.getParent('th');
+      this.fireEvent('gridColumnClick', target)
+    }
+  },
+  
+  moveColumnHeader: function(e) {
+    var target = e.target;
+    target = target.tagName == 'TH' ? target : target.getParent('th.jxGridColHead');
+    if (target) {
+      if (this.hoverColumn != target) {
+        if (this.hoverColumn) {
+          this.fireEvent('gridColumnLeave', this.hoverColumn);
         }
-
-    },
-
-    /**
-     * APIMethod: setModel
-     * set the model for the grid to display.  If a model is attached to the grid
-     * it is removed and the new model is displayed. However, It needs to have
-     * the same columns
-     *
-     * Parameters:
-     * model - {Object} the model to use for this grid
-     */
-    setModel : function (model) {
-        this.model = model;
-        if (this.model) {
-            this.render();
-            this.domObj.resize();
+        if (!target.hasClass('jxGridColHead')) {
+          this.leaveGrid(e);
         } else {
-            this.destroyGrid();
+          this.hoverColumn = target;
+          this.fireEvent('gridColumnEnter', target);
         }
-    },
+      }
+    }
+  },
 
-    /**
-     * APIMethod: getModel
-     * gets the model set for this grid.
-     */
-    getModel : function () {
-        return this.model;
-    },
-
-    /**
-     * APIMethod: destroyGrid
-     * destroy the contents of the grid safely
-     */
-    destroyGrid : function () {
-
-        var n = this.colTableBody.cloneNode(false);
-        this.colTable.replaceChild(n, this.colTableBody);
-        this.colTableBody = n;
-
-        n = this.rowTableHead.cloneNode(false);
-        this.rowTable.replaceChild(n, this.rowTableHead);
-        this.rowTableHead = n;
-
-        n = this.gridTableBody.cloneNode(false);
-        this.gridTable.replaceChild(n, this.gridTableBody);
-        this.gridTableBody = n;
-
-        document.id(this.rowColObj).empty();
-        
-        if (Jx.Styles.isStyleSheetDefined(this.styleSheet)) {
-        	Jx.Styles.removeStyleSheet(this.styleSheet);
+  clickRowHeader: function(e) {
+    var target = e.target;
+    if (target.getParent('tbody')) {
+      target = target.tagName == 'TH' ? target : target.getParent('th'),
+      this.fireEvent('gridRowClick', target)
+    }
+  },
+  
+  moveRowHeader: function(e) {
+    var target = e.target;
+    target = target.tagName == 'TH' ? target : target.getParent('th.jxGridRowHead');
+    if (target) {
+      if (this.hoverRow != target) {
+        if (this.hoverRow) {
+          this.fireEvent('gridRowLeave', this.hoverRow);
         }
-
-    },
-
-    /**
-     * APIMethod: render
-     * Create the grid for the current model
-     */
-    render : function () {
-        this.destroyGrid();
-
-        this.fireEvent('beginCreateGrid', this);
-
-        if (this.model && this.model.loaded) {
-            var model = this.model;
-            var nColumns = this.columns.getColumnCount();
-            var nRows = model.count();
-            var th;
-
-            /* create header if necessary */
-            if (this.columns.useHeaders()) {
-                this.colTableBody.setStyle('visibility', 'visible');
-                var colHeight = this.columns.getHeaderHeight();
-                var trBody = new Element('tr', {
-                    styles : {
-                        height : colHeight
-                    }
-                });
-                this.colTableBody.appendChild(trBody);
-
-                var headerList = this.makeList(trBody);
-
-                this.columns.getHeaders(headerList);
-
-                /* one extra column at the end for filler */
-                th = new Element('th', {
-                    'class':'jxGridColHead',
-                    styles: {
-                      width: 1000,
-                      height: colHeight - 1
-                    }
-                }).inject(trBody);
-            } else {
-                //hide the headers
-                this.colTableBody.setStyle('visibility', 'hidden');
-            }
-
-            //This section actually adds the rows
-            this.model.first();
-            while (this.model.valid()) {
-                tr = this.row.getGridRowElement(this.model.getPosition());
-                var rl = this.makeList(tr);
-                this.gridTableBody.appendChild(tr);
-                //this.rowList.add(rl.container);
-
-                //Actually add the columns
-                this.columns.getColumnCells(rl);
-
-                if (this.model.hasNext()) {
-                    this.model.next();
-                } else {
-                    break;
-                }
-
-            }
-            
-            
-            //Moved rowheaders after other columns so we can figure the heights
-            //of each row (after render)
-            if (this.row.useHeaders()) {
-                this.rowTableHead.setStyle('visibility', 'visible');
-
-                //loop through all rows and add header
-                this.model.first();
-                while (this.model.valid()) {
-                    var tr = new Element('tr',{
-                    	'class': 'jxGridRow'+this.model.getPosition()
-                    });
-                    tr.store('jxRowData', {row:this.model.getPosition()});
-                    var rowHeaderList = this.makeList(tr);
-                    this.row.getRowHeader(rowHeaderList);
-                    this.rowTableHead.appendChild(tr);
-                    if (this.model.hasNext()) {
-                        this.model.next();
-                    } else {
-                        break;
-                    }
-                }
-                /* one extra row at the end for filler */
-                tr = new Element('tr').inject(this.rowTableHead);
-                th = new Element('th', {
-                    'class' : 'jxGridRowHead',
-                    styles : {
-                        width : this.row.getRowHeaderWidth(),
-                        height : 1000
-                    }
-                }).inject(tr);
-            } else {
-                //hide row headers
-                this.rowTableHead.setStyle('visibility', 'hidden');
-            }
-            
-            this.domObj.resize();
-            this.resizeRowsCols();
-            this.resize();
-
-            this.fireEvent('doneCreateGrid', this);
+        if (!target.hasClass('jxGridRowHead')) {
+          this.leaveGrid(e);
         } else {
-            this.model.load();
+          this.hoverRow = target;
+          this.fireEvent('gridRowEnter', target);
         }
-        
-    },
-
-    /**
-     * Method: modelChanged
-     * Event listener that is fired when the model changes in some way
-     */
-    modelChanged : function (row, col) {
-        //grab new TD
-        var column = this.columns.getIndexFromGrid(col);
-        var td = document.id(this.gridObj.childNodes[0].childNodes[0].childNodes[row].childNodes[column]);
-
-        var currentRow = this.model.getPosition();
-        this.model.moveTo(row);
-        // need to find out whether the header is used or not, to have the right reference back
-        var colIndex = this.options.row.useHeaders ? column+1 : column;
-        var newTD = this.columns.getColumnCell(this.columns.getByName(col),colIndex);
-        //get parent list
-        var list = td.getParent().retrieve('jxList');
-        list.replace(td, newTD);
-        this.columns.updateRule(col);
-        this.model.moveTo(currentRow);
-    },
-    
-    /**
-     * APIMethod: addRow
-     * Adds a row to the table. Can add to either the beginning or the end 
-     * based on passed flag
-     */
-    addRow: function (store, record, position) {
-        if (this.model.loaded) {
-            if (position === 'bottom') {
-                this.model.last();
-            } else {
-                this.model.first();
-                this.renumberGrid(0, 1);
-            }
-            
-            //row header
-            if (this.row.useHeaders()) {
-                var rowHeight = this.row.getHeight();
-                var tr = new Element('tr', {
-                    styles : {
-                        height : rowHeight
-                    }
-                });
-                var rowHeaderList = this.makeList(tr);
-                this.row.getRowHeader(rowHeaderList);
-                if (position === 'top') {
-                    tr.inject(this.rowTableHead, position);
-                } else {
-                    var lastTr = this.rowTableHead.children[this.rowTableHead.children.length - 1];
-                    tr.inject(lastTr, 'before');
-                }
-            }
-            tr = this.row.getGridRowElement();
-            tr.store('jxRowData', {row: this.model.getPosition()});
-            var rl = this.makeList(tr);
-            this.columns.getColumnCells(rl);
-            tr.inject(this.gridTableBody, position);
+      }
+    }
+  },
+  
+  clickCell: function(e) {
+    var target = e.target;
+    if (target.getParent('tbody')) {
+      target = target.tagName == 'TD' ? target : target.getParent('td');
+      this.fireEvent('gridCellClick', target);
+    }
+  },
+  
+  moveCell: function(e) {
+    var target = e.target,
+        data,
+        body,
+        row,
+        index,
+        column;
+    target = target.tagName == 'TD' ? target : target.getParent('td.jxGridCell');
+    if (target) {
+      if (this.hoverCell != target) {
+        if (this.hoverCell) {
+          this.fireEvent('gridCellLeave', this.hoverCell);
         }
-    },
-    
-    renumberGrid: function (offset, increment) {
-        var l = this.gridTable.rows.length;
-        for (var i = offset; i < l; i++) {
-            var r = document.id(this.gridTable.rows[i]);
-            var d = r.retrieve('jxRowData');
-            d.row += increment;
-            r.store('jxRowData', d);
-            $A(r.children).each(function(cell){
-                var d = cell.retrieve('jxCellData');
-                d.row += increment;
-                cell.store('jxCellData', d);
-            },this);
+        if (!target.hasClass('jxGridCell')) {
+          this.leaveGrid(e);
+        } else {
+          this.hoverCell = target;
+          this.getCellData(target);
+          this.fireEvent('gridCellEnter', target);
         }
-    },
-    
-    removeRow: function (store, index) {
-        this.gridTable.deleteRow(index);
-        this.rowTable.deleteRow(index);
-        this.renumberGrid(index, -1);
-    },
-    
-    removeRows: function (store, first, last) {
-      for (var i = first; i <= last; i++) {
-          this.removeRow(first);
       }
-    },
-    
-    /**
-     * Method: makeList
-     * utility method used to make row lists
-     *
-     * Parameters:
-     * container - the row to use as the Jx.List container
-     */
-    makeList: function (container) {
-        var l = new Jx.List(container, {
-            hover: true,
-            select: true
-        }, this.selection);
-        var target = this;
-        l.addEvents({
-            mouseenter: this.onMouseEnter,
-            mouseleave: this.onMouseLeave
-        });
-        this.lists.push(l);
-        return l;
-    },
+    }
+  },
+  
+  getCellData: function(cell) {
+    var data = null,
+        index,
+        column,
+        row;
+    if (!cell.hasClass('jxGridCell')) {
+      cell = cell.getParent('td.jxGridCell');
+    }
+    if (cell) {
+      // data = cell.retrieve('jxCellData');
+      if (!data) {
+        body = this.gridTableBody;
+        row = body.getChildren().indexOf(cell.getParent('tr'));
+        this.columns.columns.some(function(col,idx){
+          if (cell.hasClass('jxGridCol'+idx)) {
+            index = idx;
+            column = col;
+            return true;
+          }
+          return false;
+        })
+        data = {
+          row: row,
+          column: column,
+          index: index
+        };
+        cell.store('jxCellData', data);
+      }
+    }
+    return data;
+  },
+  
+  leaveGrid: function(e) {
+    this.hoverCell = null;
+    this.fireEvent('gridMouseLeave');
+  },
+  
+  changeText : function(lang) {
+      this.parent();
+      this.render();
+  },
+      
+  addEvent: function(name, fn) {
+    this.wantEvent(name);
+    this.parent(name, fn);
+  }
+});
+/*
+---
 
-    onSelect: function (cell, select) {
-        this.fireEvent('gridCellSelect', [cell,select,this]);
-    },
+name: Jx.Grid.Renderer
 
-    onUnselect: function (cell, select) {
-        this.fireEvent('gridCellUnselect', [cell,select,this]);
-    },
+description: Base class for all renderers. Used to create the contents of column.
 
-    onMouseEnter: function (cell, list) {
-        this.fireEvent('gridCellEnter', [cell,list,this]);
-    },
+license: MIT-style license.
 
-    onMouseLeave: function (cell, list) {
-        this.fireEvent('gridCellLeave', [cell,list,this]);
-    },
+requires:
+ - Jx.Grid
 
-    changeText : function(lang) {
-        this.parent();
-        /*
-        this.resize();
-        this.resizeRowsCols();
-        */
-        this.render();
-    }
+provides: [Jx.Grid.Renderer]
 
-});
+...
+ */
 /**
  * Class: Jx.Grid.Renderer
  * This is the base class and namespace for all grid renderers.
@@ -31401,6 +33078,8 @@
      * the store.
      */
   attached: null,
+  
+  domInsert: false,
 
   classes: $H({
     domObj: 'jxGridCellContent'
@@ -31423,20 +33102,36 @@
     }
   }
   
-});/**
+});/*
+---
+
+name: Jx.Grid.Renderer.Text
+
+description: Renders data as straight text.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Grid.Renderer
+
+provides: [Jx.Grid.Renderer.Text]
+
+...
+ */
+/**
  * Class: Jx.Grid.Renderer.Text
- * This is the default renderer for grid cells. It works the same as the 
- * original column implementation. It needs a store, a field name, and an 
+ * This is the default renderer for grid cells. It works the same as the
+ * original column implementation. It needs a store, a field name, and an
  * optional formatter as well as other options.
- * 
+ *
  * Extends: <Jx.Grid.Renderer>
- * 
+ *
  */
 Jx.Grid.Renderer.Text = new Class({
-  
+
   Family: 'Jx.Grid.Renderer.Text',
   Extends: Jx.Grid.Renderer,
-  
+
   options: {
         /**
          * Option: formatter
@@ -31457,10 +33152,10 @@
         /**
          * Option: textTemplate
          * Will be used for creating the text that goes iside the template. Use
-         * placeholders for indicating the field(s). You can add as much text 
-         * as you want. for example, if you wanted to display someone's full 
-         * name that is brokem up in the model with first and last names you 
-         * can write a template like '{lastName}, {firstName}' and as long as 
+         * placeholders for indicating the field(s). You can add as much text
+         * as you want. for example, if you wanted to display someone's full
+         * name that is brokem up in the model with first and last names you
+         * can write a template like '{lastName}, {firstName}' and as long as
          * the text between { and } are field names in the store they will be
          * substituted properly.
          */
@@ -31471,50 +33166,52 @@
          */
         css: null
   },
-  
+
   store: null,
-  
+
   columnsNeeded: null,
-  
-  
+
+
   init: function () {
-    this.parent();
-    //check the formatter
-    if ($defined(this.options.formatter)
-                && !(this.options.formatter instanceof Jx.Formatter)) {
-            var t = Jx.type(this.options.formatter);
-            if (t === 'object') {
-                // allow users to leave the options object blank
-                if(!$defined(this.options.formatter.options)) {
-                  this.options.formatter.options = {}
-                }
-                this.options.formatter = new Jx.Formatter[this.options.formatter.name](
-                        this.options.formatter.options);
-            }
-        }
+      this.parent();
+      var options = this.options,
+          t;
+      //check the formatter
+      if ($defined(options.formatter) &&
+          !(options.formatter instanceof Jx.Formatter)) {
+          t = Jx.type(options.formatter);
+          if (t === 'object') {
+              // allow users to leave the options object blank
+              if(!$defined(options.formatter.options)) {
+                  options.formatter.options = {}
+              }
+              options.formatter = new Jx.Formatter[options.formatter.name](
+                      options.formatter.options);
+          }
+      }
   },
-  
+
   setColumn: function (column) {
     this.parent();
-    
-    this.store = column.grid.getModel();
+
+    this.store = column.grid.getStore();
     this.attached = true;
-    
+
     if ($defined(this.options.textTemplate)) {
       this.columnsNeeded = this.store.parseTemplate(this.options.textTemplate);
     }
   },
-  
+
   render: function () {
     this.parent();
-    
+
     var text = '';
     if ($defined(this.options.textTemplate)) {
         if (!$defined(this.columnsNeeded) || (Jx.type(this.columnsNeeded) === 'array' && this.columnsNeeded.length === 0)) {
             this.columnsNeeded = this.store.parseTemplate(this.options.textTemplate);
         }
         text = this.store.fillTemplate(null,this.options.textTemplate,this.columnsNeeded);
-    } 
+    }
     if ($defined(this.options.formatter)) {
         text = this.options.formatter.format(text);
     }
@@ -31526,10 +33223,27 @@
     } else if ($defined(this.options.css) && Jx.type(this.options.css) === 'string'){
       this.domObj.addClass(this.options.css);
     }
-        
+
   }
 
-});/**
+});/*
+---
+
+name: Jx.Grid.Renderer.Checkbox
+
+description: Renders a checkbox in a column. Can be connected to a store column or as a standalone check column.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Grid.Renderer
+ - Jx.Field.Checkbox
+
+provides: [Jx.Grid.Renderer.Checkbox]
+
+...
+ */
+/**
  * Class: Jx.Grid.Renderer.CheckBox
  * Renders a checkbox into the cell. Allows options for connecting the cell
  * to a model field and propogating changes back to the store.
@@ -31554,6 +33268,8 @@
     }
   },
   
+  domInsert: true,
+  
   init: function () {
     this.parent();
   },
@@ -31579,7 +33295,7 @@
     this.column = column;
     
     if (this.options.useStore) {
-      this.store = this.column.grid.getModel();
+      this.store = this.column.grid.getStore();
       this.attached = true;
     }
   },
@@ -31595,7 +33311,7 @@
     if (this.options.updateStore) {
       this.updateStore(field);
     }
-    this.column.grid.fireEvent('checkBlur',[this.column, field]);
+    this.fireEvent('change',[this.column, field]);
   },
   
   updateStore: function (field) {
@@ -31610,51 +33326,87 @@
   }
   
   
-});/**
- * Class: Jx.Grid.Renderer.Button
- * Renders a <Jx.Button> into the cell. You can add s many buttons as you'd like per column by passing button configs
- * in as an array option to options.buttonOptions
- *
- * Extends: <Jx.Grid.Renderer>
- *
- */
-Jx.Grid.Renderer.Button = new Class({
-
-    Family: 'Jx.Grid.Renderer.Button',
-    Extends: Jx.Grid.Renderer,
-
-    Binds: [],
-
-    options: {
-        template: '<span class="buttons"></span>',
-        /**
-         * Option: buttonOptions
-         * an array of option configurations for <Jx.Button>
-         */
-        buttonOptions: null
-    },
-
-    classes:  $H({
-        domObj: 'buttons'
-    }),
-
-    init: function () {
-        this.parent();
-    },
-
-    render: function () {
-        this.parent();
-
-        $A(this.options.buttonOptions).each(function(opts){
-            var button = new Jx.Button(opts);
-            this.domObj.grab(document.id(button));
-        },this);
-
-    }
-});// $Id: grid.selector.js 826 2010-03-31 18:46:16Z pagameba $
+});/*
+---
+
+name: Jx.Grid.Renderer.Button
+
+description: "Renders one or more buttons in a single column.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Grid.Renderer
+ - Jx.Button
+
+
+provides: [Jx.Grid.Renderer.Button]
+
+...
+ */
 /**
- * Class: Jx.Plugin.Selector
+ * Class: Jx.Grid.Renderer.Button
+ * Renders a <Jx.Button> into the cell. You can add s many buttons as you'd like per column by passing button configs
+ * in as an array option to options.buttonOptions
  *
+ * Extends: <Jx.Grid.Renderer>
+ *
+ */
+Jx.Grid.Renderer.Button = new Class({
+
+    Family: 'Jx.Grid.Renderer.Button',
+    Extends: Jx.Grid.Renderer,
+
+    Binds: [],
+
+    options: {
+        template: '<span class="buttons"></span>',
+        /**
+         * Option: buttonOptions
+         * an array of option configurations for <Jx.Button>
+         */
+        buttonOptions: null
+    },
+    
+    domInsert: true,
+
+    classes:  $H({
+        domObj: 'buttons'
+    }),
+
+    init: function () {
+        this.parent();
+    },
+
+    render: function () {
+        this.parent();
+
+        $A(this.options.buttonOptions).each(function(opts){
+            var button = new Jx.Button(opts);
+            this.domObj.grab(document.id(button));
+        },this);
+
+    }
+});/*
+---
+
+name: Jx.Plugin.Grid.Selector
+
+description: Allows selecting rows, columns, and cells in grids
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.Grid
+
+provides: [Jx.Plugin.Grid.Selector]
+
+...
+ */
+// $Id: grid.selector.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
+/**
+ * Class: Jx.Plugin.Grid.Selector
+ *
  * Extends: <Jx.Plugin>
  *
  * Grid plugin to select rows, columns, and/or cells.
@@ -31669,11 +33421,11 @@
  */
 Jx.Plugin.Grid.Selector = new Class({
 
-	Family: 'Jx.Plugin.Grid.Selector',
+    Family: 'Jx.Plugin.Grid.Selector',
     Extends : Jx.Plugin,
-    
-    Binds: ['select','checkSelection','checkAll','afterGridRender'],
 
+    Binds: ['select','checkSelection','checkAll','afterGridRender','onCellClick'],
+
     options : {
         /**
          * Option: cell
@@ -31697,7 +33449,7 @@
         multiple: false,
         /**
          * Option: useCheckColumn
-         * Whether to use a check box column as the row header or as the 
+         * Whether to use a check box column as the row header or as the
          * first column in the grid and use it for manipulating selections.
          */
         useCheckColumn: false,
@@ -31707,12 +33459,15 @@
          */
         checkAsHeader: false
     },
+    
+    domInsert: true,
+    
     /**
      * Property: selected
      * Holds arrays of selected rows and/or columns and their headers
      */
     selected: null,
-    
+
     /**
      * APIMethod: init
      * construct a new instance of the plugin.  The plugin must be attached
@@ -31721,6 +33476,7 @@
     init: function() {
         this.parent();
         this.selected = $H({
+            cells: [],
             columns: [],
             rows: [],
             rowHeads: [],
@@ -31739,66 +33495,74 @@
         if (!$defined(grid) && !(grid instanceof Jx.Grid)) {
             return;
         }
+        var options = this.options,
+            template;
         this.grid = grid;
-        this.grid.addEvent('gridCellSelect', this.select);
-        if (this.options.cell) {
-            this.oldSelectionClass = this.grid.selection.options.selectedClass;
-            this.grid.selection.options.selectClass = "jxGridCellSelected";
-            if (this.options.multiple) {
-            	this.grid.selection.options.selectMode = 'multiple';
-            }
-        }
-        
+
         //setup check column if needed
-        if (this.options.useCheckColumn) {
-        	
-        	var template = '<span class="jxGridCellContent">';
-        	
-        	if (this.options.multiple) {
-        		template += '<span class="jxInputContainer jxInputContainerCheck"><input class="jxInputCheck" type="checkbox" name="checkAll" id="checkAll"/></span>';
-        	} else {
-        		template += '</span>';
-        	}
-        	
-        	template += "</span>";
-        	
-        	this.checkColumn = new Jx.Column({
-        		template: template,
-        		renderMode: 'fit',
-        		renderer: new Jx.Grid.Renderer.Checkbox({
-        		//	onChange: this.checkSelection
-        		}),
-        		name: 'selection'
-        	}, this.grid);
-        	this.grid.columns.columns.reverse();
-        	this.grid.columns.columns.push(this.checkColumn);
-        	this.grid.columns.columns.reverse();
-        	
-        	if (this.options.checkAsHeader) {
-        		this.oldHeaderColumn = this.grid.row.options.headerColumn;
-        		this.grid.row.options.headerColumn = 'selection';
-        		
-        		if (this.options.multiple) {
-                    this.grid.addEvent('doneCreateGrid', this.afterGridRender);
-        		}
-        	}
-            //attach event to header
-            if (this.options.multiple) {
-                var ch = document.id(this.checkColumn).getElement('input');
-                ch.addEvents({
-                    'change': this.checkAll
-                });
-            }
+        if (options.useCheckColumn) {
+          template = '<span class="jxGridCellContent">';
+          if (options.multiple) {
+            template += '<span class="jxInputContainer jxInputContainerCheck"><input class="jxInputCheck" type="checkbox" name="checkAll" id="checkAll"/></span>';
+          } else {
+            template += '</span>';
+          }
 
+          template += "</span>";
+
+          this.checkColumn = new Jx.Column({
+            template: template,
+            renderMode: 'fixed',
+            width: 20,
+            renderer: null,
+            name: 'selection'
+          }, grid);
+          this.checkColumn.options.renderer = this;
+          grid.columns.columns.reverse();
+          grid.columns.columns.push(this.checkColumn);
+          grid.columns.columns.reverse();
+
+          if (options.checkAsHeader) {
+              this.oldHeaderColumn = grid.row.options.headerColumn;
+              grid.row.options.useHeaders = true;
+              grid.row.options.headerColumn = 'selection';
+
+              if (options.multiple) {
+                  grid.addEvent('doneCreateGrid', this.afterGridRender);
+              }
+          }
+          //attach event to header
+          if (options.multiple) {
+              document.id(this.checkColumn).getElement('input').addEvents({
+                  'change': this.checkAll
+              });
+          }
+        } else {
+          grid.wantEvent('gridCellClick');
+          grid.addEvent('gridCellClick', this.onCellClick);
         }
     },
+    
+    render: function() {
+      this.domObj = new Element('input', {
+        'class': 'jxGridSelector',
+        type: 'checkbox',
+        events: {
+          change: this.checkSelection
+        }
+      });
+    },
+    
+    toElement: function() {
+      return this.domObj;
+    },
 
     afterGridRender: function () {
         if (this.options.checkAsHeader) {
             var chkCol = document.id(this.checkColumn).clone();
             chkCol.getElement('input').addEvent('change',this.checkAll);
-            this.grid.rowColObj.adopt(chkCol);
-            //document.id(this.checkColumn).inject(this.grid.rowColObj);
+            this.grid.rowColContainer.adopt(chkCol);
+            //document.id(this.checkColumn).inject(this.grid.rowColContainer);
         }
         this.grid.removeEvent('doneCreateGrid',this.afterGridRender);
     },
@@ -31806,100 +33570,132 @@
      * APIMethod: detach
      */
     detach: function() {
-        if (this.grid) {
-            this.grid.removeEvent('gridCellSelect', this.select);
-            if (this.options.cell) {
-                this.grid.selection.options.selectedClass = this.oldSelectionClass;
+        var grid = this.grid,
+            options = this.options,
+            col;
+        if (grid) {
+            grid.gridTableBody.removeEvents({
+              click: this.onCellClick
+            })
+        }
+        if (options.useCheckColumn) {
+            col = grid.columns.getByName('selection');
+            grid.columns.columns.erase(col);
+            if (options.checkAsHeader) {
+                grid.row.options.headerColumn = this.oldHeaderColumn;
             }
         }
-        if (this.options.useCheckColumn) {
-        	var col = this.grid.columns.getByName('selection');
-        	this.grid.columns.columns.erase(col);
-        	if (this.options.checkAsHeader) {
-        		this.grid.row.options.headerColumn = this.oldHeaderColumn;
-        	}
-        }
         this.grid = null;
     },
     /**
      * APIMethod: activate
      * Allows programatic access to turning selections on.
-     * 
+     *
      * Parameters:
      * opt - the option to turn on. One of 'cell', 'column', or 'row'
      */
     activate: function (opt) {
         this.options[opt] = true;
-        if (opt === 'cell') {
-            this.oldSelectionClass = this.grid.selection.options.selectedClass;
-            this.grid.selection.options.selectClass = "jxGridCellSelected";
-        }
     },
     /**
      * APIMethod: deactivate
      * Allows programatic access to turning selections off.
-     * 
+     *
      * Parameters:
      * opt - the option to turn off. One of 'cell', 'column', or 'row'
      */
     deactivate: function (opt) {
+        var gridTableRows = this.grid.gridTable.rows,
+            selected = this.selected,
+            i;
         this.options[opt] = false;
         if (opt === 'cell') {
-            this.grid.selection.selected().each(function(cell){
-                this.grid.selection.unselect(cell);
-            },this);
-            this.grid.selection.options.selectClass = this.oldSelectionClass;
-            
+            selected.get('cells').each(function(cell) {
+              cell.removeClass('jxGridCellSelected');
+            });
+            selected.set('cells',[]);
         } else if (opt === 'row') {
-        	
-        	this.selected.get('rows').each(function(row){
-        		row.removeClass('jxGridRowSelected');
-        	},this);
-        	this.selected.set('rows',[]);
-        	
-        	this.selected.get('rowHeads').each(function(rowHead){
-        		rowHead.removeClass('jxGridRowHeaderSelected');
-        	},this);
-        	this.selected.set('rowHeads',[]);
-        	
+          selected.get('rows').each(function(row){
+            row.removeClass('jxGridRowSelected');
+          });
+          selected.set('rows',[]);
+          selected.get('rowHeads').each(function(rowHead){
+            rowHead.removeClass('jxGridRowHeaderSelected');
+          });
+          selected.set('rowHeads',[]);
         } else {
-            this.selected.get('columns').each(function(column){
-                for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
-                    this.grid.gridTable.rows[i].cells[column].removeClass('jxGridColumnSelected');
+            selected.get('columns').each(function(column){
+                for (i = 0; i < gridTableRows.length; i++) {
+                    gridTableRows[i].cells[column].removeClass('jxGridColumnSelected');
                 }
-            },this);
-            this.selected.set('columns',[]);
-            
-            this.selected.get('columnHeads').each(function(rowHead){
-        		rowHead.removeClass('jxGridColumnHeaderSelected');
-        	},this);
-        	this.selected.set('columnHeads',[]);
+            });
+            selected.set('columns',[]);
+
+            selected.get('columnHeads').each(function(rowHead){
+            rowHead.removeClass('jxGridColumnHeaderSelected');
+          },this);
+          selected.set('columnHeads',[]);
         }
     },
+    
     /**
+     * Method: onCellClick
+     * dispatch clicking on a table cell
+     */
+    onCellClick: function(cell) {
+        if (cell) {
+            this.select(cell);
+        }
+    },
+    
+    /**
      * Method: select
      * dispatches the grid click to the various selection methods
      */
     select : function (cell) {
+        var data = cell.retrieve('jxCellData'),
+            options = this.options,
+            col;
 
-        // console.log('select method');
-        var data = cell.retrieve('jxCellData');
-        // console.log(data);
-
-        if (this.options.row && $defined(data.row)) {
+        if (options.cell && $defined(data.row) && $defined(data.index)) {
+          this.selectCell(cell);
+        }
+        
+        if (options.row && $defined(data.row)) {
             this.selectRow(data.row);
         }
 
-        if (this.options.column && $defined(data.index)) {
+        if (options.column && $defined(data.index)) {
             if (this.grid.row.useHeaders()) {
                 this.selectColumn(data.index - 1);
             } else {
                 this.selectColumn(data.index);
             }
         }
-
     },
+    
     /**
+     * Method: selectCell
+     * select a cell
+     *
+     * Parameters: 
+     * cell - {DOMElement} the cell element to select
+     */
+    selectCell: function(cell) {
+        if (!this.options.cell) { return; }
+        var cells = this.selected.get('cells');
+        if (cell.hasClass('jxGridCellSelected')) {
+          cell.removeClass('jxGridCellSelected');
+          cells.erase(cell);
+          this.fireEvent('unselectCell', cell);
+        } else {
+          cell.addClass('jxGridCellSelected');
+          cells.push(cell);
+          this.fireEvent('selectCell', cell);
+        }
+    },
+    
+    /**
      * Method: selectRow
      * Select a row and apply the jxGridRowSelected style to it.
      *
@@ -31908,55 +33704,68 @@
      */
     selectRow: function (row) {
         if (!this.options.row) { return; }
+        var options = this.options,
+            r = this.grid.gridTableBody.rows,
+            tr = document.id((row >= 0 && row < r.length) ? r[row] : null),
+            rows = this.selected.get('rows');
+        if (tr) {
+            if (tr.hasClass('jxGridRowSelected')) {
+                tr.removeClass('jxGridRowSelected');
+                this.setCheckField(row, false);
+                if (options.multiple && options.useCheckColumn) {
+                    if (options.checkAsHeader) {
+                        document.id(this.grid.rowColContainer).getElement('input').removeProperty('checked');
+                    } else {
+                        document.id(this.checkColumn).getElement('input').removeProperty('checked');
+                    }
+                }
+                //search array and remove this item
+                rows.erase(tr);
+                this.fireEvent('unselectRow', row);
+            } else {
+                tr.store('jxRowData', {row: row});
+                rows.push(tr);
+                tr.addClass('jxGridRowSelected');
+                this.setCheckField(row, true);
+                this.fireEvent('selectRow', row);
+            }
 
-        var tr = (row >= 0 && row < this.grid.gridTableBody.rows.length) ? this.grid.gridTableBody.rows[row] : null;
-        tr = document.id(tr);
-        
-        var rows = this.selected.get('rows');
-	    if (tr.hasClass('jxGridRowSelected')) {
-	        tr.removeClass('jxGridRowSelected');
-	        this.setCheckField(row, false);
-
-            if (this.options.multiple && this.options.useCheckColumn) {
-                if (this.options.checkAsHeader) {
-                    document.id(this.grid.rowColObj).getElement('input').removeProperty('checked');
-                } else {
-                    document.id(this.checkColumn).getElement('input').removeProperty('checked');
+            if (!this.options.multiple) {
+                var unselected = [];
+                rows.each(function(row){
+                  var idx;
+                  if (row !== tr) {
+                    idx = row.retrieve('jxRowData').row;
+                    row.removeClass('jxGridRowSelected');
+                    this.setCheckField(idx,false);
+                    rows.erase(row);
+                    unselected.push(idx);
+                    this.fireEvent('unselectRow', idx);
+                  }
+                },this);
+                if (unselected.length) {
+                  this.fireEvent('unselectRows', [unselected]);
                 }
             }
-
-	        //search array and remove this item
-	        rows.erase(tr);
-	    } else {
-	        rows.push(tr);
-	        tr.addClass('jxGridRowSelected');
-	        this.setCheckField(row, true);
-	    }
-	        
-	    if (!this.options.multiple) {
-	    	rows.each(function(row){
-	    		if (row !== tr) {
-	    			row.removeClass('jxGridRowSelected');
-	    			this.setCheckField(row.retrieve('jxRowData').row,false);
-	    			rows.erase(row);
-	    		}
-	    	},this);
         }
-        	
-	    this.selectRowHeader(row);
+        this.selectRowHeader(row);
+    },
 
-    },
-    
     setCheckField: function (row, checked) {
-    	if (this.options.useCheckColumn) {
-    		var check;
-    		if (this.options.checkAsHeader) {
-    			check = document.id(this.grid.rowTableHead.rows[row].cells[0]).getFirst().getFirst();
-    		} else {
-    			var col = this.grid.columns.getIndexFromGrid(this.checkColumn.name);
-    			check = document.id(this.grid.gridTableBody.rows[row].cells[col]).getFirst().getFirst();
-    		}
-        	check.retrieve('field').setValue(checked);
+        var grid = this.grid,
+            options = this.options,
+            check,
+            col,
+            cell;
+        if (options.useCheckColumn) {
+            if (options.checkAsHeader) {
+              cell = document.id(grid.rowTableBody.rows[row].cells[0]);
+            } else {
+              col = grid.columns.getIndexFromGrid(this.checkColumn.name);
+              cell = document.id(grid.gridTableBody.rows[row].cells[col]);
+            }
+            check = cell.getElement('.jxGridSelector')
+            check.set('checked', checked);
         }
     },
     /**
@@ -31971,31 +33780,32 @@
         if (!this.grid.row.useHeaders()) {
             return;
         }
-        var cell = (row >= 0 && row < this.grid.rowTableHead.rows.length) ? 
-        		this.grid.rowTableHead.rows[row].cells[0] : null;
+        var rows = this.grid.rowTableBody.rows,
+            cell = document.id((row >= 0 && row < rows.length) ? 
+                              rows[row].cells[0] : null),
+            cells;
 
         if (!cell) {
             return;
         }
-        cell = document.id(cell);
-        var cells = this.selected.get('rowHeads');
+        cells = this.selected.get('rowHeads');
         if (cells.contains(cell)) {
             cell.removeClass('jxGridRowHeaderSelected');
             cells.erase(cell);
         } else {
-        	cell.addClass('jxGridRowHeaderSelected');
-        	cells.push(cell);
+          cell.addClass('jxGridRowHeaderSelected');
+          cells.push(cell);
         }
-        
+
         if (!this.options.multiple) {
-        	cells.each(function(c){
-        		if (c !== cell) {
-        			c.removeClass('jxGridRowHeaderSelected');
-        			cells.erase(c);
-        		}
-        	},this);
+          cells.each(function(c){
+            if (c !== cell) {
+              c.removeClass('jxGridRowHeaderSelected');
+              cells.erase(c);
+            }
+          },this);
         }
-        
+
     },
     /**
      * Method: selectColumn
@@ -32006,34 +33816,37 @@
      * col - {Integer} the column to select
      */
     selectColumn: function (col) {
-        if (col >= 0 && col < this.grid.gridTable.rows[0].cells.length) {
-        	var cols = this.selected.get('columns');
-        	
-        	var m = '';
+        var gridTable = this.grid.gridTable,
+            cols = this.selected.get('columns'),
+            m = '',
+            i;
+        if (col >= 0 && col < gridTable.rows[0].cells.length) {
             if (cols.contains(col)) {
-            	//deselect
-            	m = 'removeClass';
-            	cols.erase(col);
+                //deselect
+                m = 'removeClass';
+                cols.erase(col);
+                this.fireEvent('unselectColumn', col);
             } else {
-            	//select
-            	m = 'addClass';
-            	cols.push(col);
+                //select
+                m = 'addClass';
+                cols.push(col);
+                this.fireEvent('selectColumn', col);
             }
-            for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
-                this.grid.gridTable.rows[i].cells[col][m]('jxGridColumnSelected');
+            for (i = 0; i < gridTable.rows.length; i++) {
+                gridTable.rows[i].cells[col][m]('jxGridColumnSelected');
             }
-            
+
             if (!this.options.multiple) {
-            	cols.each(function(c){
-            		if (c !== col) {
-            			for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
-                            this.grid.gridTable.rows[i].cells[c].removeClass('jxGridColumnSelected');
-                        }
-            			cols.erase(c);
-            		}
-            	},this);
+                cols.each(function(c){
+                  if (c !== col) {
+                      for (i = 0; i < gridTable.rows.length; i++) {
+                          gridTable.rows[i].cells[c].removeClass('jxGridColumnSelected');
+                      }
+                      cols.erase(c);
+                      this.fireEvent('unselectColumn', c);
+                  }
+                }, this);
             }
-            
             this.selectColumnHeader(col);
         }
     },
@@ -32046,71 +33859,74 @@
      * col - {Integer} the column header to select
      */
     selectColumnHeader: function (col) {
-        if (this.grid.colTableBody.rows.length === 0
-                || !this.grid.row.useHeaders()) {
+        var rows = this.grid.colTableBody;
+        if (rows.length === 0 || !this.grid.row.useHeaders()) {
             return;
         }
 
+        var cell = (col >= 0 && col < rows[0].cells.length) ?
+            rows[0].cells[col] : null;
 
-        var cell = (col >= 0 && col < this.grid.colTableBody.rows[0].cells.length) ? 
-        		this.grid.colTableBody.rows[0].cells[col] : null;
-        		
         if (cell === null) {
             return;
         }
 
         cell = document.id(cell);
         cells = this.selected.get('columnHeads');
-        
+
         if (cells.contains(cell)) {
             cell.removeClass('jxGridColumnHeaderSelected');
             cells.erase(cell);
         } else {
-        	cell.addClass('jxGridColumnHeaderSelected');
-        	cells.push(cell);
+          cell.addClass('jxGridColumnHeaderSelected');
+          cells.push(cell);
         }
-        
+
         if (!this.options.multiple) {
-        	cells.each(function(c){
-        		if (c !== cell) {
-        			c.removeClass('jxGridColumnHeaderSelected');
-        			cells.erase(c);
-        		}
-        	},this);
+          cells.each(function(c){
+            if (c !== cell) {
+              c.removeClass('jxGridColumnHeaderSelected');
+              cells.erase(c);
+            }
+          });
         }
-
     },
     /**
      * Method: checkSelection
-     * Checks whether a row's check box is/isn't checked and modifies the 
+     * Checks whether a row's check box is/isn't checked and modifies the
      * selection appropriately.
-     * 
+     *
      * Parameters:
      * column - <Jx.Column> that created the checkbox
      * field - <Jx.Field.Checkbox> instance that was checked/unchecked
+     * created the checkbox
      */
-    checkSelection: function (column, field) {
-    	var data = document.id(field).getParent().retrieve('jxCellData');
-    	this.selectRow(data.row);
+    checkSelection: function (event) {
+      var cell =  event.target.getParent('tr'),
+          row;
+      if (cell) {
+        row = cell.getParent().getChildren().indexOf(cell);
+        this.selectRow(row);
+      }
     },
     /**
      * Method: checkAll
      * Checks all checkboxes in the column the selector inserted.
      */
     checkAll: function () {
-        var col;
-        var rows;
-        var checked;
+        var grid = this.grid,
+            col,
+            rows,
+            checked = this.options.checkAsHeader ? 
+                          grid.rowColContainer.getElement('input').get('checked') :
+                          this.checkColumn.domObj.getElement('input').get('checked');
 
-        checked = this.options.checkAsHeader ? this.grid.rowColObj.getElement('input').get('checked') :
-                this.checkColumn.domObj.getElement('input').get('checked');
-
         if (this.options.checkAsHeader) {
             col = 0;
-            rows = this.grid.rowTableHead.rows;
+            rows = grid.rowTableBody.rows;
         } else {
-            col = this.grid.columns.getIndexFromGrid(this.checkColumn.name);
-            rows = this.grid.gridTableBody.rows;
+            col = grid.columns.getIndexFromGrid(this.checkColumn.name);
+            rows = grid.gridTableBody.rows;
         }
 
         $A(rows).each(function(row, idx) {
@@ -32124,9 +33940,25 @@
         }, this);
     }
 });
-// $Id: grid.prelighter.js 912 2010-05-21 21:33:08Z pagameba $
+/*
+---
+
+name: Jx.Plugin.Grid.Prelighter
+
+description: Highlights rows, columns, cells, and headers in grids
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.Grid
+
+provides: [Jx.Plugin.Grid.Prelighter]
+
+...
+ */
+// $Id: grid.prelighter.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
- * Class: Jx.Plugin.Prelighter
+ * Class: Jx.Plugin.Grid.Prelighter
  *
  * Extends: <Jx.Plugin>
  *
@@ -32196,8 +34028,20 @@
             return;
         }
         this.grid = grid;
+        this.grid.wantEvent('gridCellEnter');
+        this.grid.wantEvent('gridCellLeave');
+        this.grid.wantEvent('gridRowEnter');
+        this.grid.wantEvent('gridRowLeave');
+        this.grid.wantEvent('gridColumnEnter');
+        this.grid.wantEvent('gridColumnLeave');
+        this.grid.wantEvent('gridMouseLeave');
+        
         this.grid.addEvent('gridCellEnter', this.bound.lighton);
         this.grid.addEvent('gridCellLeave', this.bound.lightoff);
+        this.grid.addEvent('gridRowEnter', this.bound.lighton);
+        this.grid.addEvent('gridRowLeave', this.bound.lightoff);
+        this.grid.addEvent('gridColumnEnter', this.bound.lighton);
+        this.grid.addEvent('gridColumnLeave', this.bound.lightoff);
         this.grid.addEvent('gridMouseLeave', this.bound.mouseleave);
     },
     /**
@@ -32207,6 +34051,10 @@
         if (this.grid) {
             this.grid.removeEvent('gridCellEnter', this.bound.lighton);
             this.grid.removeEvent('gridCellLeave', this.bound.lightoff);
+            this.grid.removeEvent('gridRowEnter', this.bound.lighton);
+            this.grid.removeEvent('gridRowLeave', this.bound.lightoff);
+            this.grid.removeEvent('gridColumnEnter', this.bound.lighton);
+            this.grid.removeEvent('gridColumnLeave', this.bound.lightoff);
             this.grid.removeEvent('gridMouseLeave', this.bound.mouseleave);
         }
         this.grid = null;
@@ -32234,42 +34082,40 @@
     /**
      * Method: lighton
      */
-    lighton : function (cell, list, grid) {
-        this.light(cell, list, grid, true);
+    lighton : function (cell) {
+        this.light(cell, true);
 
     },
     /**
      * Method: lightoff
      */
-    lightoff : function (cell, list, grid) {
-        this.light(cell, list, grid, false);
+    lightoff : function (cell) {
+        this.light(cell, false);
 
     },
     /**
      * Method: light
      * dispatches the event to the various prelight methods.
      */
-    light: function (cell, list, grid, on) {
-        var data = cell.retrieve('jxCellData');
+    light: function (cell, on) {
+        var parent = cell.getParent(),
+            rowIndex = parent.getParent().getChildren().indexOf(parent),
+            colIndex = cell.getParent().getChildren().indexOf(cell);
 
         if (this.options.cell) {
             this.prelightCell(cell, on);
         }
         if (this.options.row) {
-            this.prelightRow(data.row, on);
+            this.prelightRow(rowIndex, on);
         }
         if (this.options.column) {
-            if (this.grid.row.useHeaders()) {
-                this.prelightColumn(data.index - 1, on);
-            } else {
-                this.prelightColumn(data.index, on);
-            }
+            this.prelightColumn(colIndex, on);
         }
         if (this.options.rowHeader) {
-            this.prelightRowHeader(data.row, on);
+            this.prelightRowHeader(rowIndex, on);
         }
         if (this.options.columnHeader) {
-            this.prelightColumnHeader(data.index - 1, on);
+            this.prelightColumnHeader(colIndex, on);
         }
     },
 
@@ -32285,7 +34131,7 @@
         if ($defined(this.prelitRowHeader) && !on) {
             this.prelitRowHeader.removeClass('jxGridRowHeaderPrelight');
         } else if (on) {
-            this.prelitRowHeader = (row >= 0 && row < this.grid.rowTableHead.rows.length) ? this.grid.rowTableHead.rows[row].cells[0] : null;
+            this.prelitRowHeader = (row >= 0 && row < this.grid.rowTableBody.rows.length) ? this.grid.rowTableBody.rows[row].cells[0] : null;
             if (this.prelitRowHeader) {
                 this.prelitRowHeader.addClass('jxGridRowHeaderPrelight');
             }
@@ -32345,15 +34191,15 @@
      * on - flag to tell if we're lighting on or off
      */
     prelightColumn : function (col, on) {
-        if (col >= 0 && col < this.grid.gridTable.rows[0].cells.length) {
+        if (col >= 0 && col < this.grid.gridTableBody.rows[0].cells.length) {
             if ($defined(this.prelitColumn) && !on) {
-                for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
-                    this.grid.gridTable.rows[i].cells[this.prelitColumn].removeClass('jxGridColumnPrelight');
+                for (var i = 0; i < this.grid.gridTableBody.rows.length; i++) {
+                    this.grid.gridTableBody.rows[i].cells[this.prelitColumn].removeClass('jxGridColumnPrelight');
                 }
             } else if (on) {
                 this.prelitColumn = col;
-                for (i = 0; i < this.grid.gridTable.rows.length; i++) {
-                    this.grid.gridTable.rows[i].cells[col].addClass('jxGridColumnPrelight');
+                for (i = 0; i < this.grid.gridTableBody.rows.length; i++) {
+                    this.grid.gridTableBody.rows[i].cells[col].addClass('jxGridColumnPrelight');
                 }
             }
             this.prelightColumnHeader(col, on);
@@ -32385,8 +34231,8 @@
             this.prelitCell.removeClass('jxGridCellPrelight');
         }
         if ($defined(this.prelitColumn)) {
-            for (var i = 0; i < this.grid.gridTable.rows.length; i++) {
-                this.grid.gridTable.rows[i].cells[this.prelitColumn].removeClass('jxGridColumnPrelight');
+            for (var i = 0; i < this.grid.gridTableBody.rows.length; i++) {
+                this.grid.gridTableBody.rows[i].cells[this.prelitColumn].removeClass('jxGridColumnPrelight');
             }
         }
         if ($defined(this.prelitRow)) {
@@ -32400,9 +34246,27 @@
         }
     }
 });
-// $Id: grid.sorter.js 809 2010-03-28 04:15:14Z jonlb at comcast.net $
+/*
+---
+
+name: Jx.Plugin.Grid.Sorter
+
+description: Enables column sorting in grids
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.Grid
+
+provides: [Jx.Plugin.Grid.Sorter]
+
+images:
+ - emblems.png
+...
+ */
+// $Id: grid.sorter.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
- * Class: Jx.Plugin.Sorter
+ * Class: Jx.Plugin.Grid.Sorter
  *
  * Extends: <Jx.Plugin>
  *
@@ -32413,100 +34277,125 @@
  *
  * This file is licensed under an MIT style license
  */
-Jx.Plugin.Grid.Sorter = new Class({
+ Jx.Plugin.Grid.Sorter = new Class({
+   Family: 'Jx.Plugin.Grid.Sorter',
+   Extends: Jx.Plugin,
+   Binds: ['sort', 'modifyHeaders'],
 
-    Family: 'Jx.Plugin.Grid.Sorter',
-    Extends : Jx.Plugin,
-    Binds: ['sort', 'addHeaderClass'],
+   /**
+    * Property: current
+    * refernce to the currently sorted column
+    */
+   current: null,
 
-    /**
-     * Property: current
-     * refernce to the currently sorted column
-     */
-    current : null,
-    /**
-     * Property: direction
-     * tell us what direction the sort is in (either 'asc' or 'desc')
-     */
-    direction : null,
-    /**
-     * Property: currentGridIndex
-     * Holds the index of the column in the grid
-     */
-    currentGridIndex : null,
-    /**
-     * APIMethod: attach
-     * Sets up the plugin and attaches the plugin to the grid events it
-     * will be monitoring
-     */
-    attach: function (grid) {
-        if (!$defined(grid) && !(grid instanceof Jx.Grid)) {
-            return;
-        }
+   /**
+    * Property: direction
+    * tell us what direction the sort is in (either 'asc' or 'desc')
+    */
+   direction: null,
 
-        this.grid = grid;
+   options: {
+     event: 'gridColumnClick',
+     sortableClass: 'jxColSortable',
+     ascendingClass: 'jxGridColumnSortedAsc',
+     descendingClass: 'jxGridColumnSortedDesc'
+   },
 
-        this.grid.addEvent('gridCellSelect', this.sort);
-    },
-    /**
-     * APIMethod: detach
-     */
-    detach: function() {
-        if (this.grid) {
-            this.grid.removeEvent('gridCellSelect', this.sort);
-        }
-        this.grid = null;
-    },
-    /**
-     * Method: sort
-     * called when a grid header is clicked.
-     *
-     * Parameters:
-     * cell - The cell clicked
-     */
-    sort : function (cell) {
-        var data = cell.retrieve('jxCellData');
-        if (data.colHeader) {
-            var column = data.column;
-            if (column.isSortable()) {
-                if (column === this.current) {
-                    //reverse sort order
-                    this.direction = (this.direction === 'asc') ? 'desc' : 'asc';
-                } else {
-                    this.current = column;
-                    this.direction = 'asc';
-                    this.currentGridIndex = data.index - 1;
-                }
+   /**
+    * APIMethod: attach
+    * Sets up the plugin and attaches the plugin to the grid events it
+    * will be monitoring
+    */
+   attach: function(grid) {
+     this.parent(grid);
+     if (!$defined(grid) && !(grid instanceof Jx.SimpleGrid)) {
+         return;
+     }
 
-                // The grid should be listening for the sortFinished event and
-                // will re-render the grid we will listen for the grid's
-                // doneCreateGrid event to add the header
-                this.grid.addEvent('doneCreateGrid', this.addHeaderClass);
-                //sort the store
-                var strategy = this.grid.getModel().getStrategy('sort');
-                if (strategy) {
-                  strategy.sort(this.current.name, null, this.direction);
-                }
-            }
+     this.grid = grid;
 
-        }
-    },
-    /**
-     * Method: addHeaderClass
-     * Event listener that adds the proper sorted column class to the
-     * column we sorted by so that the sort arrow shows
-     */
-    addHeaderClass : function () {
-        this.grid.removeEvent('doneCreateGrid', this.addHeaderClass);
+     this.grid.wantEvent('gridColumnClick');
+     this.grid.addEvent('gridColumnClick', this.sort);
+     this.grid.addEvent('doneCreateGrid', this.modifyHeaders);
+   },
 
-        //get header TD
-        var th = this.grid.colTable.rows[0].cells[this.currentGridIndex];
-        th.addClass('jxGridColumnSorted' + this.direction.capitalize());
-    }
-});
-// $Id: grid.resize.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+   /**
+    * APIMethod: detach
+    */
+   detach: function() {
+     if (this.grid) {
+         this.grid.removeEvent(this.options.event, this.sort);
+     }
+     this.grid = null;
+   },
+
+   modifyHeaders: function() {
+     var grid = this.grid,
+         columnTable = grid.colObj,
+         store = grid.store,
+         c = this.options.sortableClass;
+     if (grid.columns.useHeaders()) {
+       grid.columns.columns.each(function(col, index) {
+         if (!col.isHidden() && col.isSortable()) {
+           var th = columnTable.getElement('.jxGridCol'+index);
+           th.addClass(c);
+         }
+       });
+     }
+   },
+
+   /**
+    * Method: sort
+    * called when a grid header is clicked.
+    *
+    * Parameters:
+    * cell - The cell clicked
+    */
+   sort: function(el) {
+     var current = this.current,
+         store = this.grid.store,
+         sorter = store.getStrategy('sort'),
+         data = el.retrieve('jxCellData'),
+         dir = 'asc',
+         opt = this.options;
+
+     if (sorter && $defined(data.column) && data.column.isSortable()) {
+       if (el.hasClass(opt.ascendingClass)) {
+         el.removeClass(opt.ascendingClass).addClass(opt.descendingClass);
+         dir = 'desc';
+       } else if (el.hasClass(opt.descendingClass)) {
+         el.removeClass(opt.descendingClass).addClass(opt.ascendingClass);
+       } else {
+         el.addClass(opt.ascendingClass);
+       }
+       if (current && el != current) {
+         current.removeClass(opt.ascendingClass).removeClass(opt.descendingClass);
+       }
+       this.current = el;
+       sorter.sort(data.column.name, null, dir);
+     }
+   }
+ });
+
+/*
+---
+
+name: Jx.Plugin.Grid.Resize
+
+description: Enables column resizing in grids
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.Grid
+
+provides: [Jx.Plugin.Grid.Resize]
+
+...
+ */
+// $Id: grid.resize.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
- * Class: Jx.Plugin.Resize
+ * Class: Jx.Plugin.Grid.Resize
  *
  * Extends: <Jx.Plugin>
  *
@@ -32563,32 +34452,38 @@
      * Sets up the plugin and connects it to the grid
      */
     attach: function (grid) {
-        if (!$defined(grid) && !(grid instanceof Jx.Grid)) {
-            return;
-        }
-        this.grid = grid;
+      this.parent(grid);
+      if (!$defined(grid) && !(grid instanceof Jx.Grid)) {
+          return;
+      }
+      this.grid = grid;
+      if (grid.columns.useHeaders()) {
         this.grid.addEvent('doneCreateGrid', this.createHandles);
         this.grid.addEvent('beginCreateGrid', this.removeHandles);
         this.createHandles();
+      }
     },
     /**
      * APIMethod: detach
      */
     detach: function() {
-        if (this.grid) {
-            this.grid.removeEvent('doneCreateGrid', this.createHandles);
-            this.grid.removeEvent('beginCreateGrid', this.removeHandles);
-        }
-        this.grid = null;
+      this.parent();
+      if (this.grid) {
+          this.grid.removeEvent('doneCreateGrid', this.createHandles);
+          this.grid.removeEvent('beginCreateGrid', this.removeHandles);
+      }
+      this.grid = null;
     },
 
     activate: function(option) {
         if ($defined(this.options[option])) {
           this.options[option] = true;
         }
-        this.createHandles();
+        if (this.grid.columns.useHeaders()) {
+          this.createHandles();
+        }
     },
-    
+
     deactivate: function(option) {
         if ($defined(this.options[option])) {
           this.options[option] = false;
@@ -32612,60 +34507,53 @@
      * create handles that let the user drag to resize columns and rows
      */
     createHandles: function() {
-        this.removeHandles();
-        if (this.options.column && this.grid.columns.useHeaders()) {
-            var hf = this.grid.row.getRowHeaderColumn();
-            this.grid.columns.columns.each(function(col, idx) {
-                if (col.options.name != hf && 
-                    col.isResizable() && 
-                    col.domObj) {
-                    var el = new Element('div', {
-                        'class':'jxGridColumnResize',
-                        title: this.options.tooltip == '' ? this.getText({set:'Jx',key:'plugin.resize',value:'tooltip'}) : this.getText(this.options.tooltip),
-                        events: {
-                            dblclick: function() {
-                                col.options.renderMode = 'fit';
-                                col.options.width = 'auto';
-                                col.setWidth(col.getWidth(true));
-                            }
-                        }
-                    }).inject(col.domObj);
-                    el.store('col', col);
-                    this.els.column.push(el);
-                    this.drags.column.push(new Drag(el, {
-                        limit: {y:[0,0]},
-                        snap: 2,
-                        onBeforeStart: function(el) {
-                          var l = el.getPosition(el.parentNode).x.toInt();
-                          el.setStyles({
-                            left: l,
-                            right: null
-                          });
-                          
-                        },
-                        onStart: function(el) {
-                          var l = el.getPosition(el.parentNode).x.toInt();
-                          el.setStyles({
-                            left: l,
-                            right: null
-                          });
-                        },
-                        onDrag: function(el) {
-                            var col = el.retrieve('col');
-                            col.options.renderMode = 'fixed';
-                            var w = el.getPosition(el.parentNode).x.toInt();
-                            col.setWidth(w);
-                        },
-                        onComplete: function(el) {
-                          el.setStyle('left', null);
-                          col.grid.resizeRowsCols("rows");
-                        }
-                    }));
+      var grid = this.grid,
+          store = grid.store;
+      this.removeHandles();
+      if (this.options.column) {
+        grid.columns.columns.each(function(col, idx) {
+          if (col.isResizable() && !col.isHidden()) {
+            var colEl = grid.colObj.getElement('.jxGridCol'+idx+ ' .jxGridCellContent');
+            var el = new Element('div', {
+              'class':'jxGridColumnResize',
+              title: this.options.tooltip == '' ? this.getText({set:'Jx',key:'plugin.resize',value:'tooltip'}) : this.getText(this.options.tooltip),
+              events: {
+                dblclick: function() {
+                  // size to fit?
                 }
-            }, this);
-        }
+              }
+            }).inject(colEl);
+            this.els.column.push(el);
+            this.drags.column.push(new Drag(el, {
+                limit: {y:[0,0]},
+                snap: 2,
+                onBeforeStart: function(el) {
+                  var l = el.getPosition(el.parentNode).x.toInt();
+                  el.setStyles({
+                    left: l,
+                    right: null
+                  });
 
-        //if (this.options.row && this.grid.row.useHeaders()) {}
+                },
+                onStart: function(el) {
+                  var l = el.getPosition(el.parentNode).x.toInt();
+                  el.setStyles({
+                    left: l,
+                    right: null
+                  });
+                },
+                onDrag: function(el) {
+                    var w = el.getPosition(el.parentNode).x.toInt();
+                    col.setWidth(w);
+                },
+                onComplete: function(el) {
+                  el.setStyle('left', null);
+                }
+            }));
+          }
+        }, this);
+      }
+      //if (this.options.row && this.grid.row.useHeaders()) {}
     },
     /**
      * Method: createText
@@ -32678,10 +34566,28 @@
         this.els[option].each(function(el) { el.set('title',txt); } );
       }, this);
     }
-});
-// $Id: grid.editor.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Plugin.Grid.Editor
+
+description: Enables inline editing in grids
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.Grid
+ - More/Keyboard
+
+provides: [Jx.Plugin.Grid.Editor]
+
+images:
+ - icons.png
+...
+ */
+// $Id: grid.editor.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
- * Class: Jx.Plugin.Editor
+ * Class: Jx.Plugin.Grid.Editor
  *
  * Extends: <Jx.Plugin>
  *
@@ -32698,7 +34604,7 @@
 Jx.Plugin.Grid.Editor = new Class({
 
     Extends : Jx.Plugin,
-    Binds: ['activate','deactivate','changeText'],
+    Binds: ['activate','deactivate','changeText','onCellClick'],
 
     options : {
       /**
@@ -32753,7 +34659,7 @@
        * Default options will be added automatically if custom options are entered.
        *
        * Preferences:
-       *   field             - Default * for all types or the name of the column in the model (Jx.Store)
+       *   field             - Default * for all types or the name of the column in the store (Jx.Store)
        *   type              - Input type to show (Text, Password, Textarea, Select, Checkbox)
        *   options           - All Jx.Field options for this column. More options depend on what type you are using.
        *                       See Jx.Form.[yourField] for details
@@ -32866,11 +34772,10 @@
      *   field        : Reference to the Jx.Field instance that will be created
      *   cell         : Reference to the cell inside the table 
      *   span         : Reference to the Dom Element inside the selected cell of the grid
-     *   oldValue     : Old value of the cell from the grid's model
+     *   oldValue     : Old value of the cell from the grid's store
      *   newValue     : Object with <data> and <error> for better validation possibilites
      *   timeoutId    : TimeoutId if the focus blurs the input.
-     *   coords       : Coordinates of the selected cell
-     *   colOptions   : Reference to the column's option in which the cell is
+     *   data         : Reference to the cell data
      *   fieldOptions : Reference to the field options of this column
      */
     activeCell : {
@@ -32880,8 +34785,7 @@
       oldValue    : null,
       newValue    : { data: null, error: false },
       timeoutId   : null,
-      coords      : {},
-      colOptions  : {},
+      data        : {},
       fieldOptions: {}
     },
     /**
@@ -32941,8 +34845,9 @@
       }
       this.grid = grid;
 
-      this.grid.addEvent('gridCellSelect', this.activate);
-      this.grid.addEvent('gridCellUnSelect', this.deactivate);
+      //this.grid.gridTableBody.addEvent('click', this.onCellClick);
+      this.grid.wantEvent('gridCellClick');
+      this.grid.addEvent('gridCellClick', this.onCellClick);
 
       /*
        * add default field options to the options in case some new options were entered
@@ -32972,22 +34877,22 @@
       this.keyboardMethods = {
         saveNClose     : function(ev) {
           if(self.activeCell.fieldOptions.type != 'Textarea' || (self.activeCell.fieldOptions.type == 'Textarea' && ev.key != 'enter')) {
-            self.deactivate()
+            self.deactivate();
           }
         },
-        saveNGoUp      : function(ev) {ev.preventDefault();self.getPrevCellInCol()},
-        saveNGoRight   : function(ev) {ev.preventDefault();self.getNextCellInRow()},
-        saveNGoDown    : function(ev) {ev.preventDefault();self.getNextCellInCol()},
-        saveNGoLeft    : function(ev) {ev.preventDefault();self.getPrevCellInRow()},
-        cancelNClose   : function(ev) {ev.preventDefault();self.deactivate(false)},
-        cancelNGoUp    : function(ev) {ev.preventDefault();self.getPrevCellInCol(false)},
-        cancelNGoRight : function(ev) {ev.preventDefault();self.getNextCellInRow(false)},
-        cancelNGoDown  : function(ev) {ev.preventDefault();self.getNextCellInCol(false)},
-        cancelNGoLeft  : function(ev) {ev.preventDefault();self.getPrevCellInRow(false)},
-        valueIncrement : function(ev) {ev.preventDefault();self.cellValueIncrement(true)},
-        valueDecrement : function(ev) {ev.preventDefault();self.cellValueIncrement(false)}
+        saveNGoUp      : function(ev) {ev.preventDefault();self.getPrevCellInCol();},
+        saveNGoRight   : function(ev) {ev.preventDefault();self.getNextCellInRow();},
+        saveNGoDown    : function(ev) {ev.preventDefault();self.getNextCellInCol();},
+        saveNGoLeft    : function(ev) {ev.preventDefault();self.getPrevCellInRow();},
+        cancelNClose   : function(ev) {ev.preventDefault();self.deactivate(false);},
+        cancelNGoUp    : function(ev) {ev.preventDefault();self.getPrevCellInCol(false);},
+        cancelNGoRight : function(ev) {ev.preventDefault();self.getNextCellInRow(false);},
+        cancelNGoDown  : function(ev) {ev.preventDefault();self.getNextCellInCol(false);},
+        cancelNGoLeft  : function(ev) {ev.preventDefault();self.getPrevCellInRow(false);},
+        valueIncrement : function(ev) {ev.preventDefault();self.cellValueIncrement(true);},
+        valueDecrement : function(ev) {ev.preventDefault();self.cellValueIncrement(false);}
       };
-      
+
       var keyboardEvents = {};
       for(var i in this.options.keys) {
         if($defined(this.keyboardMethods[this.options.keys[i]])) {
@@ -33016,7 +34921,7 @@
      */
     detach: function() {
       if (this.grid) {
-        this.grid.removeEvent('gridClick', this.activate);
+        this.grid.removeEvent('gridCellClick', this.onCellClick);
       }
       this.grid = null;
       this.keyboard = null;
@@ -33046,7 +34951,15 @@
       }
       this.options.enabled = false;
     },
+
     /**
+     * Method: onCellClick
+     * dispatch clicking on a table cell
+     */
+    onCellClick: function(cell) {
+      this.activate(cell);
+    },
+    /**
      * Method: activate
      * activates the input field or breaks up if conditions are not fulfilled
      *
@@ -33057,156 +34970,174 @@
      * @return void
      */
     activate: function(cell) {
-      if(!this.options.enabled)
+      // if not enabled or the cell is null, do nothing at all
+      if(!this.options.enabled || !cell)
         return;
 
-      var data  = cell.retrieve('jxCellData');
-      // @todo Rename Header too??
-      // return if a table header was clicked
-      if(($defined(data.colHeader) && data.colHeader) || ($defined(data.rowHeader) && data.rowHeader))
+      // activate can be called by clicking on the same cell or a
+      // different one
+      if (this.activeCell.cell) {
+        if (this.activeCell.cell != cell) {
+          if (!this.deactivate()) {
+            return;
+          }
+        } else {
+          // they are the same, ignore?
+          return;
+        }
+      }
+      
+      var data  = this.grid.getCellData(cell); //.retrieve('jxCellData');
+
+      if (!data || !$defined(data.row) || !$defined(data.column)) {
+        if($defined(console)) {
+          console.warn('out of grid %o',cell);
+          console.warn('data was %o', data);
+        }
         return;
-      var row   = data.row,
-          index = data.index;
+      }
 
-      clearTimeout(this.activeCell.timeoutId);
+      // column marked as not editable
+      if (!data.column.options.isEditable) {
+        return;
+      }
 
-      if(this.cellIsInGrid(row, index)) {
+      if (this.activeCell.timeoutId) {
+        clearTimeout(activeCell.timeoutId);
+      }
 
-        var colIndex   = this.grid.options.row.useHeaders ? index-1 : index;
-        var model      = this.grid.getModel(),
-            //cell       = this.grid.gridTableBody.rows[row].cells[col] ? this.grid.gridTableBody.rows[row].cells[col] : null,
-            colOptions = this.grid.columns.getByGridIndex(colIndex).options;
-        if (!cell || !colOptions.isEditable) {
-          return;
-        }
-        // if disabling a currently active one fails (mandatory for example) do not continue
-        if(this.activeCell.cell != null && this.deactivate() == false) {
-          return;
-        }
+      // set active record index to selected row
+      this.grid.store.moveTo(data.row);
 
-        // set active record index to selected row
-        model.moveTo(row);
-        
-        // store properties of the active cell
-        this.activeCell = {
-          oldValue      : model.get(data.index),
-          newValue      : {data: null, error: false},
-          fieldOptions  : this.getFieldOptionsByColName(colOptions.name),
-          colOptions    : colOptions,
-          coords        : {row : row, index : index},
-          cell          : cell,
-          span          : cell.getElement('span.jxGridCellContent'),
-          validator     : null,
-          field         : null,
-          timeoutId     : null
-        }
+      // set up the data objects we need
+      var options = this.options,
+          grid = this.grid,
+          store = grid.getStore(),
+          index = grid.columns.getIndexFromGrid(data.column.name),
+          colOptions = data.column.options,
+          activeCell = {
+            oldValue      : store.get(data.column.name),
+            newValue      : {data: null, error: false},
+            fieldOptions  : this.getFieldOptionsByColName(data.column.name),
+            data          : data,
+            cell          : cell,
+            span          : cell.getElement('span.jxGridCellContent'),
+            validator     : null,
+            field         : null,
+            timeoutId     : null
+          },
+          jxFieldOptions = activeCell.fieldOptions.options,
+          oldValue,
+          groups,
+          k,
+          n;
 
-        // check if this column has special validation settings - otherwise use default from this.options.validate
-        if(!$defined(this.activeCell.colOptions.validate) || typeof(this.activeCell.colOptions.validate) != 'boolean') {
-          this.activeCell.colOptions.validate = this.options.validate;
-        }
+      // check if this column has special validation settings - 
+      // otherwise use default from this.options.validate
+      if(!$defined(data.column.options.validate) || typeof(data.column.options.validate) != 'boolean') {
+        data.column.options.validate = options.validate;
+        cell.store('jxCellData', data);
+      }
 
-        var jxFieldOptions = $defined(this.activeCell.fieldOptions.options) ? this.activeCell.fieldOptions.options : {}
-
-        // check for different input field types
-        switch(this.activeCell.fieldOptions.type) {
-          case 'Text':
-          case 'Color':
-          case 'Password':
-          case 'File':
-            jxFieldOptions.value = this.activeCell.oldValue;
-            break;
-          case 'Textarea':
-            jxFieldOptions.value = this.activeCell.oldValue.replace(/<br \/>/gi, '\n');
-            break;
-          case 'Select':
-            // find out which visible value fits to the value inside <option>{value}</option> and set it to selected
-            var oldValue  = this.activeCell.oldValue.toString();
-            function setCombos(opts, oldValue) {
-              for(var i = 0, j = opts.length; i < j; i++) {
-                if(opts[i].value == oldValue) {
-                  opts[i].selected = true;
-                }else{
-                  opts[i].selected = false;
-                }
+      // check for different input field types
+      switch(activeCell.fieldOptions.type) {
+        case 'Text':
+        case 'Color':
+        case 'Password':
+        case 'File':
+          jxFieldOptions.value = activeCell.oldValue;
+          break;
+        case 'Textarea':
+          jxFieldOptions.value = activeCell.oldValue.replace(/<br \/>/gi, '\n');
+          break;
+        case 'Select':
+          // find out which visible value fits to the value inside
+          // <option>{value}</option> and set it to selected
+          jxFieldOptions.value = oldValue  = activeCell.oldValue.toString();
+          function setCombos(opts, oldValue) {
+            for(var i = 0, j = opts.length; i < j; i++) {
+              if(opts[i].value == oldValue) {
+                opts[i].selected = true;
+              }else{
+                opts[i].selected = false;
               }
-              return opts;
             }
+            return opts;
+          }
 
-            if(jxFieldOptions.comboOpts) {
-              jxFieldOptions.comboOpts = setCombos(jxFieldOptions.comboOpts, oldValue);
-            }else if(jxFieldOptions.optGroups) {
-              var groups = jxFieldOptions.optGroups;
-              for(var k = 0, n = groups.length; k < n; k++) {
-                groups[k].options = setCombos(groups[k].options, oldValue);
-              }
-              jxFieldOptions.optGroups = groups;
+          if(jxFieldOptions.comboOpts) {
+            jxFieldOptions.comboOpts = setCombos(jxFieldOptions.comboOpts, oldValue);
+          }else if(jxFieldOptions.optGroups) {
+            groups = jxFieldOptions.optGroups;
+            for(k = 0, n = groups.length; k < n; k++) {
+              groups[k].options = setCombos(groups[k].options, oldValue);
             }
-            break;
-          case 'Radio':
-          case 'Checkbox':
-          default:
-            $defined(console) ? console.warn("Fieldtype %o is not supported yet. If you have set a validator for a column, you maybe have forgotton to enter a field type.", this.activeCell.fieldOptions.type) : false;
-            return;
-            break;
-        }
-
-        // update the 'oldValue' to the formatted style, to compare the new value with the formatted one instead with the non-formatted-one
-        if(this.options.fieldFormatted && this.activeCell.colOptions.renderer.options.formatter != null) {
-          if(!$defined(this.activeCell.colOptions.fieldFormatted) || this.activeCell.colOptions.fieldFormatted == true ) {
-            jxFieldOptions.value = this.activeCell.colOptions.renderer.options.formatter.format(jxFieldOptions.value);
-            this.activeCell.oldValue = jxFieldOptions.value;
+            jxFieldOptions.optGroups = groups;
           }
-        }
+          break;
+        case 'Radio':
+        case 'Checkbox':
+        default:
+          $defined(console) ? console.warn("Fieldtype %o is not supported yet. If you have set a validator for a column, you maybe have forgotton to enter a field type.", activeCell.fieldOptions.type) : false;
+          return;
+          break;
+      }
 
-        // create jx.field
-        this.activeCell.field = new Jx.Field[this.activeCell.fieldOptions.type.capitalize()](jxFieldOptions);
-        // create validator
-        if(this.options.validate && this.activeCell.colOptions.validate) {
-          this.activeCell.validator = new Jx.Plugin.Field.Validator(this.activeCell.fieldOptions.validatorOptions);
-          this.activeCell.validator.attach(this.activeCell.field);
+      // update the 'oldValue' to the formatted style, to compare the new value with the formatted one instead with the non-formatted-one
+      if(options.fieldFormatted && colOptions.renderer.options.formatter != null) {
+        if(!$defined(colOptions.fieldFormatted) || colOptions.fieldFormatted == true ) {
+          jxFieldOptions.value = colOptions.renderer.options.formatter.format(jxFieldOptions.value);
+          activeCell.oldValue = jxFieldOptions.value;
         }
-        this.setStyles(cell);
+      }
 
-        if(this.options.useKeyboard) {
-          this.keyboard.activate();
-        }
+      // create jx.field
+      activeCell.field = new Jx.Field[activeCell.fieldOptions.type.capitalize()](jxFieldOptions);
+      // create validator
+      if(options.validate && colOptions.validate) {
+        activeCell.validator = new Jx.Plugin.Field.Validator(activeCell.fieldOptions.validatorOptions);
+        activeCell.validator.attach(activeCell.field);
+      }
 
-        // convert a string to an integer if somebody entered a numeric value in quotes, if it failes: make false
-        if(typeof(this.options.blurDelay) == 'string') {
-          this.options.blurDelay = this.options.blurDelay.toInt() ? this.options.blurDelay.toInt() : false;
-        }
+      // store properties of the active cell
+      this.activeCell = activeCell;
+      this.setStyles(cell);
 
-        // add a onblur() and onfocus() event to the input field if enabled.
-        if(this.options.blurDelay !== false && typeof(this.options.blurDelay) == 'number') {
-          var self = this;
-          this.activeCell.field.field.addEvents({
-            // activate the timeout to close the input/poup
-            'blur' : function() {
-              // @todo For some reason, webkit does not clear the timeout correctly when navigating through the grid with keyboard
-              clearTimeout(self.activeCell.timeoutId);
-              self.activeCell.timeoutId = self.deactivate.delay(self.options.blurDelay);
-            },
-            // clear the timeout when the user focusses again
-            'focus' : function() {
-              clearTimeout(self.activeCell.timeoutId);
-            }, 
-            // clear the timeout when the user puts the mouse over the input
-            'mouseover' : function() {
-              clearTimeout(self.activeCell.timeoutId);
-            }
+      if(options.useKeyboard) {
+        this.keyboard.activate();
+      }
+
+      // convert a string to an integer if somebody entered a numeric value in quotes, if it failes: make false
+      if(typeof(options.blurDelay) == 'string') {
+        options.blurDelay = options.blurDelay.toInt() ? options.blurDelay.toInt() : false;
+      }
+
+      // add a onblur() and onfocus() event to the input field if enabled.
+      if(options.blurDelay !== false && typeof(options.blurDelay) == 'number') {
+        activeCell.field.field.addEvents({
+          // activate the timeout to close the input/poup
+          'blur' : function() {
+            // @todo For some reason, webkit does not clear the timeout correctly when navigating through the grid with keyboard
+            clearTimeout(activeCell.timeoutId);
+            activeCell.timeoutId = this.deactivate.delay(this.options.blurDelay);
+          }.bind(this),
+          // clear the timeout when the user focusses again
+          'focus' : function() {
+            clearTimeout(activeCell.timeoutId);
+          }, 
+          // clear the timeout when the user puts the mouse over the input
+          'mouseover' : function() {
+            clearTimeout(activeCell.timeoutId);
+          }
+        });
+        if(this.popup.domObj != null) {
+          this.popup.domObj.addEvent('mouseenter', function() {
+            clearTimeout(activeCell.timeoutId);
           });
-          if(this.popup.domObj != null) {
-            this.popup.domObj.addEvent('mouseenter', function() {
-              clearTimeout(self.activeCell.timeoutId);
-            });
-          }
         }
+      }
 
-        this.activeCell.field.field.focus();
-      }else{
-        if($defined(console)) {console.warn('out of grid %o',cell)}
-      }
+      activeCell.field.field.focus();
     }, 
     /**
      * APIMethod: deactivate
@@ -33218,64 +35149,69 @@
      * @return true if no data error occured, false if error (popup/input stays visible)
      */
     deactivate: function(save) {
+      var newValue = {data : null, error : false},
+          index,
+          activeCell = this.activeCell,
+          grid = this.grid,
+          store = grid.store,
+          options = this.options,
+          highlighter,
+          cellBg;
 
-      clearTimeout(this.activeCell.timeoutId);
-      
-      if(this.activeCell.field !== null) {
+      clearTimeout(activeCell.timeoutId);
+
+      if(activeCell.field !== null) {
         save = $defined(save) ? save : true;
 
-        var newValue = {data : null, error : false};
 
-        // update the value in the model
-        if(save && this.activeCell.field.getValue().toString() != this.activeCell.oldValue.toString()) {
-          this.grid.model.moveTo(this.activeCell.coords.row);
+        // update the value in the column
+        if(save && activeCell.field.getValue().toString() != activeCell.oldValue.toString()) {
+          store.moveTo(activeCell.data.row);
           /*
            * @todo webkit shrinks the rows when the value is updated... but refreshing the grid
            *       immidiately returns in a wrong calculating of the cell position (getCoordinates)
            */
-          switch(this.activeCell.fieldOptions.type) {
+          switch (activeCell.fieldOptions.type) {
             case 'Select':
-              var index = this.activeCell.field.field.selectedIndex;
-              newValue.data = document.id(this.activeCell.field.field.options[index]).get('value');
+              index = activeCell.field.field.selectedIndex;
+              newValue.data = document.id(activeCell.field.field.options[index]).get('value');
               break;
             case 'Textarea':
-              newValue.data = this.activeCell.field.getValue().replace(/\n/gi, '<br />');
+              newValue.data = activeCell.field.getValue().replace(/\n/gi, '<br />');
               break;
             default:
-              newValue.data = this.activeCell.field.getValue();
+              newValue.data = activeCell.field.getValue();
               break;
           }
-          if(save) {
-            this.activeCell.newValue.data = newValue.data;
-            // manually blur the field to activate the validator -> continues with this.terminate()
-            //this.activeCell.timeoutId = this.activeCell.field.field.blur.delay(50, this.activeCell.field.field);
+          if (save) {
+            activeCell.newValue.data = newValue.data;
           }
           // validation only if it should be saved!
-          if(this.activeCell.validator != null && !this.activeCell.validator.isValid()) {
+          if (activeCell.validator != null && !activeCell.validator.isValid()) {
             newValue.error = true;
-            this.activeCell.field.field.focus.delay(50, this.activeCell.field.field);
+            activeCell.field.field.focus.delay(50, activeCell.field.field);
           }
-        }else{
-          this.activeCell.span.show();
+        } else {
+          activeCell.span.show();
         }
 
-
-        if(save && newValue.data != null && newValue.error == false) {
-          this.grid.model.set(this.activeCell.coords.index, newValue.data);
+        // var data = activeCell.cell.retrieve('jxCellData');
+        if (save && newValue.data != null && newValue.error == false) {
+          store.set(activeCell.data.column.name, newValue.data);
           this.addFormatterUriClickListener();
         // else show error message and cell
-        }else if(newValue.error == true) {
-          this.activeCell.span.show();
+        } else if (newValue.error == true) {
+          activeCell.span.show();
         }
 
         // update reference to activeCell
-        if($defined(this.activeCell.coords.row) && $defined(this.activeCell.coords.index)) {
-          var colIndex = this.grid.options.row.useHeaders ? this.activeCell.coords.index-1 : this.activeCell.coords.index;
-          this.activeCell.cell = this.grid.gridTableBody.rows[this.activeCell.coords.row].cells[colIndex];
+        if ($defined(activeCell.data.row) && $defined(activeCell.data.index)) {
+          var colIndex = grid.row.useHeaders() ? activeCell.data.index-1 : activeCell.data.index;
+          this.activeCell.cell = grid.gridTableBody.rows[this.activeCell.data.row].cells[colIndex];
         }
 
-        if(this.options.useKeyboard) {
-          this.activeCell.field.removeEvent('keypress', this.setKeyboard);
+        if (options.useKeyboard) {
+          activeCell.field.removeEvent('keypress', this.setKeyboard);
         }
 
         /**
@@ -33283,29 +35219,29 @@
          * we could also pass an Fx.Tween element?
          * the row could probably be highlighted as well?
          */
-        if(this.options.cellChangeFx.use) {
-          var highlighter = new Fx.Tween(this.activeCell.cell, {
+        if(options.cellChangeFx.use) {
+          highlighter = new Fx.Tween(this.activeCell.cell, {
             duration: 250,
             onComplete: function(ev) {
               this.element.removeProperty('style');
             }
           });
-          var currentCellBg = this.activeCell.cell.getStyle('background-color');
-          currentCellBg = currentCellBg == 'transparent' ? '#fff' : currentCellBg;
-          if(newValue.data != null && newValue.error == false) {
-            highlighter.start('background-color',this.options.cellChangeFx.success, currentCellBg);
-          }else if(newValue.error){
-            highlighter.start('background-color',this.options.cellChangeFx.error, currentCellBg);
+          cellBg = activeCell.cell.getStyle('background-color');
+          cellBg = cellBg == 'transparent' ? '#fff' : cellBg;
+          if (newValue.data != null && newValue.error == false) {
+            highlighter.start('background-color',options.cellChangeFx.success, cellBg);
+          } else if (newValue.error){
+            highlighter.start('background-color',options.cellChangeFx.error, cellBg);
           }
         }
 
         // check for error and keep input field alive
-        if(newValue.error) {
-          if(this.options.cellChangeFx.use) {
-            this.activeCell.field.field.highlight(this.options.cellChangeFx.error);
+        if (newValue.error) {
+          if(options.cellChangeFx.use) {
+            activeCell.field.field.highlight(options.cellChangeFx.error);
           }
-          this.activeCell.field.field.setStyle('border','1px solid '+this.options.cellChangeFx.error);
-          this.activeCell.field.field.focus();
+          activeCell.field.field.setStyle('border','1px solid '+options.cellChangeFx.error);
+          activeCell.field.field.focus();
           return false;
         // otherwise hide it
         }else{
@@ -33325,50 +35261,54 @@
      * @return void
      */
     setStyles : function(cell) {
+      var styles, 
+          size,
+          options = this.options,
+          activeCell = this.activeCell;
       // popup
-      if(this.options.popup.use) {
-        if(this.options.popup.useLabels) {
-          this.activeCell.field.options.label = this.activeCell.colOptions.header;
-          this.activeCell.field.render();
+      if (options.popup.use) {
+        if (options.popup.useLabels) {
+          activeCell.field.options.label = activeCell.data.column.options.header;
+          activeCell.field.render();
         }
-        var styles = {
+        styles = {
           field : {
-            'width'  : this.activeCell.field.type == 'Select' ?
+            'width'  : activeCell.field.type == 'Select' ?
                          cell.getContentBoxSize().width + 5 + "px" :
                          cell.getContentBoxSize().width - 14 + "px",
             'margin' : 'auto 0'
           }
         };
-        this.activeCell.field.field.setStyles(styles.field);
+        activeCell.field.field.setStyles(styles.field);
         this.showPopUp(cell);
       // No popup
-      }else {
-        var size   = cell.getContentBoxSize(),
-            styles = {
-              domObj : {
-                position: 'absolute'
-              },
-              field : {
-                width : size.width + "px",
-                'margin-left' : 0
-              }
-            };
+      } else {
+        size   = cell.getContentBoxSize();
+        styles = {
+          domObj : {
+            position: 'absolute'
+          },
+          field : {
+            width : size.width + "px",
+            'margin-left' : 0
+          }
+        };
 
-        this.activeCell.field.domObj.setStyles(styles.domObj);
-        this.activeCell.field.field.setStyles(styles.field);
-       
-        this.activeCell.field.domObj.inject(document.body);
-        Jx.Widget.prototype.position(this.activeCell.field.domObj, cell, {
+        activeCell.field.domObj.setStyles(styles.domObj);
+        activeCell.field.field.setStyles(styles.field);
+
+        activeCell.field.domObj.inject(document.body);
+        Jx.Widget.prototype.position(activeCell.field.domObj, cell, {
             horizontal: ['left left'],
             vertical: ['top top']
         });
 
-        this.activeCell.span.hide();
+        activeCell.span.hide();
       }
 
       // COMMENT: an outline of the cell helps identifying the currently active cell
-      if(this.options.cellOutline.use) {
-        cell.setStyle('outline', this.options.cellOutline.style);
+      if(options.cellOutline.use) {
+        cell.setStyle('outline', options.cellOutline.style);
       }
     },
     /**
@@ -33412,7 +35352,7 @@
           template  = Jx.Widget.prototype.processTemplate(this.options.popup.template, this.classes);
 
       popup = template.jxGridEditorPopup;
-      
+
       innerWrapper = template.jxGridEditorPopupInnerWrapper;
       /**
        * COMMENT: first positioning is always in the top left of the grid..
@@ -33531,11 +35471,10 @@
         span          : null,
         timeoutId     : null,
         //popup         : null,   // do not destroy the popup, it might be used again
-        colOptions    : {},
-        coords        : {},
+        data           : {},
         fieldOptions  : {},
         validator     : null
-      }
+      };
     },
     /**
      * Method: unsetPopUp
@@ -33561,38 +35500,42 @@
      */
     getNextCellInRow: function(save) {
       save = $defined(save) ? save : true;
-      if(this.activeCell.cell != null) {
-        var nextCell = true, nextRow = true,
-            sumCols = this.grid.columns.columns.length,
-            jxCellClass = 'td.jxGridCell:not(.jxGridCellUnattached)';
-        var i = 0;
+      var nextCell = true,
+          nextRow = true,
+          sumCols = this.grid.columns.columns.length,
+          jxCellClass = 'td.jxGridCell:not(.jxGridCellUnattached)',
+          i = 0,
+          data,
+          cell = this.activeCell.cell,
+          options = this.options;
+      if (this.activeCell.cell != null) {
         do {
-          nextCell = i > 0 ? nextCell.getNext(jxCellClass) : this.activeCell.cell.getNext(jxCellClass);
+          nextCell = i > 0 ? nextCell.getNext(jxCellClass) : cell.getNext(jxCellClass);
           // check if cell is still in row, otherwise returns null
-          if(nextCell == null) {
-            nextRow  = this.activeCell.cell.getParent('tr').getNext();
+          if (nextCell == null) {
+            nextRow  = cell.getParent('tr').getNext();
             // check if this was the last row in the table
-            if(nextRow == null && this.options.keypressLoop) {
-              nextRow = this.activeCell.cell.getParent('tbody').getFirst();
-            }else if(nextRow == null && !this.options.keypressLoop){
+            if (nextRow == null && options.keypressLoop) {
+              nextRow = cell.getParent('tbody').getFirst();
+            } else if(nextRow == null && !options.keypressLoop){
               return;
             }
             nextCell = nextRow.getFirst(jxCellClass);
           }
-          var data  = nextCell.retrieve('jxCellData');
+          data = this.grid.getCellData(nextCell);
           i++;
           // if all columns are set to uneditable during runtime, jump out of the loop after
           // running through 2 times to prevent an endless-loop and browser crash :)
-          if(i == sumCols*2) {
+          if (i == sumCols*2) {
             this.deactivate(save);
             return;
           }
-        }while(!data.col.options.isEditable);
+        } while(data && !data.column.options.isEditable);
 
-        if(save === false) {
+        if (save === false) {
           this.deactivate(save);
         }
-        this.grid.selection.select(nextCell);
+        this.activate(nextCell);
       }
     },
     /**
@@ -33606,26 +35549,33 @@
      */
     getPrevCellInRow: function(save) {
       save = $defined(save) ? save : true;
-      if(this.activeCell.cell != null) {
-        var prevCell, prevRow, i = 0,
-            sumCols = this.grid.columns.columns.length,
-            jxCellClass = 'td.jxGridCell:not(.jxGridCellUnattached)';
+      var prevCell, 
+          prevRow, 
+          i = 0,
+          data,
+          row,
+          index,
+          cell = this.activeCell.cell,
+          sumCols = this.grid.columns.columns.length,
+          jxCellClass = 'td.jxGridCell:not(.jxGridCellUnattached)',
+          options = this.options;
+      if(cell != null) {
         do {
-          prevCell = i > 0 ? prevCell.getPrevious(jxCellClass) : this.activeCell.cell.getPrevious(jxCellClass);
+          prevCell = i > 0 ? prevCell.getPrevious(jxCellClass) : cell.getPrevious(jxCellClass);
           // check if cell is still in row, otherwise returns null
           if(prevCell == null) {
-            prevRow  = this.activeCell.cell.getParent('tr').getPrevious();
+            prevRow  = cell.getParent('tr').getPrevious();
             // check if this was the last row in the table
-            if(prevRow == null && this.options.keypressLoop) {
-              prevRow = this.activeCell.cell.getParent('tbody').getLast();
-            }else if(prevRow == null && !this.options.keypressLoop) {
+            if(prevRow == null && options.keypressLoop) {
+              prevRow = cell.getParent('tbody').getLast();
+            }else if(prevRow == null && !options.keypressLoop) {
               return;
             }
             prevCell = prevRow.getLast(jxCellClass);
           }
-          var data  = prevCell.retrieve('jxCellData'),
-              row   = data.row,
-              index = data.index;
+          data  = this.grid.getCellData(prevCell);
+          row   = data.row;
+          index = data.index;
           i++;
           // if all columns are set to uneditable during runtime, jump out of the loop after
           // running through 2 times to prevent an endless-loop and browser crash :)
@@ -33633,12 +35583,12 @@
             this.deactivate(save);
             return;
           }
-        }while(!data.col.options.isEditable);
+        }while(data && !data.column.options.isEditable);
 
         if(save === false) {
           this.deactivate(save);
         }
-        this.grid.selection.select(prevCell);
+        this.activate(prevCell);
       }
     },
     /**
@@ -33650,18 +35600,20 @@
      * @return void
      */
     getNextCellInCol : function(save) {
+      var nextRow,
+          nextCell,
+          activeCell = this.activeCell;
       save = $defined(save) ? save : true;
-      if(this.activeCell.cell != null) {
-        var nextRow, nextCell;
-        nextRow = this.activeCell.cell.getParent().getNext();
-        if(nextRow == null) {
-          nextRow = this.activeCell.cell.getParent('tbody').getFirst();
+      if (activeCell.cell != null) {
+        nextRow = activeCell.cell.getParent().getNext();
+        if (nextRow == null) {
+          nextRow = activeCell.cell.getParent('tbody').getFirst();
         }
-        nextCell = nextRow.getElement('td.jxGridCol'+this.activeCell.coords.index);
-        if(save === false) {
+        nextCell = nextRow.getElement('td.jxGridCol'+activeCell.data.index);
+        if (save === false) {
           this.deactivate(save);
         }
-        this.grid.selection.select(nextCell);
+        this.activate(nextCell);
       }
     },
     /**
@@ -33673,18 +35625,20 @@
      * @return void
      */
     getPrevCellInCol : function(save) {
+      var prevRow,
+          prevCell,
+          activeCell = this.activeCell;
       save = $defined(save) ? save : true;
-      if(this.activeCell.cell != null) {
-        var prevRow, prevCell;
-        prevRow = this.activeCell.cell.getParent().getPrevious();
-        if(prevRow == null) {
-          prevRow = this.activeCell.cell.getParent('tbody').getLast();
+      if (activeCell.cell != null) {
+        prevRow = activeCell.cell.getParent().getPrevious();
+        if (prevRow == null) {
+          prevRow = activeCell.cell.getParent('tbody').getLast();
         }
-        prevCell = prevRow.getElement('td.jxGridCol'+this.activeCell.coords.index);
-        if(save === false) {
+        prevCell = prevRow.getElement('td.jxGridCol'+activeCell.data.index);
+        if (save === false) {
           this.deactivate(save);
         }
-        this.grid.selection.select(prevCell);
+        this.activate(prevCell);
       }
     },
     /**
@@ -33696,35 +35650,37 @@
      * @return void
      */
     cellValueIncrement : function(bool) {
-      var dataType = this.activeCell.colOptions.dataType,
-          valueNew = null;
-      switch(dataType) {
+      var activeCell = this.activeCell,
+          dataType = activeCell.data.column.options.dataType,
+          valueNew = null,
+          formatter;
+      switch (dataType) {
         case 'numeric':
         case 'currency':
-          valueNew = this.activeCell.field.getValue().toInt();
-          if(typeof(valueNew) == 'number') {
-            if(bool) {
+          valueNew = activeCell.field.getValue().toInt();
+          if (typeof(valueNew) == 'number') {
+            if (bool) {
               valueNew++;
-            }else{
+            } else {
               valueNew--;
             }
           }
           break;
         case 'date':
-          valueNew = Date.parse(this.activeCell.field.getValue());
-          if(valueNew instanceof Date) {
-            if(bool) {
+          valueNew = Date.parse(activeCell.field.getValue());
+          if (valueNew instanceof Date) {
+            if (bool) {
               valueNew.increment();
-            }else{
+            } else {
               valueNew.decrement();
             }
-            var formatter = new Jx.Formatter.Date();
+            formatter = new Jx.Formatter.Date();
             valueNew = formatter.format(valueNew);
           }
           break;
       }
-      if(valueNew != null) {
-        this.activeCell.field.setValue(valueNew);
+      if (valueNew != null) {
+        activeCell.field.setValue(valueNew);
       }
     },
     /**
@@ -33790,7 +35746,7 @@
           }
         });
         // add an event to all anchors inside these columns
-        this.grid.gridTable.getElements('tr').each(function(tr,i) {
+        this.grid.gridObj.getElements('tr').each(function(tr,i) {
           tableCols = tr.getElements('td.jxGridCell');
           for(var j = 0, k = uriCols.length; j < k; j++) {
             anchor = tableCols[uriCols[j]-1].getElement('a');
@@ -33829,11 +35785,43 @@
     	}
     }
 }); 
+/*
+---
+
+name: Jx.Plugin.DataView
+
+description: Namespace for DataView plugins
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin
+
+provides: [Jx.Plugin.DataView]
+...
+ */
 /**
  * Namespace: Jx.Plugin.DataView
  * The namespace for all dataview plugins
  */
-Jx.Plugin.DataView = {};// $Id: slide.js 826 2010-03-31 18:46:16Z pagameba $
+Jx.Plugin.DataView = {};/*
+---
+
+name: Jx.Slide
+
+description: A class that shows and hides elements using a slide effect. Does not use a wrapper element or require a fixed width or height.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+ - Core/Fx.Tween
+
+provides: [Jx.Slide]
+
+...
+ */
+// $Id: slide.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Slide
  * Hides and shows an element without depending on a fixed width or height
@@ -33954,7 +35942,23 @@
             this.target.tween(this.options.type, 0);
         }
     }
-});
+});/*
+---
+
+name: Jx.Plugin.DataView.GroupFolder
+
+description: Enables closing and opening groups in a group dataview
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.DataView
+ - Jx.Slide
+
+provides: [Jx.Plugin.DataView.GroupFolder]
+
+...
+ */
 /**
  * Class: Jx.Plugin.DataView.GroupFolder
  *
@@ -34061,7 +36065,23 @@
         header.addClass(this.options.headerClass + '-closed');
     }
 });
-// $Id: plugin.field.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Plugin.Field
+
+description: Namespace for Jx.Field plugins
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin
+
+provides: [Jx.Plugin.Field]
+
+...
+ */
+// $Id: plugin.field.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Plugin.Field
  * Field plugin namespace
@@ -34072,7 +36092,25 @@
  *
  * This file is licensed under an MIT style license
  */
-Jx.Plugin.Field = {};// $Id: field.validator.js 912 2010-05-21 21:33:08Z pagameba $
+Jx.Plugin.Field = {};/*
+---
+
+name: Jx.Plugin.Field.Validator
+
+description: Provides validation services for Jx.Field subclasses
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.Field
+ - More/Form.Validator
+ - More/Form.Validator.Extras
+
+provides: [Jx.Plugin.Field.Validator]
+
+...
+ */
+// $Id: field.validator.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Plugin.Field.Validator
  *
@@ -34242,7 +36280,23 @@
 
 
 });
-// $Id: plugin.form.js 649 2009-11-30 22:19:48Z pagameba $
+/*
+---
+
+name: Jx.Plugin.Form
+
+description: Namespace for Jx.Form plugins
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin
+
+provides: [Jx.Plugin.Form]
+
+...
+ */
+// $Id: plugin.form.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Plugin.Form
  * Form plugin namespace
@@ -34253,7 +36307,24 @@
  *
  * This file is licensed under an MIT style license
  */
-Jx.Plugin.Form = {};// $Id: form.validator.js 912 2010-05-21 21:33:08Z pagameba $
+Jx.Plugin.Form = {};/*
+---
+
+name: Jx.Plugin.Form.Validator
+
+description: Provides validation services for Jx.Form
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.Form
+ - Jx.Plugin.Field.Validator
+
+provides: [Jx.Plugin.Form.Validator]
+
+...
+ */
+// $Id: form.validator.js 970 2010-08-23 12:20:57Z pagameba $
 /**
  * Class: Jx.Plugin.Form.Validator
  *
@@ -34276,6 +36347,7 @@
         /**
          * Option: fields
          * This will be key/value pairs for each of the fields as shown here:
+         * (code)
          * {
          *     fieldID: {
          *          ... options for Field.Validator plugin ...
@@ -34283,16 +36355,35 @@
          *     fieldID: {...
          *     }
          * }
+         * (end)
          */
         fields: null,
-
+        /**
+         * Option: fieldDefaults
+         * {Object} contains named defaults for field validators to be
+         * triggered on blur or change.  Default is:
+         * (code)
+         * {
+         *    validateOnBlur: true
+         *    validateOnChange: false
+         * }
+         * (end)
+         */
         fieldDefaults: {
             validateOnBlur: true,
             validateOnChange: true
         },
-
+        /**
+         * Option: validateOnSubmit
+         * {Boolean} default true.  Trigger validation on submission of
+         * form if true.
+         */
         validateOnSubmit: true,
-
+        /**
+         * Option: suspendSubmit
+         * {Boolean} default false.  Stop form submission when validator is
+         * attached.
+         */
         suspendSubmit: false
     },
     /**
@@ -34320,15 +36411,16 @@
             return;
         }
         this.form = form;
-        var plugin = this;
+        var plugin = this,
+            options = this.options;
         //override the isValid function in the form
-        this.form.isValid = function () {
+        form.isValid = function () {
             return plugin.isValid();
         };
 
-        if (this.options.validateOnSubmit && !this.options.suspendSubmit) {
+        if (options.validateOnSubmit && !options.suspendSubmit) {
             document.id(this.form).addEvent('submit', this.bound.validate);
-        } else if (this.options.suspendSubmit) {
+        } else if (options.suspendSubmit) {
             document.id(this.form).addEvent('submit', function (ev) {
                 ev.stop();
             });
@@ -34337,15 +36429,17 @@
         this.plugins = $H();
 
         //setup the fields
-        $H(this.options.fields).each(function (val, key) {
-            var opts = $merge(this.options.fieldDefaults, val);
-            var field = this.form.getField(key);
-            var p = new Jx.Plugin.Field.Validator(opts);
-            this.plugins.set(key, p);
-            p.attach(field);
-            p.addEvent('fieldValidationFailed', this.bound.failed);
-            p.addEvent('fieldValidationPassed', this.bound.passed);
-
+        $H(options.fields).each(function (val, key) {
+            var opts = $merge(this.options.fieldDefaults, val),
+                fields = this.form.getFieldsByName(key).
+                p;
+            if (fields && fields.length) {
+                p = new Jx.Plugin.Field.Validator(opts);
+                this.plugins.set(key, p);
+                p.attach(fields[0]);
+                p.addEvent('fieldValidationFailed', this.bound.failed);
+                p.addEvent('fieldValidationPassed', this.bound.passed);
+            }
         }, this);
 
     },
@@ -34417,6 +36511,22 @@
 
 
 });
+/*
+---
+
+name: Jx.Plugin.ToolbarContainer
+
+description: Namespace for Jx.Toolbar.Container
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin
+
+provides: [Jx.Plugin.ToolbarContainer]
+
+...
+ */
 /**
  * Class: Jx.Plugin.Toolbar
  * Toolbar plugin namespace
@@ -34427,7 +36537,23 @@
  *
  * This file is licensed under an MIT style license
  */
-Jx.Plugin.ToolbarContainer = {};/**
+Jx.Plugin.ToolbarContainer = {};/*
+---
+
+name: Jx.Plugin.ToolbarContainer.TabMenu
+
+description: Adds a menu of tabs to the toolbar container for easy access to all tabs.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin.ToolbarContainer
+
+provides: [Jx.Plugin.ToolbarContainer.TabMenu]
+
+...
+ */
+/**
  * Class: Jx.Plugin.ToolbarContainer.TabMenu
  *
  * Extends: <Jx.Plugin>
@@ -34450,8 +36576,6 @@
  *
  * This file is licensed under an MIT style license
  */
-
-
 Jx.Plugin.ToolbarContainer.TabMenu = new Class({
 
     Family: 'Jx.Plugin.ToolbarContainer.TabMenu',
@@ -34531,90 +36655,124 @@
 
         this.menu.add([mi]);
     }
-});
-/**
- * Class: Jx.Adaptor
- * Base class for all adaptor implementations. Provides a place to locate all
- * common code and the Jx.Adaptor namespace.  Since it extends <Jx.Plugin> all
- * adaptors will be able to be used as plugins for their respective classes.
- * Also as such, they must have the attach() and detach() methods.
- * 
- * Adaptors are specifically used to conform a <Jx.Store> to any one of 
- * the different widgets (i.e. Jx.Tree, Jx.ListView, etc...) that could
- * benefit from integration with the store. This approach was taken to minimize 
- * data access code in the widgets themselves. Widgets should have no idea where 
- * the data/items come from so that they will be usable in the broadest number
- * of situations.
- *
- * Copyright 2010 by Jonathan Bomgardner
- * License: mit-style
- */
-Jx.Adaptor = new Class({
-	
-	Family: 'Jx.Adaptor',
-	Extends: Jx.Plugin,
-	
-	name: 'Jx.Adaptor',
-
-	options: {
-        /**
-         * Option: template
-         * The text template to use in creating the items for this adaptor
-         */
-	    template: '',
-        /**
-         * Option: useTemplate
-         * Whether or not to use the text template above. Defaults to true.
-         */
-	    useTemplate: true,
-        /**
-         * Option: store
-         * The store to use with the adaptor.
-         */
-	    store: null
-	},
-    /**
-     * Property: columnsNeeded
-     * Will hold an array of the column names needed for processing the
-     * template
-     */
-	columnsNeeded: null,
-	
-	init: function () {
-	    this.parent();
-	    
-	    this.store = this.options.store;
-	    
-	    if (this.options.useTemplate && $defined(this.store.getColumns())) {
-	        this.columnsNeeded = this.store.parseTemplate(this.options.template);
-	    }
-	},
-	
-	attach: function (widget) {
-		this.parent(widget);
-		this.widget = widget;
-	},
-	
-	detach: function () {
-		this.parent();
-	}
-	
-});/**
+});/*
+---
+
+name: Jx.Adaptor
+
+description: Base class for all Adaptors.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Plugin
+
+provides: [Jx.Adaptor]
+
+...
+ */
+/**
+ * Class: Jx.Adaptor
+ * Base class for all adaptor implementations. Provides a place to locate all
+ * common code and the Jx.Adaptor namespace.  Since it extends <Jx.Plugin> all
+ * adaptors will be able to be used as plugins for their respective classes.
+ * Also as such, they must have the attach() and detach() methods.
+ *
+ * Adaptors are specifically used to conform a <Jx.Store> to any one of
+ * the different widgets (i.e. Jx.Tree, Jx.ListView, etc...) that could
+ * benefit from integration with the store. This approach was taken to minimize
+ * data access code in the widgets themselves. Widgets should have no idea where
+ * the data/items come from so that they will be usable in the broadest number
+ * of situations.
+ *
+ * Copyright 2010 by Jonathan Bomgardner
+ * License: mit-style
+ */
+Jx.Adaptor = new Class({
+
+
+  Extends: Jx.Plugin,
+  Family: 'Jx.Adaptor',
+
+  name: 'Jx.Adaptor',
+
+  options: {
+        /**
+         * Option: template
+         * The text template to use in creating the items for this adaptor
+         */
+      template: '',
+        /**
+         * Option: useTemplate
+         * Whether or not to use the text template above. Defaults to true.
+         */
+      useTemplate: true,
+        /**
+         * Option: store
+         * The store to use with the adaptor.
+         */
+      store: null
+  },
+    /**
+     * Property: columnsNeeded
+     * Will hold an array of the column names needed for processing the
+     * template
+     */
+  columnsNeeded: null,
+
+  init: function () {
+      var options = this.options;
+      this.parent();
+
+      this.store = options.store;
+
+      if (options.useTemplate && $defined(this.store.getColumns())) {
+          this.columnsNeeded = this.store.parseTemplate(options.template);
+      }
+  },
+
+  attach: function (widget) {
+    this.parent(widget);
+    this.widget = widget;
+  },
+
+  detach: function () {
+    this.parent();
+  }
+
+});/*
+---
+
+name: Jx.Adaptor.Tree
+
+description: Base class for all adaptors that fill Jx.Tree widgets. Also acts as the namespace for other Jx.Tree adaptors.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Adaptor
+
+provides: [Jx.Adaptor.Tree]
+
+...
+ */
+/**
  * Class: Jx.Adaptor.Tree
  * This base class is used to change a store (a flat list of records) into the
  * data structure needed for a Jx.Tree. It will have 2 subclasses:
  * <Jx.Adapter.Tree.Mptt> and <Jx.Adapter.Tree.Parent>.
- * 
+ *
  * Copyright 2010 by Jonathan Bomgardner
  * License: mit-style
  */
 Jx.Adaptor.Tree = new Class({
-    
+
+
+    Extends: Jx.Adaptor,
     Family: 'Jx.Adaptor.Tree',
-    Extends: Jx.Adaptor,
-    
+
     Binds: ['fill','checkFolder'],
-    
+
     options: {
         /**
          * Option: monitorFolders
@@ -34665,12 +36823,12 @@
      */
     attach: function (tree) {
         this.parent(tree);
-        
+
         this.tree = tree;
-        
+
         if (this.options.monitorFolders) {
             this.strategy = this.store.getStrategy('progressive');
-        
+
             if (!$defined(this.strategy)) {
                 this.strategy = new Jx.Store.Strategy.Progressive({
                     dropRecords: false,
@@ -34681,71 +36839,76 @@
                 this.strategy.options.dropRecords = false;
                 this.strategy.options.getPaginationParams = function () { return {}; };
             }
-            
+
         }
-        
+
         this.store.addEvent('storeDataLoaded', this.fill);
-        
-        
+
+
     },
     /**
      * APIMethod: detach
      * removes this adaptor from the current tree.
      */
     detach: function () {
-    	this.parent();
-    	this.store.removeEvent('storeDataLoaded', this.fill);
+      this.parent();
+      this.store.removeEvent('storeDataLoaded', this.fill);
     },
     /**
      * APIMethod: firstLoad
      * Method used to start the first store load.
      */
     firstLoad: function () {
-    	//initial store load
-    	this.busy = 'tree';
-    	this.tree.setBusy(true);
+      //initial store load
+      this.busy = 'tree';
+      this.tree.setBusy(true);
         this.store.load({
             node: this.options.startingNodeKey
         });
     },
-    
+
     /**
      * APIMethod: fill
      * This function will start at this.currentRecord and add the remaining
-     * items to the tree. 
+     * items to the tree.
      */
     fill: function () {
-    	if (this.busy == 'tree') {
-    		this.tree.setBusy(false);
-    		this.busy = 'none';
-    	} else if (this.busy == 'folder') {
-    		this.busyFolder.setBusy(false);
-    		this.busy = 'none';
-    	}
+      var i,
+          template,
+          item,
+          p,
+          folder,
+          options = this.option;
+
+      if (this.busy == 'tree') {
+        this.tree.setBusy(false);
+        this.busy = 'none';
+      } else if (this.busy == 'folder') {
+        this.busyFolder.setBusy(false);
+        this.busy = 'none';
+      }
         var l = this.store.count() - 1;
-        for (var i = this.currentRecord + 1; i <= l; i++) {
-            var template = this.store.fillTemplate(i,this.options.template,this.columnsNeeded);
+        for (i = this.currentRecord + 1; i <= l; i++) {
+            template = this.store.fillTemplate(i,options.template,this.columnsNeeded);
 
-            var item;
             if (this.hasChildren(i)) {
                 //add as folder
-                var item = new Jx.TreeFolder($merge(this.options.folderOptions, {
+                item = new Jx.TreeFolder($merge(options.folderOptions, {
                     label: template
                 }));
-                
-                if (this.options.monitorFolders) {
-                	item.addEvent('disclosed', this.checkFolder);
+
+                if (options.monitorFolders) {
+                  item.addEvent('disclosed', this.checkFolder);
                 }
-                
+
                 this.folders.set(i,item);
             } else {
                 //add as item
-                var item = new Jx.TreeItem($merge(this.options.itemOptions, {
+                item = new Jx.TreeItem($merge(options.itemOptions, {
                     label: template
                 }));
             }
-            document.id(item).store('index', i);
-            document.id(item).store('jxAdaptor', this);
+            document.id(item).store('index', i).store('jxAdaptor', this);
             //check for a parent
             if (this.hasParent(i)) {
                 //add as child of parent
@@ -34765,14 +36928,16 @@
      * request additional items for a branch of the tree.
      */
     checkFolder: function (folder) {
-        var items = folder.items();
+        var items = folder.items(),
+            index,
+            node;
         if (!$defined(items) || items.length === 0) {
             //get items via the store
-        	var index = document.id(folder).retrieve('index');
-        	var node = this.store.get('primaryKey', index);
-        	this.busyFolder = folder;
-        	this.busyFolder.setBusy(true);
-        	this.busy = 'folder';
+          index = document.id(folder).retrieve('index');
+          node = this.store.get('primaryKey', index);
+          this.busyFolder = folder;
+          this.busyFolder.setBusy(true);
+          this.busy = 'folder';
             this.store.load({
                 node: node
             });
@@ -34796,18 +36961,31 @@
      * of the parent node.
      */
     getParentIndex: $empty
-    
-    
-    
-});/**
+});/*
+---
+
+name: Jx.Adaptor.Tree.Mptt
+
+description: Fills a Jx.Tree instance from a remote table that represents an MPTT (Modified Preorder Table Traversal) data source.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Adaptor.Tree
+
+provides: [Jx.Adaptor.Tree.Mptt]
+
+...
+ */
+/**
  * Class: Jx.Adaptor.Tree.Mptt
  * This class adapts a table adhering to the classic Parent-style "tree table".
- * 
+ *
  * This class requires an MPTT (Modified Preorder Tree Traversal) table. The MPTT
- * has a 'left' and a 'right' column that indicates the order of nesting. For 
- * more details see the sitepoint.com article at 
+ * has a 'left' and a 'right' column that indicates the order of nesting. For
+ * more details see the sitepoint.com article at
  * http://articles.sitepoint.com/article/hierarchical-data-database
- * 
+ *
  * if useAjax option is set to true then this adapter will send an Ajax request
  * to the server, through the store's strategy (should be Jx.Store.Strategy.Progressive)
  * to request additional nodes.
@@ -34816,66 +36994,91 @@
  * License: mit-style
  */
 Jx.Adaptor.Tree.Mptt = new Class({
-    
 
+
     Family: 'Jx.Adaptor.Tree.Mptt',
     Extends: Jx.Adaptor.Tree,
-    
+
     name: 'tree.mptt',
-    
+
     options: {
         left: 'left',
         right: 'right'
     },
-        
+
     /**
      * APIMethod: hasChildren
-     * 
-     * Parameters: 
-     * index - {integer} the array index of the row in the store (not the 
+     *
+     * Parameters:
+     * index - {integer} the array index of the row in the store (not the
      *          primary key).
      */
     hasChildren: function (index) {
-        var l = this.store.get(this.options.left, index).toInt();
-        var r = this.store.get(this.options.right, index).toInt();
+        var l = this.store.get(this.options.left, index).toInt(),
+            r = this.store.get(this.options.right, index).toInt();
         return (l + 1 !== r);
     },
-    
+
     /**
      * APIMethod: hasParent
-     * 
-     * Parameters: 
-     * index - {integer} the array index of the row in the store (not the 
+     *
+     * Parameters:
+     * index - {integer} the array index of the row in the store (not the
      *          primary key).
      */
     hasParent: function (index) {
-        var i = this.getParentIndex(index);
+        var i = this.getParentIndex(index),
+            result = false;
         if ($defined(i)) {
-            return true;
+            result = true;
         }
-        return false;
+        return result;
     },
-    
+
     /**
      * APIMethod: getParentIndex
-     * 
-     * Parameters: 
-     * index - {integer} the array index of the row in the store (not the 
+     *
+     * Parameters:
+     * index - {integer} the array index of the row in the store (not the
      *          primary key).
      */
     getParentIndex: function (index) {
-        var l = this.store.get(this.options.left, index).toInt();
-        var r = this.store.get(this.options.right, index).toInt();
-        for (var i = index-1; i >= 0; i--) {
-            var pl = this.store.get(this.options.left, i).toInt();
-            var pr = this.store.get(this.options.right, i).toInt();
+        var store = this.store,
+            options = this.options,
+            l,
+            r,
+            i,
+            pl,
+            pr;
+        l = store.get(options.left, index).toInt();
+        r = store.get(options.right, index).toInt();
+        for (i = index-1; i >= 0; i--) {
+            pl = store.get(options.left, i).toInt();
+            pr = store.get(options.right, i).toInt();
             if (pl < l && pr > r) {
                 return i;
             }
         }
         return null;
     }
-});/**
+});/*
+---
+
+name: Jx.Adaptor.Tree.Parent
+
+description: Fills a Jx.Tree instance from a standard parent/child/folder style data table.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Adaptor.Tree
+
+provides: [Jx.Adaptor.Tree.Parent]
+
+
+...
+ */
+/**
  * Class: Jx.Adapter.Tree.Parent
  * This class adapts a table adhering to the classic Parent-style "tree table".
  * 
@@ -34895,8 +37098,9 @@
  */
 Jx.Adaptor.Tree.Parent = new Class({
     
+
+    Extends: Jx.Adaptor.Tree,
     Family: 'Jx.Adaptor.Tree.Parent',
-    Extends: Jx.Adaptor.Tree,
     
     options: {
         parentColumn: 'parent',
@@ -34940,109 +37144,165 @@
         var pk = this.store.get(this.options.parentColumn, index);
         return this.store.findByColumn('primaryKey', pk);
     }
-});/**
- * Class: Jx.Adaptor.Combo
- * The namespace for all combo adaptors
- */
-Jx.Adaptor.Combo = {}
-Jx.Adaptor.Combo.Fill = new Class({
-
-    Family: 'Jx.Adaptor.Combo.Fill',
-    Extends: Jx.Adaptor,
-    name: 'combo.fill',
-    Binds: ['fill'],
-
-    /**
-     * Note: option.template is used for constructing the text for the label
-     */
-    options: {
-        /**
-         * Option: imagePathColumn
-         * points to a store column that holds the image information
-         * for the combo items.
-         */
-        imagePathColumn: null,
-        /**
-         * Option: imageClassColumn
-         * Points to a store column that holds the image class
-         * information for the combo items
-         */
-        imageClassColumn: null,
-        /**
-         * Option: selectedFn
-         * This should be a function that could be run to determine if
-         * an item should be selected. It will get passed the current store
-         * record as the only parameter. It should return either true or false.
-         */
-        selectedFn: null,
-        /**
-         * Option: noRepeats
-         * This option allows you to use any store even if it has duplicate
-         * values in it. With this option set to true the adaptor will keep
-         * track of all of teh labels it adds and will not add anything that's
-         * a duplicate.
-         */
-        noRepeats: false
-    },
-
-    labels: null,
-
-    init: function () {
-        this.parent();
-
-        if (this.options.noRepeat) {
-            this.labels = [];
-        }
-    },
-
-    attach: function (combo) {
-        this.parent(combo);
-
-        this.store.addEvent('storeDataLoaded', this.fill);
-        if (this.store.loaded) {
-            this.fill();
-        }
-    },
-
-    detach: function () {
-        this.parent();
-
-        this.store.removeEvent('storeDataLoaded', this.fill);
-    },
-
-    fill: function () {
-        //empty the combo
-        this.widget.empty();
-        //reset the store and cycle through creating the objects
-        //to pass to combo.add()
-        this.store.first();
-        var items = [];
-        this.store.each(function(record){
-            var template = this.store.fillTemplate(record,this.options.template,this.columnsNeeded);
-            if (!this.options.noRepeat || (this.options.noRepeat && !this.labels.contains(template))) {
-                var selected = false;
-                if ($type(this.options.selectedFn) == 'function') {
-                    selected = this.options.selectedFn.run(record);
-                }
-                var obj = {
-                    label: template,
-                    image: record.get(this.options.imagePathColumn),
-                    imageClass: record.get(this.options.imageClassColumn),
-                    selected: selected
-                }
-                items.push(obj);
-
-                if (this.options.noRepeat) {
-                    this.labels.push(template);
-                }
-            }
-
-        },this);
-        //pass all of the objects at once
-        this.widget.add(items);
-    }
-});// $Id: context.js 932 2010-05-28 14:02:48Z pagameba $
+});/*
+---
+
+name: Jx.Adaptor.Combo
+
+description: Namespace for all Jx.Combo adaptors.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Adaptor
+
+provides: [Jx.Adaptor.Combo]
+
+...
+*/
 /**
+ * Class: Jx.Adaptor.Combo
+ * The namespace for all combo adaptors
+ */
+Jx.Adaptor.Combo = {};/*
+---
+
+name: Jx.Adaptor.Combo.Fill
+
+description: Loads data into a Jx.Combo instance from designated column(s) of a data source.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Adaptor.Combo
+
+provides: [Jx.Adaptor.Combo.Fill]
+
+...
+ */
+Jx.Adaptor.Combo.Fill = new Class({
+
+    Family: 'Jx.Adaptor.Combo.Fill',
+    Extends: Jx.Adaptor,
+    name: 'combo.fill',
+    Binds: ['fill'],
+
+    /**
+     * Note: option.template is used for constructing the text for the label
+     */
+    options: {
+        /**
+         * Option: imagePathColumn
+         * points to a store column that holds the image information
+         * for the combo items.
+         */
+        imagePathColumn: null,
+        /**
+         * Option: imageClassColumn
+         * Points to a store column that holds the image class
+         * information for the combo items
+         */
+        imageClassColumn: null,
+        /**
+         * Option: selectedFn
+         * This should be a function that could be run to determine if
+         * an item should be selected. It will get passed the current store
+         * record as the only parameter. It should return either true or false.
+         */
+        selectedFn: null,
+        /**
+         * Option: noRepeats
+         * This option allows you to use any store even if it has duplicate
+         * values in it. With this option set to true the adaptor will keep
+         * track of all of teh labels it adds and will not add anything that's
+         * a duplicate.
+         */
+        noRepeats: false
+    },
+
+    labels: null,
+
+    init: function () {
+        this.parent();
+
+        if (this.options.noRepeat) {
+            this.labels = [];
+        }
+    },
+
+    attach: function (combo) {
+        this.parent(combo);
+
+        this.store.addEvent('storeDataLoaded', this.fill);
+        if (this.store.loaded) {
+            this.fill();
+        }
+    },
+
+    detach: function () {
+        this.parent();
+
+        this.store.removeEvent('storeDataLoaded', this.fill);
+    },
+
+    fill: function () {
+        var template,
+            items=[],
+            selected,
+            obj,
+            options = this.options,
+            noRepeat = this.options.noRepeat;
+        //empty the combo
+        this.widget.empty();
+        //reset the store and cycle through creating the objects
+        //to pass to combo.add()
+        this.store.first();
+        items = [];
+        this.store.each(function(record){
+            template = this.store.fillTemplate(record,options.template,this.columnsNeeded);
+            if (!noRepeat || (noRepeat && !this.labels.contains(template))) {
+                selected = false;
+                if ($type(options.selectedFn) == 'function') {
+                    selected = options.selectedFn.run(record);
+                }
+                obj = {
+                    label: template,
+                    image: record.get(options.imagePathColumn),
+                    imageClass: record.get(options.imageClassColumn),
+                    selected: selected
+                };
+                items.push(obj);
+
+                if (noRepeat) {
+                    this.labels.push(template);
+                }
+            }
+
+        },this);
+        //pass all of the objects at once
+        this.widget.add(items);
+    }
+});/*
+---
+
+name: Jx.Menu.Context
+
+description: A Jx.Menu that has no button but can be opened at a specific browser location to implement context menus (for instance).
+
+license: MIT-style license.
+
+requires:
+ - Jx.Menu
+
+provides: [Jx.Menu.Context]
+
+css:
+ - menu
+
+...
+ */
+// $Id: context.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
+/**
  * Class: Jx.Menu.Context
  *
  * Extends: Jx.Menu
@@ -35120,7 +37380,26 @@
 
         e.stop();
     }
-});// $Id: menu.separator.js 915 2010-05-23 13:44:48Z pagameba $
+});/*
+---
+
+name: Jx.Menu.Separator
+
+description: Convenience class to create a visual separator in a menu.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Menu
+
+provides: [Jx.Menu.Separator]
+
+images:
+ - toolbar_separator_v.png
+
+...
+ */
+// $Id: menu.separator.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Menu.Separator
  *
@@ -35190,7 +37469,24 @@
      * Show the menu item
      */
     show: $empty
-});// $Id: submenu.js 932 2010-05-28 14:02:48Z pagameba $
+});/*
+---
+
+name: Jx.Menu.SubMenu
+
+description: A sub menu contains menu items within a main menu or another sub menu.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Menu.Item
+ - Jx.Menu
+
+provides: [Jx.Menu.SubMenu]
+
+...
+ */
+// $Id: submenu.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Menu.SubMenu
  *
@@ -35408,7 +37704,23 @@
             this.visibleItem.show();
         }
     }
-});// $Id: snap.js 626 2009-11-20 13:22:22Z pagameba $
+});/*
+---
+
+name: Jx.Splitter.Snap
+
+description: A helper class to create an element that can snap a split panel open or closed.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Splitter
+
+provides: [Jx.Splitter.Snap]
+
+...
+ */
+// $Id: snap.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Splitter.Snap
  *
@@ -35537,7 +37849,34 @@
             }
         }
     }
-});// $Id: tab.js 924 2010-05-26 16:03:06Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Tab
+
+description: A single tab in a tab set.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Button
+ - Jx.Layout
+
+provides: [Jx.Tab]
+
+css:
+ - tab
+
+images:
+ - tab_top.png
+ - tab_bottom.png
+ - tab_left.png
+ - tab_right.png
+ - tab_close.png
+
+...
+ */
+// $Id: tab.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Tab
  *
@@ -35613,7 +37952,7 @@
         /* Option: template
          * the HTML template for a tab
          */
-        template: '<span class="jxTabContainer"><a class="jxTab"><span class="jxTabContent"><img class="jxTabIcon" src="'+Jx.aPixel.src+'"><span class="jxTabLabel"></span></span></a><a class="jxTabClose"></span>',
+        template: '<span class="jxTabContainer"><a class="jxTab"><span class="jxTabContent"><img class="jxTabIcon" src="'+Jx.aPixel.src+'"><span class="jxTabLabel"></span></span></a><a class="jxTabClose"></a></span>',
         /* Option: contentTemplate
          * the HTML template for a tab's content area
          */
@@ -35676,6 +38015,10 @@
           if(this.options.active) {
             this.clicked();
           }
+        }else{
+          this.addEvent('contentLoaded', function(ev) {
+            this.setActive(true);
+          }.bind(this));
         }
         this.addEvent('down', function(){
             this.content.addClass(this.options.activeTabClass);
@@ -35719,10 +38062,6 @@
         // load on demand or reload content if caching is disabled
         }else if(this.options.loadOnDemand || !this.options.cacheContent){
           this.loadContent(this.content);
-          this.addEvent('contentLoaded', function(ev) {
-            //this.setBusy(false);
-            this.setActive(true);
-          }.bind(this));
         }else{
           this.setActive(true);
         }
@@ -35741,7 +38080,23 @@
     }
     this.parent();
   }
-});// $Id: tabset.js 848 2010-04-16 12:43:31Z pagameba $
+});/*
+---
+
+name: Jx.TabSet
+
+description: A TabSet manages a set of Jx.Tab content areas by ensuring that only one of the content areas is visible (i.e. the active tab).
+
+license: MIT-style license.
+
+requires:
+ - Jx.Tab
+
+provides: [Jx.TabSet]
+
+...
+ */
+// $Id: tabset.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.TabSet
  *
@@ -35887,7 +38242,31 @@
 
 
 
-// $Id: tabbox.js 626 2009-11-20 13:22:22Z pagameba $
+/*
+---
+
+name: Jx.TabBox
+
+description: A convenience class to handle the common case of a single toolbar directly attached to the content area of the tabs.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Toolbar
+ - Jx.Panel
+ - Jx.TabSet
+
+provides: [Jx.TabBox]
+
+images:
+ - tabbar.png
+ - tabbar_bottom.png
+ - tabbar_left.png
+ - tabbar_right.png
+
+...
+ */
+// $Id: tabbox.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.TabBox
  *
@@ -36038,7 +38417,27 @@
         this.tabSet.remove(tab);
     }
 });
-// $Id: toolbar.separator.js 626 2009-11-20 13:22:22Z pagameba $
+/*
+---
+
+name: Jx.Toolbar.Separator
+
+description:  A helper class that represents a visual separator in a Jx.Toolbar.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Toolbar
+
+provides: [Jx.Toolbar.Separator]
+
+images:
+ - toolbar_separator_h.png
+ - toolbar_separator_v.png
+
+...
+ */
+// $Id: toolbar.separator.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Toolbar.Separator
  *
@@ -36068,7 +38467,30 @@
         this.domObj.appendChild(this.domSpan);
     }
 });
-// $Id: tree.js 912 2010-05-21 21:33:08Z pagameba $
+/*
+---
+
+name: Jx.Tree
+
+description: Jx.Tree displays hierarchical data in a tree structure of folders and nodes.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+ - Jx.List
+
+provides: [Jx.Tree]
+
+css:
+ - tree
+
+images:
+ - tree.png
+ - tree_vert_line.png
+...
+ */
+// $Id: tree.js 965 2010-07-07 16:27:40Z zak4ms $
 /**
  * Class: Jx.Tree
  *
@@ -36385,7 +38807,7 @@
             return false;
         }
         //path has more than one thing in it, find a folder and descend into it
-        var name = path.shift();
+        var name = path[0];
         var result = false;
         this.list.items().some(function(item) {
             var treeItem = item.retrieve('jxTreeItem');
@@ -36393,7 +38815,7 @@
                 if (path.length > 0) {
                     var folder = item.retrieve('jxTreeFolder');
                     if (folder) {
-                        result = folder.findChild(path);
+                        result = folder.findChild(path.slice(1, path.length));
                     }
                 } else {
                     result = treeItem;
@@ -36403,6 +38825,7 @@
         });
         return result;
     },
+    
     /**
      * APIMethod: setSelection
      * sets the <Jx.Selection> object to be used by this tree.  Used primarily
@@ -36430,7 +38853,29 @@
     }
 });
 
-// $Id: treeitem.js 912 2010-05-21 21:33:08Z pagameba $
+/*
+---
+
+name: Jx.TreeItem
+
+description: An item in a tree.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+
+optional:
+ - More/Drag
+
+provides: [Jx.TreeItem]
+
+images:
+ - tree_hover.png
+
+...
+ */
+// $Id: treeitem.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.TreeItem
  *
@@ -36730,7 +39175,24 @@
       this.setLabel(this.options.label);
     }
 });
-// $Id: treefolder.js 912 2010-05-21 21:33:08Z pagameba $
+/*
+---
+
+name: Jx.TreeFolder
+
+description: A Jx.TreeFolder is an item in a tree that can contain other items. It is expandable and collapsible.
+
+license: MIT-style license.
+
+requires:
+ - Jx.TreeItem
+ - Jx.Tree
+
+provides: [Jx.TreeFolder]
+
+...
+ */
+// $Id: treefolder.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.TreeFolder
  *
@@ -37004,7 +39466,27 @@
         this.tree.setSelection(selection);
         return this;
     }
-});// $Id: slider.js 727 2010-03-04 14:04:04Z pagameba $
+});/*
+---
+
+name: Jx.Slider
+
+description: A wrapper for mootools' slider class to make it more Jx Friendly.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Widget
+ - More/Slider
+
+provides: [Jx.Slider]
+
+css:
+ - slider
+
+...
+ */
+// $Id: slider.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Slider
  * This class wraps the mootools-more slider class to make it more Jx friendly
@@ -37135,7 +39617,31 @@
     set: function(value) {
       this.slider.set(value);
     }
-});// $Id: notice.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Notice
+
+description: Represents a single item used in a notifier.
+
+license: MIT-style license.
+
+requires:
+ - Jx.ListItem
+
+provides: [Jx.Notice]
+
+images:
+ - notice.png
+ - notice_error.png
+ - notice_warning.png
+ - notice_success.png
+ - icons.png
+
+
+...
+ */
+// $Id: notice.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Notice
  *
@@ -37296,7 +39802,29 @@
         klass: 'jxNoticeError'
     }
 });
-// $Id: notifier.js 776 2010-03-22 14:35:16Z pagameba $
+/*
+---
+
+name: Jx.Notifier
+
+description: Base class for notification areas that can hold temporary notices.
+
+license: MIT-style license.
+
+requires:
+ - Jx.ListView
+ - Jx.Notice
+ - Core/Fx.Tween
+
+provides: [Jx.Notifier]
+
+css:
+ - notification
+
+
+...
+ */
+// $Id: notifier.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Notifier
  *
@@ -37389,9 +39917,25 @@
             notice.hide();
         }
     }
-});// $Id: notifier.float.js 776 2010-03-22 14:35:16Z pagameba $
+});/*
+---
+
+name: Jx.Notifier.Float
+
+description: A notification area that floats in a container above other content.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Notifier
+
+provides: [Jx.Notifier.Float]
+
+...
+ */
+// $Id: notifier.float.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
- * Class: Jx.Notice.Float
+ * Class: Jx.Notifier.Float
  * A floating notice area for displaying notices, notices get chrome if
  * the notifier has chrome
  *
@@ -37466,7 +40010,26 @@
         notice.options.chrome = this.options.chrome;
         this.parent(notice);
     }
-});// $Id: scrollbar.js 776 2010-03-22 14:35:16Z pagameba $
+});/*
+---
+
+name: Jx.Scrollbar
+
+description: An implementation of a custom CSS-styled scrollbar.
+
+license: MIT-style license.
+
+requires:
+ - Jx.Slider
+
+provides: [Jx.Scrollbar]
+
+css:
+ - scrollbar
+
+...
+ */
+// $Id: scrollbar.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Scrollbar
  * Creates a custom scrollbar either vertically or horizontally (determined by
@@ -37647,7 +40210,23 @@
         var y = this.options.direction==='horizontal'?0:step;
         this.wrapper.scrollTo(x,y);
     }
-}); // $Id: formatter.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Formatter
+
+description: Base formatter object
+
+license: MIT-style license.
+
+requires:
+ - Jx.Object
+
+provides: [Jx.Formatter]
+
+...
+ */
+ // $Id: formatter.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Formatter
  *
@@ -37674,7 +40253,23 @@
      * the needed formatting functionality.
      */
     format: $empty
-});// $Id: number.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Formatter.Number
+
+description: Formats numbers including negative and floats
+
+license: MIT-style license.
+
+requires:
+ - Jx.Formatter
+
+provides: [Jx.Formatter.Number]
+
+...
+ */
+// $Id: number.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Formatter.Number
  *
@@ -37800,7 +40395,23 @@
     changeText: function (lang) {
     	this.parent();
     }
-});// $Id: currency.js 908 2010-05-19 21:12:06Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Formatter.Currency
+
+description: Formats input as currency. Currently only US currency is supported
+
+license: MIT-style license.
+
+requires:
+ - Jx.Formatter.Number
+
+provides: [Jx.Formatter.Currency]
+
+...
+ */
+// $Id: currency.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Formatter.Currency
  *
@@ -37866,7 +40477,23 @@
     changeText: function (lang) {
     	this.parent();
     }
-});// $Id: date.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Formatter.Date
+
+description: Formats dates using the mootools-more Date extensions
+
+license: MIT-style license.
+
+requires:
+ - More/Date.Extras
+ - Jx.Formatter
+
+provides: [Jx.Formatter.Date]
+...
+ */
+// $Id: date.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Formatter.Date
  *
@@ -37909,7 +40536,25 @@
         var d = Date.parse(value);
         return d.format(this.options.format);
     }
-});// $Id: uri.js 767 2010-03-17 19:35:02Z pagameba $
+});/*
+---
+
+name: Jx.Formatter.URI
+
+description: Formats uris using the mootools-more URI extensions
+
+license: MIT-style license.
+
+requires:
+ - More/String.Extras
+ - Jx.Formatter
+ - More/URI
+
+provides: [Jx.Formatter.URI]
+
+...
+ */
+// $Id: uri.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Formatter.URI
  *
@@ -37974,7 +40619,22 @@
       }
       return this.options.format.substitute(uriContent);
     }
-});// $Id: boolean.js 892 2010-05-06 21:06:26Z conrad.barthelmes $
+});/*
+---
+
+name: Jx.Formatter.Boolean
+
+description: Formats boolean input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Formatter
+
+provides: [Jx.Formatter.Boolean]
+...
+ */
+// $Id: boolean.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Formatter.Boolean
  *
@@ -38045,7 +40705,24 @@
     	this.parent();
     }
 
-});// $Id: phone.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Formatter.Phone
+
+description: Formats phone numbers in US format including area code
+
+license: MIT-style license.
+
+requires:
+ - Jx.Formatter
+
+
+provides: [Jx.Formatter.Phone]
+
+...
+ */
+// $Id: phone.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Formatter.Phone
  *
@@ -38115,8 +40792,89 @@
         ret = ret + v.substring(0, 3) + sep + v.substring(3);
         return ret;
     }
-});// $Id: checkbox.js 859 2010-04-20 21:34:00Z jonlb at comcast.net $
+});/*
+---
+
+name: Jx.Formatter.Text
+
+description: Formats strings by limiting to a max length
+
+license: MIT-style license.
+
+requires:
+ - Jx.Formatter
+
+provides: [Jx.Formatter.Text]
+
+...
+ */
+// $Id: $
 /**
+ * Class: Jx.Formatter.Text
+ *
+ * Extends: <Jx.Formatter>
+ *
+ * This class formats strings by limiting them to a maximum length
+ * and replacing the remainder with an ellipsis.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2010, Hughes Gauthier.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Formatter.Text = new Class({
+
+  Extends: Jx.Formatter,
+
+  options: {
+    /**
+     * Option: length
+     * {Integer} default null, if set to an integer value greater than
+     * 0 then the value will be truncated to length characters and
+     * the remaining characters will be replaced by an ellipsis (...)
+     */
+    length: null,
+    /**
+     * Option: ellipsis
+     * {String} the text to use as the ellipsis when truncating a string
+     * default is three periods (...)
+     */
+    ellipsis: '...'
+  },
+
+  format : function (value) {
+    var text = '' + value,
+        max = this.options.length,
+        ellipsis = this.options.ellipsis;
+
+    if (max && text.length > max) {
+      text = text.substr(0,max-ellipsis.length) + ellipsis;
+    }
+
+    return text;
+  }
+});/*
+---
+
+name: Jx.Field.Check
+
+description: Represents a checkbox input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field
+
+provides: [Jx.Field.Checkbox]
+
+...
+ */
+// $Id: checkbox.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
+/**
  * Class: Jx.Field.Check
  *
  * Extends: <Jx.Field>
@@ -38245,7 +41003,23 @@
     }
 
 });
-// $Id: radio.js 888 2010-05-04 20:01:16Z conrad.barthelmes $
+/*
+---
+
+name: Jx.Field.Radio
+
+description: Represents a radio button input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field
+
+provides: [Jx.Field.Radio]
+
+...
+ */
+// $Id: radio.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Field.Radio
  *
@@ -38372,7 +41146,23 @@
 
 
 
-// $Id: select.js 931 2010-05-28 08:28:09Z conrad.barthelmes $
+/*
+---
+
+name: Jx.Field.Select
+
+description: Represents a select, or drop down, input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field
+
+provides: [Jx.Field.Select]
+
+...
+ */
+// $Id: select.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Field.Select
  *
@@ -38572,7 +41362,23 @@
             }, this);
         }
     }
-});// $Id: textarea.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Field.Textarea
+
+description: Represents a textarea input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field
+
+provides: [Jx.Field.Textarea]
+
+...
+ */
+// $Id: textarea.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Field.Textarea
  *
@@ -38650,7 +41456,24 @@
         //TODO: Do we need to use OverText here as well??
 
     }
-});/**
+});/*
+---
+
+name: Jx.Field.Button
+
+description: Represents a button input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field
+ - Jx.Button
+
+provides: [Jx.Field.Button]
+
+...
+ */
+/**
  * Class: Jx.Field.Button
  *
  * Extends: <Jx.Field>
@@ -38729,7 +41552,27 @@
       this.parent();
       this.button.setEnabled(false);
     }
-});// $Id: jxcombo.js 932 2010-05-28 14:02:48Z pagameba $
+});/*
+---
+
+name: Jx.Field.Combo
+
+description: Represents an editable combo
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field
+ - Jx.Button
+ - Jx.Menu
+ - Jx.Menu.Item
+ - Jx.ButtonSet
+
+provides: [Jx.Field.Combo]
+
+...
+ */
+// $Id: jxcombo.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Field.Combo
  *
@@ -38966,7 +41809,23 @@
       this.setLabel('');
       this.setImage(Jx.aPixel.src);
     }
-});// $Id: password.js 649 2009-11-30 22:19:48Z pagameba $
+});/*
+---
+
+name: Jx.Field.Password
+
+description: Represents a password input
+
+license: MIT-style license.
+
+requires:
+ - Jx.Field.Text
+
+provides: [Jx.Field.Password]
+
+...
+ */
+// $Id: password.js 960 2010-06-06 22:23:16Z jonlb at comcast.net $
 /**
  * Class: Jx.Field.Password
  *
@@ -38992,7 +41851,26 @@
     },
 
     type: 'Password'
-});/**
+});/*
+---
+
+name: Jx.Field.Color
+
+description: Represents an input field with a jx.button.color
+
+license: MIT-style license.
+
+requires:
+ - Jx.Text
+ - Jx.Button.Color
+ - Jx.Form
+ - Jx.Plugin.Field.Validator
+
+provides: [Jx.Field.Color]
+
+...
+ */
+/**
  * Class: Jx.Field.Color
  *
  * Extends: <Jx.Field>



More information about the fusion-commits mailing list