[fusion-commits] r1827 - in trunk: lib widgets

svn_fusion at osgeo.org svn_fusion at osgeo.org
Fri Apr 3 14:30:10 EDT 2009


Author: madair
Date: 2009-04-03 14:30:09 -0400 (Fri, 03 Apr 2009)
New Revision: 1827

Modified:
   trunk/lib/jxlib.uncompressed.js
   trunk/widgets/Legend.js
Log:
re #241: update to JxLib 2.0 RC1; includes changes to Legend context menu

Modified: trunk/lib/jxlib.uncompressed.js
===================================================================
--- trunk/lib/jxlib.uncompressed.js	2009-04-03 14:48:38 UTC (rev 1826)
+++ trunk/lib/jxlib.uncompressed.js	2009-04-03 18:30:09 UTC (rev 1827)
@@ -4288,7 +4288,6 @@
 	},
 
 	start: function(event){
-	    event.stop();
 		if (this.options.preventDefault) event.preventDefault();
 		this.fireEvent('beforeStart', this.element);
 		this.mouse.start = event.page;
@@ -5232,7 +5231,6 @@
 	},
 
 	clickedElement: function(event){
-	    event.stop();
 		var dir = this.range < 0 ? -1 : 1;
 		var position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half;
 		position = position.limit(-this.options.offset, this.full -this.options.offset);
@@ -5444,7 +5442,7 @@
  * reset.css - Copyright (c) 2006, Yahoo! Inc. All rights reserved.
  * Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt
  ******************************************************************************
- * Jx UI Library, 2.0-beta-6
+ * Jx UI Library, 2.0-rc-1
  * Copyright (c) 2006-2008, DM Solutions Group Inc. All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -5465,7 +5463,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
-// $Id: common.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: common.js 303 2009-04-02 18:52:21Z pagameba $
 /**
  * Class: Jx
  * Jx is a global singleton object that contains the entire Jx library
@@ -5504,6 +5502,12 @@
     }    
 })();
 
+Class.Mutators.Family = function(self,name) {
+    self.$family = {'name': name};
+    return self;
+}
+
+
 /* Setup global namespace
  * If jxcore is loaded by jx.js, then the namespace and baseURL are
  * already established
@@ -5536,13 +5540,22 @@
                  * }
                  * (end)
                  */ 
-                 Jx.aPixel = document.createElement('img');
+                 Jx.aPixel = document.createElement('img', {alt:'',title:''});
                  Jx.aPixel.src = matches[1]+'/a_pixel.png';
                  Jx.baseURL = Jx.aPixel.src.substring(0,
                      Jx.aPixel.src.indexOf('a_pixel.png'));
                 
             }
         }
+	   /**
+        * Determine if we're running in Adobe AIR. If so, determine which sandbox we're in
+        */
+		var src = aScripts[0].src;
+        if (src.contains('app:')){
+		    Jx.isAir = true;
+        } else {
+		    Jx.isAir = false;
+	    }
     //});
 } 
 
@@ -6024,13 +6037,16 @@
             }
         } else if (this.options.contentURL) {
             this.contentIsLoaded = false;
-            new Request({
+            this.req = new Request({
                 url: this.options.contentURL, 
                 method:'get',
                 update: element,
                 onSuccess:(function(html) {
                     element.innerHTML = html;
                     this.contentIsLoaded = true;
+					if (Jx.isAir){
+						$clear(this.reqTimeout);
+					}
                     this.fireEvent('contentLoaded', this);
                 }).bind(this), 
                 onFailure: (function(){
@@ -6038,7 +6054,12 @@
                     this.fireEvent('contentLoadFailed', this);
                 }).bind(this),
                 headers: {'If-Modified-Since': 'Sat, 1 Jan 2000 00:00:00 GMT'}
-            }).send();
+            });
+            this.req.send();
+            if (Jx.isAir) {
+                var timeout = $defined(this.options.timeout) ? this.options.timeout : 10000;
+                this.reqTimeout = this.checkRequest.delay(timeout, this);
+            }
         } else {
             this.contentIsLoaded = true;
         }
@@ -6071,7 +6092,39 @@
     }
 });
 
+
 /**
+ * It seems AIR never returns an XHR that "fails" by not finding the 
+ * appropriate file when run in the application sandbox and retrieving a local
+ * file. This affects Jx.ContentLoader in that a "failed" event is never fired. 
+ * 
+ * To fix this, I've added a timeout that waits about 10 seconds or so in the code above
+ * for the XHR to return, if it hasn't returned at the end of the timeout, we cancel the
+ * XHR and fire the failure event.
+ *
+ * This code only gets added if we're in AIR.
+ */
+if (Jx.isAir){
+	Jx.ContentLoader.implement({
+		/**
+		 * Method: checkRequest()
+		 * Is fired after a delay to check the request to make sure it's not
+		 * failing in AIR.
+		 */
+		checkRequest: function(){
+			if (this.req.xhr.readyState === 1) {
+				//we still haven't gotten the file. Cancel and fire the
+				//failure
+				$clear(this.reqTimeout);
+				this.req.cancel();
+				this.contentIsLoaded = true;
+				this.fireEvent('contentLoadFailed', this);
+			}
+		}
+	});
+}
+
+/**
  * Class: Jx.AutoPosition
  * Mix-in class that provides a method for positioning
  * elements relative to other elements.
@@ -6139,6 +6192,7 @@
         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;
         var scroll;
         if (!$(element.parentNode) || element.parentNode ==  document.body) {
@@ -6148,7 +6202,18 @@
             page = $(element.parentNode).getContentBoxSize(); //width, height
             scroll = $(element.parentNode).getScroll();
         }
-        var coords = relative.getCoordinates(); //top, left, width, height
+        if (relative == document.body) {
+            // adjust coords for the scroll offsets to make the object
+            // appear in the right part of the page.
+            coords.left += scroll.x;
+            coords.top += scroll.y;            
+        } else if (element.parentNode == relative) {
+            // if the element is opening *inside* its relative, we want
+            // it to position correctly within it so top/left becomes
+            // the reference system.
+            coords.left = 0;
+            coords.top = 0;
+        }
         var size = element.getMarginBoxSize(); //width, height
         var left;
         var right;
@@ -6329,7 +6394,10 @@
      */
     makeChrome: function(element) {
         var c = new Element('div', {
-            'class':'jxChrome'      
+            'class':'jxChrome',
+            events: {
+                contextmenu: function(e) { e.stop(); }
+            }      
         });
         
         /* add to element so we can get the background image style */
@@ -6343,8 +6411,9 @@
         c.setStyle('padding', 0);
         
         /* 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');
-        if (!(src.contains('http://') || src.contains('https://') || src.contains('file://'))) {
+        if (!(src.contains('http://') || src.contains('https://') || src.contains('file://') || src.contains('app:/'))) {
             src = null;
         } else {
             src = src.slice(4,-1);
@@ -6366,7 +6435,9 @@
                     }).adopt(
                     new Element('img',{
                         'class':'png24',
-                        src:src
+                        src:src,
+                        alt: '',
+                        title: ''
                     }))
                 );
             }, this);
@@ -6446,8 +6517,12 @@
         $(this.addable || this.domObj).inject(reference,where);
         this.fireEvent('addTo',this);
         return this;
+    },
+    
+    toElement: function() {
+        return this.addable || this.domObj;
     }
-});// $Id: button.js 242 2008-12-10 15:19:21Z pagameba $
+});// $Id: button.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Button
  * Jx.Button creates a clickable element that can be added to a web page.
@@ -6540,6 +6615,7 @@
  */
  
 Jx.Button = new Class({
+    Family: 'Jx.Button',
     /**
      * Implements:
      * * Options
@@ -6671,7 +6747,9 @@
         if (this.options.image || !this.options.label) {
             var i = new Element('img', {
                 'class':'jx'+this.options.type+'Icon',
-                'src': Jx.aPixel.src
+                'src': Jx.aPixel.src,
+                alt: '',
+                title: ''
             });
             //if image is not a_pixel, set the background image of the image
             //otherwise let the default css take over.
@@ -6806,7 +6884,9 @@
             if (!this.domImg) {
                 var i = new Element('img', {
                     'class':'jx'+this.options.type+'Icon',
-                    'src': Jx.aPixel.src
+                    'src': Jx.aPixel.src,
+                    alt: '',
+                    title: ''
                 });
                 if (this.options.imageClass) {
                     i.addClass(this.options.imageClass);
@@ -6875,7 +6955,7 @@
     blur: function() {
         this.domA.blur();
     }
-});// $Id: button.flyout.js 247 2008-12-10 19:21:02Z fred.warnock $
+});// $Id: button.flyout.js 261 2009-03-31 18:36:52Z pagameba $
 /**
  * Class: Jx.Button.Flyout
  * Flyout buttons expose a panel when the user clicks the button.  The
@@ -6929,6 +7009,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Button.Flyout = new Class({
+    Family: 'Jx.Button.Flyout',
     /**
      * Extends:
      * <Jx.Button>
@@ -6962,11 +7043,6 @@
         if (!Jx.Button.Flyout.Stack) {
             Jx.Button.Flyout.Stack = [];
         }
-        var content = null;
-        if (options && options.content) {
-            content = options.content;
-            options.content = null;
-        }
         this.parent(options);
         this.domA.addClass('jx'+this.options.type+'Flyout');
         
@@ -6983,7 +7059,6 @@
         this.contentContainer.adopt(this.content);
         
         this.content.store('jxFlyout', this);
-        this.options.content = content;
         this.loadContent(this.content);
         this.keypressWatcher = this.keypressHandler.bindWithEvent(this);
         this.hideWatcher = this.clickHandler.bindWithEvent(this);
@@ -7101,7 +7176,7 @@
             Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1].hide();
         }
     }
-});// $Id: button.multi.js 246 2008-12-10 19:09:41Z fred.warnock $
+});// $Id: button.multi.js 276 2009-04-01 14:32:54Z pagameba $
 /**
  * Class: Jx.Button.Multi
  * Multi buttons are used to contain multiple buttons in a drop down list
@@ -7154,6 +7229,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Button.Multi = new Class({
+    Family: 'Jx.Button.Multi',
     /**
      * Extends: 
      * <Jx.Button>
@@ -7223,11 +7299,13 @@
                 document.addEvent('mousedown', this.hideWatcher);
                 document.addEvent('keyup', this.keypressWatcher);
                 
+                /* why were we doing this? It was affecting issue 13
                 if (e.$extended) {
                     e.stop();                                        
                 } else if (e.event && e.event.$extended) {
                     e.event.stop();
                 }
+                */
                 this.fireEvent('show', this);
             }).bindWithEvent(this.menu),
             'mouseenter':(function(){
@@ -7275,7 +7353,11 @@
                 }
             }).bind(this)
         });
-        a.adopt(new Element('img', {src: Jx.aPixel.src}));
+        a.adopt(new Element('img', {
+            src: Jx.aPixel.src,
+            alt: '',
+            title: ''
+        }));
         this.domObj.adopt(a);
         this.discloser = a;
         if (this.options.items) {
@@ -7388,7 +7470,7 @@
         this.setActiveButton(button);
         button.clicked();
     }
-});// $Id: colorpalette.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: colorpalette.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.ColorPalette
  * A Jx.ColorPalette presents a user interface for selecting colors.  Currently,
@@ -7418,6 +7500,7 @@
  */
 
 Jx.ColorPalette = new Class({
+    Family: 'Jx.ColorPalette',
     /**
      * Implements:
      * * Options
@@ -7434,7 +7517,8 @@
         parent: null,
         color: '#000000',
         alpha: 1,
-        hexColors: ['00', '33', '66', '99', 'CC', 'FF']
+        hexColors: ['00', '33', '66', '99', 'CC', 'FF'],
+        alphaLabel: 'alpha (%)'
     },
     /**
      */
@@ -7491,7 +7575,7 @@
 
         top.adopt(this.colorInput);
 
-        this.alphaLabel = new Element('label', {'class':'jxAlphaLabel', 'html':'alpha (%)'});
+        this.alphaLabel = new Element('label', {'class':'jxAlphaLabel', 'html':this.options.alphaLabel});
         top.adopt(this.alphaLabel);
 
         this.alphaInput = new Element('input', {
@@ -7692,7 +7776,7 @@
     }
 });
 
-// $Id: button.color.js 241 2008-12-10 15:11:05Z pagameba $ 
+// $Id: button.color.js 258 2009-03-31 17:26:30Z pagameba $ 
 /**
  * Class: Jx.Button.Color
  * A <Jx.ColorPalette> wrapped up in a Jx.Button.  The button includes a
@@ -7720,6 +7804,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Button.Color = new Class({
+    Family: 'Jx.Button.Color',
     /**
      * Extends:
      * <Jx.Button.Flyout>
@@ -7866,7 +7951,7 @@
         this.selectedSwatch.setStyles(styles);
     }
 });
-// $Id: buttonset.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: buttonset.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.ButtonSet
  * A ButtonSet manages a set of <Jx.Button> instances by ensuring that only one
@@ -7895,6 +7980,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.ButtonSet = new Class({
+    Family: 'Jx.ButtonSet',
     /**
      * Implements:
      * * Events
@@ -7998,7 +8084,7 @@
 
 
 
-// $Id: grid.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: grid.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Grid
  * A tabular control that has fixed scrolling headers on the rows and columns
@@ -8030,6 +8116,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Grid = new Class({
+    Family: 'Jx.Grid',
     Implements: [Options, Events, Jx.Addable],
     domObj : null,
     model : null,
@@ -8923,6 +9010,7 @@
  * has selected a cell by clicking on the cell in the grid.
  */
 Jx.Grid.Model = new Class({
+    Family: 'Jx.Grid.Model',
     Implements: [Events, Options],
     options: {
         colHeaderHeight: 28,
@@ -8974,7 +9062,7 @@
     
     }
 });
-// $Id: layout.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: layout.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Layout
  * Jx.Layout is used to provide more flexible layout options for applications
@@ -9001,6 +9089,7 @@
  */
  
 Jx.Layout = new Class({
+    Family: 'Jx.Layout',
     /** 
      * Implements:
      * * Options
@@ -9375,7 +9464,7 @@
 
         this.fireEvent('sizeChange',this);
     }
-});// $Id: menu.js 244 2008-12-10 15:32:49Z pagameba $
+});// $Id: menu.js 304 2009-04-02 18:57:18Z pagameba $
 /**
  * Class: Jx.Menu
  * A main menu as opposed to a sub menu that lives inside the menu.
@@ -9394,6 +9483,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Menu = new Class({
+    Family: 'Jx.Menu',
     /**
      * Implements:
      * * Options
@@ -9522,6 +9612,9 @@
      */
     eventInMenu: function(e) {
         var target = $(e.target);
+        if (!target) {
+            return false;
+        }
         if (target.descendantOf(this.domObj) ||
             target.descendantOf(this.subDomObj)) {
             return true;
@@ -9552,7 +9645,11 @@
      */
     hide: function(e) {
         if (e) {
-            if (this.eventInMenu(e)) {
+            if (this.visibleItem && this.visibleItem.eventInMenu) {
+                if (this.visibleItem.eventInMenu(e)) {
+                    return;
+                }
+            } else if (this.eventInMenu(e)) {
                 return;
             }
         }
@@ -9579,6 +9676,7 @@
         var e = o.event;
         if (Jx.Menu.Menus[0]) {
             if (Jx.Menu.Menus[0] != this) {
+                Jx.Menu.Menus[0].button.blur();
                 Jx.Menu.Menus[0].hide(e);
             } else {
                 this.hide();
@@ -9589,7 +9687,7 @@
             return;
         }
         Jx.Menu.Menus[0] = this;
-        
+        this.button.focus();
         this.contentContainer.setStyle('visibility','hidden');
         this.contentContainer.setStyle('display','block');
         $(document.body).adopt(this.contentContainer);            
@@ -9612,7 +9710,9 @@
             this.button.domA.addClass('jx'+this.button.options.type+'Active');            
         }
         if (e) {
-            e.stop();
+            //why were we doing this? it is affecting the closing of
+            //other elements like flyouts (issue 13)
+            //e.stop();
         }
         /* fix bug in IE that closes the menu as it opens because of bubbling */
         document.addEvent('mousedown', this.hideWatcher);
@@ -9645,7 +9745,7 @@
     }
 });
 
-// $Id: menu.item.js 242 2008-12-10 15:19:21Z pagameba $
+// $Id: menu.item.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Menu.Item
  * A menu item is a single entry in a menu.  It is typically composed of
@@ -9668,6 +9768,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Menu.Item = new Class({
+    Family: 'Jx.Menu.Item',
     /**
      * Extends: 
      * <Jx.Button>
@@ -9692,12 +9793,10 @@
      * options - {Object} an object containing options for <Jx.Button::initialize>
      */
     initialize: function(options) {
-        this.parent($merge(
-            {
+        this.parent($merge({
                 image: Jx.aPixel.src
             },
-            options, 
-            {
+            options, {
                 container:'li',
                 type:'MenuItem',
                 toggleClass: (options.image ? null : this.options.toggleClass)
@@ -9760,7 +9859,7 @@
     }
 });
 
-// $Id: menu.separator.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: menu.separator.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Menu.Separator
  * A convenience class to create a visual separator in a menu.
@@ -9775,6 +9874,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Menu.Separator = new Class({
+    Family: 'Jx.Menu.Separator',
     /**
      * Property: domObj
      * {HTMLElement} the HTML element that the separator is contained
@@ -9815,7 +9915,7 @@
      * Show the menu item
      */
     show: $empty
-});// $Id: menu.submenu.js 244 2008-12-10 15:32:49Z pagameba $
+});// $Id: menu.submenu.js 305 2009-04-02 18:58:16Z pagameba $
 /**
  * Class: Jx.Menu.SubMenu
  * A sub menu contains menu items within a main menu or another
@@ -9834,6 +9934,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Menu.SubMenu = new Class({
+    Family: 'Jx.Menu.SubMenu',
     /**
      * Extends:
      * <Jx.Menu.Item>
@@ -9841,12 +9942,10 @@
     Extends: Jx.Menu.Item,
     /**
      * Implements:
-     * * Options
-     * * Events
      * * <Jx.AutoPosition>
      * * <Jx.Chrome>
      */
-    Implements: [Options, Events, Jx.AutoPosition, Jx.Chrome],
+    Implements: [Jx.AutoPosition, Jx.Chrome],
     /**
      * Property: subDomObj
      * {HTMLElement} the HTML container for the sub menu.
@@ -9931,6 +10030,11 @@
     },
     
     eventInMenu: function(e) {
+        if (this.visibleItem && 
+            this.visibleItem.eventInMenu && 
+            this.visibleItem.eventInMenu(e)) {
+            return true;
+        }
         return $(e.target).descendantOf(this.domObj) ||
                $(e.target).descendantOf(this.subDomObj) ||
                this.items.some(
@@ -10066,7 +10170,7 @@
             this.visibleItem.show();
         }
     }
-});// $Id: menu.context.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: menu.context.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Menu.Context
  * A <Jx.Menu> that has no button but can be opened at a specific 
@@ -10085,6 +10189,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Menu.Context = new Class({
+    Family: 'Jx.Menu.Context',
     /** Extends:
      * <Jx.Menu>
      */
@@ -10140,7 +10245,7 @@
 
         e.stop();
     }    
-});// $Id: panel.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: panel.js 269 2009-03-31 21:53:04Z pagameba $
 /**
  * Class: Jx.Panel
  * A panel is a fundamental container object that has a content
@@ -10164,6 +10269,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Panel = new Class({
+    Family: 'Jx.Panel',
     /**
      * Implements:
      * * <Jx.ContentLoader>
@@ -10184,11 +10290,19 @@
         position: 'absolute',
         height: null,
         collapse: true,
+        collapseTooltip: 'Collapse/Expand Panel',
+        collapseLabel: 'Collapse',
+        expandLabel: 'Expand',
+        maximizeTooltip: 'Maximize Panel',
+        maximizeLabel: 'Maximize',
         detach: false,
         close: false,
+        closeTooltip: 'Close Panel',
+        closeLabel: 'Close',
         closed: false,
         hideTitle: false,
-        type: 'Panel'
+        type: 'Panel',
+        toolbars: []
     },
     
     /** 
@@ -10228,16 +10342,9 @@
      *     container's width (using the relative option in <Jx.Layout>).
      */
     initialize : function(options){
+        this.setOptions(options);
         this.toolbars = options ? options.toolbars || [] : [];
         
-        /* ugly hack around $unlink in mootools */
-        var content = null;
-        if (options && options.content) {
-            content = options.content;
-            options.content = null;
-        }
-        this.setOptions(options);
-        
         if ($defined(this.options.height) && !$defined(options.position)) {
             this.options.position = 'relative';
         }
@@ -10249,7 +10356,9 @@
         
         var i = new Element('img', {
             'class': 'jx'+this.options.type+'Icon',
-            src: Jx.aPixel.src
+            src: Jx.aPixel.src,
+            alt: '',
+            title: ''
         });
         if (this.options.image) {
             i.setStyle('backgroundImage', 'url('+this.options.image+')');
@@ -10284,7 +10393,7 @@
         if (this.options.collapse) {
             var b = new Jx.Button({
                 image: Jx.aPixel.src,
-                tooltip: 'Collapse/Expand Panel',
+                tooltip: this.options.collapseTooltip,
                 onClick: function() {
                     that.toggleCollapse();
                 }
@@ -10293,14 +10402,15 @@
             this.toolbar.add(b);
             if (this.menu) {
                 var item = new Jx.Menu.Item({
-                    label: 'Collapse',
+                    label: this.options.collapseLabel,
                     onClick: function() { that.toggleCollapse(); }
                 });
-                this.addEvent('collapse', function() {
-                    if (that.options.closed) {
-                        item.setLabel('Expand');
-                    } else {
-                        item.setLabel('Collapse');
+                this.addEvents({
+                    collapse: function() {
+                        item.setLabel(this.options.expandLabel);
+                    },
+                    expand: function() {
+                        item.setLabel(this.options.collapseLabel);
                     }
                 });
                 this.menu.add(item);
@@ -10310,7 +10420,7 @@
         if (this.options.maximize) {
             var b = new Jx.Button({
                 image: Jx.aPixel.src,
-                tooltip: 'Maximize Panel',
+                tooltip: this.options.maximizeTooltip,
                 onClick: function() {
                     that.maximize();
                 }
@@ -10319,7 +10429,7 @@
             this.toolbar.add(b);
             if (this.menu) {
                 var item = new Jx.Menu.Item({
-                    label: 'Maximize',
+                    label: this.options.maximizeLabel,
                     onClick: function() { that.maximize(); }
                 });
                 this.menu.add(item);
@@ -10329,7 +10439,7 @@
         if (this.options.close) {
             var b = new Jx.Button({
                 image: Jx.aPixel.src,
-                tooltip: 'Close Panel',
+                tooltip: this.options.closeTooltip,
                 onClick: function() {
                     that.close();
                 }
@@ -10338,7 +10448,7 @@
             this.toolbar.add(b);
             if (this.menu) {
                 var item = new Jx.Menu.Item({
-                    label: 'Close',
+                    label: this.options.closeLabel,
                     onClick: function() {
                         that.close();
                     }
@@ -10371,17 +10481,18 @@
         });
         this.domObj.adopt(this.contentContainer);
         
-        for (var i=0; i<this.toolbars.length; i++) {
-            var tb = this.toolbars[i];
-            var position = tb.options.position;
-            var tbc = this.toolbarContainers[position];
-            if (!tbc) {
-                var tbc = new Element('div');
-                new Jx.Layout(tbc);
-                this.contentContainer.adopt(tbc);
-                this.toolbarContainers[position] = tbc;
-            }
-            tb.addTo(tbc);
+        if ($type(this.options.toolbars) == 'array') {
+            this.options.toolbars.each(function(tb){
+                var position = tb.options.position;
+                var tbc = this.toolbarContainers[position];
+                if (!tbc) {
+                    var tbc = new Element('div');
+                    new Jx.Layout(tbc);
+                    this.contentContainer.adopt(tbc);
+                    this.toolbarContainers[position] = tbc;
+                }
+                tb.addTo(tbc);
+            }, this);
         }
         
         this.content = new Element('div', {
@@ -10391,10 +10502,9 @@
         this.contentContainer.adopt(this.content);
         new Jx.Layout(this.contentContainer);
         new Jx.Layout(this.content);
-        /* continue ugly $unlink hack */
-        this.options.content = content;
+        
         this.loadContent(this.content);
-        
+
         this.toggleCollapse(this.options.closed);
         
         this.addEvent('addTo', function() {
@@ -10443,38 +10553,39 @@
                     this.toolbarContainers[position].style.height = '';                
                 }
             }, this);
-            for (var i=0; i<this.toolbars.length; i++) {
-                tb = this.toolbars[i];
-                position = tb.options.position;
-                tbc = this.toolbarContainers[position];
-                // IE 6 doesn't seem to want to measure the width of things
-                // correctly
-                if (Browser.Engine.trident4) {
-                    var oldParent = $(tbc.parentNode);
-                    tbc.style.visibility = 'hidden';
-                    $(document.body).adopt(tbc);                    
-                }
-                var size = tbc.getBorderBoxSize();
-                // put it back into its real parent now we are done measuring
-                if (Browser.Engine.trident4) {
-                    oldParent.adopt(tbc);
-                    tbc.style.visibility = '';
-                }
-                switch(position) {
-                    case 'top':
-                        top = size.height;
-                        break;
-                    case 'bottom':
-                        bottom = size.height;
-                        break;
-                    case 'left':
-                        left = size.width;
-                        break;
-                    case 'right':
-                        right = size.width;
-                        break;
-                }
-            
+            if ($type(this.options.toolbars) == 'array') {
+                this.options.toolbars.each(function(tb){
+                    position = tb.options.position;
+                    tbc = this.toolbarContainers[position];
+                    // IE 6 doesn't seem to want to measure the width of 
+                    // things correctly
+                    if (Browser.Engine.trident4) {
+                        var oldParent = $(tbc.parentNode);
+                        tbc.style.visibility = 'hidden';
+                        $(document.body).adopt(tbc);                    
+                    }
+                    var size = tbc.getBorderBoxSize();
+                    // put it back into its real parent now we are done 
+                    // measuring
+                    if (Browser.Engine.trident4) {
+                        oldParent.adopt(tbc);
+                        tbc.style.visibility = '';
+                    }
+                    switch(position) {
+                        case 'top':
+                            top = size.height;
+                            break;
+                        case 'bottom':
+                            bottom = size.height;
+                            break;
+                        case 'left':
+                            left = size.width;
+                            break;
+                        case 'right':
+                            right = size.width;
+                            break;
+                    }                    
+                },this);
             }
             tbc = this.toolbarContainers['top'];
             if (tbc) {
@@ -10564,12 +10675,12 @@
         if (url.indexOf('?') == -1) {
             url = url + '?';
         }
-        //var ts = (new Date()).getTime();
-        //url = url + 'ts='+ts;
-        var opts = { method: 'get',
-                     onComplete:this.panelContentLoaded.bind(this),
-                     requestHeaders: ['If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT']};
-        var a = new Request(url, opts).send();
+        var a = new Request({
+            url: url,
+            method: 'get',
+            onComplete:this.panelContentLoaded.bind(this),
+            requestHeaders: ['If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT']
+        }).send();
     },
     /**
      * Method: panelContentLoaded
@@ -10647,7 +10758,7 @@
         this.fireEvent('close', this);
     }
     
-});// $Id: dialog.js 232 2008-12-02 12:42:14Z pagameba $
+});// $Id: dialog.js 291 2009-04-01 18:31:32Z pagameba $
 /**
  * Class: Jx.Dialog
  * A Jx.Dialog implements a floating dialog.  Dialogs represent a useful way
@@ -10678,12 +10789,16 @@
  * change - triggered when the value of an input in the dialog is changed
  * resize - triggered when the dialog is resized
  *
+ * Extends:
+ * Jx.Dialog extends <Jx.Panel>, please go there for more details.
+ *
  * License: 
  * Copyright (c) 2008, DM Solutions Group Inc.
  * 
  * This file is licensed under an MIT style license
  */
 Jx.Dialog = new Class({
+    Family: 'Jx.Dialog',
     /**
      * Extends:
      * <Jx.Panel>
@@ -10715,6 +10830,7 @@
         id: '',
         parent: null,
         resize: false,
+        resizeTooltip: '',
         move: true,
         close: true,
         collapse: true
@@ -10759,13 +10875,6 @@
         this.isOpening = false;
         this.firstShow = true;
         
-        /* ugly hack around $unlink in mootools */
-        var content = null;
-        if (options && options.content) {
-            content = options.content;
-            options.content = null;
-        }
-        
         /* initialize the panel overriding the type and position */
         this.parent($merge(
             {parent:document.body}, // these are defaults that can be overridden
@@ -10773,13 +10882,9 @@
             {type:'Dialog', position: 'absolute'} // these override anything passed to the options
         ));
         
-        /* ugly hack continued */
-        this.options.content = content;
-        this.loadContent(this.content);
-
         this.options.parent = $(this.options.parent);
         
-        if (!window.opera && this.options.modal) {
+        if (this.options.modal) {
             this.blanket = new Element('div',{
                 'class':'jxDialogModal',
                 styles:{
@@ -10835,6 +10940,7 @@
         if (this.options.resize) {
             this.resizeHandle = new Element('div', {
                 'class':'jxDialogResize',
+                title: this.options.resizeTooltip,
                 styles: {
                     'display':this.options.closed?'none':'block'
                 }
@@ -10876,6 +10982,34 @@
     },
     
     /**
+     * Method: resize
+     * resize the dialog.  This can be called when the dialog is closed
+     * or open.
+     *
+     * Parameters:
+     * width - the new width
+     * height - the new height
+     * autoPosition - boolean, false by default, if resizing an open dialog
+     * setting this to true will reposition it according to its position
+     * rules.
+     */
+    resize: function(width, height, autoPosition) {
+        this.options.width = width;
+        this.options.height = height;
+        if (this.domObj.getStyle('display') != 'none') {
+            this.layoutContent();
+            this.domObj.resize(this.options);
+            this.fireEvent('resize');
+            this.resizeChrome(this.domObj);
+            if (autoPosition) {
+                this.position(this.domObj, this.options.parent, this.options);                
+            }
+        } else {
+            this.firstShow = false;
+        }
+    },
+    
+    /**
      * Method: sizeChanged
      * overload panel's sizeChanged method
      */
@@ -10932,17 +11066,6 @@
     },
     
     /**
-     * Method: setTitle
-     * set the text of the dialog title.
-     *
-     * Parameters: 
-     * title - {String} the new title
-     */
-    setTitle: function( title ) {
-        this.title.childNodes[0].innerHTML = title;
-    },
-
-    /**
      * Method: show
      * show the dialog, external code should use the <Jx.Dialog::open> method
      * to make the dialog visible.
@@ -11010,6 +11133,23 @@
         
     },
     /**
+     * Method: openURL
+     * open the dialog and load content from the provided url.  If you don't
+     * provide a URL then the dialog opens normally.
+     *
+     * Parameters:
+     * url - <String> the url to load when opening.
+     */
+    openURL: function(url) {
+        if (url) {
+            this.options.contentURL = url;
+            this.loadContent(this.content);
+        } else {
+            this.open();
+        }
+    },
+    
+    /**
      * Method: open
      * open the dialog.  This may be delayed depending on the 
      * asynchronous loading of dialog content.  The onOpen
@@ -11024,6 +11164,8 @@
             this.show();
             this.fireEvent('open', this);
             this.isOpening = false;
+        } else {
+            this.addEvent('contentLoaded', this.open.bind(this));
         }
     },
     /**
@@ -11035,18 +11177,6 @@
         this.isOpening = false;
         this.hide();
         this.fireEvent('close');
-    },
-    /**
-     * Method: onContentLoaded
-     * handle the dialog content being loaded.  This triggers
-     * processing of inputs and the onContentLoaded callback
-     * function (if necessary).  Also, if the dialog was previously
-     * requested to be opened, this will actually open it.
-     */
-    onContentLoaded : function() {
-        if (this.isOpening) {
-            this.open();
-        }
     }
 });
 
@@ -11066,7 +11196,7 @@
     });
     
 };
-// $Id: panelset.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: panelset.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.PanelSet
  *
@@ -11097,6 +11227,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.PanelSet = new Class({
+    Family: 'Jx.PanelSet',
     /**
      * Implements:
      * * Options
@@ -11107,7 +11238,8 @@
     
     options: {
         parent: null,
-        panels: []
+        panels: [],
+        barTooltip: 'drag this bar to resize'
     },
     
     /**
@@ -11165,7 +11297,7 @@
             prepareBar: (function(i) {
                 var bar = new Element('div', {
                     'class': 'jxPanelBar',
-                    'title': 'drag this bar to resize'
+                    'title': this.options.barTooltip
                 });
                 
                 var panel = this.panels[i];
@@ -11296,7 +11428,7 @@
         }
         panel.domObj.resize({top: top, height:panelSize, bottom: null});
     }
-});// $Id: button.combo.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: button.combo.js 295 2009-04-02 13:40:34Z pagameba $
 /**
  * Class: Jx.Button.Combo
  * A drop down list of selectable items.  Items can be either a string, an image or both.
@@ -11326,17 +11458,12 @@
  * This file is licensed under an MIT style license
  */
 Jx.Button.Combo = new Class({
+    Family: 'Jx.Button.Combo',
     /**
      * Extends:
      * <Jx.Button.Multi>
      */
     Extends: Jx.Button.Multi,
-    /**
-     * Implements:
-     * * <Jx.AutoPosition>
-     * * <Jx.Chrome>
-     */
-    Implements: [Jx.AutoPosition, Jx.Chrome],
     domObj : null,
     ul : null,
     /**
@@ -11359,12 +11486,23 @@
      * is editable.
      */
     initialize: function(options) {
-        this.parent();
+        this.parent(); //we don't want to pass options to parent
         this.setOptions(options);
         this.domA.removeClass('jxButtonMulti');
-        this.domA.addClass('jxButtonComboDefault');
-        
         if (this.options.editable) {
+            // remove the button's normal A tag and replace it with a span
+            // so the input ends up not being inside an A tag - this was
+            // causing all kinds of problems for selecting text inside it
+            // due to some user-select: none classes that were introduced
+            // to make buttons not selectable in the first place.
+            //
+            // Ultimately I think we want to fix this so that the discloser
+            // in Jx.Button.Multi is a separate beast and we can use it here
+            // without inheriting from multi buttons
+            var s = new Element('span', {'class':'jxButton'});
+            s.adopt(this.domA.firstChild);
+            this.domA = s.replaces(this.domA);
+            this.domA.addClass('jxButtonComboDefault');
             this.domA.addClass('jxButtonEditCombo');
             this.domInput = new Element('input',{
                 type:'text',
@@ -11380,12 +11518,12 @@
                 },
                 value: this.options.label
             });
+            this.domLabel.empty();
             this.domLabel.addClass('jxComboInput');
             this.domLabel.adopt(this.domInput);
         } else {
             this.discloser.dispose();
             this.domA.addClass('jxButtonCombo');
-            //this.setLabel(this.options.label);
             this.addEvent('click', (function(e){
                 this.discloser.fireEvent('click', e);
             }).bindWithEvent(this));
@@ -11530,7 +11668,7 @@
         }
         return value;
     }
-});// $Id: splitter.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: splitter.js 282 2009-04-01 17:23:37Z pagameba $
 /**
  * Class: Jx.Splitter
  * a Jx.Splitter creates two or more containers within a parent container
@@ -11552,6 +11690,7 @@
  */
  
 Jx.Splitter = new Class({
+    Family: 'Jx.Splitter',
     /**
      * Implements:
      * * Options
@@ -11587,7 +11726,10 @@
         containerOptions: [],
         barOptions: [],
         layout: 'horizontal',
-        snaps: []
+        snaps: [],
+        barTooltip: 'drag this bar to resize',
+        onStart: null,
+        onFinish: null
     },
     /**
      * Constructor: Jx.Splitter
@@ -11750,7 +11892,7 @@
     prepareBar: function() {
         var o = new Element('div', {
             'class': 'jxSplitBar'+this.options.layout.capitalize(),
-            'title': 'drag this bar to resize'
+            'title': this.options.barTitle
         });
         return o;
     },
@@ -11771,6 +11913,7 @@
             fn = this.dragVertical;
         }
         this.bars.each(function(bar){
+            var mask;
             new Drag(bar, {
                 //limit: limit,
                 modifiers: modifiers,
@@ -11778,11 +11921,25 @@
                     obj.addClass('jxSplitBarDrag');
                 },
                 onComplete : (function(obj) {
+                    mask.destroy();
                     obj.removeClass('jxSplitBarDrag');
                     if (obj.retrieve('splitterObj') != this) {
                         return;
                     }
                     fn.apply(this,[obj]);
+                }).bind(this),
+                onBeforeStart: function(obj) {
+                    mask = new Element('div',{'class':'jxSplitterMask'}).inject(obj, 'after');
+                },
+                onStart: (function() {
+                    if (this.options.onStart) {
+                        this.options.onStart();
+                    }
+                }).bind(this),
+                onFinish: (function() {
+                    if (this.options.onFinish) {
+                        this.options.onFinish();
+                    }
                 }).bind(this)
             });
         }, this);
@@ -12215,7 +12372,7 @@
              }
          }
     }
-});// $Id: splitter.snap.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: splitter.snap.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Splitter.Snap
  * A helper class to create an element that can snap a split panel open or
@@ -12231,6 +12388,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Splitter.Snap = new Class({
+    Family: 'Jx.Splitter.Snap',
     /**
      * Property: snap
      * {HTMLElement} the DOM element of the snap (the thing that gets
@@ -12335,7 +12493,7 @@
             }
         }
     }
-});// $Id: tabset.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: tabset.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.TabSet
  * A TabSet manages a set of <Jx.Button.Tab> content areas by ensuring that only one
@@ -12372,6 +12530,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.TabSet = new Class({
+    Family: 'Jx.TabSet',
     Implements: [Options,Events],
     /**
      * Property: tabs
@@ -12479,7 +12638,7 @@
 
 
 
-// $Id: tabbox.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: tabbox.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.TabBox
  * A convenience class to handle the common case of a single toolbar
@@ -12504,6 +12663,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.TabBox = new Class({
+    Family: 'Jx.TabBox',
     /**
      * Implements:
      * * Options
@@ -12536,7 +12696,8 @@
         this.setOptions(options);
         this.tabBar = new Jx.Toolbar({
             type: 'TabBar', 
-            position: this.options.position
+            position: this.options.position,
+            scroll: this.options.scroll
         });
         this.panel = new Jx.Panel({
             toolbars: [this.tabBar],
@@ -12609,7 +12770,7 @@
         this.tabSet.remove(tab);
     }
 });
-// $Id: button.tab.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: button.tab.js 261 2009-03-31 18:36:52Z pagameba $
 /**
  * Class: Jx.Button.Tab
  * A single tab in a tab set.  A tab has a label (displayed in the tab) and a
@@ -12650,6 +12811,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Button.Tab = new Class({
+    Family: 'Jx.Button.Tab',
     /**
      * Extends:
      * <Jx.Button>
@@ -12677,15 +12839,9 @@
      * valid options.
      */
     initialize : function( options) {
-        var content;
-        if (options && options.content) {
-            content = options.content;
-            options.content = null;
-        }
         this.parent($merge(options, {type:'Tab', toggle:true}));
         this.content = new Element('div', {'class':'tabContent'});
         new Jx.Layout(this.content, options);
-        this.options.content = content;
         this.loadContent(this.content);
         var that = this;
         this.addEvent('down', function(){that.content.addClass('tabContentActive');});
@@ -12701,7 +12857,11 @@
                     }).bind(this)
                 } 
             });
-            a.adopt(new Element('img', {src: Jx.aPixel.src}));
+            a.adopt(new Element('img', {
+                src: Jx.aPixel.src,
+                alt: '',
+                title: ''
+            }));
             this.domObj.adopt(a);
         }
     },
@@ -12715,7 +12875,7 @@
             this.setActive(true);            
         }
     }
-});// $Id: toolbar.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: toolbar.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Toolbar
  * A toolbar is a container object that contains other objects such as
@@ -12763,6 +12923,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Toolbar = new Class({
+    Family: 'Jx.Toolbar',
     Implements: [Options,Events],
     /**
      * Property: items
@@ -12944,7 +13105,7 @@
         this.fireEvent('show', item);
     }
 });
-// $Id: toolbar.item.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: toolbar.item.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Toolbar.Item
  * A helper class to provide a container for something to go into 
@@ -12956,6 +13117,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Toolbar.Item = new Class( {
+    Family: 'Jx.Toolbar.Item',
     Implements: [Options],
     options: {
         active: true
@@ -12990,7 +13152,7 @@
             }
         }
     }
-});// $Id: toolbar.separator.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: toolbar.separator.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Toolbar.Separator
  * A helper class that represents a visual separator in a <Jx.Toolbar>
@@ -13005,6 +13167,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Toolbar.Separator = new Class({
+    Family: 'Jx.Toolbar.Separator',
     /**
      * Property: domObj
      * {HTMLElement} The DOM element that goes in the <Jx.Toolbar>
@@ -13020,7 +13183,7 @@
         this.domObj.appendChild(this.domSpan);
     }
 });
-// $Id: toolbar.container.js 241 2008-12-10 15:11:05Z pagameba $
+// $Id: toolbar.container.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Toolbar.Container
  * A toolbar container contains toolbars.  A single toolbar container fills the
@@ -13042,6 +13205,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Toolbar.Container = new Class({
+    Family: 'Jx.Toolbar.Container',
     Implements: [Options,Events, Jx.Addable],
     /**
      * Property: domObj
@@ -13164,7 +13328,6 @@
     },
     
     measure: function() {
-        
         if ((!this.scrollLeftSize || !this.scrollLeftSize.x) && this.domObj.parentNode) {
             this.scrollLeftSize = this.scrollLeft.domObj.getSize();
             this.scrollRightSize = this.scrollRight.domObj.getSize();
@@ -13265,8 +13428,22 @@
     scrollIntoView: function(item) {
         var width = this.domObj.getSize().x;
         var coords = item.domObj.getCoordinates(this.scroller);
-        var l = this.scroller.getStyle('left').toInt();
-        
+		
+		//left may be set to auto or even a zero length string. 
+		//In the previous version, in air, this would evaluate to
+		//NaN which would cause the right hand scroller to show when 
+		//the component was first created.
+		
+		//So, get the left value first
+        var l = this.scroller.getStyle('left');
+		//then check to see if it's auto or a zero length string 
+		if (l === 'auto' || l.length <= 0) {
+			//If so, set to 0.
+			l = 0;
+		} else {
+			//otherwise, convert to int
+			l = l.toInt();
+		}
         var slSize = this.scrollLeftSize ? this.scrollLeftSize.x : 0;
         var srSize = this.scrollRightSize ? this.scrollRightSize.x : 0;
         
@@ -13295,13 +13472,12 @@
         } else {
             this.scrollRight.domObj.setStyle('visibility', '');                
         }
-        
         if (left != l) {
             this.scrollFx.start('left', left);
         }
     }
 });
-// $Id: treeitem.js 239 2008-12-10 14:53:58Z pagameba $
+// $Id: treeitem.js 301 2009-04-02 16:12:11Z pagameba $
 /**
  * Class: Jx.TreeItem 
  * An item in a tree.  An item is a leaf node that has no children.
@@ -13327,6 +13503,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.TreeItem = new Class ({
+    Family: 'Jx.TreeItem',
     Implements: [Options,Events],
     /**
      * Property: domObj
@@ -13374,7 +13551,12 @@
             this.domObj.id = this.options.id;
         }
       
-        this.domNode = new Element('img',{'class': 'jxTreeImage', src: Jx.aPixel.src});
+        this.domNode = new Element('img',{
+            'class': 'jxTreeImage', 
+            src: Jx.aPixel.src,
+            alt: '',
+            title: ''
+        });
         this.domObj.appendChild(this.domNode);
         
         this.domLabel = (this.options.draw) ? 
@@ -13389,7 +13571,12 @@
         }
     },
     draw: function() {
-        var domImg = new Element('img',{'class':'jxTreeIcon', src: Jx.aPixel.src});
+        var domImg = new Element('img',{
+            'class':'jxTreeIcon', 
+            src: Jx.aPixel.src,
+            alt: '',
+            title: ''
+        });
         if (this.options.image) {
             domImg.setStyle('backgroundImage', 'url('+this.options.image+')');
         }
@@ -13407,14 +13594,17 @@
         domA.addEvents({
             click: this.selected.bind(this),
             dblclick: this.selected.bind(this),
-            contextmenu: this.showMenu.bind(this),
             drag: function(e) {e.stop();},
-            mousedown: function(e) {
-                domA.addClass('jxTreeItemPressed');
-                hasFocus = true;
-                mouseDown = true;
-                domA.focus();
-            },
+            contextmenu: function(e) { e.stop(); },
+            mousedown: (function(e) {
+               domA.addClass('jxTreeItemPressed');
+               hasFocus = true;
+               mouseDown = true;
+               domA.focus();
+               if (e.rightClick && this.options.contextMenu) {
+                   this.options.contextMenu.show(e);
+               }
+            }).bind(this),
             mouseup: function(e) {
                 domA.removeClass('jxTreeItemPressed');
                 mouseDown = false;
@@ -13502,25 +13692,9 @@
      * e - {Event} the DOM event
      */
     selected : function(e) {
-        this.lastEvent = new Event(e);
         this.fireEvent('click', this);
     },
     /**
-     * Method: showMenu
-     * Called when the DOM element for the TreeItem is right-clicked.  The
-     * node is selected and the context menu displayed (if there is one).
-     *
-     * Parameters:
-     * e - {Event} the DOM event
-     */
-    showMenu: function(e) {
-        this.lastEvent = new Event(e);
-        if (this.contextMenu) {
-            this.contextMenu.show(this.lastEvent);
-        }
-        this.lastEvent.stop();
-    },
-    /**
      * Method: getName
      * Get the label associated with a TreeItem
      *
@@ -13544,7 +13718,7 @@
             this.domObj.addClass('jxDisabled');
         }
     }
-});// $Id: treefolder.js 240 2008-12-10 15:04:11Z pagameba $
+});// $Id: treefolder.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.TreeFolder
  * A Jx.TreeFolder is an item in a tree that can contain other items.  It is
@@ -13563,6 +13737,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.TreeFolder = new Class({
+    Family: 'Jx.TreeFolder',
     Extends: Jx.TreeItem,
     /**
      * Property: subDomObj
@@ -13607,7 +13782,6 @@
         this.nodes = [];
         this.subDomObj = new Element('ul', {'class':'jxTree'});
         this.domObj.appendChild(this.subDomObj);
-        this.subDomObj.className = 'jxTree';
         if (this.options.open) {
             this.expand();
         } else {
@@ -13878,7 +14052,7 @@
         }
         return null;
     }
-});// $Id: tree.js 241 2008-12-10 15:11:05Z pagameba $
+});// $Id: tree.js 258 2009-03-31 17:26:30Z pagameba $
 /**
  * Class: Jx.Tree
  * Jx.Tree displays hierarchical data in a tree structure of folders and nodes.
@@ -13895,6 +14069,7 @@
  * This file is licensed under an MIT style license
  */
 Jx.Tree = new Class({
+    Family: 'Jx.Tree',
     Implements: [Jx.Addable],
     Extends: Jx.TreeFolder,
     /**

Modified: trunk/widgets/Legend.js
===================================================================
--- trunk/widgets/Legend.js	2009-04-03 14:48:38 UTC (rev 1826)
+++ trunk/widgets/Legend.js	2009-04-03 18:30:09 UTC (rev 1827)
@@ -251,10 +251,20 @@
             label: OpenLayers.i18n('defaultMapTitle'),
             open: true,
             draw: this.renderFolder,
+            contextMenu: this.getContextMenu(),
             'class':'fusionLegendFolder'
         };
         this.oRoot = new Jx.TreeFolder(opt);
-        this.oRoot.contextMenu = this.getContextMenu(this.oRoot);
+        this.oRoot.options.contextMenu.add(
+            new Jx.Menu.Item({
+                label: OpenLayers.i18n('collapse'),
+                onClick: OpenLayers.Function.bind(this.collapseBranch, this, this.oRoot)
+            }),
+            new Jx.Menu.Item({
+                label: OpenLayers.i18n('expand'),
+                onClick: OpenLayers.Function.bind(this.expandBranch, this, this.oRoot)
+            })
+        );
         
         this.oTree.append(this.oRoot);
         
@@ -267,47 +277,23 @@
         this.extentsChangedWatcher = this.update.bind(this);
     },
     
-    getContextMenu: function(folder) {
-        if (folder instanceof Jx.TreeFolder) {
-                        return new Jx.Menu.Context(this.name).add(
-                new Jx.Menu.Item({
-                    label: OpenLayers.i18n('collapse'),
-                    onClick: OpenLayers.Function.bind(this.collapseBranch, this, folder)
-                }),
-                new Jx.Menu.Item({
-                    label: OpenLayers.i18n('expand'),
-                    onClick: OpenLayers.Function.bind(this.expandBranch, this, folder)
-                }),
-                new Jx.Menu.Item({
-                    label: OpenLayers.i18n('refresh'),
-                    onClick: OpenLayers.Function.bind(this.update, this, folder)
-                }),
-                new Jx.Menu.Item({
-                    label: OpenLayers.i18n('collapseAll'),
-                    onClick: OpenLayers.Function.bind(this.collapseAll, this, folder)
-                }),
-                new Jx.Menu.Item({
-                    label: OpenLayers.i18n('expandAll'),
-                    onClick: OpenLayers.Function.bind(this.expandAll, this, folder)
-                })
-            );
-        } else {
-            return new Jx.Menu.Context(this.name).add(
-                new Jx.Menu.Item({
-                    label: OpenLayers.i18n('refresh'),
-                    onClick: OpenLayers.Function.bind(this.update, this, folder)
-                }),
-                new Jx.Menu.Item({
-                    label: OpenLayers.i18n('collapseAll'),
-                    onClick: OpenLayers.Function.bind(this.collapseAll, this, folder)
-                }),
-                new Jx.Menu.Item({
-                    label: OpenLayers.i18n('expandAll'),
-                    onClick: OpenLayers.Function.bind(this.expandAll, this, folder)
-                })
-            );
-        }
+    getContextMenu: function() {
+        return new Jx.Menu.Context(this.name).add(
+            new Jx.Menu.Item({
+                label: OpenLayers.i18n('refresh'),
+                onClick: OpenLayers.Function.bind(this.update, this)
+            }),
+            new Jx.Menu.Item({
+                label: OpenLayers.i18n('collapseAll'),
+                onClick: OpenLayers.Function.bind(this.collapseAll, this)
+            }),
+            new Jx.Menu.Item({
+                label: OpenLayers.i18n('expandAll'),
+                onClick: OpenLayers.Function.bind(this.expandAll, this)
+            })
+        );
     },
+    
     expandAll: function(folder) {
         for (var i=0; i<this.oTree.nodes.length; i++) {
             var item = this.oTree.nodes[i];
@@ -425,12 +411,22 @@
                 label: group.legendLabel,
                 open: group.expandInLegend,
                 draw: this.renderFolder,
+                contextMenu: this.getContextMenu(),
                 'class':'fusionLegendFolder'
             };
             group.legend.treeItem = new Jx.TreeFolder(opt);
-            group.legend.treeItem.contextMenu = this.getContextMenu(group.legend.treeItem);
             group.legend.treeItem.domObj.store('data', group);
-            
+            group.legend.treeItem.options.contextMenu.add(
+                new Jx.Menu.Item({
+                    label: OpenLayers.i18n('collapse'),
+                    onClick: OpenLayers.Function.bind(this.collapseBranch, this, group.legend.treeItem)
+                }),
+                new Jx.Menu.Item({
+                    label: OpenLayers.i18n('expand'),
+                    onClick: OpenLayers.Function.bind(this.expandBranch, this, group.legend.treeItem)
+                })
+            );
+
             folder.append(group.legend.treeItem);
             group.legend.treeItem.checkBox.checked = group.visible?true:false;
             OpenLayers.Event.observe(group.legend.treeItem.checkBox, 'click', OpenLayers.Function.bind(this.stateChanged, this, group));
@@ -616,11 +612,23 @@
             isOpen: layer.expandInLegend,
             draw: this.renderFolder,
             'class':'fusionLegendItemCheckbox',
+            contextMenu: this.getContextMenu(),
             // image overrides
             image: this.imgLayerThemeIcon
         };
         var folder = new Jx.TreeFolder(opt);
-        folder.contextMenu = this.getContextMenu(folder);
+        folder.options.contextMenu.add(
+            new Jx.Menu.Item({
+                label: OpenLayers.i18n('collapse'),
+                onClick: OpenLayers.Function.bind(this.collapseBranch, this, folder)
+            }),
+            new Jx.Menu.Item({
+                label: OpenLayers.i18n('expand'),
+                onClick: OpenLayers.Function.bind(this.expandBranch, this, folder)
+            })
+        );
+        
+        
         var layerInfo = layer.oMap.getLayerInfoUrl(layer.layerName);
         if (layerInfo) {
             var a = document.createElement('a');
@@ -661,9 +669,9 @@
         } else {
             opt.image = layer.oMap.getLegendImageURL(scale, layer, style);
         }
+        opt.contextMenu = this.getContextMenu(); 
 
         var item = new Jx.TreeItem(opt);
-        item.contextMenu = this.getContextMenu(item); 
         if (bCheckBox) {
             //item.domObj.insertBefore(layer.legend.checkBox, item.domObj.childNodes[1]);
             /* only need to add layer info if it has a check box too */
@@ -726,7 +734,7 @@
             events: {
                 click: this.selected.bindWithEvent(this),
                 dblclick: this.selected.bindWithEvent(this),
-                contextmenu: this.showMenu.bindWithEvent(this)
+                contextmenu: this.options.contextMenu.show.bindWithEvent(this.options.contextMenu)
             }
         });
         domA.appendChild(this.domImg);
@@ -756,7 +764,7 @@
             events: {
                 click: this.selected.bindWithEvent(this),
                 dblclick: this.selected.bindWithEvent(this),
-                contextmenu: this.showMenu.bindWithEvent(this)
+                contextmenu: this.options.contextMenu.show.bindWithEvent(this.options.contextMenu)
             }
         });
         
@@ -796,7 +804,7 @@
             events: {
                 click: this.selected.bindWithEvent(this),
                 dblclick: this.selected.bindWithEvent(this),
-                contextmenu: this.showMenu.bindWithEvent(this)
+                contextmenu: this.options.contextMenu.show.bindWithEvent(this.options.contextMenu)
             }
         });
         



More information about the fusion-commits mailing list