summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/layout
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo/dojox/layout')
-rw-r--r--js/dojo/dojox/layout/BorderContainer.js7
-rw-r--r--js/dojo/dojox/layout/ContentPane.js100
-rw-r--r--js/dojo/dojox/layout/DragPane.js60
-rw-r--r--js/dojo/dojox/layout/ExpandoPane.js291
-rw-r--r--js/dojo/dojox/layout/FloatingPane.js405
-rw-r--r--js/dojo/dojox/layout/GridContainer.js630
-rw-r--r--js/dojo/dojox/layout/GridContainerLite.js829
-rw-r--r--js/dojo/dojox/layout/README121
-rw-r--r--js/dojo/dojox/layout/RadioGroup.js297
-rw-r--r--js/dojo/dojox/layout/ResizeHandle.js364
-rw-r--r--js/dojo/dojox/layout/RotatorContainer.js456
-rw-r--r--js/dojo/dojox/layout/ScrollPane.js154
-rw-r--r--js/dojo/dojox/layout/TableContainer.js283
-rw-r--r--js/dojo/dojox/layout/ToggleSplitter.js296
-rw-r--r--js/dojo/dojox/layout/dnd/Avatar.js51
-rw-r--r--js/dojo/dojox/layout/dnd/PlottedDnd.js519
-rw-r--r--js/dojo/dojox/layout/ext-dijit/layout/StackContainer-touch.js49
-rw-r--r--js/dojo/dojox/layout/resources/DndGridContainer.css13
-rw-r--r--js/dojo/dojox/layout/resources/ExpandoPane.css263
-rw-r--r--js/dojo/dojox/layout/resources/ExpandoPane.html9
-rw-r--r--js/dojo/dojox/layout/resources/FloatingPane.css184
-rw-r--r--js/dojo/dojox/layout/resources/FloatingPane.html14
-rw-r--r--js/dojo/dojox/layout/resources/GridContainer.css74
-rw-r--r--js/dojo/dojox/layout/resources/GridContainer.html11
-rw-r--r--js/dojo/dojox/layout/resources/RadioGroup.css45
-rw-r--r--js/dojo/dojox/layout/resources/ResizeHandle.css52
-rw-r--r--js/dojo/dojox/layout/resources/RotatorContainer.css47
-rw-r--r--js/dojo/dojox/layout/resources/ScrollPane.css24
-rw-r--r--js/dojo/dojox/layout/resources/ScrollPane.html6
-rw-r--r--js/dojo/dojox/layout/resources/ToggleSplitter.css87
-rw-r--r--js/dojo/dojox/layout/resources/icons/gridcontainer_grip.gifbin0 -> 80 bytes
-rw-r--r--js/dojo/dojox/layout/resources/icons/grip_bg.gifbin0 -> 46 bytes
-rw-r--r--js/dojo/dojox/layout/resources/icons/pixel.gifbin0 -> 64 bytes
-rw-r--r--js/dojo/dojox/layout/resources/icons/resize.pngbin0 -> 319 bytes
-rw-r--r--js/dojo/dojox/layout/resources/icons/resizeRtl.pngbin0 -> 269 bytes
-rw-r--r--js/dojo/dojox/layout/resources/icons/rotator.pngbin0 -> 1895 bytes
-rw-r--r--js/dojo/dojox/layout/resources/icons/splitterToggleH.pngbin0 -> 2937 bytes
-rw-r--r--js/dojo/dojox/layout/resources/icons/splitterToggleV.pngbin0 -> 2938 bytes
38 files changed, 5741 insertions, 0 deletions
diff --git a/js/dojo/dojox/layout/BorderContainer.js b/js/dojo/dojox/layout/BorderContainer.js
new file mode 100644
index 0000000..de5a15d
--- /dev/null
+++ b/js/dojo/dojox/layout/BorderContainer.js
@@ -0,0 +1,7 @@
+//>>built
+// wrapped by build app
+define("dojox/layout/BorderContainer", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
+dojo.provide("dojox.layout.BorderContainer");
+
+console.error("dojox.layout.BorderContainer moved to dijit.layout.BorderContainer");
+});
diff --git a/js/dojo/dojox/layout/ContentPane.js b/js/dojo/dojox/layout/ContentPane.js
new file mode 100644
index 0000000..68cd7ad
--- /dev/null
+++ b/js/dojo/dojox/layout/ContentPane.js
@@ -0,0 +1,100 @@
+//>>built
+define("dojox/layout/ContentPane", [
+ "dojo/_base/lang",
+ "dojo/_base/xhr",
+ "dijit/layout/ContentPane",
+ "dojox/html/_base",
+ "dojo/_base/declare"
+], function (lang, xhrUtil, ContentPane, htmlUtil, declare) {
+
+/*===== var ContentPane = dijit.layout.ContentPane =====*/
+return declare("dojox.layout.ContentPane", ContentPane, {
+ // summary:
+ // An extended version of dijit.layout.ContentPane.
+ // Supports infile scripts and external ones declared by <script src=''
+ // relative path adjustments (content fetched from a different folder)
+ // <style> and <link rel='stylesheet' href='..'> tags,
+ // css paths inside cssText is adjusted (if you set adjustPaths = true)
+ //
+ // NOTE that dojo.require in script in the fetched file isn't recommended
+ // Many widgets need to be required at page load to work properly
+
+ // adjustPaths: Boolean
+ // Adjust relative paths in html string content to point to this page.
+ // Only useful if you grab content from a another folder then the current one
+ adjustPaths: false,
+
+ // cleanContent: Boolean
+ // summary:
+ // cleans content to make it less likely to generate DOM/JS errors.
+ // description:
+ // useful if you send ContentPane a complete page, instead of a html fragment
+ // scans for
+ //
+ // * title Node, remove
+ // * DOCTYPE tag, remove
+ cleanContent: false,
+
+ // renderStyles: Boolean
+ // trigger/load styles in the content
+ renderStyles: false,
+
+ // executeScripts: Boolean
+ // Execute (eval) scripts that is found in the content
+ executeScripts: true,
+
+ // scriptHasHooks: Boolean
+ // replace keyword '_container_' in scripts with 'dijit.byId(this.id)'
+ // NOTE this name might change in the near future
+ scriptHasHooks: false,
+
+ constructor: function(){
+ // init per instance properties, initializer doesn't work here because how things is hooked up in dijit._Widget
+ this.ioArgs = {};
+ this.ioMethod = xhrUtil.get;
+ },
+
+ onExecError: function(e){
+ // summary:
+ // event callback, called on script error or on java handler error
+ // overide and return your own html string if you want a some text
+ // displayed within the ContentPane
+ },
+
+ _setContent: function(cont){
+ // override dijit.layout.ContentPane._setContent, to enable path adjustments
+
+ var setter = this._contentSetter;
+ if(! (setter && setter instanceof htmlUtil._ContentSetter)) {
+ setter = this._contentSetter = new htmlUtil._ContentSetter({
+ node: this.containerNode,
+ _onError: lang.hitch(this, this._onError),
+ onContentError: lang.hitch(this, function(e){
+ // fires if a domfault occurs when we are appending this.errorMessage
+ // like for instance if domNode is a UL and we try append a DIV
+ var errMess = this.onContentError(e);
+ try{
+ this.containerNode.innerHTML = errMess;
+ }catch(e){
+ console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
+ }
+ })/*,
+ _onError */
+ });
+ };
+
+ // stash the params for the contentSetter to allow inheritance to work for _setContent
+ this._contentSetterParams = {
+ adjustPaths: Boolean(this.adjustPaths && (this.href||this.referencePath)),
+ referencePath: this.href || this.referencePath,
+ renderStyles: this.renderStyles,
+ executeScripts: this.executeScripts,
+ scriptHasHooks: this.scriptHasHooks,
+ scriptHookReplacement: "dijit.byId('"+this.id+"')"
+ };
+
+ this.inherited("_setContent", arguments);
+ }
+ // could put back _renderStyles by wrapping/aliasing dojox.html._ContentSetter.prototype._renderStyles
+});
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/layout/DragPane.js b/js/dojo/dojox/layout/DragPane.js
new file mode 100644
index 0000000..dab0405
--- /dev/null
+++ b/js/dojo/dojox/layout/DragPane.js
@@ -0,0 +1,60 @@
+//>>built
+define("dojox/layout/DragPane", ["dojo/_base/declare", "dijit/_Widget", "dojo/_base/html", "dojo/dom-style"],
+ function(declare, Widget, htmlUtil, domStyle){
+/*===== var Widget = dijit._Widget; =====*/
+return declare("dojox.layout.DragPane", Widget, {
+ // summary: Makes a pane's content dragable by/within it's surface
+ //
+ // description:
+ // A small widget which takes a node with overflow:auto and
+ // allows dragging to position the content. Useful with images,
+ // or for just adding "something" to a overflow-able div.
+ //
+ // invert: Boolean
+ // Naturally, the behavior is to invert the axis of the drag.
+ // Setting invert:false will make the pane drag in the same
+ // direction as the mouse.
+ invert: true,
+
+ postCreate: function(){
+ this.connect(this.domNode, "onmousedown", "_down");
+ this.connect(this.domNode, "onmouseleave", "_up");
+ this.connect(this.domNode, "onmouseup", "_up");
+ },
+
+ _down: function(e){
+ // summary: mousedown handler, start the dragging
+ var t = this.domNode;
+ e.preventDefault();
+ domStyle.set(t, "cursor", "move");
+ this._x = e.pageX;
+ this._y = e.pageY;
+ if ((this._x < t.offsetLeft + t.clientWidth) &&
+ (this._y < t.offsetTop + t.clientHeight)) {
+ htmlUtil.setSelectable(t,false);
+ this._mover = this.connect(t, "onmousemove", "_move");
+ }
+ },
+
+ _up: function(e){
+ // summary: mouseup handler, stop the dragging
+ htmlUtil.setSelectable(this.domNode,true);
+ domStyle.set(this.domNode, "cursor", "pointer");
+ this._mover && this.disconnect(this._mover);
+ delete this._mover;
+ },
+
+ _move: function(e){
+ // summary: mousemove listener, offset the scroll amount by the delta
+ // since our last call.
+
+ var mod = this.invert ? 1 : -1;
+ this.domNode.scrollTop += (this._y - e.pageY) * mod;
+ this.domNode.scrollLeft += (this._x - e.pageX) * mod;
+ this._x = e.pageX;
+ this._y = e.pageY;
+
+ }
+
+});
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/layout/ExpandoPane.js b/js/dojo/dojox/layout/ExpandoPane.js
new file mode 100644
index 0000000..e370bf2
--- /dev/null
+++ b/js/dojo/dojox/layout/ExpandoPane.js
@@ -0,0 +1,291 @@
+//>>built
+require({cache:{
+'url:dojox/layout/resources/ExpandoPane.html':"<div class=\"dojoxExpandoPane\">\n\t<div dojoAttachPoint=\"titleWrapper\" class=\"dojoxExpandoTitle\">\n\t\t<div class=\"dojoxExpandoIcon\" dojoAttachPoint=\"iconNode\" dojoAttachEvent=\"onclick:toggle\"><span class=\"a11yNode\">X</span></div>\t\t\t\n\t\t<span class=\"dojoxExpandoTitleNode\" dojoAttachPoint=\"titleNode\">${title}</span>\n\t</div>\n\t<div class=\"dojoxExpandoWrapper\" dojoAttachPoint=\"cwrapper\" dojoAttachEvent=\"ondblclick:_trap\">\n\t\t<div class=\"dojoxExpandoContent\" dojoAttachPoint=\"containerNode\"></div>\n\t</div>\n</div>\n"}});
+define("dojox/layout/ExpandoPane", ["dojo/_base/kernel","dojo/_base/lang","dojo/_base/declare","dojo/_base/array",
+ "dojo/_base/connect","dojo/_base/event","dojo/_base/fx","dojo/dom-style",
+ "dojo/dom-class","dojo/dom-geometry","dojo/text!./resources/ExpandoPane.html",
+ "dijit/layout/ContentPane","dijit/_TemplatedMixin","dijit/_Contained","dijit/_Container"],
+ function(kernel,lang,declare,arrayUtil,connectUtil,eventUtil,baseFx,domStyle,domClass,domGeom,
+ template,ContentPane,TemplatedMixin,Contained,Container) {
+/*=====
+var ContentPane = dijit.layout.ContentPane;
+var TemplatedMixin = dijit._TemplatedMixin;
+var Contained = dijit._Contained;
+var Container = dijit._Container;
+ =====*/
+kernel.experimental("dojox.layout.ExpandoPane"); // just to show it can be done?
+
+return declare("dojox.layout.ExpandoPane", [ContentPane, TemplatedMixin, Contained, Container],{
+ // summary: An experimental collapsing-pane for dijit.layout.BorderContainer
+ //
+ // description:
+ // Works just like a ContentPane inside of a borderContainer. Will expand/collapse on
+ // command, and supports having Layout Children as direct descendants
+ //
+
+ //maxHeight: "",
+ //maxWidth: "",
+ //splitter: false,
+ attributeMap: lang.delegate(ContentPane.prototype.attributeMap, {
+ title: { node: "titleNode", type: "innerHTML" }
+ }),
+
+ templateString: template,
+
+ // easeOut: String|Function
+ // easing function used to hide pane
+ easeOut: "dojo._DefaultEasing", // FIXME: This won't work with globalless AMD
+
+ // easeIn: String|Function
+ // easing function use to show pane
+ easeIn: "dojo._DefaultEasing", // FIXME: This won't work with globalless AMD
+
+ // duration: Integer
+ // duration to run show/hide animations
+ duration: 420,
+
+ // startExpanded: Boolean
+ // Does this widget start in an open (true) or closed (false) state
+ startExpanded: true,
+
+ // previewOpacity: Float
+ // A value from 0 .. 1 indicating the opacity to use on the container
+ // when only showing a preview
+ previewOpacity: 0.75,
+
+ // previewOnDblClick: Boolean
+ // If true, will override the default behavior of a double-click calling a full toggle.
+ // If false, a double-click will cause the preview to popup
+ previewOnDblClick: false,
+
+ baseClass: "dijitExpandoPane",
+
+ postCreate: function(){
+ this.inherited(arguments);
+ this._animConnects = [];
+
+ this._isHorizontal = true;
+
+ if(lang.isString(this.easeOut)){
+ this.easeOut = lang.getObject(this.easeOut);
+ }
+ if(lang.isString(this.easeIn)){
+ this.easeIn = lang.getObject(this.easeIn);
+ }
+
+ var thisClass = "", rtl = !this.isLeftToRight();
+ if(this.region){
+ switch(this.region){
+ case "trailing" :
+ case "right" :
+ thisClass = rtl ? "Left" : "Right";
+ break;
+ case "leading" :
+ case "left" :
+ thisClass = rtl ? "Right" : "Left";
+ break;
+ case "top" :
+ thisClass = "Top";
+ break;
+ case "bottom" :
+ thisClass = "Bottom";
+ break;
+ }
+ domClass.add(this.domNode, "dojoxExpando" + thisClass);
+ domClass.add(this.iconNode, "dojoxExpandoIcon" + thisClass);
+ this._isHorizontal = /top|bottom/.test(this.region);
+ }
+ domStyle.set(this.domNode, {
+ overflow: "hidden",
+ padding:0
+ });
+
+ this.connect(this.domNode, "ondblclick", this.previewOnDblClick ? "preview" : "toggle");
+
+ if(this.previewOnDblClick){
+ this.connect(this.getParent(), "_layoutChildren", lang.hitch(this, function(){
+ this._isonlypreview = false;
+ }));
+ }
+
+ },
+
+ _startupSizes: function(){
+
+ this._container = this.getParent();
+ this._closedSize = this._titleHeight = domGeom.getMarginBox(this.titleWrapper).h;
+
+ if(this.splitter){
+ // find our splitter and tie into it's drag logic
+ var myid = this.id;
+ arrayUtil.forEach(dijit.registry.toArray(), function(w){
+ if(w && w.child && w.child.id == myid){
+ this.connect(w,"_stopDrag","_afterResize");
+ }
+ }, this);
+ }
+
+ this._currentSize = domGeom.getContentBox(this.domNode); // TODO: can compute this from passed in value to resize(), see _LayoutWidget for example
+ this._showSize = this._currentSize[(this._isHorizontal ? "h" : "w")];
+ this._setupAnims();
+
+ if(this.startExpanded){
+ this._showing = true;
+ }else{
+ this._showing = false;
+ this._hideWrapper();
+ this._hideAnim.gotoPercent(99,true);
+ }
+
+ this._hasSizes = true;
+ },
+
+ _afterResize: function(e){
+ var tmp = this._currentSize; // the old size
+ this._currentSize = domGeom.getMarginBox(this.domNode); // the new size
+ var n = this._currentSize[(this._isHorizontal ? "h" : "w")]
+ if(n > this._titleHeight){
+ if(!this._showing){
+ this._showing = !this._showing;
+ this._showEnd();
+ }
+ this._showSize = n;
+ this._setupAnims();
+ }else{
+ this._showSize = tmp[(this._isHorizontal ? "h" : "w")];
+ this._showing = false;
+ this._hideWrapper();
+ this._hideAnim.gotoPercent(89,true);
+ }
+
+ },
+
+ _setupAnims: function(){
+ // summary: Create the show and hide animations
+ arrayUtil.forEach(this._animConnects, connectUtil.disconnect);
+
+ var _common = {
+ node:this.domNode,
+ duration:this.duration
+ },
+ isHorizontal = this._isHorizontal,
+ showProps = {},
+ hideProps = {},
+ dimension = isHorizontal ? "height" : "width"
+ ;
+
+ showProps[dimension] = {
+ end: this._showSize
+ };
+ hideProps[dimension] = {
+ end: this._closedSize
+ };
+
+ this._showAnim = baseFx.animateProperty(lang.mixin(_common,{
+ easing:this.easeIn,
+ properties: showProps
+ }));
+ this._hideAnim = baseFx.animateProperty(lang.mixin(_common,{
+ easing:this.easeOut,
+ properties: hideProps
+ }));
+
+ this._animConnects = [
+ connectUtil.connect(this._showAnim, "onEnd", this, "_showEnd"),
+ connectUtil.connect(this._hideAnim, "onEnd", this, "_hideEnd")
+ ];
+ },
+
+ preview: function(){
+ // summary: Expand this pane in preview mode (does not affect surrounding layout)
+
+ if(!this._showing){
+ this._isonlypreview = !this._isonlypreview;
+ }
+ this.toggle();
+ },
+
+ toggle: function(){
+ // summary: Toggle this pane's visibility
+ if(this._showing){
+ this._hideWrapper();
+ this._showAnim && this._showAnim.stop();
+ this._hideAnim.play();
+ }else{
+ this._hideAnim && this._hideAnim.stop();
+ this._showAnim.play();
+ }
+ this._showing = !this._showing;
+ },
+
+ _hideWrapper: function(){
+ // summary: Set the Expando state to "closed"
+ domClass.add(this.domNode, "dojoxExpandoClosed");
+
+ domStyle.set(this.cwrapper,{
+ visibility: "hidden",
+ opacity: "0",
+ overflow: "hidden"
+ });
+ },
+
+ _showEnd: function(){
+ // summary: Common animation onEnd code - "unclose"
+ domStyle.set(this.cwrapper, {
+ opacity: 0,
+ visibility:"visible"
+ });
+ baseFx.anim(this.cwrapper, {
+ opacity: this._isonlypreview ? this.previewOpacity : 1
+ }, 227);
+ domClass.remove(this.domNode, "dojoxExpandoClosed");
+ if(!this._isonlypreview){
+ setTimeout(lang.hitch(this._container, "layout"), 15);
+ }else{
+ this._previewShowing = true;
+ this.resize();
+ }
+ },
+
+ _hideEnd: function(){
+ // summary: Callback for the hide animation - "close"
+
+ // every time we hide, reset the "only preview" state
+ if(!this._isonlypreview){
+ setTimeout(lang.hitch(this._container, "layout"), 25);
+ }else{
+ this._previewShowing = false;
+ }
+ this._isonlypreview = false;
+
+ },
+
+ resize: function(/* Object? */newSize){
+ // summary:
+ // we aren't a layout widget, but need to act like one:
+ // newSize: Object
+ // The size object to resize to
+
+ if(!this._hasSizes){ this._startupSizes(newSize); }
+
+ // compute size of container (ie, size left over after title bar)
+ var currentSize = domGeom.getMarginBox(this.domNode);
+ this._contentBox = {
+ w: newSize && "w" in newSize ? newSize.w : currentSize.w,
+ h: (newSize && "h" in newSize ? newSize.h : currentSize.h) - this._titleHeight
+ };
+ domStyle.set(this.containerNode, "height", this._contentBox.h + "px");
+
+ if(newSize){
+ domGeom.setMarginBox(this.domNode, newSize);
+ }
+
+ this._layoutChildren();
+ },
+
+ _trap: function(e){
+ // summary: Trap stray events
+ eventUtil.stop(e);
+ }
+});
+});
diff --git a/js/dojo/dojox/layout/FloatingPane.js b/js/dojo/dojox/layout/FloatingPane.js
new file mode 100644
index 0000000..97c034f
--- /dev/null
+++ b/js/dojo/dojox/layout/FloatingPane.js
@@ -0,0 +1,405 @@
+//>>built
+require({cache:{
+'url:dojox/layout/resources/FloatingPane.html':"<div class=\"dojoxFloatingPane\" id=\"${id}\">\n\t<div tabindex=\"0\" role=\"button\" class=\"dojoxFloatingPaneTitle\" dojoAttachPoint=\"focusNode\">\n\t\t<span dojoAttachPoint=\"closeNode\" dojoAttachEvent=\"onclick: close\" class=\"dojoxFloatingCloseIcon\"></span>\n\t\t<span dojoAttachPoint=\"maxNode\" dojoAttachEvent=\"onclick: maximize\" class=\"dojoxFloatingMaximizeIcon\">&thinsp;</span>\n\t\t<span dojoAttachPoint=\"restoreNode\" dojoAttachEvent=\"onclick: _restore\" class=\"dojoxFloatingRestoreIcon\">&thinsp;</span>\t\n\t\t<span dojoAttachPoint=\"dockNode\" dojoAttachEvent=\"onclick: minimize\" class=\"dojoxFloatingMinimizeIcon\">&thinsp;</span>\n\t\t<span dojoAttachPoint=\"titleNode\" class=\"dijitInline dijitTitleNode\"></span>\n\t</div>\n\t<div dojoAttachPoint=\"canvas\" class=\"dojoxFloatingPaneCanvas\">\n\t\t<div dojoAttachPoint=\"containerNode\" role=\"region\" tabindex=\"-1\" class=\"${contentClass}\">\n\t\t</div>\n\t\t<span dojoAttachPoint=\"resizeHandle\" class=\"dojoxFloatingResizeHandle\"></span>\n\t</div>\n</div>\n"}});
+define("dojox/layout/FloatingPane", ["dojo/_base/kernel","dojo/_base/lang","dojo/_base/window","dojo/_base/declare",
+ "dojo/_base/fx","dojo/_base/connect","dojo/_base/array","dojo/_base/sniff",
+ "dojo/window","dojo/dom","dojo/dom-class","dojo/dom-geometry","dojo/dom-construct",
+ "dijit/_TemplatedMixin","dijit/_Widget","dijit/BackgroundIframe","dojo/dnd/Moveable",
+ "./ContentPane","./ResizeHandle","dojo/text!./resources/FloatingPane.html"], function(
+ kernel, lang, winUtil, declare, baseFx, connectUtil, arrayUtil,
+ has, windowLib, dom, domClass, domGeom, domConstruct, TemplatedMixin, Widget, BackgroundIframe,
+ Moveable, ContentPane, ResizeHandle, template){
+
+/*=====
+var Widget = dijit._Widget;
+var TemplatedMixin = dijit._TemplatedMixin;
+var ContentPane = dojox.layout.ContentPane;
+=====*/
+kernel.experimental("dojox.layout.FloatingPane");
+var FloatingPane = declare("dojox.layout.FloatingPane", [ ContentPane, TemplatedMixin ],{
+ // summary:
+ // A non-modal Floating window.
+ //
+ // description:
+ // Makes a `dojox.layout.ContentPane` float and draggable by it's title [similar to TitlePane]
+ // and over-rides onClick to onDblClick for wipeIn/Out of containerNode
+ // provides minimize(dock) / show() and hide() methods, and resize [almost]
+ //
+ // closable: Boolean
+ // Allow closure of this Node
+ closable: true,
+
+ // dockable: Boolean
+ // Allow minimizing of pane if true
+ dockable: true,
+
+ // resizable: Boolean
+ // Allow resizing of pane true if true
+ resizable: false,
+
+ // maxable: Boolean
+ // Horrible param name for "Can you maximize this floating pane?"
+ maxable: false,
+
+ // resizeAxis: String
+ // One of: x | xy | y to limit pane's sizing direction
+ resizeAxis: "xy",
+
+ // title: String
+ // Title to use in the header
+ title: "",
+
+ // dockTo: DomNode?
+ // if empty, will create private layout.Dock that scrolls with viewport
+ // on bottom span of viewport.
+ dockTo: "",
+
+ // duration: Integer
+ // Time is MS to spend toggling in/out node
+ duration: 400,
+
+ /*=====
+ // iconSrc: String
+ // [not implemented yet] will be either icon in titlepane to left
+ // of Title, and/or icon show when docked in a fisheye-like dock
+ // or maybe dockIcon would be better?
+ iconSrc: null,
+ =====*/
+
+ // contentClass: String
+ // The className to give to the inner node which has the content
+ contentClass: "dojoxFloatingPaneContent",
+
+ // animation holders for toggle
+ _showAnim: null,
+ _hideAnim: null,
+ // node in the dock (if docked)
+ _dockNode: null,
+
+ // privates:
+ _restoreState: {},
+ _allFPs: [],
+ _startZ: 100,
+
+ templateString: template,
+
+ attributeMap: lang.delegate(Widget.prototype.attributeMap, {
+ title: { type:"innerHTML", node:"titleNode" }
+ }),
+
+ postCreate: function(){
+ this.inherited(arguments);
+ new Moveable(this.domNode,{ handle: this.focusNode });
+ //this._listener = dojo.subscribe("/dnd/move/start",this,"bringToTop");
+
+ if(!this.dockable){ this.dockNode.style.display = "none"; }
+ if(!this.closable){ this.closeNode.style.display = "none"; }
+ if(!this.maxable){
+ this.maxNode.style.display = "none";
+ this.restoreNode.style.display = "none";
+ }
+ if(!this.resizable){
+ this.resizeHandle.style.display = "none";
+ }else{
+ this.domNode.style.width = domGeom.getMarginBox(this.domNode).w + "px";
+ }
+ this._allFPs.push(this);
+ this.domNode.style.position = "absolute";
+
+ this.bgIframe = new BackgroundIframe(this.domNode);
+ this._naturalState = domGeom.position(this.domNode);
+ },
+
+ startup: function(){
+ if(this._started){ return; }
+
+ this.inherited(arguments);
+
+ if(this.resizable){
+ if(has("ie")){
+ this.canvas.style.overflow = "auto";
+ }else{
+ this.containerNode.style.overflow = "auto";
+ }
+
+ this._resizeHandle = new ResizeHandle({
+ targetId: this.id,
+ resizeAxis: this.resizeAxis
+ },this.resizeHandle);
+
+ }
+
+ if(this.dockable){
+ // FIXME: argh.
+ var tmpName = this.dockTo;
+
+ if(this.dockTo){
+ this.dockTo = dijit.byId(this.dockTo);
+ }else{
+ this.dockTo = dijit.byId('dojoxGlobalFloatingDock');
+ }
+
+ if(!this.dockTo){
+ var tmpId, tmpNode;
+ // we need to make our dock node, and position it against
+ // .dojoxDockDefault .. this is a lot. either dockto="node"
+ // and fail if node doesn't exist or make the global one
+ // once, and use it on empty OR invalid dockTo="" node?
+ if(tmpName){
+ tmpId = tmpName;
+ tmpNode = dom.byId(tmpName);
+ }else{
+ tmpNode = domConstruct.create('div', null, winUtil.body());
+ domClass.add(tmpNode,"dojoxFloatingDockDefault");
+ tmpId = 'dojoxGlobalFloatingDock';
+ }
+ this.dockTo = new Dock({ id: tmpId, autoPosition: "south" }, tmpNode);
+ this.dockTo.startup();
+ }
+
+ if((this.domNode.style.display == "none")||(this.domNode.style.visibility == "hidden")){
+ // If the FP is created dockable and non-visible, start up docked.
+ this.minimize();
+ }
+ }
+ this.connect(this.focusNode,"onmousedown","bringToTop");
+ this.connect(this.domNode, "onmousedown","bringToTop");
+
+ // Initial resize to give child the opportunity to lay itself out
+ this.resize(domGeom.position(this.domNode));
+
+ this._started = true;
+ },
+
+ setTitle: function(/* String */ title){
+ // summary: Update the Title bar with a new string
+ kernel.deprecated("pane.setTitle", "Use pane.set('title', someTitle)", "2.0");
+ this.set("title", title);
+ },
+
+ close: function(){
+ // summary: Close and destroy this widget
+ if(!this.closable){ return; }
+ connectUtil.unsubscribe(this._listener);
+ this.hide(lang.hitch(this,function(){
+ this.destroyRecursive();
+ }));
+ },
+
+ hide: function(/* Function? */ callback){
+ // summary: Close, but do not destroy this FloatingPane
+ baseFx.fadeOut({
+ node:this.domNode,
+ duration:this.duration,
+ onEnd: lang.hitch(this,function() {
+ this.domNode.style.display = "none";
+ this.domNode.style.visibility = "hidden";
+ if(this.dockTo && this.dockable){
+ this.dockTo._positionDock(null);
+ }
+ if(callback){
+ callback();
+ }
+ })
+ }).play();
+ },
+
+ show: function(/* Function? */callback){
+ // summary: Show the FloatingPane
+ var anim = baseFx.fadeIn({node:this.domNode, duration:this.duration,
+ beforeBegin: lang.hitch(this,function(){
+ this.domNode.style.display = "";
+ this.domNode.style.visibility = "visible";
+ if (this.dockTo && this.dockable) { this.dockTo._positionDock(null); }
+ if (typeof callback == "function") { callback(); }
+ this._isDocked = false;
+ if (this._dockNode) {
+ this._dockNode.destroy();
+ this._dockNode = null;
+ }
+ })
+ }).play();
+ this.resize(domGeom.position(this.domNode));
+ this._onShow(); // lazy load trigger
+ },
+
+ minimize: function(){
+ // summary: Hide and dock the FloatingPane
+ if(!this._isDocked){ this.hide(lang.hitch(this,"_dock")); }
+ },
+
+ maximize: function(){
+ // summary: Make this FloatingPane full-screen (viewport)
+ if(this._maximized){ return; }
+ this._naturalState = domGeom.position(this.domNode);
+ if(this._isDocked){
+ this.show();
+ setTimeout(lang.hitch(this,"maximize"),this.duration);
+ }
+ domClass.add(this.focusNode,"floatingPaneMaximized");
+ this.resize(windowLib.getBox());
+ this._maximized = true;
+ },
+
+ _restore: function(){
+ if(this._maximized){
+ this.resize(this._naturalState);
+ domClass.remove(this.focusNode,"floatingPaneMaximized");
+ this._maximized = false;
+ }
+ },
+
+ _dock: function(){
+ if(!this._isDocked && this.dockable){
+ this._dockNode = this.dockTo.addNode(this);
+ this._isDocked = true;
+ }
+ },
+
+ resize: function(/* Object */dim){
+ // summary: Size the FloatingPane and place accordingly
+ dim = dim || this._naturalState;
+ this._currentState = dim;
+
+ // From the ResizeHandle we only get width and height information
+ var dns = this.domNode.style;
+ if("t" in dim){ dns.top = dim.t + "px"; }
+ else if("y" in dim){ dns.top = dim.y + "px"; }
+ if("l" in dim){ dns.left = dim.l + "px"; }
+ else if("x" in dim){ dns.left = dim.x + "px"; }
+ dns.width = dim.w + "px";
+ dns.height = dim.h + "px";
+
+ // Now resize canvas
+ var mbCanvas = { l: 0, t: 0, w: dim.w, h: (dim.h - this.focusNode.offsetHeight) };
+ domGeom.setMarginBox(this.canvas, mbCanvas);
+
+ // If the single child can resize, forward resize event to it so it can
+ // fit itself properly into the content area
+ this._checkIfSingleChild();
+ if(this._singleChild && this._singleChild.resize){
+ this._singleChild.resize(mbCanvas);
+ }
+ },
+
+ bringToTop: function(){
+ // summary: bring this FloatingPane above all other panes
+ var windows = arrayUtil.filter(
+ this._allFPs,
+ function(i){
+ return i !== this;
+ },
+ this);
+ windows.sort(function(a, b){
+ return a.domNode.style.zIndex - b.domNode.style.zIndex;
+ });
+ windows.push(this);
+
+ arrayUtil.forEach(windows, function(w, x){
+ w.domNode.style.zIndex = this._startZ + (x * 2);
+ domClass.remove(w.domNode, "dojoxFloatingPaneFg");
+ }, this);
+ domClass.add(this.domNode, "dojoxFloatingPaneFg");
+ },
+
+ destroy: function(){
+ // summary: Destroy this FloatingPane completely
+ this._allFPs.splice(arrayUtil.indexOf(this._allFPs, this), 1);
+ if(this._resizeHandle){
+ this._resizeHandle.destroy();
+ }
+ this.inherited(arguments);
+ }
+});
+
+var Dock = declare("dojox.layout.Dock",[Widget, TemplatedMixin],{
+ // summary:
+ // A widget that attaches to a node and keeps track of incoming / outgoing FloatingPanes
+ // and handles layout
+
+ templateString: '<div class="dojoxDock"><ul dojoAttachPoint="containerNode" class="dojoxDockList"></ul></div>',
+
+ // private _docked: array of panes currently in our dock
+ _docked: [],
+
+ _inPositioning: false,
+
+ autoPosition: false,
+
+ addNode: function(refNode){
+ // summary: Instert a dockNode refernce into the dock
+
+ var div = domConstruct.create('li', null, this.containerNode),
+ node = new DockNode({
+ title: refNode.title,
+ paneRef: refNode
+ }, div)
+ ;
+ node.startup();
+ return node;
+ },
+
+ startup: function(){
+
+ if (this.id == "dojoxGlobalFloatingDock" || this.isFixedDock) {
+ // attach window.onScroll, and a position like in presentation/dialog
+ this.connect(window, 'onresize', "_positionDock");
+ this.connect(window, 'onscroll', "_positionDock");
+ if(has("ie")){
+ this.connect(this.domNode, "onresize", "_positionDock");
+ }
+ }
+ this._positionDock(null);
+ this.inherited(arguments);
+
+ },
+
+ _positionDock: function(/* Event? */e){
+ if(!this._inPositioning){
+ if(this.autoPosition == "south"){
+ // Give some time for scrollbars to appear/disappear
+ setTimeout(lang.hitch(this, function() {
+ this._inPositiononing = true;
+ var viewport = windowLib.getBox();
+ var s = this.domNode.style;
+ s.left = viewport.l + "px";
+ s.width = (viewport.w-2) + "px";
+ s.top = (viewport.h + viewport.t) - this.domNode.offsetHeight + "px";
+ this._inPositioning = false;
+ }), 125);
+ }
+ }
+ }
+
+
+});
+
+var DockNode = declare("dojox.layout._DockNode",[Widget, TemplatedMixin],{
+ // summary:
+ // dojox.layout._DockNode is a private widget used to keep track of
+ // which pane is docked.
+ //
+ // title: String
+ // Shown in dock icon. should read parent iconSrc?
+ title: "",
+
+ // paneRef: Widget
+ // reference to the FloatingPane we reprasent in any given dock
+ paneRef: null,
+
+ templateString:
+ '<li dojoAttachEvent="onclick: restore" class="dojoxDockNode">'+
+ '<span dojoAttachPoint="restoreNode" class="dojoxDockRestoreButton" dojoAttachEvent="onclick: restore"></span>'+
+ '<span class="dojoxDockTitleNode" dojoAttachPoint="titleNode">${title}</span>'+
+ '</li>',
+
+ restore: function(){
+ // summary: remove this dock item from parent dock, and call show() on reffed floatingpane
+ this.paneRef.show();
+ this.paneRef.bringToTop();
+ this.destroy();
+ }
+});
+
+return FloatingPane;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/layout/GridContainer.js b/js/dojo/dojox/layout/GridContainer.js
new file mode 100644
index 0000000..cdb2d9e
--- /dev/null
+++ b/js/dojo/dojox/layout/GridContainer.js
@@ -0,0 +1,630 @@
+//>>built
+define("dojox/layout/GridContainer", [
+ "dojo/_base/kernel",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "dojo/_base/declare",
+ "dojo/_base/html",
+ "dojo/_base/lang",
+ "dojo/_base/window",
+ "dojo/ready", // dojo.ready
+ "dojox/layout/GridContainerLite"
+],function(dojo){
+ return dojo.declare(
+ "dojox.layout.GridContainer",
+ dojox.layout.GridContainerLite,
+ {
+ // summary:
+ // A grid containing any kind of objects and acting like web portals.
+ //
+ // description:
+ // This component inherits of all features of gridContainerLite plus :
+ // - Resize colums
+ // - Add / remove columns
+ // - Fix columns at left or at right.
+ // example:
+ // | <div dojoType="dojox.layout.GridContainer" nbZones="3" isAutoOrganized="true">
+ // | <div dojoType="dijit.layout.ContentPane">Content Pane 1 : Drag Me !</div>
+ // | <div dojoType="dijit.layout.ContentPane">Content Pane 2 : Drag Me !</div>
+ // | <div dojoType="dijit.layout.ContentPane">Content Pane 3 : Drag Me !</div>
+ // | </div>
+ //
+ // example:
+ // | dojo.ready(function(){
+ // | var cpane1 = new dijit.layout.ContentPane({ title:"cpane1", content: "Content Pane 1 : Drag Me !" }),
+ // | cpane2 = new dijit.layout.ContentPane({ title:"cpane2", content: "Content Pane 2 : Drag Me !" }),
+ // | cpane3 = new dijit.layout.ContentPane({ title:"cpane3", content: "Content Pane 3 : Drag Me !" });
+ // |
+ // | var widget = new dojox.layout.GridContainer({
+ // | nbZones: 3,
+ // | isAutoOrganized: true
+ // | }, dojo.byId("idNode"));
+ // | widget.addChild(cpane1, 0, 0);
+ // | widget.addChild(cpane2, 1, 0);
+ // | widget.addChild(cpane3, 2, 1);
+ // | widget.startup();
+ // | });
+
+ // hasResizableColumns: Boolean
+ // Allow or not resizing of columns by a grip handle.
+ hasResizableColumns: true,
+
+ // liveResizeColumns: Boolean
+ // Specifies whether columns resize as you drag (true) or only upon mouseup (false)
+ liveResizeColumns : false,
+
+ // minColWidth: Integer
+ // Minimum column width in percentage.
+ minColWidth: 20,
+
+ // minChildWidth: Integer
+ // Minimum children width in pixel (only used for IE6 which doesn't handle min-width css property)
+ minChildWidth: 150,
+
+ // mode: String
+ // Location to add/remove columns, must be set to 'left' or 'right' (default).
+ mode: "right",
+
+ // isRightFixed: Boolean
+ // Define if the last right column is fixed.
+ // Used when you add or remove columns by calling setColumns method.
+ isRightFixed: false,
+
+ // isLeftFixed: Boolean
+ // Define if the last left column is fixed.
+ // Used when you add or remove columns by calling setColumns method.
+ isLeftFixed: false,
+
+ startup: function(){
+ // summary:
+ // Call the startup of GridContainerLite and place grips
+ // if user has chosen the hasResizableColumns attribute to true.
+
+ //console.log("dojox.layout.GridContainer ::: startup");
+ this.inherited(arguments);
+ if(this.hasResizableColumns){
+ for(var i = 0; i < this._grid.length - 1; i++){
+ this._createGrip(i);
+ }
+ // If widget has a container parent, grips will be placed
+ // by method onShow.
+ if(!this.getParent()){
+ // Fix IE7 :
+ // The CSS property height:100% for the grip
+ // doesn't work anytime. It's necessary to wait
+ // the end of loading before to place grips.
+ dojo.ready(dojo.hitch(this, "_placeGrips"));
+ }
+ }
+ },
+
+ resizeChildAfterDrop : function(/*Node*/node, /*Object*/targetArea, /*Integer*/indexChild){
+ // summary:
+ // Call when a child is dropped.
+ // description:
+ // Allow to resize and put grips
+ // node:
+ // domNode of dropped widget.
+ // targetArea:
+ // AreaManager Object containing information of targetArea
+ // indexChild:
+ // Index where the dropped widget has been placed
+
+ if(this.inherited(arguments)){
+ this._placeGrips();
+ }
+ },
+
+ onShow: function(){
+ // summary:
+ // Place grips in the right place when the GridContainer becomes visible.
+
+ //console.log("dojox.layout.GridContainer ::: onShow");
+ this.inherited(arguments);
+ this._placeGrips();
+ },
+
+ resize: function(){
+ // summary:
+ // Resize the GridContainer widget and columns.
+ // Replace grips if it's necessary.
+ // tags:
+ // callback
+
+ //console.log("dojox.layout.GridContainer ::: resize");
+ this.inherited(arguments);
+ // Fix IE6 :
+ // IE6 calls method resize itself.
+ // If the GridContainer is not visible at this time,
+ // the method _placeGrips can return a negative value with
+ // contentBox method. (see method _placeGrip() with Fix Ie6 for the height)
+ if(this._isShown() && this.hasResizableColumns){
+ this._placeGrips();
+ }
+ },
+
+ _createGrip: function(/*Integer*/ index){
+ // summary:
+ // Create a grip for a specific zone.
+ // index:
+ // index where the grip has to be created.
+ // tags:
+ // protected
+
+ //console.log("dojox.layout.GridContainer ::: _createGrip");
+ var dropZone = this._grid[index],
+ grip = dojo.create("div", { 'class': "gridContainerGrip" }, this.domNode);
+ dropZone.grip = grip;
+ dropZone.gripHandler = [
+ this.connect(grip, "onmouseover", function(e){
+ var gridContainerGripShow = false;
+ for(var i = 0; i < this._grid.length - 1; i++){
+ if(dojo.hasClass(this._grid[i].grip, "gridContainerGripShow")){
+ gridContainerGripShow = true;
+ break;
+ }
+ }
+ if(!gridContainerGripShow){
+ dojo.removeClass(e.target, "gridContainerGrip");
+ dojo.addClass(e.target, "gridContainerGripShow");
+ }
+ })[0],
+ this.connect(grip, "onmouseout", function(e){
+ if(!this._isResized){
+ dojo.removeClass(e.target, "gridContainerGripShow");
+ dojo.addClass(e.target, "gridContainerGrip");
+ }
+ })[0],
+ this.connect(grip, "onmousedown", "_resizeColumnOn")[0],
+ this.connect(grip, "ondblclick", "_onGripDbClick")[0]
+ ];
+ },
+
+ _placeGrips: function(){
+ // summary:
+ // Define the position of a grip and place it on page.
+ // tags:
+ // protected
+
+ //console.log("dojox.layout.GridContainer ::: _placeGrips");
+ var gripWidth, height, left = 0, grip;
+ var scroll = this.domNode.style.overflowY;
+
+ dojo.forEach(this._grid, function(dropZone){
+ if(dropZone.grip){
+ grip = dropZone.grip;
+ if(!gripWidth){
+ gripWidth = grip.offsetWidth / 2;
+ }
+
+ left += dojo.marginBox(dropZone.node).w;
+
+ dojo.style(grip, "left", (left - gripWidth) + "px");
+ //if(dojo.isIE == 6){ do it fot all navigators
+ if(!height){
+ height = dojo.contentBox(this.gridNode).h;
+ }
+ if(height > 0){
+ dojo.style(grip, "height", height + "px");
+ }
+ //}
+ }
+ }, this);
+ },
+
+ _onGripDbClick: function(){
+ // summary:
+ // Called when a double click is catch. Resize all columns with the same width.
+ // The method resize of children have to be called.
+ // tags:
+ // callback protected
+
+ //console.log("dojox.layout.GridContainer ::: _onGripDbClick");
+ this._updateColumnsWidth(this._dragManager);
+ this.resize();
+ },
+
+ _resizeColumnOn: function(/*Event*/e){
+ // summary:
+ // Connect events to listen the resize action.
+ // Change the type of width columns (% to px).
+ // Calculate the minwidth according to the children.
+ // tags:
+ // callback
+
+ //console.log("dojox.layout.GridContainer ::: _resizeColumnOn", e);
+ this._activeGrip = e.target;
+ this._initX = e.pageX;
+ e.preventDefault();
+
+ dojo.body().style.cursor = "ew-resize";
+
+ this._isResized = true;
+
+ var tabSize = [];
+ var grid;
+ var i;
+
+ for(i = 0; i < this._grid.length; i++){
+ tabSize[i] = dojo.contentBox(this._grid[i].node).w;
+ }
+
+ this._oldTabSize = tabSize;
+
+ for(i = 0; i < this._grid.length; i++){
+ grid = this._grid[i];
+ if(this._activeGrip == grid.grip){
+ this._currentColumn = grid.node;
+ this._currentColumnWidth = tabSize[i];
+ this._nextColumn = this._grid[i + 1].node;
+ this._nextColumnWidth = tabSize[i + 1];
+ }
+ grid.node.style.width = tabSize[i] + "px";
+ }
+
+ // calculate the minWidh of all children for current and next column
+ var calculateChildMinWidth = function(childNodes, minChild){
+ var width = 0;
+ var childMinWidth = 0;
+
+ dojo.forEach(childNodes, function(child){
+ if(child.nodeType == 1){
+ var objectStyle = dojo.getComputedStyle(child);
+ var minWidth = (dojo.isIE) ? minChild : parseInt(objectStyle.minWidth);
+
+ childMinWidth = minWidth +
+ parseInt(objectStyle.marginLeft) +
+ parseInt(objectStyle.marginRight);
+
+ if(width < childMinWidth){
+ width = childMinWidth;
+ }
+ }
+ });
+ return width;
+ }
+ var currentColumnMinWidth = calculateChildMinWidth(this._currentColumn.childNodes, this.minChildWidth);
+
+ var nextColumnMinWidth = calculateChildMinWidth(this._nextColumn.childNodes, this.minChildWidth);
+
+ var minPix = Math.round((dojo.marginBox(this.gridContainerTable).w * this.minColWidth) / 100);
+
+ this._currentMinCol = currentColumnMinWidth;
+ this._nextMinCol = nextColumnMinWidth;
+
+ if(minPix > this._currentMinCol){
+ this._currentMinCol = minPix;
+ }
+ if(minPix > this._nextMinCol){
+ this._nextMinCol = minPix;
+ }
+ this._connectResizeColumnMove = dojo.connect(dojo.doc, "onmousemove", this, "_resizeColumnMove");
+ this._connectOnGripMouseUp = dojo.connect(dojo.doc, "onmouseup", this, "_onGripMouseUp");
+ },
+
+ _onGripMouseUp: function(){
+ // summary:
+ // Call on the onMouseUp only if the reiszeColumnMove was not called.
+ // tags:
+ // callback
+
+ //console.log(dojox.layout.GridContainer ::: _onGripMouseUp");
+ dojo.body().style.cursor = "default";
+
+ dojo.disconnect(this._connectResizeColumnMove);
+ dojo.disconnect(this._connectOnGripMouseUp);
+
+ this._connectOnGripMouseUp = this._connectResizeColumnMove = null;
+
+ if(this._activeGrip){
+ dojo.removeClass(this._activeGrip, "gridContainerGripShow");
+ dojo.addClass(this._activeGrip, "gridContainerGrip");
+ }
+
+ this._isResized = false;
+ },
+
+ _resizeColumnMove: function(/*Event*/e){
+ // summary:
+ // Change columns size.
+ // tags:
+ // callback
+
+ //console.log("dojox.layout.GridContainer ::: _resizeColumnMove");
+ e.preventDefault();
+ if(!this._connectResizeColumnOff){
+ dojo.disconnect(this._connectOnGripMouseUp);
+ this._connectOnGripMouseUp = null;
+ this._connectResizeColumnOff = dojo.connect(dojo.doc, "onmouseup", this, "_resizeColumnOff");
+ }
+
+ var d = e.pageX - this._initX;
+ if(d == 0){ return; }
+
+ if(!(this._currentColumnWidth + d < this._currentMinCol ||
+ this._nextColumnWidth - d < this._nextMinCol)){
+
+ this._currentColumnWidth += d;
+ this._nextColumnWidth -= d;
+ this._initX = e.pageX;
+ this._activeGrip.style.left = parseInt(this._activeGrip.style.left) + d + "px";
+
+ if(this.liveResizeColumns){
+ this._currentColumn.style["width"] = this._currentColumnWidth + "px";
+ this._nextColumn.style["width"] = this._nextColumnWidth + "px";
+ this.resize();
+ }
+ }
+ },
+
+ _resizeColumnOff: function(/*Event*/e){
+ // summary:
+ // Disconnect resize events.
+ // Change the type of width columns (px to %).
+ // tags:
+ // callback
+
+ //console.log("dojox.layout.GridContainer ::: _resizeColumnOff");
+ dojo.body().style.cursor = "default";
+
+ dojo.disconnect(this._connectResizeColumnMove);
+ dojo.disconnect(this._connectResizeColumnOff);
+
+ this._connectResizeColumnOff = this._connectResizeColumnMove = null;
+
+ if(!this.liveResizeColumns){
+ this._currentColumn.style["width"] = this._currentColumnWidth + "px";
+ this._nextColumn.style["width"] = this._nextColumnWidth + "px";
+ //this.resize();
+ }
+
+ var tabSize = [],
+ testSize = [],
+ tabWidth = this.gridContainerTable.clientWidth,
+ node,
+ update = false,
+ i;
+
+ for(i = 0; i < this._grid.length; i++){
+ node = this._grid[i].node;
+ if(dojo.isIE){
+ tabSize[i] = dojo.marginBox(node).w;
+ testSize[i] = dojo.contentBox(node).w;
+ }
+ else{
+ tabSize[i] = dojo.contentBox(node).w;
+ testSize = tabSize;
+ }
+ }
+
+ for(i = 0; i < testSize.length; i++){
+ if(testSize[i] != this._oldTabSize[i]){
+ update = true;
+ break;
+ }
+ }
+
+ if(update){
+ var mul = dojo.isIE ? 100 : 10000;
+ for(i = 0; i < this._grid.length; i++){
+ this._grid[i].node.style.width = Math.round((100 * mul * tabSize[i]) / tabWidth) / mul + "%";
+ }
+ this.resize();
+ }
+
+ if(this._activeGrip){
+ dojo.removeClass(this._activeGrip, "gridContainerGripShow");
+ dojo.addClass(this._activeGrip, "gridContainerGrip");
+ }
+
+ this._isResized = false;
+ },
+
+ setColumns: function(/*Integer*/nbColumns){
+ // summary:
+ // Set the number of columns.
+ // nbColumns:
+ // Number of columns
+
+ //console.log("dojox.layout.GridContainer ::: setColumns");
+ var z, j;
+ if(nbColumns > 0){
+ var length = this._grid.length,
+ delta = length - nbColumns;
+ if(delta > 0){
+ var count = [], zone, start, end, nbChildren;
+ // Check if right or left columns are fixed
+ // Columns are not taken in account and can't be deleted
+ if(this.mode == "right"){
+ end = (this.isLeftFixed && length > 0) ? 1 : 0;
+ start = (this.isRightFixed) ? length - 2 : length - 1
+ for(z = start; z >= end; z--){
+ nbChildren = 0;
+ zone = this._grid[z].node;
+ for(j = 0; j < zone.childNodes.length; j++){
+ if(zone.childNodes[j].nodeType == 1 && !(zone.childNodes[j].id == "")){
+ nbChildren++;
+ break;
+ }
+ }
+ if(nbChildren == 0){ count[count.length] = z; }
+ if(count.length >= delta){
+ this._deleteColumn(count);
+ break;
+ }
+ }
+ if(count.length < delta){
+ dojo.publish("/dojox/layout/gridContainer/noEmptyColumn", [this]);
+ }
+ }
+ else{ // mode = "left"
+ start = (this.isLeftFixed && length > 0) ? 1 : 0;
+ end = (this.isRightFixed) ? length - 1 : length;
+ for(z = start; z < end; z++){
+ nbChildren = 0;
+ zone = this._grid[z].node;
+ for(j = 0; j < zone.childNodes.length; j++){
+ if(zone.childNodes[j].nodeType == 1 && !(zone.childNodes[j].id == "")){
+ nbChildren++;
+ break;
+ }
+ }
+ if(nbChildren == 0){ count[count.length] = z; }
+ if(count.length >= delta){
+ this._deleteColumn(count);
+ break;
+ }
+ }
+ if(count.length < delta){
+ //Not enough empty columns
+ dojo.publish("/dojox/layout/gridContainer/noEmptyColumn", [this]);
+ }
+ }
+ }
+ else{
+ if(delta < 0){ this._addColumn(Math.abs(delta)); }
+ }
+ if(this.hasResizableColumns){ this._placeGrips(); }
+ }
+ },
+
+ _addColumn: function(/*Integer*/nbColumns){
+ // summary:
+ // Add some columns.
+ // nbColumns:
+ // Number of column to added
+ // tags:
+ // private
+
+ //console.log("dojox.layout.GridContainer ::: _addColumn");
+ var grid = this._grid,
+ dropZone,
+ node,
+ index,
+ length,
+ isRightMode = (this.mode == "right"),
+ accept = this.acceptTypes.join(","),
+ m = this._dragManager;
+
+ //Add a grip to the last column
+ if(this.hasResizableColumns && ((!this.isRightFixed && isRightMode)
+ || (this.isLeftFixed && !isRightMode && this.nbZones == 1) )){
+ this._createGrip(grid.length - 1);
+ }
+
+ for(var i = 0; i < nbColumns; i++){
+ // Fix CODEX defect #53025 :
+ // Apply acceptType attribute on each new column.
+ node = dojo.create("td", {
+ 'class': "gridContainerZone dojoxDndArea" ,
+ 'accept': accept,
+ 'id': this.id + "_dz" + this.nbZones
+ });
+
+ length = grid.length;
+
+ if(isRightMode){
+ if(this.isRightFixed){
+ index = length - 1;
+ grid.splice(index, 0, {
+ 'node': grid[index].node.parentNode.insertBefore(node, grid[index].node)
+ });
+ }
+ else{
+ index = length;
+ grid.push({ 'node': this.gridNode.appendChild(node) });
+ }
+ }
+ else{
+ if(this.isLeftFixed){
+ index = (length == 1) ? 0 : 1;
+ this._grid.splice(1, 0, {
+ 'node': this._grid[index].node.parentNode.appendChild(node, this._grid[index].node)
+ });
+ index = 1;
+ }
+ else{
+ index = length - this.nbZones;
+ this._grid.splice(index, 0, {
+ 'node': grid[index].node.parentNode.insertBefore(node, grid[index].node)
+ });
+ }
+ }
+ if(this.hasResizableColumns){
+ //Add a grip to resize columns
+ if((!isRightMode && this.nbZones != 1) ||
+ (!isRightMode && this.nbZones == 1 && !this.isLeftFixed) ||
+ (isRightMode && i < nbColumns-1) ||
+ (isRightMode && i == nbColumns-1 && this.isRightFixed)){
+ this._createGrip(index);
+ }
+ }
+ // register tnbZoneshe new area into the areaManager
+ m.registerByNode(grid[index].node);
+ this.nbZones++;
+ }
+ this._updateColumnsWidth(m);
+ },
+
+ _deleteColumn: function(/*Array*/indices){
+ // summary:
+ // Remove some columns with indices passed as an array.
+ // indices:
+ // Column index array
+ // tags:
+ // private
+
+ //console.log("dojox.layout.GridContainer ::: _deleteColumn");
+ var child, grid, index,
+ nbDelZones = 0,
+ length = indices.length,
+ m = this._dragManager;
+ for(var i = 0; i < length; i++){
+ index = (this.mode == "right") ? indices[i] : indices[i] - nbDelZones;
+ grid = this._grid[index];
+
+ if(this.hasResizableColumns && grid.grip){
+ dojo.forEach(grid.gripHandler, function(handler){
+ dojo.disconnect(handler);
+ });
+ dojo.destroy(this.domNode.removeChild(grid.grip));
+ grid.grip = null;
+ }
+
+ m.unregister(grid.node);
+ dojo.destroy(this.gridNode.removeChild(grid.node));
+ this._grid.splice(index, 1);
+ this.nbZones--;
+ nbDelZones++;
+ }
+
+ // last grip
+ var lastGrid = this._grid[this.nbZones-1];
+ if(lastGrid.grip){
+ dojo.forEach(lastGrid.gripHandler, dojo.disconnect);
+ dojo.destroy(this.domNode.removeChild(lastGrid.grip));
+ lastGrid.grip = null;
+ }
+
+ this._updateColumnsWidth(m);
+ },
+
+ _updateColumnsWidth: function(/*Object*/ manager){
+ // summary:
+ // Update the columns width.
+ // manager:
+ // dojox.mdnd.AreaManager singleton
+ // tags:
+ // private
+
+ //console.log("dojox.layout.GridContainer ::: _updateColumnsWidth");
+ this.inherited(arguments);
+ manager._dropMode.updateAreas(manager._areaList);
+ },
+
+ destroy: function(){
+ dojo.unsubscribe(this._dropHandler);
+ this.inherited(arguments);
+ }
+ });
+});
diff --git a/js/dojo/dojox/layout/GridContainerLite.js b/js/dojo/dojox/layout/GridContainerLite.js
new file mode 100644
index 0000000..ea63d65
--- /dev/null
+++ b/js/dojo/dojox/layout/GridContainerLite.js
@@ -0,0 +1,829 @@
+//>>built
+require({cache:{
+'url:dojox/layout/resources/GridContainer.html':"<div id=\"${id}\" class=\"gridContainer\" dojoAttachPoint=\"containerNode\" tabIndex=\"0\" dojoAttachEvent=\"onkeypress:_selectFocus\">\n\t<div dojoAttachPoint=\"gridContainerDiv\">\n\t\t<table class=\"gridContainerTable\" dojoAttachPoint=\"gridContainerTable\" cellspacing=\"0\" cellpadding=\"0\">\n\t\t\t<tbody>\n\t\t\t\t<tr dojoAttachPoint=\"gridNode\" >\n\t\t\t\t\t\n\t\t\t\t</tr>\n\t\t\t</tbody>\n\t\t</table>\n\t</div>\n</div>"}});
+define("dojox/layout/GridContainerLite", ["dojo/_base/kernel",
+ "dojo/text!./resources/GridContainer.html",
+ "dojo/ready",
+ "dojo/_base/array","dojo/_base/lang",
+ "dojo/_base/declare","dojo/text","dojo/_base/sniff","dojo/_base/html",
+ "dojox/mdnd/AreaManager","dojox/mdnd/DropIndicator",
+ "dojox/mdnd/dropMode/OverDropMode","dojox/mdnd/AutoScroll","dijit/_Templated",
+ "dijit/layout/_LayoutWidget",
+ "dijit/focus", // dijit.focus()
+ "dijit/_base/focus" // dijit.getFocus()
+],function(dojo,template){
+
+ var gcl = dojo.declare(
+ "dojox.layout.GridContainerLite",
+ [dijit.layout._LayoutWidget, dijit._TemplatedMixin],
+ {
+ // summary:
+ // The GridContainerLite is a container of child elements that are placed in a kind of grid.
+ //
+ // description:
+ // GridContainerLite displays the child elements by column
+ // (ie: the children widths are fixed by the column width of the grid but
+ // the children heights are free).
+ // Each child is movable by drag and drop inside the GridContainer.
+ // The position of other children is automatically calculated when a child is moved.
+ //
+ // example:
+ // | <div dojoType="dojox.layout.GridContainerLite" nbZones="3" isAutoOrganized="true">
+ // | <div dojoType="dijit.layout.ContentPane">Content Pane 1 : Drag Me !</div>
+ // | <div dojoType="dijit.layout.ContentPane">Content Pane 2 : Drag Me !</div>
+ // | <div dojoType="dijit.layout.ContentPane">Content Pane 3 : Drag Me !</div>
+ // | </div>
+ //
+ // example:
+ // | dojo.ready(function(){
+ // | var cpane1 = new dijit.layout.ContentPane({
+ // | title:"cpane1", content: "Content Pane 1 : Drag Me !"
+ // | }),
+ // | cpane2 = new dijit.layout.ContentPane({
+ // | title:"cpane2",
+ // | content: "Content Pane 2 : Drag Me !"
+ // | }),
+ // | cpane3 = new dijit.layout.ContentPane({
+ // | title:"cpane3",
+ // | content: "Content Pane 3 : Drag Me !"
+ // | });
+ // |
+ // | var widget = new dojox.layout.GridContainerLite({
+ // | nbZones: 3,
+ // | isAutoOrganized: true
+ // | }, dojo.byId("idNode"));
+ // | widget.addChild(cpane1, 0, 0);
+ // | widget.addChild(cpane2, 1, 0);
+ // | widget.addChild(cpane3, 2, 1);
+ // | widget.startup();
+ // | });
+
+ // autoRefresh: Boolean
+ // Enable the refresh of registered areas on drag start.
+ autoRefresh: true,
+
+
+ // templateString: String
+ // template of gridContainer.
+ templateString: template,
+
+ // dragHandleClass: Array :
+ // CSS class enabling a drag handle on a child.
+ dragHandleClass: "dojoxDragHandle",
+
+ // nbZones: Integer
+ // The number of dropped zones, by default 1.
+ nbZones: 1,
+
+ // doLayout: Boolean
+ // If true, change the size of my currently displayed child to match my size.
+ doLayout: true,
+
+ // isAutoOrganized: Boolean
+ // If true, widgets are organized automatically,
+ // else the attribute colum of child will define the right column.
+ isAutoOrganized: true,
+
+ // acceptTypes: Array
+ // The GridContainer will only accept the children that fit to the types.
+ acceptTypes: [],
+
+ // colWidths: String
+ // A comma separated list of column widths. If the column widths do not add up
+ // to 100, the remaining columns split the rest of the width evenly
+ // between them.
+ colWidths: "",
+
+ constructor: function(/*Object*/props, /*DOMNode*/node){
+ this.acceptTypes = (props || {}).acceptTypes || ["text"];
+ this._disabled = true;
+ },
+
+ postCreate: function(){
+ //console.log("dojox.layout.GridContainerLite ::: postCreate");
+ this.inherited(arguments);
+ this._grid = [];
+
+ this._createCells();
+
+ // need to resize dragged child when it's dropped.
+ this.subscribe("/dojox/mdnd/drop", "resizeChildAfterDrop");
+ this.subscribe("/dojox/mdnd/drag/start", "resizeChildAfterDragStart");
+
+ this._dragManager = dojox.mdnd.areaManager();
+ // console.info("autorefresh ::: ", this.autoRefresh);
+ this._dragManager.autoRefresh = this.autoRefresh;
+
+ // Add specific dragHandleClass to the manager.
+ this._dragManager.dragHandleClass = this.dragHandleClass;
+
+ if(this.doLayout){
+ this._border = {
+ 'h':(dojo.isIE) ? dojo._getBorderExtents(this.gridContainerTable).h : 0,
+ 'w': (dojo.isIE == 6) ? 1 : 0
+ }
+ }
+ else{
+ dojo.style(this.domNode, "overflowY", "hidden");
+ dojo.style(this.gridContainerTable, "height", "auto");
+ }
+ // Call postCreate of dijit.layout._LayoutWidget.
+ this.inherited(arguments);
+
+ },
+
+ startup: function(){
+ //console.log("dojox.layout.GridContainerLite ::: startup");
+ if(this._started){ return; }
+
+ if(this.isAutoOrganized){
+ this._organizeChildren();
+ }
+ else{
+ this._organizeChildrenManually();
+ }
+
+ // Need to call getChildren because getChildren return null
+ // The children are not direct children because of _organizeChildren method
+ dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+
+ // Need to enable the Drag And Drop only if the GridContainer is visible.
+ if(this._isShown()){
+ this.enableDnd();
+ }
+ this.inherited(arguments);
+ },
+
+ resizeChildAfterDrop: function(/*Node*/node, /*Object*/targetArea, /*Integer*/indexChild){
+ // summary:
+ // Resize the GridContainerLite inner table and the dropped widget.
+ // description:
+ // These components are resized only if the targetArea.node is a
+ // child of this instance of gridContainerLite.
+ // To be resized, the dropped node must have also a method resize.
+ // node:
+ // domNode of dropped widget.
+ // targetArea:
+ // AreaManager Object containing information of targetArea
+ // indexChild:
+ // Index where the dropped widget has been placed
+ // returns:
+ // True if resized.
+
+ //console.log("dojox.layout.GridContainerLite ::: resizeChildAfterDrop");
+ if(this._disabled){
+ return false;
+ }
+ if(dijit.getEnclosingWidget(targetArea.node) == this){
+ var widget = dijit.byNode(node);
+ if(widget.resize && dojo.isFunction(widget.resize)){
+ widget.resize();
+ }
+
+ // Update the column of the widget
+ widget.set("column", node.parentNode.cellIndex);
+
+ if(this.doLayout){
+ var domNodeHeight = this._contentBox.h,
+ divHeight = dojo.contentBox(this.gridContainerDiv).h;
+ if(divHeight >= domNodeHeight){
+ dojo.style(this.gridContainerTable, "height",
+ (domNodeHeight - this._border.h) + "px");
+ }
+ }
+ return true;
+ }
+ return false;
+ },
+
+ resizeChildAfterDragStart: function(/*Node*/node, /*Object*/sourceArea, /*Integer*/indexChild){
+ // summary:
+ // Resize the GridContainerLite inner table only if the drag source
+ // is a child of this gridContainer.
+ // node:
+ // domNode of dragged widget.
+ // sourceArea:
+ // AreaManager Object containing information of sourceArea
+ // indexChild:
+ // Index where the dragged widget has been placed
+
+ //console.log("dojox.layout.GridContainerLite ::: resizeChildAfterDragStart");
+ if(this._disabled){
+ return false;
+ }
+ if(dijit.getEnclosingWidget(sourceArea.node) == this){
+ this._draggedNode = node;
+ if(this.doLayout){
+ dojo.marginBox(this.gridContainerTable, {
+ 'h': dojo.contentBox(this.gridContainerDiv).h - this._border.h
+ });
+ }
+ return true;
+ }
+ return false;
+ },
+
+ getChildren: function(){
+ // summary:
+ // A specific method which returns children after they were placed in zones.
+ // returns:
+ // An array containing all children (widgets).
+ // tags:
+ // protected
+
+ //console.log("dojox.layout.GridContainerLite ::: _getChildren");
+ var children = [];
+ dojo.forEach(this._grid, function(dropZone){
+ children = children.concat(dojo.query("> [widgetId]", dropZone.node).map(dijit.byNode));
+ });
+ return children; // Array
+ },
+
+ _isShown: function(){
+ // summary:
+ // Check if the domNode is visible or not.
+ // returns:
+ // true if the content is currently shown
+ // tags:
+ // protected
+
+ //console.log("dojox.layout.GridContainerLite ::: _isShown");
+ if("open" in this){ // for TitlePane, etc.
+ return this.open; // Boolean
+ }
+ else{
+ var node = this.domNode;
+ return (node.style.display != 'none') && (node.style.visibility != 'hidden') && !dojo.hasClass(node, "dijitHidden"); // Boolean
+ }
+ },
+
+ layout: function(){
+ // summary:
+ // Resize of each child
+
+ //console.log("dojox.layout.GridContainerLite ::: layout");
+ if(this.doLayout){
+ var contentBox = this._contentBox;
+ dojo.marginBox(this.gridContainerTable, {
+ 'h': contentBox.h - this._border.h
+ });
+ dojo.contentBox(this.domNode, {
+ 'w': contentBox.w - this._border.w
+ });
+ }
+ dojo.forEach(this.getChildren(), function(widget){
+ if(widget.resize && dojo.isFunction(widget.resize)){
+ widget.resize();
+ }
+ });
+ },
+
+ onShow: function(){
+ // summary:
+ // Enabled the Drag And Drop if it's necessary.
+
+ //console.log("dojox.layout.GridContainerLite ::: onShow");
+ if(this._disabled){
+ this.enableDnd();
+ }
+ },
+
+ onHide: function(){
+ // summary:
+ // Disabled the Drag And Drop if it's necessary.
+
+ //console.log("dojox.layout.GridContainerLite ::: onHide");
+ if(!this._disabled){
+ this.disableDnd();
+ }
+ },
+
+ _createCells: function(){
+ // summary:
+ // Create the columns of the GridContainer.
+ // tags:
+ // protected
+
+ //console.log("dojox.layout.GridContainerLite ::: _createCells");
+ if(this.nbZones === 0){ this.nbZones = 1; }
+ var accept = this.acceptTypes.join(","),
+ i = 0;
+
+ var origWidths = this.colWidths || [];
+ var widths = [];
+ var colWidth;
+ var widthSum = 0;
+
+ // Calculate the widths of each column.
+ for(i = 0; i < this.nbZones; i++){
+ if(widths.length < origWidths.length){
+ widthSum += origWidths[i];
+ widths.push(origWidths[i]);
+ }else{
+ if(!colWidth){
+ colWidth = (100 - widthSum)/(this.nbZones - i);
+ }
+ widths.push(colWidth);
+ }
+ }
+
+ i = 0;
+ while(i < this.nbZones){
+ // Add the parameter accept in each zone used by AreaManager
+ // (see method dojox.mdnd.AreaManager:registerByNode)
+ this._grid.push({
+ 'node': dojo.create("td", {
+ 'class': "gridContainerZone",
+ 'accept': accept,
+ 'id': this.id + "_dz" + i,
+ 'style': {
+ 'width': widths[i] + "%"
+ }
+ }, this.gridNode)
+ });
+ i++;
+ }
+ },
+
+ _getZonesAttr: function(){
+ // summary:
+ // return array of zone (domNode)
+ return dojo.query(".gridContainerZone", this.containerNode);
+ },
+
+ enableDnd: function(){
+ // summary:
+ // Enable the Drag And Drop for children of GridContainer.
+
+ //console.log("dojox.layout.GridContainerLite ::: enableDnd");
+ var m = this._dragManager;
+ dojo.forEach(this._grid, function(dropZone){
+ m.registerByNode(dropZone.node);
+ });
+ m._dropMode.updateAreas(m._areaList);
+ this._disabled = false;
+ },
+
+ disableDnd: function(){
+ // summary:
+ // Disable the Drag And Drop for children of GridContainer.
+
+ //console.log("dojox.layout.GridContainerLite ::: disableDnd");
+ var m = this._dragManager;
+ dojo.forEach(this._grid, function(dropZone){
+ m.unregister(dropZone.node);
+ });
+ m._dropMode.updateAreas(m._areaList);
+ this._disabled = true;
+ },
+
+ _organizeChildren: function(){
+ // summary:
+ // List all zones and insert child into columns.
+
+ //console.log("dojox.layout.GridContainerLite ::: _organizeChildren");
+ var children = dojox.layout.GridContainerLite.superclass.getChildren.call(this);
+ var numZones = this.nbZones,
+ numPerZone = Math.floor(children.length / numZones),
+ mod = children.length % numZones,
+ i = 0;
+ // console.log('numPerZone', numPerZone, ':: mod', mod);
+ for(var z = 0; z < numZones; z++){
+ for(var r = 0; r < numPerZone; r++){
+ this._insertChild(children[i], z);
+ i++;
+ }
+ if(mod > 0){
+ try{
+ this._insertChild(children[i], z);
+ i++;
+ }
+ catch(e){
+ console.error("Unable to insert child in GridContainer", e);
+ }
+ mod--;
+ }
+ else if(numPerZone === 0){
+ break; // Optimization
+ }
+ }
+ },
+
+ _organizeChildrenManually: function (){
+ // summary:
+ // Organize children by column property of widget.
+
+ //console.log("dojox.layout.GridContainerLite ::: _organizeChildrenManually");
+ var children = dojox.layout.GridContainerLite.superclass.getChildren.call(this),
+ length = children.length,
+ child;
+ for(var i = 0; i < length; i++){
+ child = children[i];
+ try{
+ this._insertChild(child, child.column - 1);
+ }
+ catch(e){
+ console.error("Unable to insert child in GridContainer", e);
+ }
+ }
+ },
+
+ _insertChild: function(/*Widget*/child, /*Integer*/column, /*Integer?*/p){
+ // summary:
+ // Insert a child in a specific column of the GridContainer widget.
+ // column:
+ // Column number
+ // p:
+ // Place in the zone (0 - first)
+ // returns:
+ // The widget inserted
+
+ //console.log("dojox.layout.GridContainerLite ::: _insertChild", child, column, p);
+ var zone = this._grid[column].node,
+ length = zone.childNodes.length;
+ if(typeof(p) == undefined || p > length){
+ p = length;
+ }
+ if(this._disabled){
+ dojo.place(child.domNode, zone, p);
+ dojo.attr(child.domNode, "tabIndex", "0");
+ }
+ else{
+ if(!child.dragRestriction){
+ this._dragManager.addDragItem(zone, child.domNode, p, true);
+ }
+ else{
+ dojo.place(child.domNode, zone, p);
+ dojo.attr(child.domNode, "tabIndex", "0");
+ }
+ }
+ child.set("column", column);
+ return child; // Widget
+ },
+
+ removeChild: function(/*Widget*/ widget){
+ //console.log("dojox.layout.GridContainerLite ::: removeChild");
+ if(this._disabled){
+ this.inherited(arguments);
+ }
+ else{
+ this._dragManager.removeDragItem(widget.domNode.parentNode, widget.domNode);
+ }
+ },
+
+ addService: function(/*Object*/child, /*Integer?*/column, /*Integer?*/p){
+ //console.log("dojox.layout.GridContainerLite ::: addService");
+ dojo.deprecated("addService is deprecated.", "Please use instead.", "Future");
+ this.addChild(child, column, p);
+ },
+
+ addChild: function(/*Object*/child, /*Integer?*/column, /*Integer?*/p){
+ // summary:
+ // Add a child in a specific column of the GridContainer widget.
+ // child:
+ // widget to insert
+ // column:
+ // column number
+ // p:
+ // place in the zone (first = 0)
+ // returns:
+ // The widget inserted
+
+ //console.log("dojox.layout.GridContainerLite ::: addChild");
+ child.domNode.id = child.id;
+ dojox.layout.GridContainerLite.superclass.addChild.call(this, child, 0);
+ if(column < 0 || column == undefined){ column = 0; }
+ if(p <= 0){ p = 0; }
+ try{
+ return this._insertChild(child, column, p);
+ }
+ catch(e){
+ console.error("Unable to insert child in GridContainer", e);
+ }
+ return null; // Widget
+ },
+
+ _setColWidthsAttr: function(value){
+ this.colWidths = dojo.isString(value) ? value.split(",") : (dojo.isArray(value) ? value : [value]);
+
+ if(this._started){
+ this._updateColumnsWidth();
+ }
+ },
+
+ _updateColumnsWidth: function(/*Object*/ manager){
+ // summary:
+ // Update the columns width.
+ // manager:
+ // dojox.mdnd.AreaManager singleton
+ // tags:
+ // private
+
+ //console.log("dojox.layout.GridContainer ::: _updateColumnsWidth");
+ var length = this._grid.length;
+
+ var origWidths = this.colWidths || [];
+ var widths = [];
+ var colWidth;
+ var widthSum = 0;
+ var i;
+
+ // Calculate the widths of each column.
+ for(i = 0; i < length; i++){
+ if(widths.length < origWidths.length){
+ widthSum += origWidths[i] * 1;
+ widths.push(origWidths[i]);
+ }else{
+ if(!colWidth){
+ colWidth = (100 - widthSum)/(this.nbZones - i);
+
+ // If the numbers don't work out, make the remaining columns
+ // an even width and let the code below average
+ // out the differences.
+ if(colWidth < 0){
+ colWidth = 100 / this.nbZones;
+ }
+ }
+ widths.push(colWidth);
+ widthSum += colWidth * 1;
+ }
+ }
+
+ // If the numbers are wrong, divide them all so they add up to 100
+ if(widthSum > 100){
+ var divisor = 100 / widthSum;
+ for(i = 0; i < widths.length; i++){
+ widths[i] *= divisor;
+ }
+ }
+
+ // Set the widths of each node
+ for(i = 0; i < length; i++){
+ this._grid[i].node.style.width = widths[i] + "%";
+ }
+ },
+
+ _selectFocus: function(/*Event*/event){
+ // summary:
+ // Enable keyboard accessibility into the GridContainer.
+ // description:
+ // Possibility to move focus into the GridContainer (TAB, LEFT ARROW, RIGHT ARROW, UP ARROW, DOWN ARROW).
+ // Possibility to move GridContainer's children (Drag and Drop) with keyboard. (SHIFT + ARROW).
+ // If the type of widget is not draggable, a popup is displayed.
+
+ //console.log("dojox.layout.GridContainerLite ::: _selectFocus");
+ if(this._disabled){ return; }
+ var key = event.keyCode,
+ k = dojo.keys,
+ zone = null,
+ focus = dijit.getFocus(),
+ focusNode = focus.node,
+ m = this._dragManager,
+ found,
+ i,
+ j,
+ r,
+ children,
+ area,
+ widget;
+ if(focusNode == this.containerNode){
+ area = this.gridNode.childNodes;
+ switch(key){
+ case k.DOWN_ARROW:
+ case k.RIGHT_ARROW:
+ found = false;
+ for(i = 0; i < area.length; i++){
+ children = area[i].childNodes;
+ for(j = 0; j < children.length; j++){
+ zone = children[j];
+ if(zone != null && zone.style.display != "none"){
+ dijit.focus(zone);
+ dojo.stopEvent(event);
+ found = true;
+ break;
+ }
+ }
+ if(found){ break };
+ }
+ break;
+ case k.UP_ARROW:
+ case k.LEFT_ARROW:
+ area = this.gridNode.childNodes;
+ found = false;
+ for(i = area.length-1; i >= 0 ; i--){
+ children = area[i].childNodes;
+ for(j = children.length; j >= 0; j--){
+ zone = children[j];
+ if(zone != null && zone.style.display != "none"){
+ dijit.focus(zone);
+ dojo.stopEvent(event);
+ found = true;
+ break;
+ }
+ }
+ if(found){ break };
+ }
+ break;
+ }
+ }
+ else{
+ if(focusNode.parentNode.parentNode == this.gridNode){
+ var child = (key == k.UP_ARROW || key == k.LEFT_ARROW) ? "lastChild" : "firstChild";
+ var pos = (key == k.UP_ARROW || key == k.LEFT_ARROW) ? "previousSibling" : "nextSibling";
+ switch(key){
+ case k.UP_ARROW:
+ case k.DOWN_ARROW:
+ dojo.stopEvent(event);
+ found = false;
+ var focusTemp = focusNode;
+ while(!found){
+ children = focusTemp.parentNode.childNodes;
+ var num = 0;
+ for(i = 0; i < children.length; i++){
+ if(children[i].style.display != "none"){ num++ };
+ if(num > 1){ break; }
+ }
+ if(num == 1){ return; }
+ if(focusTemp[pos] == null){
+ zone = focusTemp.parentNode[child];
+ }
+ else{
+ zone = focusTemp[pos];
+ }
+ if(zone.style.display === "none"){
+ focusTemp = zone;
+ }
+ else{
+ found = true;
+ }
+ }
+ if(event.shiftKey){
+ var parent = focusNode.parentNode;
+ for(i = 0; i < this.gridNode.childNodes.length; i++){
+ if(parent == this.gridNode.childNodes[i]){
+ break;
+ }
+ }
+ children = this.gridNode.childNodes[i].childNodes;
+ for(j = 0; j < children.length; j++){
+ if(zone == children[j]){
+ break;
+ }
+ }
+ if(dojo.isMoz || dojo.isWebKit){ i-- };
+
+ widget = dijit.byNode(focusNode);
+ if(!widget.dragRestriction){
+ r = m.removeDragItem(parent, focusNode);
+ this.addChild(widget, i, j);
+ dojo.attr(focusNode, "tabIndex", "0");
+ dijit.focus(focusNode);
+ }
+ else{
+ dojo.publish("/dojox/layout/gridContainer/moveRestriction", [this]);
+ }
+ }
+ else{
+ dijit.focus(zone);
+ }
+ break;
+ case k.RIGHT_ARROW:
+ case k.LEFT_ARROW:
+ dojo.stopEvent(event);
+ if(event.shiftKey){
+ var z = 0;
+ if(focusNode.parentNode[pos] == null){
+ if(dojo.isIE && key == k.LEFT_ARROW){
+ z = this.gridNode.childNodes.length-1;
+ }
+ }
+ else if(focusNode.parentNode[pos].nodeType == 3){
+ z = this.gridNode.childNodes.length - 2;
+ }
+ else{
+ for(i = 0; i < this.gridNode.childNodes.length; i++){
+ if(focusNode.parentNode[pos] == this.gridNode.childNodes[i]){
+ break;
+ }
+ z++;
+ }
+ if(dojo.isMoz || dojo.isWebKit){ z-- };
+ }
+ widget = dijit.byNode(focusNode);
+ var _dndType = focusNode.getAttribute("dndtype");
+ if(_dndType == null){
+ //check if it's a dijit object
+ if(widget && widget.dndType){
+ _dndType = widget.dndType.split(/\s*,\s*/);
+ }
+ else{
+ _dndType = ["text"];
+ }
+ }
+ else{
+ _dndType = _dndType.split(/\s*,\s*/);
+ }
+ var accept = false;
+ for(i = 0; i < this.acceptTypes.length; i++){
+ for(j = 0; j < _dndType.length; j++){
+ if(_dndType[j] == this.acceptTypes[i]){
+ accept = true;
+ break;
+ }
+ }
+ }
+ if(accept && !widget.dragRestriction){
+ var parentSource = focusNode.parentNode,
+ place = 0;
+ if(k.LEFT_ARROW == key){
+ var t = z;
+ if(dojo.isMoz || dojo.isWebKit){ t = z + 1 };
+ place = this.gridNode.childNodes[t].childNodes.length;
+ }
+ // delete of manager :
+ r = m.removeDragItem(parentSource, focusNode);
+ this.addChild(widget, z, place);
+ dojo.attr(r, "tabIndex", "0");
+ dijit.focus(r);
+ }
+ else{
+ dojo.publish("/dojox/layout/gridContainer/moveRestriction", [this]);
+ }
+ }
+ else{
+ var node = focusNode.parentNode;
+ while(zone === null){
+ if(node[pos] !== null && node[pos].nodeType !== 3){
+ node = node[pos];
+ }
+ else{
+ if(pos === "previousSibling"){
+ node = node.parentNode.childNodes[node.parentNode.childNodes.length-1];
+ }
+ else{
+ node = (dojo.isIE)? node.parentNode.childNodes[0]: node.parentNode.childNodes[1];
+ }
+ }
+ zone = node[child];
+ if(zone && zone.style.display == "none"){
+ // check that all elements are not hidden
+ children = zone.parentNode.childNodes;
+ var childToSelect = null;
+ if(pos == "previousSibling"){
+ for(i = children.length-1; i >= 0; i--){
+ if(children[i].style.display != "none"){
+ childToSelect = children[i];
+ break;
+ }
+ }
+ }
+ else{
+ for(i = 0; i < children.length; i++){
+ if(children[i].style.display != "none"){
+ childToSelect = children[i];
+ break;
+ }
+ }
+ }
+ if(!childToSelect){
+ focusNode = zone;
+ node = focusNode.parentNode;
+ zone = null;
+ }
+ else{
+ zone = childToSelect;
+ }
+ }
+ }
+ dijit.focus(zone);
+ }
+ break;
+ }
+ }
+ }
+ },
+
+ destroy: function(){
+ //console.log("dojox.layout.GridContainerLite ::: destroy");
+ var m = this._dragManager;
+ dojo.forEach(this._grid, function(dropZone){
+ m.unregister(dropZone.node);
+ });
+ this.inherited(arguments);
+ }
+ });
+
+ dojo.extend(dijit._Widget, {
+
+ // column: String
+ // Column of the grid to place the widget.
+ // Defined only if dojo.require("dojox.layout.GridContainerLite") is done.
+ column : "1",
+
+ // dragRestriction: Boolean
+ // If true, the widget can not be draggable.
+ // Defined only if dojo.require("dojox.layout.GridContainerLite") is done.
+ dragRestriction : false
+ });
+ return gcl;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/layout/README b/js/dojo/dojox/layout/README
new file mode 100644
index 0000000..225dce1
--- /dev/null
+++ b/js/dojo/dojox/layout/README
@@ -0,0 +1,121 @@
+-------------------------------------------------------------------------------
+dojox.layout Experimental and Extended Layout Widgets
+-------------------------------------------------------------------------------
+Version 1.0
+Release date: 10/31/2007
+-------------------------------------------------------------------------------
+Project state:
+
+[BorderContainer] deprecated, use dijit.layout.BorderContainer
+[ContentPane] beta
+[DragPane] experimental
+[ExpandoPane] experimental
+[FloatingPane] sub-experimental
+[GridContainer] experimental
+[RadioGroup] experimental
+[RadioGroupFade/Slide] experimental
+[ResizeHandle] experimental
+[RotatorContainer] beta
+[ScrollPane] experimental
+[TableContainer] experimental
+
+-------------------------------------------------------------------------------
+Credits
+
+[BorderContainer] Adam Peller (peller)
+[ContentPane] Fredrik Johansson (mumme)
+[DragPane] Peter Higgins (dante)
+[ExpandoPane] Peter Higgins (dante)
+[FloatingPane] Peter Higgins (dante)
+[GridContainer/GridContainerLite] Erwan Morvillez (emorvillez), Jeff Cunat (jfcunat), Guillaume Mouricou (gmouricou), Peter Higgins (dante)
+[RadioGroup/Fade/Slide] Peter Higgins (dante)
+[ResizeHandle] Peter Higgins (dante)
+[RotatorContainer] Chris Barber (cb1)
+[ScrollPane] Peter Higgins (dante), Shane O'Sullivan (sos)
+[TableContainer] Shane O'Sullivan (sos)
+
+-------------------------------------------------------------------------------
+Project description
+
+ placeholder for dijit.layout extensions. Currently only:
+
+ dojo.layout.BorderContainer - deprecated, simple replacement at dijit.layout.BorderContainer
+
+ dojox.layout.ContentPane - an extension on dijit ContentPane.
+ Supports inline scripts, inline styles, relative path adjustments
+ and having a table tag as domNode.
+
+ dojox.layout.DragPane - an experimental start of a simple Dragable pane
+ (drag larger content around inside of a sized pane) Does not support borderContainer
+ LayoutContainer resizing yet.
+
+ dojox.layout.ExpandoPane - Intended only as a child of BorderContainer, provides an
+ experimental layout region (top/left/right/bottom) that collapses when toggled, hiding
+ the layout children contained within.
+
+ dojox.layout.FloatingPane - an extension on TitlePane for drag/drop
+ operation, "docking" [minimize/maximize], and resizing. HIGHLY experimental.
+
+ dojox.layout.GridContainer - displays children in a definable grid-layout,
+ allowing children to optionally be repositioned with DnD
+
+ dojox.layout.RadioGroup - a stack container with sliding or fading transitions
+ (and an internal button set to mimic a tab container, but fires on hover)
+ - RadioGroupFade - fade transitions
+ - RadioGroupSlide - slide transitions
+
+ dojox.layout.ResizeHandle - resize handle to attach to a domNode.
+ works well on normal domNodes, but will require adding a resizeTo(w,h)
+ method to any widget you wish to use it on. [experimental]
+
+ dojox.layout.RotatorContainer - similar to a RadioGroup, but provides advanced button's and
+ control.
+
+ dojox.layout.ScrollPane - a dynamically scrolling pane. Adjusts naturally sized content
+ to a "viewport" and scrolls based on relative mouse position.
+
+ dojox.layout.TableContainer - A container widget that lays out child widgets using a
+ Table element. It can create labels for each widget, placed either above or
+ beside the widgets.
+
+-------------------------------------------------------------------------------
+Dependencies
+
+ require Dojo Core, Dojo Base (fx), and Dijit
+
+-------------------------------------------------------------------------------
+Installation:
+
+ checkout:
+
+ http://svn.dojotoolkit.org/src/dojox/trunk/layout/
+ http://svn.dojotoolkit.org/src/dijit/trunk/
+
+ and require via:
+ dojo.require("dojox.layout.FloatingPane");
+ or:
+ dojo.require("dojox.layout.ContentPane");
+ etc ...
+
+ Each component has a required CSS File with a similar name, contained within the
+ /resources folder. Include that file in your page. For instance, if using
+ the dojox.layout.ExpandoPane:
+
+ <link rel="stylesheet" href="dojo-tree/dojox/layout/resources/ExpandoPane.css" />
+
+-------------------------------------------------------------------------------
+Basic Usage:
+
+ <div dojoType="dojox.layout.FloatingPane" title="my title">
+ Content To be Floated
+ </div>
+
+ <div dojoType="dojox.layout.ContentPane"
+ adjustPaths="true"
+ renderStyles="true"
+ executeScripts="true"
+ href="my/page/containing/scripts/and/styles/in/a/sub/folder.html"
+ >
+ Initial content, will be replace by href.
+ paths in folder.html will be adjusted to match this page
+ </div>
diff --git a/js/dojo/dojox/layout/RadioGroup.js b/js/dojo/dojox/layout/RadioGroup.js
new file mode 100644
index 0000000..a83add0
--- /dev/null
+++ b/js/dojo/dojox/layout/RadioGroup.js
@@ -0,0 +1,297 @@
+//>>built
+define("dojox/layout/RadioGroup", ["dojo/_base/kernel","dojo/_base/declare","dojo/_base/html","dojo/_base/lang","dojo/_base/query",
+ "dijit/_Widget","dijit/_Templated","dijit/_Contained","dijit/layout/StackContainer",
+ "dojo/fx/easing","dojo/_base/fx","dojo/dom-construct","dojo/dom-class"],function(
+ kernel,declare,html,lang,query,Widget,Templated,Contained,StackContainer,easing,baseFx,domConstruct,domClass){
+
+kernel.experimental("dojox.layout.RadioGroup");
+
+//
+// dojox.layout.RadioGroup - an experimental (probably poorly named) Layout widget extending StackContainer
+// that accepts ContentPanes as children, and applies aesthetically pleasing responsive transition animations
+// attached to :hover of the Buttons created.
+//
+// FIXME: take the Buttons out of the root template, and allow layoutAlign or similar attrib to use a different
+// template, or build the template dynamically?
+//
+/*=====
+ var StackContainer = dijit.layout.StackContainer,
+ Templated = dijit._Templated,
+ Contained = dijit._Contained,
+ Widget = dijit._Widget;
+=====*/
+
+var RadioGroup = declare("dojox.layout.RadioGroup",[StackContainer,Templated],{
+ // summary: A Container that turns its Layout Children into a single Pane and transitions between states
+ // onHover of the button
+ //
+
+ // duration: Integer
+ // used for Fade and Slide RadioGroup's, the duration to run the transition animation. does not affect anything
+ // in default RadioGroup
+ duration: 750,
+
+ // hasButtons: Boolean
+ // toggles internal button making on or off
+ hasButtons: false,
+
+ // buttonClass: String
+ // The full declared className of the Button widget to use for hasButtons
+ buttonClass: "dojox.layout._RadioButton",
+
+ // templateString: String
+ // the template for our container
+ templateString: '<div class="dojoxRadioGroup">'
+ +' <div dojoAttachPoint="buttonHolder" style="display:none;">'
+ +' <table class="dojoxRadioButtons"><tbody><tr class="dojoxRadioButtonRow" dojoAttachPoint="buttonNode"></tr></tbody></table>'
+ +' </div>'
+ +' <div class="dojoxRadioView" dojoAttachPoint="containerNode"></div>'
+ +'</div>',
+
+ startup: function(){
+ // summary: scan the container for children, and make "tab buttons" for them
+ this.inherited(arguments);
+ this._children = this.getChildren();
+ this._buttons = this._children.length;
+ this._size = html.coords(this.containerNode);
+ if(this.hasButtons){
+ html.style(this.buttonHolder, "display", "block");
+ }
+ },
+
+ _setupChild: function(/* dijit._Widget */child){
+ // summary: Creates a hover button for a child node of the RadioGroup
+ html.style(child.domNode, "position", "absolute");
+ if(this.hasButtons){
+
+ var tmp = this.buttonNode.appendChild(domConstruct.create('td'));
+ var n = domConstruct.create("div", null, tmp),
+ _Button = lang.getObject(this.buttonClass),
+ tmpw = new _Button({
+ label: child.title,
+ page: child
+ }, n)
+ ;
+
+ lang.mixin(child, { _radioButton: tmpw });
+ tmpw.startup();
+ }
+ child.domNode.style.display = "none";
+ },
+
+ removeChild: function(child){
+ if(this.hasButtons && child._radioButton){
+ child._radioButton.destroy();
+ delete child._radioButton;
+ }
+ this.inherited(arguments);
+ },
+
+ // FIXME: shouldn't have to rewriting these, need to take styling out of _showChild and _hideChild
+ // and use classes on the domNode in _transition or something similar (in StackContainer)
+ _transition: function(/*dijit._Widget*/ newWidget, /*dijit._Widget*/ oldWidget){
+ // summary: called when StackContainer receives a selectChild call, used to transition the panes.
+ this._showChild(newWidget);
+ if(oldWidget){
+ this._hideChild(oldWidget);
+ }
+ // Size the new widget, in case this is the first time it's being shown,
+ // or I have been resized since the last time it was shown.
+ // page must be visible for resizing to work
+ if(this.doLayout && newWidget.resize){
+ newWidget.resize(this._containerContentBox || this._contentBox);
+ }
+ },
+
+ _showChild: function(/*dijit._Widget*/ page){
+ // summary: show the selected child widget
+ var children = this.getChildren();
+ page.isFirstChild = (page == children[0]);
+ page.isLastChild = (page == children[children.length-1]);
+ page.selected = true;
+
+ page.domNode.style.display="";
+
+ if(page._onShow){
+ page._onShow(); // trigger load in ContentPane
+ }else if(page.onShow){
+ page.onShow();
+ }
+ },
+
+ _hideChild: function(/*dijit._Widget*/ page){
+ // summary: hide the specified child widget
+ page.selected = false;
+ page.domNode.style.display="none";
+ if(page.onHide){
+ page.onHide();
+ }
+ }
+
+});
+
+declare("dojox.layout.RadioGroupFade", RadioGroup, {
+ // summary: An extension on a stock RadioGroup, that fades the panes.
+
+ _hideChild: function(page){
+ // summary: hide the specified child widget
+ baseFx.fadeOut({
+ node:page.domNode,
+ duration:this.duration,
+ onEnd: lang.hitch(this,"inherited", arguments, arguments)
+ }).play();
+ },
+
+ _showChild: function(page){
+ // summary: show the specified child widget
+ this.inherited(arguments);
+ html.style(page.domNode, "opacity", 0);
+ baseFx.fadeIn({
+ node:page.domNode,
+ duration:this.duration
+ }).play();
+ }
+});
+
+declare("dojox.layout.RadioGroupSlide", RadioGroup, {
+ // summary: A Sliding Radio Group
+ // description:
+ // An extension on a stock RadioGroup widget, sliding the pane
+ // into view from being hidden. The entry direction is randomized
+ // on each view
+ //
+
+ // easing: Function
+ // A hook to override the default easing of the pane slides.
+ easing: "dojo.fx.easing.backOut",
+
+ // zTop: Integer
+ // A z-index to apply to the incoming pane
+ zTop: 99,
+
+ constructor: function(){
+ if(lang.isString(this.easing)){
+ this.easing = lang.getObject(this.easing);
+ }
+ },
+
+ _positionChild: function(page){
+ // summary: set the child out of view immediately after being hidden
+
+ // FIXME: is there a real "size" floating around always?
+ if(!this._size){ return; }
+
+ // there should be a contest: obfuscate this function as best you can.
+ var rA = true, rB = true;
+ switch(page.slideFrom){
+ case "bottom" : rB = !rB; break;
+ case "right" : rA = !rA; rB = !rB; break;
+ case "top" : break;
+ case "left" : rA = !rA; break;
+ default:
+ rA = Math.round(Math.random());
+ rB = Math.round(Math.random());
+ break;
+ }
+ var prop = rA ? "top" : "left",
+ val = (rB ? "-" : "") + (this._size[rA ? "h" : "w" ] + 20) + "px";
+
+ html.style(page.domNode, prop, val);
+
+ },
+
+ _showChild: function(page){
+ // summary: Slide in the selected child widget
+
+ var children = this.getChildren();
+ page.isFirstChild = (page == children[0]);
+ page.isLastChild = (page == children[children.length-1]);
+ page.selected = true;
+
+ html.style(page.domNode,{
+ zIndex: this.zTop, display:""
+ })
+
+ if(this._anim && this._anim.status()=="playing"){
+ this._anim.gotoPercent(100,true);
+ }
+
+ this._anim = baseFx.animateProperty({
+ node:page.domNode,
+ properties: {
+ left: 0,
+ top: 0
+ },
+ duration: this.duration,
+ easing: this.easing,
+ onEnd: lang.hitch(page, function(){
+ if(this.onShow){ this.onShow(); }
+ if(this._onShow){ this._onShow(); }
+ }),
+ beforeBegin: lang.hitch(this, "_positionChild", page)
+ });
+ this._anim.play();
+ },
+
+ _hideChild: function(page){
+ // summary: reset the position of the hidden pane out of sight
+
+ page.selected = false;
+ page.domNode.style.zIndex = this.zTop - 1;
+ if(page.onHide){
+ page.onHide();
+ }
+
+ }
+
+});
+
+declare("dojox.layout._RadioButton",[Widget,Templated,Contained],{
+ // summary: The Buttons for a RadioGroup
+ //
+ // description: A private widget used to manipulate the StackContainer (RadioGroup*). Don't create directly.
+ //
+
+ // label: String
+ // the Text Label of the button
+ label: "",
+
+ // domNode to tell parent to select
+ page: null,
+
+ templateString: '<div dojoAttachPoint="focusNode" class="dojoxRadioButton"><span dojoAttachPoint="titleNode" class="dojoxRadioButtonLabel">${label}</span></div>',
+
+ startup: function(){
+ // summary: start listening to mouseOver
+ this.connect(this.domNode, "onmouseenter", "_onMouse");
+ },
+
+ _onMouse: function(/* Event */e){
+ // summary: set the selected child on hover, and set our hover state class
+ this.getParent().selectChild(this.page);
+ this._clearSelected();
+ domClass.add(this.domNode,"dojoxRadioButtonSelected");
+
+ },
+
+ _clearSelected: function(){
+ // summary: remove hover state class from sibling Buttons. This is easier (and more reliable)
+ // than setting up an additional connection to onMouseOut
+
+ // FIXME: this relies on the template being [div][span]node[/span][/div]
+ query(".dojoxRadioButtonSelected", this.domNode.parentNode.parentNode)
+ .removeClass("dojoxRadioButtonSelected")
+ ;
+ }
+
+});
+
+lang.extend(Widget,{
+ // slideFrom: String
+ // A parameter needed by RadioGroupSlide only. An optional paramter to force
+ // the ContentPane to slide in from a set direction. Defaults
+ // to "random", or specify one of "top", "left", "right", "bottom"
+ // to slideFrom top, left, right, or bottom.
+ slideFrom: "random"
+})
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/layout/ResizeHandle.js b/js/dojo/dojox/layout/ResizeHandle.js
new file mode 100644
index 0000000..5986bc1
--- /dev/null
+++ b/js/dojo/dojox/layout/ResizeHandle.js
@@ -0,0 +1,364 @@
+//>>built
+define("dojox/layout/ResizeHandle", ["dojo/_base/kernel","dojo/_base/lang","dojo/_base/connect","dojo/_base/array","dojo/_base/event",
+ "dojo/_base/fx","dojo/_base/window","dojo/fx","dojo/window","dojo/dom","dojo/dom-class",
+ "dojo/dom-geometry","dojo/dom-style","dijit/_base/manager","dijit/_Widget","dijit/_TemplatedMixin",
+ "dojo/_base/declare"], function (
+ kernel, lang, connect, arrayUtil, eventUtil, fxBase, windowBase, fxUtil, windowUtil,
+ domUtil, domClass, domGeometry, domStyle, manager, Widget, TemplatedMixin, declare) {
+
+kernel.experimental("dojox.layout.ResizeHandle");
+
+/*=====
+ var Widget = dijit._Widget;
+ var TemplatedMixin = dijit._TemplatedMixin;
+=====*/
+var ResizeHandle = declare("dojox.layout.ResizeHandle",[Widget, TemplatedMixin],
+ {
+ // summary: A dragable handle used to resize an attached node.
+ //
+ // description:
+ // The handle on the bottom-right corner of FloatingPane or other widgets that allows
+ // the widget to be resized.
+ // Typically not used directly.
+ //
+ // targetId: String
+ // id of the Widget OR DomNode that I will size
+ targetId: "",
+
+ // targetContainer: DomNode
+ // over-ride targetId and attch this handle directly to a reference of a DomNode
+ targetContainer: null,
+
+ // resizeAxis: String
+ // one of: x|y|xy limit resizing to a single axis, default to xy ...
+ resizeAxis: "xy",
+
+ // activeResize: Boolean
+ // if true, node will size realtime with mouse movement,
+ // if false, node will create virtual node, and only resize target on mouseUp
+ activeResize: false,
+
+ // activeResizeClass: String
+ // css class applied to virtual resize node.
+ activeResizeClass: "dojoxResizeHandleClone",
+
+ // animateSizing: Boolean
+ // only applicable if activeResize = false. onMouseup, animate the node to the
+ // new size
+ animateSizing: true,
+
+ // animateMethod: String
+ // one of "chain" or "combine" ... visual effect only. combine will "scale"
+ // node to size, "chain" will alter width, then height
+ animateMethod: "chain",
+
+ // animateDuration: Integer
+ // time in MS to run sizing animation. if animateMethod="chain", total animation
+ // playtime is 2*animateDuration
+ animateDuration: 225,
+
+ // minHeight: Integer
+ // smallest height in px resized node can be
+ minHeight: 100,
+
+ // minWidth: Integer
+ // smallest width in px resize node can be
+ minWidth: 100,
+
+ // constrainMax: Boolean
+ // Toggle if this widget cares about the maxHeight and maxWidth
+ // parameters.
+ constrainMax: false,
+
+ // maxHeight: Integer
+ // Largest height size in px the resize node can become.
+ maxHeight:0,
+
+ // maxWidth: Integer
+ // Largest width size in px the reize node can become.
+ maxWidth:0,
+
+ // fixedAspect: Boolean
+ // Toggle to enable this widget to maintain the aspect
+ // ratio of the attached node.
+ fixedAspect: false,
+
+ // intermediateChanges: Boolean
+ // Toggle to enable/disable this widget from firing onResize
+ // events at every step of a resize. If `activeResize` is true,
+ // and this is false, onResize only fires _after_ the drop
+ // operation. Animated resizing is not affected by this setting.
+ intermediateChanges: false,
+
+ // startTopic: String
+ // The name of the topic this resizehandle publishes when resize is starting
+ startTopic: "/dojo/resize/start",
+
+ // endTopic: String
+ // The name of the topic this resizehandle publishes when resize is complete
+ endTopic:"/dojo/resize/stop",
+
+ templateString: '<div dojoAttachPoint="resizeHandle" class="dojoxResizeHandle"><div></div></div>',
+
+ postCreate: function(){
+ // summary: setup our one major listener upon creation
+ this.connect(this.resizeHandle, "onmousedown", "_beginSizing");
+ if(!this.activeResize){
+ // there shall be only a single resize rubberbox that at the top
+ // level so that we can overlay it on anything whenever the user
+ // resizes something. Since there is only one mouse pointer he
+ // can't at once resize multiple things interactively.
+ this._resizeHelper = manager.byId('dojoxGlobalResizeHelper');
+ if(!this._resizeHelper){
+ this._resizeHelper = new _ResizeHelper({
+ id: 'dojoxGlobalResizeHelper'
+ }).placeAt(windowBase.body());
+ domClass.add(this._resizeHelper.domNode, this.activeResizeClass);
+ }
+ }else{ this.animateSizing = false; }
+
+ if(!this.minSize){
+ this.minSize = { w: this.minWidth, h: this.minHeight };
+ }
+
+ if(this.constrainMax){
+ this.maxSize = { w: this.maxWidth, h: this.maxHeight }
+ }
+
+ // should we modify the css for the cursor hover to n-resize nw-resize and w-resize?
+ this._resizeX = this._resizeY = false;
+ var addClass = lang.partial(domClass.add, this.resizeHandle);
+ switch(this.resizeAxis.toLowerCase()){
+ case "xy" :
+ this._resizeX = this._resizeY = true;
+ // FIXME: need logic to determine NW or NE class to see
+ // based on which [todo] corner is clicked
+ addClass("dojoxResizeNW");
+ break;
+ case "x" :
+ this._resizeX = true;
+ addClass("dojoxResizeW");
+ break;
+ case "y" :
+ this._resizeY = true;
+ addClass("dojoxResizeN");
+ break;
+ }
+ },
+
+ _beginSizing: function(/*Event*/ e){
+ // summary: setup movement listeners and calculate initial size
+
+ if(this._isSizing){ return; }
+
+ connect.publish(this.startTopic, [ this ]);
+ this.targetWidget = manager.byId(this.targetId);
+
+ this.targetDomNode = this.targetWidget ? this.targetWidget.domNode : domUtil.byId(this.targetId);
+ if(this.targetContainer){ this.targetDomNode = this.targetContainer; }
+ if(!this.targetDomNode){ return; }
+
+ if(!this.activeResize){
+ var c = domGeometry.position(this.targetDomNode, true);
+ this._resizeHelper.resize({l: c.x, t: c.y, w: c.w, h: c.h});
+ this._resizeHelper.show();
+ }
+
+ this._isSizing = true;
+ this.startPoint = { x:e.clientX, y:e.clientY };
+
+ // widget.resize() or setting style.width/height expects native box model dimension
+ // (in most cases content-box, but it may be border-box if in backcompact mode)
+ var style = domStyle.getComputedStyle(this.targetDomNode),
+ borderModel = domGeometry.boxModel==='border-model',
+ padborder = borderModel?{w:0,h:0}:domGeometry.getPadBorderExtents(this.targetDomNode, style),
+ margin = domGeometry.getMarginExtents(this.targetDomNode, style),
+ mb;
+ mb = this.startSize = {
+ w: domStyle.get(this.targetDomNode, 'width', style),
+ h: domStyle.get(this.targetDomNode, 'height', style),
+ //ResizeHelper.resize expects a bounding box of the
+ //border box, so let's keep track of padding/border
+ //width/height as well
+ pbw: padborder.w, pbh: padborder.h,
+ mw: margin.w, mh: margin.h};
+
+ this._pconnects = [
+ connect.connect(windowBase.doc,"onmousemove",this,"_updateSizing"),
+ connect.connect(windowBase.doc,"onmouseup", this, "_endSizing")
+ ];
+
+ eventUtil.stop(e);
+ },
+
+ _updateSizing: function(/*Event*/ e){
+ // summary: called when moving the ResizeHandle ... determines
+ // new size based on settings/position and sets styles.
+
+ if(this.activeResize){
+ this._changeSizing(e);
+ }else{
+ var tmp = this._getNewCoords(e, 'border');
+ if(tmp === false){ return; }
+ this._resizeHelper.resize(tmp);
+ }
+ e.preventDefault();
+ },
+
+ _getNewCoords: function(/* Event */ e, /* String */ box){
+
+ // On IE, if you move the mouse above/to the left of the object being resized,
+ // sometimes clientX/Y aren't set, apparently. Just ignore the event.
+ try{
+ if(!e.clientX || !e.clientY){ return false; }
+ }catch(e){
+ // sometimes you get an exception accessing above fields...
+ return false;
+ }
+ this._activeResizeLastEvent = e;
+
+ var dx = (this.isLeftToRight()?1:-1) * (this.startPoint.x - e.clientX),
+ dy = this.startPoint.y - e.clientY,
+ newW = this.startSize.w - (this._resizeX ? dx : 0),
+ newH = this.startSize.h - (this._resizeY ? dy : 0),
+ r = this._checkConstraints(newW, newH)
+ ;
+
+ switch(box){
+ case 'margin':
+ r.w += this.startSize.mw;
+ r.h += this.startSize.mh;
+ //pass through
+ case "border":
+ r.w += this.startSize.pbw;
+ r.h += this.startSize.pbh;
+ break;
+ //default: //native, do nothing
+ }
+
+ return r; // Object
+ },
+
+ _checkConstraints: function(newW, newH){
+ // summary: filter through the various possible constaint possibilities.
+
+ // minimum size check
+ if(this.minSize){
+ var tm = this.minSize;
+ if(newW < tm.w){
+ newW = tm.w;
+ }
+ if(newH < tm.h){
+ newH = tm.h;
+ }
+ }
+
+ // maximum size check:
+ if(this.constrainMax && this.maxSize){
+ var ms = this.maxSize;
+ if(newW > ms.w){
+ newW = ms.w;
+ }
+ if(newH > ms.h){
+ newH = ms.h;
+ }
+ }
+
+ if(this.fixedAspect){
+ var w = this.startSize.w, h = this.startSize.h,
+ delta = w * newH - h * newW;
+ if(delta<0){
+ newW = newH * w / h;
+ }else if(delta>0){
+ newH = newW * h / w;
+ }
+ }
+
+ return { w: newW, h: newH }; // Object
+ },
+
+ _changeSizing: function(/*Event*/ e){
+ // summary: apply sizing information based on information in (e) to attached node
+
+ var isWidget = this.targetWidget && lang.isFunction(this.targetWidget.resize),
+ tmp = this._getNewCoords(e, isWidget && 'margin');
+ if(tmp === false){ return; }
+
+ if(isWidget){
+ this.targetWidget.resize(tmp);
+ }else{
+ if(this.animateSizing){
+ var anim = fxUtil[this.animateMethod]([
+ fxBase.animateProperty({
+ node: this.targetDomNode,
+ properties: {
+ width: { start: this.startSize.w, end: tmp.w }
+ },
+ duration: this.animateDuration
+ }),
+ fxBase.animateProperty({
+ node: this.targetDomNode,
+ properties: {
+ height: { start: this.startSize.h, end: tmp.h }
+ },
+ duration: this.animateDuration
+ })
+ ]);
+ anim.play();
+ }else{
+ domStyle.set(this.targetDomNode,{
+ width: tmp.w + "px",
+ height: tmp.h + "px"
+ });
+ }
+ }
+ if(this.intermediateChanges){
+ this.onResize(e);
+ }
+ },
+
+ _endSizing: function(/*Event*/ e){
+ // summary: disconnect listenrs and cleanup sizing
+ arrayUtil.forEach(this._pconnects, connect.disconnect);
+ var pub = lang.partial(connect.publish, this.endTopic, [ this ]);
+ if(!this.activeResize){
+ this._resizeHelper.hide();
+ this._changeSizing(e);
+ setTimeout(pub, this.animateDuration + 15);
+ }else{
+ pub();
+ }
+ this._isSizing = false;
+ this.onResize(e);
+ },
+
+ onResize: function(e){
+ // summary: Stub fired when sizing is done. Fired once
+ // after resize, or often when `intermediateChanges` is
+ // set to true.
+ }
+
+});
+
+var _ResizeHelper = dojo.declare("dojox.layout._ResizeHelper", Widget, {
+ // summary: A global private resize helper shared between any
+ // `dojox.layout.ResizeHandle` with activeSizing off.
+
+ show: function(){
+ // summary: show helper to start resizing
+ domStyle.set(this.domNode, "display", "");
+ },
+
+ hide: function(){
+ // summary: hide helper after resizing is complete
+ domStyle.set(this.domNode, "display", "none");
+ },
+
+ resize: function(/* Object */dim){
+ // summary: size the widget and place accordingly
+ domGeometry.setMarginBox(this.domNode, dim);
+ }
+
+});
+return ResizeHandle;
+});
diff --git a/js/dojo/dojox/layout/RotatorContainer.js b/js/dojo/dojox/layout/RotatorContainer.js
new file mode 100644
index 0000000..5ab65d9
--- /dev/null
+++ b/js/dojo/dojox/layout/RotatorContainer.js
@@ -0,0 +1,456 @@
+//>>built
+define("dojox/layout/RotatorContainer", ["dojo/_base/declare","dojo/_base/html","dojo/_base/connect","dojo/_base/lang","dojo/_base/array",
+ "dojo/_base/fx","dojo/fx","dijit/_base/manager","dijit/layout/StackContainer","dijit/layout/StackController","dijit/_Widget",
+ "dijit/_Templated","dijit/_Contained"
+],function(declare,html,connect,lang,array,baseFx,coreFx,manager,
+ StackContainer,StackController,Widget,Templated,Contained){
+
+/*=====
+ var Widget = dijit._Widget,
+ Templated = dijit._Templated,
+ Contained = dijit._Contained,
+ StackContainer = dijit.layout.StackContainer,
+ StackController = dijit.layout.StackController;
+=====*/
+var RotatorContainer = declare("dojox.layout.RotatorContainer",[StackContainer, Templated], {
+ // summary:
+ // Extends a StackContainer to automatically transition between children
+ // and display navigation in the form of tabs or a pager.
+ //
+ // description:
+ // The RotatorContainer cycles through the children with a transition.
+ //
+ // published topics:
+ // [widgetId]-update - Notifies pager(s) that a child has changed.
+ // Parameters:
+ // /*boolean*/ playing - true if playing, false if paused
+ // /*int*/ current - current selected child
+ // /*int*/ total - total number of children
+ //
+ // example:
+ // | <div dojoType="dojox.layout.RotatorContainer" id="myRotator" showTabs="true" autoStart="true" transitionDelay="5000">
+ // | <div id="pane1" dojoType="dijit.layout.ContentPane" title="1">
+ // | Pane 1!
+ // | </div>
+ // | <div id="pane2" dojoType="dijit.layout.ContentPane" title="2">
+ // | Pane 2!
+ // | </div>
+ // | <div id="pane3" dojoType="dijit.layout.ContentPane" title="3" transitionDelay="10000">
+ // | Pane 3 with overrided transitionDelay!
+ // | </div>
+ // | </div>
+
+ templateString: '<div class="dojoxRotatorContainer"><div dojoAttachPoint="tabNode"></div><div class="dojoxRotatorPager" dojoAttachPoint="pagerNode"></div><div class="dojoxRotatorContent" dojoAttachPoint="containerNode"></div></div>',
+
+ // showTabs: Boolean
+ // Sets the display of the tabs. The tabs are actually a StackController.
+ // The child's title is used for the tab's label.
+ showTabs: true,
+
+ // transitionDelay: int
+ // The delay in milliseconds before transitioning to the next child.
+ transitionDelay: 5000,
+
+ // transition: String
+ // The type of transition to perform when switching children.
+ // A null transition will transition instantly.
+ transition: "fade",
+
+ // transitionDuration: int
+ // The duration of the transition in milliseconds.
+ transitionDuration: 1000,
+
+ // autoStart: Boolean
+ // Starts the timer to transition children upon creation.
+ autoStart: true,
+
+ // suspendOnHover: Boolean
+ // Pause the rotator when the mouse hovers over it.
+ suspendOnHover: false,
+
+ // pauseOnManualChange: Boolean
+ // Pause the rotator when the tab is changed or the pager's next/previous
+ // buttons are clicked.
+ pauseOnManualChange: null,
+
+ // reverse: Boolean
+ // Causes the rotator to rotate in reverse order.
+ reverse: false,
+
+ // pagerId: String
+ // ID the pager widget.
+ pagerId: "",
+
+ // cycles: int
+ // Number of cycles before pausing.
+ cycles: -1,
+
+ // pagerClass: String
+ // The declared Class of the Pager used for this Widget
+ pagerClass: "dojox.layout.RotatorPager",
+
+ postCreate: function(){
+ // summary: Initializes the DOM nodes, tabs, and transition stuff.
+ this.inherited(arguments);
+
+ // force this DOM node to a relative position and make sure the children are absolute positioned
+ html.style(this.domNode, "position", "relative");
+
+ // validate the cycles counter
+ if(this.cycles-0 == this.cycles && this.cycles != -1){
+ // we need to add 1 because we decrement cycles before the animation starts
+ this.cycles++;
+ }else{
+ this.cycles = -1;
+ }
+
+ // if they didn't specify the pauseOnManualChange, then we want it to be the opposite of
+ // the suspendOnHover since it doesn't make sense to do both, unless you really want to
+ if(this.pauseOnManualChange === null){
+ this.pauseOnManualChange = !this.suspendOnHover;
+ }
+
+ // create the stack controller if we are using tabs
+ var id = this.id || "rotator"+(new Date()).getTime(),
+ sc = new StackController({ containerId:id }, this.tabNode);
+ this.tabNode = sc.domNode;
+ this._stackController = sc;
+ html.style(this.tabNode, "display", this.showTabs ? "" : "none");
+
+ // if the controller's tabs are clicked, check if we should pause and reset the cycle counter
+ this.connect(sc, "onButtonClick","_manualChange");
+
+ // set up our topic listeners
+ this._subscriptions = [
+ connect.subscribe(this.id+"-cycle", this, "_cycle"),
+ connect.subscribe(this.id+"-state", this, "_state")
+ ];
+
+ // make sure the transition duration isn't less than the transition delay
+ var d = Math.round(this.transitionDelay * 0.75);
+ if(d < this.transitionDuration){
+ this.transitionDuration = d;
+ }
+
+ // wire up the mouse hover events
+ if(this.suspendOnHover){
+ this.connect(this.domNode, "onmouseover", "_onMouseOver");
+ this.connect(this.domNode, "onmouseout", "_onMouseOut");
+ }
+ },
+
+ startup: function(){
+ // summary: Initializes the pagers.
+ if(this._started){ return; }
+
+ // check if the pager is defined within the rotator container
+ var c = this.getChildren();
+ for(var i=0, len=c.length; i<len; i++){
+ if(c[i].declaredClass == this.pagerClass){
+ this.pagerNode.appendChild(c[i].domNode);
+ break;
+ }
+ }
+
+ // process the child widgets
+ this.inherited(arguments);
+
+ // check if we should start automatically
+ if(this.autoStart){
+ // start playing
+ setTimeout(lang.hitch(this, "_play"), 10);
+ }else{
+ // update the pagers with the initial state
+ this._updatePager();
+ }
+ },
+
+ destroy: function(){
+ // summary: Unsubscribe to all of our topics
+ array.forEach(this._subscriptions, connect.unsubscribe);
+ this.inherited(arguments);
+ },
+
+ _setShowTabsAttr: function(/*anything*/value){
+ this.showTabs = value;
+ html.style(this.tabNode, "display", value ? "" : "none");
+ },
+
+ _updatePager: function(){
+ // summary: Notify the pager's current and total numbers.
+ var c = this.getChildren();
+ connect.publish(this.id+"-update", [this._playing, array.indexOf(c, this.selectedChildWidget)+1, c.length]);
+ },
+
+ _onMouseOver: function(){
+ // summary: Triggered when the mouse is moved over the rotator container.
+
+ // temporarily suspend the cycling, but don't officially pause it
+ this._resetTimer();
+ this._over = true;
+ },
+
+ _onMouseOut: function(){
+ // summary: Triggered when the mouse is moved off the rotator container.
+ this._over = false;
+
+ // if we were playing, resume playback in 200ms
+ // we need to wait because we may be moused over again right away
+ if(this._playing){
+ clearTimeout(this._timer);
+ this._timer = setTimeout(lang.hitch(this, "_play", true), 200);
+ }
+ },
+
+ _resetTimer: function(){
+ // summary: Resets the timer used to start the next transition.
+ clearTimeout(this._timer);
+ this._timer = null;
+ },
+
+ _cycle: function(/*boolean or int*/next){
+ // summary: Cycles to the next/previous child.
+
+ // if next is an int, then _cycle() was called via a timer
+ // if next is a boolean, then _cycle() was called via the next/prev buttons, stop playing and reset cycles
+ if(next instanceof Boolean || typeof next == "boolean"){
+ this._manualChange();
+ }
+
+ var c = this.getChildren(),
+ len = c.length,
+ i = array.indexOf(c, this.selectedChildWidget) + (next === false || (next !== true && this.reverse) ? -1 : 1);
+ this.selectChild(c[(i < len ? (i < 0 ? len-1 : i) : 0)]);
+ this._updatePager();
+ },
+
+ _manualChange: function(){
+ // summary: This function is only called when a manual change occurs in which
+ // case we may need to stop playing and we need to reset the cycle counter
+ if(this.pauseOnManualChange){
+ this._playing = false;
+ }
+ this.cycles = -1;
+ },
+
+ _play: function(skip){
+ // summary: Schedules the next transition.
+ this._playing = true;
+ this._resetTimer();
+ if(skip !== true && this.cycles>0){
+ this.cycles--;
+ }
+ if(this.cycles==0){
+ this._pause();
+ }else if((!this.suspendOnHover || !this._over) && this.transitionDelay){
+ // check if current pane has a delay
+ this._timer = setTimeout(lang.hitch(this, "_cycle"), this.selectedChildWidget.domNode.getAttribute("transitionDelay") || this.transitionDelay);
+ }
+ this._updatePager();
+ },
+
+ _pause: function(){
+ // summary: Clears the transition timer and pauses the rotator.
+ this._playing = false;
+ this._resetTimer();
+ },
+
+ _state: function(playing){
+ // summary: Fired when the play/pause pager button is toggled.
+ if(playing){
+ // since we were manually changed, disable the cycle counter
+ this.cycles = -1;
+ this._play();
+ }else{
+ this._pause();
+ }
+ },
+
+ _transition: function(/*dijit._Widget*/ next, /*dijit._Widget*/ prev){
+ // summary: Dispatches the appropriate transition.
+ this._resetTimer();
+
+ // check if we have anything to transition
+ if(prev && this.transitionDuration){
+ switch(this.transition){
+ case "fade": this._fade(next, prev); return;
+ }
+ }
+
+ this._transitionEnd();
+ this.inherited(arguments);
+ },
+
+ _transitionEnd: function(){
+ if(this._playing){
+ this._play();
+ }else{
+ this._updatePager();
+ }
+ },
+
+ _fade: function(/*dijit._Widget*/ next, /*dijit._Widget*/ prev){
+ // summary: Crossfades two children.
+ this._styleNode(prev.domNode, 1, 1);
+ this._styleNode(next.domNode, 0, 2);
+
+ // show the next child and make sure it's sized properly
+ this._showChild(next);
+ if(this.doLayout && next.resize){
+ next.resize(this._containerContentBox || this._contentBox);
+ }
+
+ // create the crossfade animation
+ var args = { duration:this.transitionDuration },
+ anim = coreFx.combine([
+ baseFx["fadeOut"](lang.mixin({node:prev.domNode}, args)),
+ baseFx["fadeIn"](lang.mixin({node:next.domNode}, args))
+ ]);
+
+ this.connect(anim, "onEnd", lang.hitch(this,function(){
+ this._hideChild(prev);
+ this._transitionEnd();
+ }));
+
+ anim.play();
+ },
+
+ _styleNode: function(/*DOMnode*/node, /*number*/opacity, /*int*/zIndex){
+ // summary: Helper function to style the children.
+ html.style(node, "opacity", opacity);
+ html.style(node, "zIndex", zIndex);
+ html.style(node, "position", "absolute");
+ }
+});
+
+declare("dojox.layout.RotatorPager", [Widget, Templated, Contained], {
+ // summary:
+ // Defines controls used to manipulate a RotatorContainer
+ //
+ // description:
+ // A pager can be defined one of two ways:
+ // * Externally of the RotatorContainer's template and tell the
+ // RotatorPager the rotatorId of the RotatorContainer
+ // * As a direct descendant of the RotatorContainer (i.e. inside the
+ // RotatorContainer's template)
+ //
+ // The pager can contain the following components:
+ // * Previous button
+ // - Must be a dijit.form.Button
+ // - dojoAttachPoint must be named "previous"
+ // * Next button
+ // - Must be a dijit.form.Button
+ // - dojoAttachPoint must be named "next"
+ // * Play/Pause toggle button
+ // - Must be a dijit.form.ToggleButton
+ // - dojoAttachPoint must be named "playPause"
+ // - Use iconClass to specify toggled state
+ // * Current child #
+ // - dojoAttachPoint must be named "current"
+ // * Total # of children
+ // - dojoAttachPoint must be named "total"
+ //
+ // You can choose to exclude specific controls as well as add elements
+ // for styling.
+ //
+ // Should you need a pager, but don't want to use Dijit buttons, you can
+ // write your own pager widget and just wire it into the topics. The
+ // topic names are prefixed with the widget ID of the RotatorContainer.
+ // Notifications are received from and sent to the RotatorContainer as
+ // well as other RotatorPagers.
+ //
+ // published topics:
+ // [widgetId]-cycle - Notify that the next or previous button was pressed.
+ // Parameters:
+ // /*boolean*/ next - true if next, false if previous
+ // [widgetId]-state - Notify that the play/pause button was toggled.
+ // Parameters:
+ // /*boolean*/ playing - true if playing, false if paused
+ //
+ // example:
+ // A pager with the current/total children and previous/next buttons.
+ // | <div dojoType="dojox.layout.RotatorPager" rotatorId="myRotator">
+ // | <button dojoType="dijit.form.Button" dojoAttachPoint="previous">Prev</button>
+ // | <span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
+ // | <button dojoType="dijit.form.Button" dojoAttachPoint="next">Next</button>
+ // | </div>
+ //
+ // example:
+ // A pager with only a play/pause toggle button.
+ // | <div dojoType="dojox.layout.RotatorPager" rotatorId="myRotator">
+ // | <button dojoType="dijit.form.ToggleButton" dojoAttachPoint="playPause"></button>
+ // | </div>
+ //
+ // example:
+ // A pager styled with iconClass.
+ // | <div dojoType="dojox.layout.RotatorPager" class="rotatorIcons" rotatorId="myRotator">
+ // | <button dojoType="dijit.form.Button" iconClass="previous" dojoAttachPoint="previous">Prev</button>
+ // | <button dojoType="dijit.form.ToggleButton" iconClass="playPause" dojoAttachPoint="playPause"></button>
+ // | <button dojoType="dijit.form.Button" iconClass="next" dojoAttachPoint="next">Next</button>
+ // | <span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
+ // | </div>
+
+ widgetsInTemplate: true,
+
+ // rotatorId: int
+ // The ID of the rotator this pager is tied to.
+ // Only required if defined outside of the RotatorContainer's container.
+ rotatorId: "",
+
+ postMixInProperties: function(){
+ this.templateString = "<div>" + this.srcNodeRef.innerHTML + "</div>";
+ },
+
+ postCreate: function(){
+ var p = manager.byId(this.rotatorId) || this.getParent();
+ if(p && p.declaredClass == "dojox.layout.RotatorContainer"){
+ if(this.previous){
+ connect.connect(this.previous, "onClick", function(){
+ connect.publish(p.id+"-cycle", [false]);
+ });
+ }
+ if(this.next){
+ connect.connect(this.next, "onClick", function(){
+ connect.publish(p.id+"-cycle", [true]);
+ });
+ }
+ if(this.playPause){
+ connect.connect(this.playPause, "onClick", function(){
+ this.set('label', this.checked ? "Pause" : "Play");
+ connect.publish(p.id+"-state", [this.checked]);
+ });
+ }
+ this._subscriptions = [
+ connect.subscribe(p.id+"-state", this, "_state"),
+ connect.subscribe(p.id+"-update", this, "_update")
+ ];
+ }
+ },
+
+ destroy: function(){
+ // summary: Unsubscribe to all of our topics
+ array.forEach(this._subscriptions, connect.unsubscribe);
+ this.inherited(arguments);
+ },
+
+ _state: function(/*boolean*/playing){
+ // summary: Updates the display of the play/pause button
+ if(this.playPause && this.playPause.checked != playing){
+ this.playPause.set("label", playing ? "Pause" : "Play");
+ this.playPause.set("checked", playing);
+ }
+ },
+
+ _update: function(/*boolean*/playing, /*int*/current, /*int*/total){
+ // summary: Updates the pager's play/pause button, current child, and total number of children.
+ this._state(playing);
+ if(this.current && current){
+ this.current.innerHTML = current;
+ }
+ if(this.total && total){
+ this.total.innerHTML = total;
+ }
+ }
+});
+return RotatorContainer;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/layout/ScrollPane.js b/js/dojo/dojox/layout/ScrollPane.js
new file mode 100644
index 0000000..edfe998
--- /dev/null
+++ b/js/dojo/dojox/layout/ScrollPane.js
@@ -0,0 +1,154 @@
+//>>built
+require({cache:{
+'url:dojox/layout/resources/ScrollPane.html':"<div class=\"dojoxScrollWindow\" dojoAttachEvent=\"onmouseenter: _enter, onmouseleave: _leave\">\n <div class=\"dojoxScrollWrapper\" style=\"${style}\" dojoAttachPoint=\"wrapper\" dojoAttachEvent=\"onmousemove: _calc\">\n\t<div class=\"dojoxScrollPane\" dojoAttachPoint=\"containerNode\"></div>\n </div>\n <div dojoAttachPoint=\"helper\" class=\"dojoxScrollHelper\"><span class=\"helperInner\">|</span></div>\n</div>"}});
+define("dojox/layout/ScrollPane", ["dojo/_base/kernel","dojo/_base/declare","dojo/_base/html","dojo/_base/fx",
+ "dijit/_Templated","dijit/layout/ContentPane","dojo/dom-class",
+ "dojo/text!./resources/ScrollPane.html"],
+function(kernel,declare,html,baseFx,Templated,ContentPane,domClass,template){
+
+kernel.experimental("dojox.layout.ScrollPane");
+
+// FIXME: need to adust the _line somehow, it stops scrolling
+
+/*=====
+ var ContentPane = dijit.layout.ContentPane,
+ Templated = dijit._Templated;
+=====*/
+
+declare("dojox.layout.ScrollPane",[ContentPane, Templated],{
+ // summary: A pane that "scrolls" its content based on the mouse poisition inside
+ //
+ // description:
+ // A sizable container that takes it's content's natural size and creates
+ // a scroll effect based on the relative mouse position. It is an interesting
+ // way to display lists of data, or blocks of content, within a confined
+ // space.
+ //
+ // Horizontal scrolling is supported. Combination scrolling is not.
+ //
+ // example:
+ // | <div dojoType="dojox.layout.ScrollPane" style="width:150px height:300px;">
+ // | <!-- any height content -->
+ // | </div>
+ //
+ // _line: dojo._Line
+ // storage for our top and bottom most scrollpoints
+ _line: null,
+
+ // _lo: the height of the visible pane
+ _lo: null,
+
+ _offset: 15,
+
+ // orientation: String
+ // either "horizontal" or "vertical" for scroll orientation.
+ orientation: "vertical",
+
+ // alwaysShow: Boolean
+ // whether the scroll helper should hide when mouseleave
+ autoHide: true,
+ templateString: template,
+
+ resize: function(size){
+ // summary: calculates required sizes. Call this if you add/remove content manually, or reload the content.
+
+ // if size is passed, it means we need to take care of sizing ourself (this is for IE<8)
+ if(size){
+ if(size.h){
+ html.style(this.domNode,'height',size.h+'px');
+ }
+ if(size.w){
+ html.style(this.domNode,'width',size.w+'px');
+ }
+ }
+ var dir = this._dir,
+ vert = this._vertical,
+ val = this.containerNode[(vert ? "scrollHeight" : "scrollWidth")];
+
+ html.style(this.wrapper, this._dir, this.domNode.style[this._dir]);
+ this._lo = html.coords(this.wrapper, true);
+
+ this._size = Math.max(0, val - this._lo[(vert ? "h" : "w")]);
+ if(!this._size){
+ this.helper.style.display="none";
+ //make sure we reset scroll position, otherwise the content may be hidden
+ this.wrapper[this._scroll]=0;
+ return;
+ }else{
+ this.helper.style.display="";
+ }
+ this._line = new baseFx._Line(0 - this._offset, this._size + (this._offset * 2));
+
+ // share a relative position w the scroll offset via a line
+ var u = this._lo[(vert ? "h" : "w")],
+ r = Math.min(1, u / val), // ratio
+ s = u * r, // size
+ c = Math.floor(u - (u * r)); // center
+
+ this._helpLine = new baseFx._Line(0, c);
+
+ // size the helper
+ html.style(this.helper, dir, Math.floor(s) + "px");
+
+ },
+
+ postCreate: function(){
+ this.inherited(arguments);
+ // for the helper
+ if(this.autoHide){
+ this._showAnim = baseFx._fade({ node:this.helper, end:0.5, duration:350 });
+ this._hideAnim = baseFx.fadeOut({ node:this.helper, duration: 750 });
+ }
+
+ // orientation helper
+ this._vertical = (this.orientation == "vertical");
+ if(!this._vertical){
+ domClass.add(this.containerNode,"dijitInline");
+ this._dir = "width";
+ this._edge = "left";
+ this._scroll = "scrollLeft";
+ }else{
+ this._dir = "height";
+ this._edge = "top";
+ this._scroll = "scrollTop";
+ }
+
+ if(this._hideAnim){
+ this._hideAnim.play();
+ }
+ html.style(this.wrapper,"overflow","hidden");
+
+ },
+
+ _set: function(/* Float */n){
+ if(!this._size){ return; }
+ // summary: set the pane's scroll offset, and position the virtual scroll helper
+ this.wrapper[this._scroll] = Math.floor(this._line.getValue(n));
+ html.style(this.helper, this._edge, Math.floor(this._helpLine.getValue(n)) + "px");
+ },
+
+ _calc: function(/* Event */e){
+ // summary: calculate the relative offset of the cursor over the node, and call _set
+ if(!this._lo){ this.resize(); }
+ this._set(this._vertical ?
+ ((e.pageY - this._lo.y) / this._lo.h) :
+ ((e.pageX - this._lo.x) / this._lo.w)
+ );
+ },
+
+ _enter: function(e){
+ if(this._hideAnim){
+ if(this._hideAnim.status() == "playing"){
+ this._hideAnim.stop();
+ }
+ this._showAnim.play();
+ }
+ },
+
+ _leave: function(e){
+ if(this._hideAnim){
+ this._hideAnim.play();
+ }
+ }
+});
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/layout/TableContainer.js b/js/dojo/dojox/layout/TableContainer.js
new file mode 100644
index 0000000..fddbf4b
--- /dev/null
+++ b/js/dojo/dojox/layout/TableContainer.js
@@ -0,0 +1,283 @@
+//>>built
+define("dojox/layout/TableContainer", ["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/declare", "dojo/dom-class", "dojo/dom-construct",
+ "dojo/_base/array", "dojo/dom-prop", "dojo/dom-style", "dijit/_WidgetBase", "dijit/layout/_LayoutWidget"],
+function(kernel, lang, declare, domClass, domConstruct, arrayUtil, domProp, domStyle, _WidgetBase, _LayoutWidget){
+
+kernel.experimental("dojox.layout.TableContainer");
+
+/*===== var LayoutWidget = dijit.layout._LayoutWidget; =====*/
+var TableContainer = declare("dojox.layout.TableContainer", _LayoutWidget, {
+ // summary:
+ // A container that lays out its child widgets in a table layout.
+ //
+ // description:
+ // The TableContainer lays out child widgets in a Table layout.
+ // Each widget can specify a "label" or a "title" parameter.
+ // This label is displayed either above or to the left of
+ // a widget depending on whether the "orientation" attribute
+ // is "horiz" or "vert", for horizontal and vertical respectively.
+ // The number of columns is configured using the "cols" attribute.
+ // The width of labels can be configured using the "labelWidth" parameter.
+ //
+ // example:
+ // | <div dojoType="dojox.layout.TableContainer" orientation="vert" cols="3>
+ // | <div dojoType="dijit.form.TextInput" value="John" label="First Name:"></div>
+ // | <div dojoType="dijit.form.CheckBox" label="Is Student?:"></div>
+ // | <div dojoType="dojox.form.DateTextBox" label="Date Of Birth:"></div>
+ // | </div>
+ //
+
+ cols: 1,
+
+ // labelWidth: Number|String
+ // Defines the width of a label. If the value is a number, it is
+ // treated as a pixel value. The other valid value is a percentage,
+ // e.g. "50%"
+ labelWidth: "100",
+
+ // showLabels: Boolean
+ // True if labels should be displayed, false otherwise.
+ showLabels: true,
+
+ // orientation: String
+ // Either "horiz" or "vert" for label orientation.
+ orientation: "horiz",
+
+ // spacing: Number
+ // The cell spacing to apply to the table.
+ spacing: 1,
+
+ // customClass: String
+ // A CSS class that will be applied to child elements. For example, if
+ // the class is "myClass", the table will have "myClass-table" applied to it,
+ // each label TD will have "myClass-labelCell" applied, and each
+ // widget TD will have "myClass-valueCell" applied.
+ customClass: "",
+
+ postCreate: function(){
+ this.inherited(arguments);
+ this._children = [];
+
+ // If the orientation, customClass or cols attributes are changed,
+ // layout the widgets again.
+ this.connect(this, "set", function(name, value){
+ if(value && (name == "orientation" || name == "customClass" || name == "cols")) {
+ this.layout();
+ }
+ });
+ },
+
+ startup: function() {
+ if(this._started) {
+ return;
+ }
+ this.inherited(arguments);
+ if(this._initialized) {
+ return;
+ }
+ var children = this.getChildren();
+ if(children.length < 1) {
+ return;
+ }
+ this._initialized = true;
+
+ domClass.add(this.domNode, "dijitTableLayout");
+
+ // Call startup on all child widgets
+ arrayUtil.forEach(children, function(child){
+ if(!child.started && !child._started) {
+ child.startup();
+ }
+ });
+ this.resize();
+ this.layout();
+ },
+
+ resize: function(){
+ // summary:
+ // Resizes all children. This widget itself
+ // does not resize, as it takes up 100% of the
+ // available width.
+ arrayUtil.forEach(this.getChildren(), function(child){
+ if(typeof child.resize == "function") {
+ child.resize();
+ }
+ });
+ },
+
+ layout: function(){
+ // summary:
+ // Lays out the child widgets.
+ if(!this._initialized){
+ return;
+ }
+
+ var children = this.getChildren();
+
+ var childIds = {};
+ var _this = this;
+
+ function addCustomClass(node, type, count) {
+ if(_this.customClass != "") {
+ var clazz = _this.customClass+ "-" + (type || node.tagName.toLowerCase());
+ domClass.add(node, clazz);
+
+ if(arguments.length > 2) {
+ domClass.add(node, clazz + "-" + count);
+ }
+ }
+ }
+
+ // Find any new children that have been added since the last layout() call
+ arrayUtil.forEach(this._children, lang.hitch(this, function(child){
+ childIds[child.id] = child;
+ }));
+
+ arrayUtil.forEach(children, lang.hitch(this, function(child, index){
+ if(!childIds[child.id]) {
+ // Add pre-existing children to the start of the array
+ this._children.push(child);
+ }
+ }));
+
+ // Create the table. It fills the width of it's container.
+ var table = domConstruct.create("table", {
+ "width": "100%",
+ "class": "tableContainer-table tableContainer-table-" + this.orientation,
+ "cellspacing" : this.spacing
+ },
+ this.domNode);
+
+ var tbody = domConstruct.create("tbody");
+ table.appendChild(tbody);
+
+ addCustomClass(table, "table", this.orientation);
+
+ var width = Math.floor(100 / this.cols) + "%";
+
+ var labelRow = domConstruct.create("tr", {}, tbody);
+ var childRow = (!this.showLabels || this.orientation == "horiz")
+ ? labelRow : domConstruct.create("tr", {}, tbody);
+ var maxCols = this.cols * (this.showLabels ? 2 : 1);
+ var numCols = 0;
+
+ // Iterate over the children, adding them to the table.
+ arrayUtil.forEach(this._children, lang.hitch(this, function(child, index){
+
+ var colspan = child.colspan || 1;
+
+ if(colspan > 1) {
+ colspan = this.showLabels ?
+ Math.min(maxCols - 1, colspan * 2 -1): Math.min(maxCols, colspan);
+ }
+
+ // Create a new row if we need one
+ if(numCols + colspan - 1 + (this.showLabels ? 1 : 0)>= maxCols) {
+ numCols = 0;
+ labelRow = domConstruct.create("tr", {}, tbody);
+ childRow = this.orientation == "horiz" ? labelRow : domConstruct.create("tr", {}, tbody);
+ }
+ var labelCell;
+
+ // If labels should be visible, add them
+ if(this.showLabels) {
+ labelCell = domConstruct.create("td", {"class": "tableContainer-labelCell"}, labelRow);
+
+ // If the widget should take up both the label and value,
+ // then just set the class on it.
+ if(child.spanLabel) {
+ domProp.set(labelCell, this.orientation == "vert" ? "rowspan" : "colspan", 2);
+ }
+ else {
+ // Add the custom label class to the label cell
+ addCustomClass(labelCell, "labelCell");
+ var labelProps = {"for": child.get("id")};
+ var label = domConstruct.create("label", labelProps, labelCell);
+
+ if(Number(this.labelWidth) > -1 ||
+ String(this.labelWidth).indexOf("%") > -1) {
+
+ // Set the width of the label cell with either a pixel or percentage value
+ domStyle.set(labelCell, "width",
+ String(this.labelWidth).indexOf("%") < 0
+ ? this.labelWidth + "px" : this.labelWidth);
+ }
+
+ label.innerHTML = child.get("label") || child.get("title");
+ }
+ }
+ var childCell;
+
+ if(child.spanLabel && labelCell) {
+ childCell = labelCell;
+ } else {
+ childCell = domConstruct.create("td", {
+ "class" : "tableContainer-valueCell"
+ }, childRow);
+ }
+ if(colspan > 1) {
+ domProp.set(childCell, "colspan", colspan);
+ }
+
+ // Add the widget cell's custom class, if one exists.
+ addCustomClass(childCell, "valueCell", index);
+
+ childCell.appendChild(child.domNode);
+ numCols += colspan + (this.showLabels ? 1 : 0);
+ }));
+
+ if(this.table) {
+ this.table.parentNode.removeChild(this.table);
+ }
+ // Refresh the layout of any child widgets, allowing them to resize
+ // to their new parent.
+ arrayUtil.forEach(children, function(child){
+ if(typeof child.layout == "function") {
+ child.layout();
+ }
+ });
+ this.table = table;
+ this.resize();
+ },
+
+ destroyDescendants: function(/*Boolean*/ preserveDom){
+ // summary:
+ // Destroys all the widgets inside this.containerNode,
+ // but not this widget itself
+ arrayUtil.forEach(this._children, function(child){ child.destroyRecursive(preserveDom); });
+ },
+
+ _setSpacingAttr: function(value) {
+ // summary:
+ // Sets the spacing attribute.
+ this.spacing = value;
+ if(this.table) {
+ this.table.cellspacing = Number(value);
+ }
+ }
+});
+
+// Extend the default widget with both label and title elements, as
+// well as a "spanLabel" attribute. If a widget
+lang.extend(_WidgetBase, {
+ // label: String
+ // The label to display for a given widget
+ label: "",
+
+ // title: String
+ // The label to display for a given widget. This is interchangeable
+ // with the 'label' parameter, as some widgets already have a use
+ // for the 'label', and this can be used instead to avoid conflicts.
+ title: "",
+
+ // spanLabel: Boolean
+ // Setting spanLabel to true makes the widget take up both the
+ // label and value cells. Defaults to false.
+ spanLabel: false,
+
+ // colspan: Number
+ // The number of columns this widget should span.
+ colspan: 1
+});
+return TableContainer;
+});
diff --git a/js/dojo/dojox/layout/ToggleSplitter.js b/js/dojo/dojox/layout/ToggleSplitter.js
new file mode 100644
index 0000000..40f0383
--- /dev/null
+++ b/js/dojo/dojox/layout/ToggleSplitter.js
@@ -0,0 +1,296 @@
+//>>built
+define("dojox/layout/ToggleSplitter", ["dojo", "dijit", "dijit/layout/BorderContainer"], function(dojo, dijit) {
+
+dojo.experimental("dojox.layout.ToggleSplitter");
+
+dojo.declare("dojox.layout.ToggleSplitter", dijit.layout._Splitter, {
+ // summary:
+ // A draggable and clickable spacer between two items in a dijit.layout.BorderContainer`.
+ // description:
+ // This is instantiated by `dijit.layout.BorderContainer. Users should not
+ // create it directly.
+ // tags:
+ // private
+
+/*=====
+ // container: [const] dijit.layout.BorderContainer
+ // Pointer to the parent BorderContainer
+ container: null,
+
+ // child: [const] dijit.layout._LayoutWidget
+ // Pointer to the pane associated with this splitter
+ child: null,
+
+ // region: [const] String
+ // Region of pane associated with this splitter.
+ // "top", "bottom", "left", "right".
+ region: null,
+=====*/
+
+ // state: String
+ // the initial and current state of the splitter (and its attached pane)
+ // It has three values: full, collapsed (optional), closed
+ state: "full",
+
+ // _closedSize: String
+ // the css height/width value to apply by default when the attached pane is closed
+ _closedSize: "0",
+
+ baseClass: "dojoxToggleSplitter",
+
+ templateString: '<div class="dijitSplitter dojoxToggleSplitter" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_startDrag,onmouseenter:_onMouse,onmouseleave:_onMouse">' +
+ '<div dojoAttachPoint="toggleNode" class="dijitSplitterThumb dojoxToggleSplitterIcon" tabIndex="0" role="separator" ' +
+ 'dojoAttachEvent="onmousedown:_onToggleNodeMouseDown,onclick:_toggle,onmouseenter:_onToggleNodeMouseMove,onmouseleave:_onToggleNodeMouseMove,onfocus:_onToggleNodeMouseMove,onblur:_onToggleNodeMouseMove">' +
+ '<span class="dojoxToggleSplitterA11y" dojoAttachPoint="a11yText"></span></div>' +
+ '</div>',
+
+ postCreate: function(){
+ this.inherited(arguments);
+
+ // add a region css hook so that it can figure out the region correctly
+ var region = this.region;
+ dojo.addClass(this.domNode, this.baseClass + region.charAt(0).toUpperCase() + region.substring(1));
+ },
+
+ startup: function(){
+ this.inherited(arguments);
+
+ // we have to wait until startup to be sure the child exists in the dom
+ // and has non-zero size (if its supposed to be showing)
+ var parentPane = this.child,
+ paneNode = this.child.domNode,
+ intPaneSize = dojo.style(paneNode, (this.horizontal ? "height" : "width"));
+
+ this.domNode.setAttribute("aria-controls", paneNode.id);
+
+ // creation of splitters is an opaque process in BorderContainer,
+ // so if we want to get init params, we have to retrieve them from the attached BC child
+ // NOTE: for this to work we have to extend the prototype of dijit._Widget (some more)
+ dojo.forEach(["toggleSplitterState", "toggleSplitterFullSize", "toggleSplitterCollapsedSize"], function(name){
+ var pname = name.substring("toggleSplitter".length);
+ pname = pname.charAt(0).toLowerCase() + pname.substring(1);
+ if(name in this.child){
+ this[pname] = this.child[name];
+ }
+ }, this);
+
+ if(!this.fullSize){
+ // Store the current size as the fullSize if none was provided
+ // dojo.style always returns a integer (pixel) value for height/width
+ // use an arbitrary default if a pane was initialized closed and no fullSize provided
+ // If collapsedSize is not specified, collapsed state does not exist.
+ this.fullSize = this.state == "full" ? intPaneSize + "px" : "75px";
+ }
+
+ this._openStyleProps = this._getStyleProps(paneNode, "full");
+
+ // update state
+ this._started = true;
+ this.set("state", this.state);
+
+ return this;
+ },
+
+ _onKeyPress: function(evt){
+ if(this.state == "full"){
+ this.inherited(arguments);
+ }
+ if(evt.charCode == dojo.keys.SPACE || evt.keyCode == dojo.keys.ENTER){
+ this._toggle(evt);
+ }
+ },
+
+ _onToggleNodeMouseDown: function(evt){
+ dojo.stopEvent(evt);
+ this.toggleNode.focus();
+ },
+
+ _startDrag: function(e){
+ if(this.state == "full"){
+ this.inherited(arguments);
+ }
+ },
+
+ _stopDrag: function(e){
+ this.inherited(arguments);
+ this.toggleNode.blur();
+ },
+
+ _toggle: function(evt){
+ var state;
+ switch(this.state){
+ case "full":
+ state = this.collapsedSize ? "collapsed" : "closed";
+ break;
+ case "collapsed":
+ state = "closed";
+ break;
+ default:
+ state = "full";
+ }
+ this.set("state", state);
+ },
+
+ _onToggleNodeMouseMove: function(evt){
+ var baseClass = this.baseClass,
+ toggleNode = this.toggleNode,
+ on = this.state == "full" || this.state == "collapsed",
+ leave = evt.type == "mouseout" || evt.type == "blur";
+
+ dojo.toggleClass(toggleNode, baseClass + "IconOpen", leave && on);
+ dojo.toggleClass(toggleNode, baseClass + "IconOpenHover", !leave && on);
+ dojo.toggleClass(toggleNode, baseClass + "IconClosed", leave && !on);
+ dojo.toggleClass(toggleNode, baseClass + "IconClosedHover", !leave && !on);
+ },
+
+ _handleOnChange: function(preState){
+ // summary
+ // Effect the state change with the new value of this.state
+ var paneNode = this.child.domNode,
+ openProps, paneStyle,
+ dim = this.horizontal ? "height" : "width";
+
+ if(this.state == "full"){
+ // change to full open state
+ var styleProps = dojo.mixin({
+ display: "block",
+ overflow: "auto",
+ visibility: "visible"
+ }, this._openStyleProps);
+ styleProps[dim] = (this._openStyleProps && this._openStyleProps[dim]) ? this._openStyleProps[dim] : this.fullSize;
+
+ dojo.style(this.domNode, "cursor", "");
+ dojo.style(paneNode, styleProps);
+ }else if(this.state == "collapsed"){
+ paneStyle = dojo.getComputedStyle(paneNode);
+ openProps = this._getStyleProps(paneNode, "full", paneStyle);
+ this._openStyleProps = openProps;
+
+ dojo.style(this.domNode, "cursor", "auto");
+ dojo.style(paneNode, dim, this.collapsedSize);
+ }else{
+ // change to closed state
+ if(!this.collapsedSize){
+ paneStyle = dojo.getComputedStyle(paneNode);
+ openProps = this._getStyleProps(paneNode, "full", paneStyle);
+ this._openStyleProps = openProps;
+ }
+ var closedProps = this._getStyleProps(paneNode, "closed", paneStyle);
+
+ dojo.style(this.domNode, "cursor", "auto");
+ dojo.style(paneNode, closedProps);
+ }
+ this._setStateClass();
+ if(this.container._started){
+ this.container._layoutChildren(this.region);
+ }
+ },
+
+ _getStyleProps: function(paneNode, state, paneStyle){
+ // summary:
+ // Create an object with the style property name: values
+ // that will need to be applied to the child pane render the given state
+ if(!paneStyle){
+ paneStyle = dojo.getComputedStyle(paneNode);
+ }
+ var styleProps = {},
+ dim = this.horizontal ? "height" : "width";
+
+ styleProps["overflow"] = (state != "closed") ? paneStyle["overflow"] : "hidden";
+ styleProps["visibility"] = (state != "closed") ? paneStyle["visibility"] : "hidden";
+
+ // Use the inline width/height style value, in preference to the computedStyle
+ // for the open width/height
+ styleProps[dim] = (state != "closed") ? paneNode.style[dim] || paneStyle[dim] : this._closedSize;
+
+ // We include the padding, border, margin width values for restoring on state full open
+ var edgeNames = ["Top", "Right", "Bottom", "Left"];
+ dojo.forEach(["padding", "margin", "border"], function(pname){
+ for(var i = 0; i < edgeNames.length; i++){
+ var fullName = pname + edgeNames[i];
+ if(pname == "border"){
+ fullName += "Width";
+ }
+ if(undefined !== paneStyle[fullName]){
+ styleProps[fullName] = (state != "closed") ? paneStyle[fullName] : 0;
+ }
+ }
+ });
+
+ return styleProps;
+ },
+
+ _setStateClass: function(){
+ // Summary:
+ // Apply the appropriate classes for the current open state
+ var arrow = "&#9652", region = this.region.toLowerCase(),
+ baseClass = this.baseClass,
+ toggleNode = this.toggleNode,
+ on = this.state == "full" || this.state == "collapsed",
+ focused = this.focused;
+
+ dojo.toggleClass(toggleNode, baseClass + "IconOpen", on && !focused);
+ dojo.toggleClass(toggleNode, baseClass + "IconClosed", !on && !focused);
+ dojo.toggleClass(toggleNode, baseClass + "IconOpenHover", on && focused);
+ dojo.toggleClass(toggleNode, baseClass + "IconClosedHover", !on && focused);
+
+ // For a11y
+ if(region == "top" && on || region == "bottom" && !on){
+ arrow = "&#9650";
+ }else if(region == "top" && !on || region == "bottom" && on){
+ arrow = "&#9660";
+ }else if(region == "right" && on || region == "left" && !on){
+ arrow = "&#9654";
+ }else if(region == "right" && !on || region == "left" && on){
+ arrow = "&#9664";
+ }
+
+ this.a11yText.innerHTML = arrow;
+ },
+
+ _setStateAttr: function(/*Strring*/ state){
+ // summary:
+ // setter for the state property
+ if(!this._started) {
+ return;
+ }
+ var preState = this.state;
+ this.state = state;
+
+ this._handleOnChange(preState);
+ var evtName;
+ switch(state){
+ case "full":
+ this.domNode.setAttribute("aria-expanded", true);
+ evtName = "onOpen";
+ break;
+ case "collapsed":
+ this.domNode.setAttribute("aria-expanded", true);
+ evtName = "onCollapsed";
+ break;
+ default:
+ this.domNode.setAttribute("aria-expanded", false);
+ evtName = "onClosed";
+ }
+ this[evtName](this.child);
+ },
+
+ onOpen: function(pane){ /*Stub*/ },
+ onCollapsed: function(pane){ /*Stub*/ },
+ onClosed: function(pane){ /*Stub*/ }
+});
+
+// As BC places no constraints on what kind of widgets can be children
+// we have to extend the base class to ensure the properties we need can be set (both in markup and programatically)
+dojo.extend(dijit._Widget, {
+ // toggleSplitterOpen: Boolean
+ toggleSplitterState: "full",
+
+ // toggleSplitterClosedThreshold: String
+ // A css size value (e.g. "100px")
+ toggleSplitterFullSize: "",
+
+ toggleSplitterCollapsedSize: ""
+});
+
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/layout/dnd/Avatar.js b/js/dojo/dojox/layout/dnd/Avatar.js
new file mode 100644
index 0000000..e8be1fb
--- /dev/null
+++ b/js/dojo/dojox/layout/dnd/Avatar.js
@@ -0,0 +1,51 @@
+//>>built
+// wrapped by build app
+define("dojox/layout/dnd/Avatar", ["dijit","dojo","dojox","dojo/require!dojo/dnd/Avatar,dojo/dnd/common"], function(dijit,dojo,dojox){
+dojo.provide("dojox.layout.dnd.Avatar");
+
+dojo.require("dojo.dnd.Avatar");
+dojo.require("dojo.dnd.common");
+
+dojo.declare("dojox.layout.dnd.Avatar", dojo.dnd.Avatar, {
+ // summary:
+ // An Object, which represents the object being moved in a GridContainer
+ constructor: function(manager, opacity){
+ this.opacity = opacity || 0.9;
+ },
+
+ construct: function(){
+ // summary:
+ // A constructor function. it is separate so it can be (dynamically)
+ // overwritten in case of need.
+
+ var source = this.manager.source,
+ node = source.creator ?
+ // create an avatar representation of the node
+ source._normalizedCreator(source.getItem(this.manager.nodes[0].id).data, "avatar").node :
+ // or just clone the node and hope it works
+ this.manager.nodes[0].cloneNode(true)
+ ;
+
+ dojo.addClass(node, "dojoDndAvatar");
+
+ node.id = dojo.dnd.getUniqueId();
+ node.style.position = "absolute";
+ node.style.zIndex = 1999;
+ node.style.margin = "0px"
+ node.style.width = dojo.marginBox(source.node).w + "px"
+
+ // add contructor object params to define it
+ dojo.style(node, "opacity", this.opacity);
+ this.node = node;
+ },
+
+ update: function(){
+ // summary: Updates the avatar to reflect the current DnD state.
+ dojo.toggleClass(this.node, "dojoDndAvatarCanDrop", this.manager.canDropFlag);
+ },
+
+ _generateText: function(){ /* nada. */ }
+
+});
+
+});
diff --git a/js/dojo/dojox/layout/dnd/PlottedDnd.js b/js/dojo/dojox/layout/dnd/PlottedDnd.js
new file mode 100644
index 0000000..b53e090
--- /dev/null
+++ b/js/dojo/dojox/layout/dnd/PlottedDnd.js
@@ -0,0 +1,519 @@
+//>>built
+// wrapped by build app
+define("dojox/layout/dnd/PlottedDnd", ["dijit","dojo","dojox","dojo/require!dojo/dnd/Source,dojo/dnd/Manager,dojox/layout/dnd/Avatar"], function(dijit,dojo,dojox){
+dojo.provide("dojox.layout.dnd.PlottedDnd");
+
+dojo.require("dojo.dnd.Source");
+dojo.require("dojo.dnd.Manager");
+dojo.require("dojox.layout.dnd.Avatar");
+
+dojo.declare("dojox.layout.dnd.PlottedDnd", [dojo.dnd.Source], {
+ // summary:
+ // dnd source handling plotted zone to show the dropping area
+ GC_OFFSET_X: dojo.dnd.manager().OFFSET_X,
+ GC_OFFSET_Y: dojo.dnd.manager().OFFSET_Y,
+
+ constructor: function(/*Node*/node, /*Object*/params){
+
+ this.childBoxes = null;
+ this.dropIndicator = new dojox.layout.dnd.DropIndicator("dndDropIndicator", "div");
+ this.withHandles = params.withHandles;
+ this.handleClasses = params.handleClasses;
+ this.opacity = params.opacity;
+ this.allowAutoScroll = params.allowAutoScroll;//MODIF MYS
+ this.dom = params.dom;
+ this.singular = true;
+ this.skipForm = true;
+ this._over = false;
+ this.defaultHandleClass = "GcDndHandle";
+ this.isDropped = false;
+ this._timer = null;
+ //Initialize the params to calculate offset
+ this.isOffset = (params.isOffset)?true:false;
+ this.offsetDrag = (params.offsetDrag) ? params.offsetDrag : {x:0,y:0};
+ this.hideSource = params.hideSource ? params.hideSource : true;
+ this._drop = this.dropIndicator.create();
+
+ },
+
+ _calculateCoords : function(/*Boolean*/height){
+ // summary: Calculate each position of children
+ dojo.forEach(this.node.childNodes, function(child){
+ var c = dojo.coords(child, true);
+ child.coords = {
+ xy: c,
+ w: child.offsetWidth / 2,
+ h: child.offsetHeight / 2,
+ mw: c.w
+ };
+ if(height){
+ child.coords.mh = c.h;
+ }
+ }, this);
+ },
+
+ _legalMouseDown: function(/*Event*/e){
+ // summary: Checks if user clicked on "approved" items.
+ if(!this.withHandles){ return true; }
+ for(var node = (e.target); node && node != this.node; node = node.parentNode){
+ if(dojo.hasClass(node, this.defaultHandleClass)){
+ return true;
+ }
+ }
+ return false; // Boolean
+ },
+
+ setDndItemSelectable: function(/*Node*/node, /*Boolean*/isSelectable) {
+ // summary: set an item as selectable
+ for(var _node = node; _node && node != this.node; _node = _node.parentNode) {
+ if (dojo.hasClass(_node,"dojoDndItem")) {
+ dojo.setSelectable(_node, isSelectable);
+ return;
+ }
+ }
+ },
+
+ getDraggedWidget: function(/*Node*/node) {
+ // summary: Return one or more widget selected during the drag.
+ var _node = node;
+ while (_node && _node.nodeName.toLowerCase()!="body" && !dojo.hasClass(_node,"dojoDndItem")) {
+ _node = _node.parentNode;
+ }
+ return (_node) ? dijit.byNode(_node) : null;
+ },
+
+ isAccepted: function(/*Node*/ node) {
+ // summary: test if this node can be accepted
+ var _dndType = (node) ? node.getAttribute("dndtype") : null;
+ return (_dndType && _dndType in this.accept);
+ },
+
+ onDndStart:function(/*Object*/source, /*Array*/nodes, /*Object*/copy){
+ // summary: Called to initiate the DnD operation.
+
+ this.firstIndicator = (source == this);
+ this._calculateCoords(true);
+ //this.isDropped = true;
+ var m = dojo.dnd.manager();
+ if(nodes[0].coords){
+ this._drop.style.height = nodes[0].coords.mh + "px";
+ dojo.style(m.avatar.node, "width", nodes[0].coords.mw + "px");
+ }else{
+ this._drop.style.height = m.avatar.node.clientHeight+"px";
+ }
+ this.dndNodes = nodes;
+ dojox.layout.dnd.PlottedDnd.superclass.onDndStart.call(this,source, nodes, copy);
+ if(source == this && this.hideSource){
+ dojo.forEach(nodes, function(n){
+ dojo.style(n, "display","none");
+ });
+ }
+
+ },
+
+ onDndCancel:function(){
+ // summary: Called to cancel the DnD operation.
+ var m = dojo.dnd.manager();
+ if(m.source == this && this.hideSource){
+ var nodes = this.getSelectedNodes();
+ dojo.forEach(nodes, function(n){
+ dojo.style(n, "display","");
+ });
+ }
+ dojox.layout.dnd.PlottedDnd.superclass.onDndCancel.call(this);
+ this.deleteDashedZone();
+ },
+
+ onDndDrop: function(source,nodes,copy,target) {
+ // summary: Called to finish the DnD operation
+ try{
+ if(!this.isAccepted(nodes[0])){
+ this.onDndCancel();
+ }else{
+ if(source == this && this._over && this.dropObject){
+ this.current = this.dropObject.c;
+ }
+ dojox.layout.dnd.PlottedDnd.superclass.onDndDrop.call(this, source, nodes, copy, target);
+ this._calculateCoords(true);
+ }
+ }catch(e){
+ console.warn(e);
+ }
+ },
+
+ onMouseDown: function(/*Event*/e) {
+ // summary: Event processor for onmousedown.
+ if(this.current == null){
+ this.selection = {};
+ }else{
+ if(this.current == this.anchor){
+ this.anchor = null;
+ }
+ }
+ if(this.current !== null){
+ var c = dojo.coords(this.current, true);
+ this.current.coords = {
+ xy: c,
+ w: this.current.offsetWidth / 2,
+ h: this.current.offsetHeight / 2,
+ mh: c.h,
+ mw: c.w
+ };
+ this._drop.style.height = this.current.coords.mh + "px";
+
+ if(this.isOffset){
+ if(this.offsetDrag.x == 0 && this.offsetDrag.y == 0){
+ var NoOffsetDrag = true;
+ var coords = dojo.coords(this._getChildByEvent(e));
+ this.offsetDrag.x = coords.x - e.pageX;
+ this.offsetDrag.y = coords.y - e.clientY;
+ }
+ if(this.offsetDrag.y < 16 && this.current != null){
+ this.offsetDrag.y = this.GC_OFFSET_Y;
+ }
+
+ var m = dojo.dnd.manager();
+ m.OFFSET_X = this.offsetDrag.x;
+ m.OFFSET_Y = this.offsetDrag.y;
+ if (NoOffsetDrag) {
+ this.offsetDrag.x = 0;
+ this.offsetDrag.y = 0;
+ }
+ }
+ }
+
+ if(dojo.dnd.isFormElement(e)){
+ this.setDndItemSelectable(e.target,true);
+ }else{
+ this.containerSource = true;
+ var _draggedWidget = this.getDraggedWidget(e.target);
+ if(_draggedWidget && _draggedWidget.dragRestriction){
+ // FIXME: not clear what this was supposed to mean ... this code needs more cleanups.
+ // dragRestriction = true;
+ }else{
+ dojox.layout.dnd.PlottedDnd.superclass.onMouseDown.call(this,e);
+ }
+ }
+ },
+
+ onMouseUp: function(/*Event*/e) {
+ // summary: Event processor for onmouseup.
+ dojox.layout.dnd.PlottedDnd.superclass.onMouseUp.call(this,e);
+ this.containerSource = false;
+ if (!dojo.isIE && this.mouseDown){
+ this.setDndItemSelectable(e.target,true);
+ }
+ var m = dojo.dnd.manager();
+ m.OFFSET_X = this.GC_OFFSET_X;
+ m.OFFSET_Y = this.GC_OFFSET_Y;
+ },
+
+ onMouseMove: function(e) {
+ // summary: Event processor for onmousemove
+ var m = dojo.dnd.manager();
+ if(this.isDragging) {
+ var before = false;
+ if(this.current != null || (this.current == null && !this.dropObject)){
+ if(this.isAccepted(m.nodes[0]) || this.containerSource){
+ before = this.setIndicatorPosition(e);
+ }
+ }
+ if(this.current != this.targetAnchor || before != this.before){
+ this._markTargetAnchor(before);
+ m.canDrop(!this.current || m.source != this || !(this.current.id in this.selection));
+ }
+
+ if(this.allowAutoScroll){
+ this._checkAutoScroll(e);
+ }
+ }else{
+ if(this.mouseDown && this.isSource){
+ var nodes = this.getSelectedNodes();
+ if(nodes.length){
+ m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e)));
+ }
+ }
+
+ if(this.allowAutoScroll){
+ this._stopAutoScroll();
+ }
+ }
+ },
+
+ _markTargetAnchor: function(/*Boolean*/before){
+ // summary: Assigns a class to the current target anchor based on "before" status
+ if(this.current == this.targetAnchor && this.before == before){ return; }
+ this.targetAnchor = this.current;
+ this.targetBox = null;
+ this.before = before;
+ },
+
+ _unmarkTargetAnchor: function(){
+ // summary: Removes a class of the current target anchor based on "before" status.
+ if(!this.targetAnchor){ return; }
+ this.targetAnchor = null;
+ this.targetBox = null;
+ this.before = true;
+ },
+
+ setIndicatorPosition: function(/*Event*/e) {
+ // summary: set the position of the drop indicator
+ var before = false;
+ if(this.current){
+ if (!this.current.coords || this.allowAutoScroll) {
+ this.current.coords = {
+ xy: dojo.coords(this.current, true),
+ w: this.current.offsetWidth / 2,
+ h: this.current.offsetHeight / 2
+ };
+ }
+ before = this.horizontal ?
+ (e.pageX - this.current.coords.xy.x) < this.current.coords.w :
+ (e.pageY - this.current.coords.xy.y) < this.current.coords.h
+ this.insertDashedZone(before);
+ }else{
+ if(!this.dropObject /*|| dojo.isIE*/){ this.insertDashedZone(false); }
+ }
+ return before;
+ },
+
+
+ onOverEvent:function(){
+ this._over = true;
+ dojox.layout.dnd.PlottedDnd.superclass.onOverEvent.call(this);
+ if (this.isDragging) {
+ var m = dojo.dnd.manager();
+ if (!this.current && !this.dropObject && this.getSelectedNodes()[0] && this.isAccepted(m.nodes[0]))
+ this.insertDashedZone(false);
+ }
+ },
+
+ onOutEvent: function() {
+ this._over = false;
+ this.containerSource = false;
+ dojox.layout.dnd.PlottedDnd.superclass.onOutEvent.call(this);
+ if (this.dropObject) this.deleteDashedZone();
+ },
+
+ deleteDashedZone: function() {
+ // summary: hide the dashed zone
+ this._drop.style.display = "none";
+ var next = this._drop.nextSibling;
+ while (next != null) {
+ next.coords.xy.y -= parseInt(this._drop.style.height);
+ next = next.nextSibling;
+ }
+ delete this.dropObject;
+ },
+
+ insertDashedZone: function(/*Boolean*/before) {
+ // summary: Insert the dashed zone at the right place
+ if(this.dropObject){
+ if( before == this.dropObject.b &&
+ ((this.current && this.dropObject.c == this.current.id) ||
+ (!this.current && !this.dropObject.c))
+ ){
+ return;
+ }else{
+ this.deleteDashedZone();
+ }
+ }
+ this.dropObject = { n: this._drop, c: this.current ? this.current.id : null, b: before};
+ if(this.current){
+ dojo.place(this._drop, this.current, before ? "before" : "after");
+ if(!this.firstIndicator){
+ var next = this._drop.nextSibling;
+ while(next != null){
+ next.coords.xy.y += parseInt(this._drop.style.height);
+ next = next.nextSibling;
+ }
+ }else{
+ this.firstIndicator = false;
+ }
+ }else{
+ this.node.appendChild(this._drop);
+ }
+ this._drop.style.display = "";
+ },
+
+ insertNodes: function(/*Boolean*/addSelected, /*Array*/data, /*Boolean*/before, /*Node*/anchor){
+ // summary: Inserts new data items (see Dojo Container's insertNodes method for details).
+ if(this.dropObject){
+ dojo.style(this.dropObject.n,"display","none");
+ dojox.layout.dnd.PlottedDnd.superclass.insertNodes.call(this,true,data,true,this.dropObject.n);
+ this.deleteDashedZone();
+ }else{
+ return dojox.layout.dnd.PlottedDnd.superclass.insertNodes.call(this,addSelected,data,before,anchor);
+ }
+ var _widget = dijit.byId(data[0].getAttribute("widgetId"));
+ if (_widget) {
+ dojox.layout.dnd._setGcDndHandle(_widget, this.withHandles, this.handleClasses);
+ if(this.hideSource)
+ dojo.style(_widget.domNode, "display", "");
+ }
+ },
+
+ _checkAutoScroll: function(e){
+ if(this._timer){
+ clearTimeout(this._timer);
+ }
+ this._stopAutoScroll();
+ var node = this.dom,
+ y = this._sumAncestorProperties(node,"offsetTop")
+ ;
+ //Down
+ if( (e.pageY - node.offsetTop +30 ) > node.clientHeight ){
+ this.autoScrollActive = true;
+ this._autoScrollDown(node);
+ } else if ( (node.scrollTop > 0) && (e.pageY - y) < 30){
+ //Up
+ this.autoScrollActive = true;
+ this._autoScrollUp(node);
+ }
+ },
+
+ _autoScrollUp: function(node){
+ if( this.autoScrollActive && node.scrollTop > 0) {
+ node.scrollTop -= 30;
+ this._timer = setTimeout(dojo.hitch(this,"_autoScrollUp",node), 100);
+ }
+ },
+
+ _autoScrollDown: function(node){
+ if( this.autoScrollActive && (node.scrollTop < (node.scrollHeight-node.clientHeight))){
+ node.scrollTop += 30;
+ this._timer = setTimeout(dojo.hitch(this, "_autoScrollDown",node), 100);
+ }
+ },
+
+ _stopAutoScroll: function(){
+ this.autoScrollActive = false;
+ },
+
+ _sumAncestorProperties: function(node, prop){
+ // summary
+ // Returns the sum of the passed property on all ancestors of node.
+ node = dojo.byId(node);
+ if(!node){ return 0; }
+
+ var retVal = 0;
+ while(node){
+ var val = node[prop];
+ if(val){
+ retVal += val - 0;
+ if(node == dojo.body()){ break; }// opera and khtml #body & #html has the same values, we only need one value
+ }
+ node = node.parentNode;
+ }
+ return retVal; // integer
+ }
+
+});
+
+dojox.layout.dnd._setGcDndHandle = function(service,withHandles,handleClasses, first) {
+ var cls = "GcDndHandle";
+ if(!first){
+ dojo.query(".GcDndHandle", service.domNode).removeClass(cls);
+ }
+ if(!withHandles){
+ dojo.addClass(service.domNode, cls);
+ }else{
+ var _hasHandle = false;
+ for(var i = handleClasses.length - 1; i >= 0; i--){
+ var _node = dojo.query("." + handleClasses[i], service.domNode)[0];
+ if(_node){
+ _hasHandle = true;
+ if(handleClasses[i] != cls){
+ var _gripNode = dojo.query("." + cls, service.domNode);
+ if(_gripNode.length == 0){
+ dojo.removeClass(service.domNode, cls);
+ }else{
+ _gripNode.removeClass(cls);
+ }
+ dojo.addClass(_node, cls);
+ }
+ }
+ }
+ if(!_hasHandle){
+ dojo.addClass(service.domNode, cls);
+ }
+ }
+};
+
+dojo.declare("dojox.layout.dnd.DropIndicator", null, {
+ // summary: An empty widget to show at the user the drop zone of the widget.
+ constructor: function(/*String*/cn, /*String*/tag) {
+ this.tag = tag || "div";
+ this.style = cn || null;
+ },
+
+ isInserted : function(){
+ return (this.node.parentNode && this.node.parentNode.nodeType==1);
+ },
+
+ create : function(/*Node*//*nodeRef*/){
+ if(this.node && this.isInserted()){ return this.node; }
+ var h = "90px",
+ el = dojo.doc.createElement(this.tag);
+
+ if(this.style){
+ el.className = this.style;
+ el.style.height = h;
+ }else{
+ // FIXME: allow this to be done mostly in CSS?
+ dojo.style(el, {
+ position:"relative",
+ border:"1px dashed #F60",
+ margin:"2px",
+ height: h
+ })
+ }
+ this.node = el;
+ return el;
+ },
+
+ destroy : function(){
+ if(!this.node || !this.isInserted()){ return; }
+ this.node.parentNode.removeChild(this.node);
+ this.node = null;
+ }
+});
+
+dojo.extend(dojo.dnd.Manager, {
+
+ canDrop: function(flag){
+ var canDropFlag = this.target && flag;
+ if(this.canDropFlag != canDropFlag){
+ this.canDropFlag = canDropFlag;
+ if(this.avatar){ this.avatar.update(); }
+ }
+
+ },
+
+ makeAvatar: function(){
+ //summary: Makes the avatar, it is separate to be overwritten dynamically, if needed.
+ return (this.source.declaredClass == "dojox.layout.dnd.PlottedDnd") ?
+ new dojox.layout.dnd.Avatar(this, this.source.opacity) :
+ new dojo.dnd.Avatar(this)
+ ;
+ }
+});
+
+if(dojo.isIE){
+ dojox.layout.dnd.handdleIE = [
+ dojo.subscribe("/dnd/start", null, function(){
+ IEonselectstart = document.body.onselectstart;
+ document.body.onselectstart = function(){ return false; };
+ }),
+ dojo.subscribe("/dnd/cancel", null, function(){
+ document.body.onselectstart = IEonselectstart;
+ }),
+ dojo.subscribe("/dnd/drop", null, function(){
+ document.body.onselectstart = IEonselectstart;
+ })
+ ];
+ dojo.addOnWindowUnload(function(){
+ dojo.forEach(dojox.layout.dnd.handdleIE, dojo.unsubscribe);
+ });
+}
+});
diff --git a/js/dojo/dojox/layout/ext-dijit/layout/StackContainer-touch.js b/js/dojo/dojox/layout/ext-dijit/layout/StackContainer-touch.js
new file mode 100644
index 0000000..48b795e
--- /dev/null
+++ b/js/dojo/dojox/layout/ext-dijit/layout/StackContainer-touch.js
@@ -0,0 +1,49 @@
+//>>built
+// wrapped by build app
+define("dojox/layout/ext-dijit/layout/StackContainer-touch", ["dijit","dojo","dojox","dojo/require!dijit/layout/StackContainer"], function(dijit,dojo,dojox){
+dojo.provide("dojox.layout.ext-dijit.layout.StackContainer-touch");
+dojo.experimental("dojox.layout.ext-dijit.layout.StackContainer-touch");
+dojo.require("dijit.layout.StackContainer");
+
+// To support "flick" actions on iPhone, iPod Touch, etc.
+// Implemented as a mixin to work with StackContainer (horizontal) and AccordionContainer (vertical)
+// TODO: use native CSS animations for fx, provide live tracking of touch and perhaps a 'bounce' effect.
+
+dojo.connect(dijit.layout.StackContainer.prototype, "postCreate", function(){
+ this.axis = (this.baseClass == "dijitAccordionContainer") ? "Y" : "X";
+ dojo.forEach(
+ ["touchstart", "touchmove", "touchend", "touchcancel"],
+ function(p){
+ this.connect(this.domNode, p, function(e){
+ switch(e.type){
+ case "touchmove":
+ e.preventDefault();
+ if(this.touchPosition){
+ var delta = e.touches[0]["page" + this.axis] - this.touchPosition;
+ if(Math.abs(delta) > 100){
+ if(this.axis == "Y"){ delta *= -1;}
+ delete this.touchPosition;
+ if(delta > 0){
+ !this.selectedChildWidget.isLastChild && this.forward();
+ }else{
+ !this.selectedChildWidget.isFirstChild && this.back();
+ }
+ }
+ }
+ break;
+ case "touchstart":
+ if(e.touches.length == 1){
+ this.touchPosition = e.touches[0]["page" + this.axis];
+ break;
+ }
+ // else fallthrough
+ case "touchend":
+ case "touchcancel":
+ delete this.touchPosition;
+ }
+ });
+ },
+ this);
+});
+
+});
diff --git a/js/dojo/dojox/layout/resources/DndGridContainer.css b/js/dojo/dojox/layout/resources/DndGridContainer.css
new file mode 100644
index 0000000..1d42d20
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/DndGridContainer.css
@@ -0,0 +1,13 @@
+/**********************************dojox.layout.dnd************************************/
+/* item-specific settings */
+.dojoDndItemOver {background-color: #feb !important;}
+.dojoDndItemSelected {background: #ccf; color: #444;}
+.dojoDndItemBefore {border-top: 3px solid red;}
+.dojoDndItemAfter {border-bottom: 3px solid red;}
+.dojoDndItemAnchor {background: #ccf; color: black;}
+.dojoDndItemOver.dojoDndItemSelected {background: #ec8;}
+.dojoDndItemOver.dojoDndItemAnchor {background: #feb !important;}
+/* avatar-specific settings */
+/*.dojoDndAvatarHeader {display:none;} move to gridContainer */
+.dojoDndAvatarItem {background: #eee;}
+.dndDropIndicator {border: 1px dashed #FF6600;cursor: default;} \ No newline at end of file
diff --git a/js/dojo/dojox/layout/resources/ExpandoPane.css b/js/dojo/dojox/layout/resources/ExpandoPane.css
new file mode 100644
index 0000000..47001a3
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/ExpandoPane.css
@@ -0,0 +1,263 @@
+ /* dojox.layout.ExpandoPane */
+
+ .dojoxExpandoPane {
+ overflow:hidden;
+ z-index:440 !important;
+ }
+
+ .dojoxExpandoPane .dojoxExpandoWrapper {
+ overflow:hidden;
+ }
+
+ .dojoxExpandoClosed .dojoxExpandoTitleNode {
+ display:none;
+ }
+
+ /* hide all layout children scrollbars when closed */
+ .dojoxExpandoClosed .dojoxExpandoWrapper * {
+ overflow:hidden !important;
+ }
+
+ .dojoxExpandoTitleNode {
+ padding-right:6px;
+ padding-left:6px;
+ }
+
+ .dojoxExpandoIcon .a11yNode {
+ display:none;
+ visibility:hidden;
+ }
+
+ .dojoxExpandoBottom .dojoxExpandoIcon,
+ .dojoxExpandoTop .dojoxExpandoIcon,
+ .dojoxExpandoLeft .dojoxExpandoIcon {
+ float:right;
+ margin-right:2px;
+ }
+
+ .dojoxExpandoRight .dojoxExpandoIcon {
+ float:left;
+ margin-left:2px;
+ }
+
+ .dojoxExpandoIcon {
+ width:14px;
+ cursor:pointer;
+ background-position:-60px 0px;
+ background-repeat: no-repeat;
+ height:14px;
+ }
+
+ .dojoxExpandoClosed .dojoxExpandoIcon {
+ background-position: 0px 0px;
+ margin:0 auto;
+ }
+
+ .dijitBorderContainer-dijitExpandoPane {
+ border: none !important;
+ }
+
+ /* soria definitions */
+
+ .soria .dojoxExpandoTitle {
+ height:16px;
+ font-size:0.9em;
+ font-weight:bold;
+ padding:3px;
+ padding-top:6px;
+ padding-bottom:5px;
+ background:#F0F4FC url("../../../dijit/themes/soria/images/tabContainerSprite.gif") repeat-x scroll 0pt -50px;
+ border-left: 1px solid #B1BADF;
+ border-right: 1px solid #B1BADF;
+ }
+
+ .soria .dojoxExpandoClosed .dojoxExpandoTitle {
+ background: none;
+ background-color: #F0F4FC;
+ border: none;
+ }
+
+ .soria .dojoxExpandoClosed {
+ background: none;
+ background-color: #F0F4FC;
+ border: 1px solid #B1BADF !important;
+ }
+
+ .soria .dojoxExpandoIcon {
+ background-image: url('../../../dijit/themes/soria/images/spriteRoundedIconsSmall.png');
+ }
+
+ .dj_ie6 .soria .dojoxExpandoIcon {
+ background-image: url('../../../dijit/themes/soria/images/spriteRoundedIconsSmall.gif');
+ }
+
+ /* tundra styles */
+ .tundra .dojoxExpandoTitle {
+ font-weight: bold;
+ padding: 5px;
+ padding-top: 6px;
+ padding-bottom: 6px;
+ background: #fafafa url("../../../dijit/themes/tundra/images/accordionItemActive.gif") repeat-x scroll left top;
+ border-top: 1px solid #ccc;
+ border-left: 1px solid #ccc;
+ border-right: 1px solid #ccc;
+ }
+
+ .tundra .dojoxExpandoClosed .dojoxExpandoTitle {
+ background: none;
+ background-color: #fafafa;
+ border: none;
+ padding:3px;
+ }
+
+ .tundra .dojoxExpandoClosed {
+ background: none;
+ background-color: #fafafa;
+ border: 1px solid #ccc !important;
+ }
+
+ .tundra .dojoxExpandoRight .dojoxExpandoTitle,
+ .tundra .dojoxExpandoLeft .dojoxExpandoTitle,
+ .tundra .dojoxExpandoClosed .dojoxExpandoTitle,
+ .tundra .dojoxExpandoClosed {
+ background-color: #fafafa;
+ }
+
+ .tundra .dojoxExpandoIcon {
+ background-image: url('../../../dijit/themes/tundra/images/spriteRoundedIconsSmall.gif');
+ }
+
+ .tundra .dojoxExpandoClosed .dojoxExpandoIconLeft,
+ .tundra .dojoxExpandoClosed .dojoxExpandoIconRight,
+ .tundra .dojoxExpandoClosed .dojoxExpandoIconTop,
+ .tundra .dojoxExpandoClosed .dojoxExpandoIconBottom {
+ margin-top: 3px;
+ }
+
+ /* claro styles */
+ .claro .dojoxExpandoTitle {
+ font-weight: bold;
+ border:1px solid #769DC0;
+ border-bottom:none;
+ background-color:#cde8ff;
+ background-image: url("../../../dijit/themes/claro/layout/images/accordion.png");
+ background-position:0px 0px;
+ background-repeat:repeat-x;
+ padding: 5px 7px 2px 7px;
+ min-height:17px;
+ color:#4a4a4a;
+ }
+
+ .claro .dojoxExpandoClosed .dojoxExpandoTitle {
+ background: none;
+ background-color: #E6E6E7;
+ border: none;
+ padding:3px;
+ }
+
+ .claro .dojoxExpandoClosed {
+ background: none;
+ background-color: #E6E6E7;
+ border: 1px solid #769DC0 !important;
+ }
+
+ .claro .dojoxExpandoRight .dojoxExpandoTitle,
+ .claro .dojoxExpandoLeft .dojoxExpandoTitle,
+ .claro .dojoxExpandoClosed .dojoxExpandoTitle{
+ background-color: #E6E6E7;
+ }
+ .claro .dojoxExpandoClosed .dojoxExpandoTitle{
+ background-image: url("../../../dijit/themes/claro/layout/images/accordion.png");
+ background-position:0 0;
+ }
+
+ /* FIXME: use tundra spriteRoundedIconsSmall for now,
+ because there is no compatible image files in claro (15x15
+ icon, and icons are arranged in the same order as in
+ spriteRoundedIconsSmall.gif */
+ .claro .dojoxExpandoIcon {
+ background-image: url('../../../dijit/themes/tundra/images/spriteRoundedIconsSmall.gif');
+ }
+
+ .claro .dojoxExpandoClosed .dojoxExpandoIconLeft,
+ .claro .dojoxExpandoClosed .dojoxExpandoIconRight,
+ .claro .dojoxExpandoClosed .dojoxExpandoIconTop,
+ .claro .dojoxExpandoClosed .dojoxExpandoIconBottom {
+ margin-top: 3px;
+ }
+
+ /* nihilo theme styles */
+ .nihilo .dojoxExpandoPane {
+ background: #fafafa;
+ }
+
+ .nihilo .dojoxExpandoTitle {
+ height:16px;
+ font-size:0.9em;
+ font-weight:bold;
+ padding:3px;
+ padding-top:6px;
+ padding-bottom:5px;
+ background:#fafafa url("../../../dijit/themes/nihilo/images/tabContainerSprite.gif") repeat-x scroll 0pt -50px;
+ border-left: 1px solid #ccc;
+ border-right: 1px solid #ccc;
+ }
+
+ .nihilo .dojoxExpandoClosed .dojoxExpandoTitle {
+ background: none;
+ background-color: #fafafa;
+ border: none;
+ }
+
+ .nihilo .dojoxExpandoClosed {
+ background: none;
+ background-color: #fafafa;
+ border: 1px solid #ccc !important;
+ }
+
+ .nihilo .dojoxExpandoIcon {
+ background-image: url('../../../dijit/themes/nihilo/images/spriteRoundedIconsSmall.png');
+ }
+
+ .dj_ie6 .nihilo .dojoxExpandoIcon {
+ background-image: url('../../../dijit/themes/nihilo/images/spriteRoundedIconsSmall.gif');
+ }
+
+ .nihilo .dojoxExpandoTop {
+ border-bottom:1px solid #ccc;
+ border-left:1px solid #ccc;
+ border-right:1px solid #ccc;
+ }
+
+ /* open/closed states */
+
+ .dojoxExpandoClosed .dojoxExpandoIcon {
+ margin-right:4px;
+ }
+ .dojoxExpandoIconLeft {
+ background-position: 0 0;
+ }
+ .dojoxExpandoClosed .dojoxExpandoIconLeft {
+ background-position: -30px 0;
+ margin-right: 4px;
+ }
+ .dojoxExpandoIconRight {
+ background-position: -30px 0;
+ }
+ .dojoxExpandoClosed .dojoxExpandoIconRight {
+ background-position: 0 0;
+ margin-left: 4px;
+ }
+ .dojoxExpandoIconBottom {
+ background-position: -15px 0;
+ }
+ .dojoxExpandoClosed .dojoxExpandoIconBottom {
+ background-position: -45px 0;
+ margin-top:1px;
+ }
+ .dojoxExpandoIconTop {
+ background-position: -45px 0;
+ }
+ .dojoxExpandoClosed .dojoxExpandoIconTop {
+ background-position: -15px 0;
+ }
diff --git a/js/dojo/dojox/layout/resources/ExpandoPane.html b/js/dojo/dojox/layout/resources/ExpandoPane.html
new file mode 100644
index 0000000..a2e646f
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/ExpandoPane.html
@@ -0,0 +1,9 @@
+<div class="dojoxExpandoPane">
+ <div dojoAttachPoint="titleWrapper" class="dojoxExpandoTitle">
+ <div class="dojoxExpandoIcon" dojoAttachPoint="iconNode" dojoAttachEvent="onclick:toggle"><span class="a11yNode">X</span></div>
+ <span class="dojoxExpandoTitleNode" dojoAttachPoint="titleNode">${title}</span>
+ </div>
+ <div class="dojoxExpandoWrapper" dojoAttachPoint="cwrapper" dojoAttachEvent="ondblclick:_trap">
+ <div class="dojoxExpandoContent" dojoAttachPoint="containerNode"></div>
+ </div>
+</div>
diff --git a/js/dojo/dojox/layout/resources/FloatingPane.css b/js/dojo/dojox/layout/resources/FloatingPane.css
new file mode 100644
index 0000000..613cd11
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/FloatingPane.css
@@ -0,0 +1,184 @@
+.dojoxFloatingPane {
+ background-color:#fff;
+ position:relative;
+ border: 1px solid #dedede;
+ overflow: hidden;
+ -webkit-box-shadow: 0px 5px 10px #adadad;
+}
+
+.dojoxFloatingPaneFg {
+ -webkit-box-shadow: 0px 8px 20px #525252;
+}
+
+/* titleNode */
+.dojoxFloatingPaneTitle {
+ background: #cccccc;
+ background:#fafafa repeat-x bottom left;
+ border:1px solid #bfbfbf;
+ padding:4px 4px 2px 4px;
+ cursor: pointer;
+ white-space: nowrap;
+}
+
+.soria .dojoxFloatingPaneTitle {
+ background:#fff url("../../../dijit/themes/soria/images/titleBar.png") repeat-x top left;
+ border:1px solid #b1badf;
+ font-size: 0.9em;
+ font-weight: bold;
+ line-height:1.2em;
+}
+
+
+.tundra .dojoxFloatingPaneTitle {
+ background:#fafafa url("../../../dijit/themes/tundra/images/titleBarBg.gif") repeat-x bottom left;
+ border:1px solid #bfbfbf;
+ color:#000;
+}
+
+
+/* Icons */
+.dojoxFloatingCloseIcon {
+ background:url('../../../dijit/themes/tundra/images/tabClose.png') no-repeat center center;
+ width:16px;
+ height:16px;
+ overflow:hidden;
+ float:right;
+}
+
+.dojoxFloatingMinimizeIcon {
+ background:url('../../../dijit/themes/tundra/images/spriteArrows.png') no-repeat 0px center;
+ width:7px;
+ margin: 0px 4px;
+ overflow:hidden;
+ float:right;
+}
+.soria .dojoxFloatingMinimizeIcon {
+ background:url("../../../dijit/themes/soria/images/spriteRoundedIconsSmallBl.png") no-repeat -15px top;
+ width: 14px;
+ margin: 0px 2px;
+}
+
+.floatingPaneMaximized .dojoxFloatingMaximizeIcon { display:none; }
+.dojoxFloatingMaximizeIcon {
+ background:url('../../../dijit/themes/tundra/images/spriteArrows.png') no-repeat -21px center;
+ width:7px;
+ margin: 0px 4px;
+ overflow:hidden;
+ float:right;
+}
+.soria .dojoxFloatingMaximizeIcon {
+ background:url("../../../dijit/themes/soria/images/spriteRoundedIconsSmallBl.png") no-repeat -45px top;
+}
+
+.floatingPaneMaximized .dojoxFloatingRestoreIcon { display:inline; }
+.dojoxFloatingRestoreIcon {
+ background:url('../../../dijit/themes/tundra/images/spriteArrows.png') no-repeat 0px center;
+ width:7px;
+ margin: 0px 4px;
+ float:right;
+ display:none;
+}
+
+.dojoxFloatingResizeHandle {
+ background:url('icons/resize.png') no-repeat bottom right;
+ position:absolute;
+ right:0;
+ bottom:0;
+ width:16px;
+ height:16px;
+ cursor:nw-resize;
+}
+
+.dojoxFloatingCloseIcon {
+ width:15px;
+ height:15px;
+ overflow:hidden;
+ float:right;
+ cursor:pointer;
+}
+
+.soria .dojoxFloatingCloseIcon {
+ background:url("../../../dijit/themes/soria/images/spriteRoundedIconsSmallBl.png") no-repeat -60px top;
+}
+
+.tundra .dojoxFloatingCloseIcon {
+ background:url('../../../dijit/themes/tundra/images/tabClose.png') no-repeat center center;
+}
+
+/* our un-used dock styles for now */
+.dojoxFloatingDockDefault {
+ position:absolute;
+ bottom:0px;
+ left:0px;
+ overflow:hidden;
+ margin:0;
+ margin-bottom:3px;
+ padding:0px;
+ width:100%;
+ z-index:99; /* position the dock _just_ below the lowest pane */
+
+ background:transparent;
+ /* background-color:#fff;
+ border-top:1px solid #ccc;
+ */
+}
+
+.dojoxDockList {
+ padding: 0px;
+ margin: 0px;
+}
+
+.dojoxDockRestoreButton {
+ background:url('../../../dijit/themes/tundra/images/folderClosed.gif') no-repeat center center;
+ width:16px; height:16px;
+ overflow:hidden;
+ float:left;
+ margin-top:2px;
+}
+.soria .dojoxDockRestoreButton {
+ background:url("../../../dijit/themes/soria/images/spriteRoundedIconsSmallBl.png") no-repeat -45px top;
+}
+
+.dojoxDockTitleNode {
+ overflow:hidden;
+}
+
+/* Modifications */
+
+.dojoxDock {
+ display: block;
+ border: 1px solid black;
+ position: absolute;
+ padding:0;
+ margin:0;
+ background:#fcfcfc;
+}
+
+.dojoxDockNode {
+ border: 1px solid #adadad;
+ border-radius: 2px;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 3px;
+ cursor:pointer;
+ list-style: none;
+ padding: 2px;
+ margin: 0px;
+ height: 16px;
+ width: auto;
+ float: left;
+ background: #fafafa url("../../../dijit/themes/tundra/images/titleBarBg.gif") repeat-x bottom left;
+}
+.soria .dojoxDockNode {
+ background:#b7cdee url("../../../dijit/themes/soria/images/titleBar.png") repeat-x;
+}
+
+.dojoxFloatingPaneContent {
+ overflow: auto;
+ background-color: #fff;
+ height: 100%;
+ width: 100%;
+}
+
+.dojoxFloatingPaneCanvas {
+ background-color:#fff;
+}
diff --git a/js/dojo/dojox/layout/resources/FloatingPane.html b/js/dojo/dojox/layout/resources/FloatingPane.html
new file mode 100644
index 0000000..a96ccdd
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/FloatingPane.html
@@ -0,0 +1,14 @@
+<div class="dojoxFloatingPane" id="${id}">
+ <div tabindex="0" role="button" class="dojoxFloatingPaneTitle" dojoAttachPoint="focusNode">
+ <span dojoAttachPoint="closeNode" dojoAttachEvent="onclick: close" class="dojoxFloatingCloseIcon"></span>
+ <span dojoAttachPoint="maxNode" dojoAttachEvent="onclick: maximize" class="dojoxFloatingMaximizeIcon">&thinsp;</span>
+ <span dojoAttachPoint="restoreNode" dojoAttachEvent="onclick: _restore" class="dojoxFloatingRestoreIcon">&thinsp;</span>
+ <span dojoAttachPoint="dockNode" dojoAttachEvent="onclick: minimize" class="dojoxFloatingMinimizeIcon">&thinsp;</span>
+ <span dojoAttachPoint="titleNode" class="dijitInline dijitTitleNode"></span>
+ </div>
+ <div dojoAttachPoint="canvas" class="dojoxFloatingPaneCanvas">
+ <div dojoAttachPoint="containerNode" role="region" tabindex="-1" class="${contentClass}">
+ </div>
+ <span dojoAttachPoint="resizeHandle" class="dojoxFloatingResizeHandle"></span>
+ </div>
+</div>
diff --git a/js/dojo/dojox/layout/resources/GridContainer.css b/js/dojo/dojox/layout/resources/GridContainer.css
new file mode 100644
index 0000000..6eda93c
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/GridContainer.css
@@ -0,0 +1,74 @@
+@import url("../../mdnd/resources/dnd.css");
+.dj_ie6 .gridContainer *{
+ zoom:1;
+}
+
+.gridContainer{
+ display:block;
+ position:relative;
+ background:#FFF;
+ margin:0;
+ width:100%;
+ /*height:1%;*/ /*Bug focus with IE6/7)*/
+ height:auto;
+ overflow-y:auto;
+ overflow-x:hidden !important;
+}
+
+.gridContainerTable{
+ width:100%;
+ border:1px solid #BFBFBF;
+}
+
+.gridContainerTable tbody, .gridContainerTable tr{
+ height:100%;
+}
+
+.gridContainerZone{
+ vertical-align:top;
+ background-color:#FDFDFD;
+ height:100%;
+}
+
+.gridContainerZone .serviceWidgetTitleText h2{
+ position:relative;
+}
+
+.gridContainerGrip{
+ cursor:default;
+ position:absolute;
+ top:0;
+ width:10px;
+ padding:0;
+ margin:0;
+ background-image:url(icons/pixel.gif);
+ height:100%;
+}
+
+.gridContainerGripShow{
+ cursor:e-resize;
+ position:absolute;
+ top:0;
+ width:10px;
+ padding:0;
+ margin:0;
+ background-image:url(icons/gridcontainer_grip.gif);
+ height:100%;
+}
+
+.dropIndicator{
+ border:2px dashed #BFBFBF;
+}
+
+.dropIndicator > div{
+ background-color:#FFF;
+}
+
+.dj_ie6 .dropIndicator,
+.dj_ie6 .dojoxPortlet .dijitContentPane,
+.dj_ie6 .dojoxPortlet, .dj_ie6 .dojoxPortlet.dijitTitlePane{
+ margin: 10px;
+}
+.gridContainerZone > *{
+ margin: 10px !important;
+}
diff --git a/js/dojo/dojox/layout/resources/GridContainer.html b/js/dojo/dojox/layout/resources/GridContainer.html
new file mode 100644
index 0000000..c92a917
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/GridContainer.html
@@ -0,0 +1,11 @@
+<div id="${id}" class="gridContainer" dojoAttachPoint="containerNode" tabIndex="0" dojoAttachEvent="onkeypress:_selectFocus">
+ <div dojoAttachPoint="gridContainerDiv">
+ <table class="gridContainerTable" dojoAttachPoint="gridContainerTable" cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr dojoAttachPoint="gridNode" >
+
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div> \ No newline at end of file
diff --git a/js/dojo/dojox/layout/resources/RadioGroup.css b/js/dojo/dojox/layout/resources/RadioGroup.css
new file mode 100644
index 0000000..d4d67d2
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/RadioGroup.css
@@ -0,0 +1,45 @@
+/* RadioGroup base Button styling: */
+.dojoxRadioButtons {
+ margin:0; padding:4px;
+ width:100%;
+ outline:0;
+}
+
+.dojoxRadioButtons tbody {
+ margin:0; padding:0;
+ width:100%;
+}
+
+.dojoxRadioButton {
+ text-align:center;
+ cursor:pointer;
+ margin:0;
+}
+
+.dojoxRadioButtonSelected {
+ border:1px solid #ededed;
+}
+.tundra .dojoxRadioButtonSelected {
+ border:1px solid #a0a0a0;
+ background:#b7b7b7;
+}
+.soria .dojoxRadioButtonSelected {
+ background:#b7cdee url('../../../dijit/themes/soria/images/gradientTopBg.png') repeat-x top center;
+}
+
+.dojoxRadioButtonLabel {
+ padding:8px;
+ text-align:center;
+ display:block;
+}
+
+.dojoxRadioGroup {
+ overflow:hidden;
+ border:0;
+ margin:0; padding:0;
+}
+.dojoxRadioView {
+ position:relative;
+ overflow:hidden;
+ height:100%;
+} \ No newline at end of file
diff --git a/js/dojo/dojox/layout/resources/ResizeHandle.css b/js/dojo/dojox/layout/resources/ResizeHandle.css
new file mode 100644
index 0000000..533d250
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/ResizeHandle.css
@@ -0,0 +1,52 @@
+.dojoxResizeHandle {
+ float: right;
+ position: absolute;
+ right: 2px;
+ bottom: 2px;
+ width: 13px;
+ height: 13px;
+ z-index: 20;
+ background-image: url('icons/resize.png');
+ line-height: 0px;
+}
+
+.dijitRtl .dojoxResizeHandle {
+ float: right;
+ left: 0px;
+ right: auto;
+ background-image: url('icons/resizeRtl.png');
+}
+
+.dojoxResizeNW {
+ cursor: nw-resize;
+}
+
+.dijitRtl .dojoxResizeNW {
+ cursor: ne-resize;
+}
+
+.dojoxResizeNE {
+ cursor: ne-resize;
+}
+
+.dijitRtl .dojoxResizeNE {
+ cursor: nw-resize;
+}
+
+.dojoxResizeW {
+ cursor: w-resize;
+}
+
+
+.dojoxResizeN {
+ cursor: n-resize;
+}
+
+.dojoxResizeHandleClone {
+ position:absolute; top:0; left:0;
+ border:1px dashed #666;
+ z-index:999;
+}
+
+
+
diff --git a/js/dojo/dojox/layout/resources/RotatorContainer.css b/js/dojo/dojox/layout/resources/RotatorContainer.css
new file mode 100644
index 0000000..0c87a8a
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/RotatorContainer.css
@@ -0,0 +1,47 @@
+.dojoxRotatorContainer .dijitStackController,
+.dojoxRotatorPager {
+ position:absolute;
+ z-index:3;
+}
+
+.dojoxRotatorContent {
+ position:absolute;
+ z-index:1;
+}
+
+.dojoxRotatorContainer {
+ border:1px solid #9b9b9b;
+}
+
+.dojoxRotatorContainer .dijitStackController {
+ right:5px;
+ top:5px;
+}
+
+.dojoxRotatorContainer .dijitStackController .dijitToggleButtonChecked .dijitButtonNode {
+ background-color:#000;
+ background-image:none;
+ color:#fff;
+}
+
+.dojoxRotatorContainer .dojoxRotatorPager{bottom:5px;right:5px;}
+
+.rotatorIcons .dijitButton{margin:0;}
+.rotatorIcons .dijitButtonNode{background:none !important;border:0 !important;padding:0 !important;}
+.rotatorIcons .dijitButtonText{display:none;}
+.rotatorIcons .previous,
+.rotatorIcons .next,
+.rotatorIcons .playPause,
+.rotatorIcons .dijitToggleButtonChecked .playPause{background-image:url("icons/rotator.png");background-repeat:no-repeat;display:block;height:16px;width:16px;}
+.rotatorIcons .previous{background-position:0 0;}
+.rotatorIcons .dijitButtonHover .previous{background-position:0 -16px;}
+.rotatorIcons .dijitButtonActive .previous{background-position:0 -32px;}
+.rotatorIcons .next{background-position:-16px 0;}
+.rotatorIcons .dijitButtonHover .next{background-position:-16px -16px;}
+.rotatorIcons .dijitButtonActive .next{background-position:-16px -32px;}
+.rotatorIcons .playPause{background-position:-32px 0;}
+.rotatorIcons .dijitToggleButtonHover .playPause{background-position:-32px -16px;}
+.rotatorIcons .dijitToggleButtonActive .playPause{background-position:-32px -32px;}
+.rotatorIcons .dijitToggleButtonChecked .playPause{background-position:-48px 0;}
+.rotatorIcons .dijitToggleButtonCheckedHover .playPause{background-position:-48px -16px;}
+.rotatorIcons .dijitToggleButtonCheckedActive .playPause{background-position:-48px -32px;}
diff --git a/js/dojo/dojox/layout/resources/ScrollPane.css b/js/dojo/dojox/layout/resources/ScrollPane.css
new file mode 100644
index 0000000..3dc7386
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/ScrollPane.css
@@ -0,0 +1,24 @@
+.dojoxScrollWindow {
+ position:relative;
+ overflow:hidden;
+}
+
+.dojoxScrollHelper .helperInner {
+ visibility: hidden;
+}
+
+.dojoxScrollHelper {
+ border:1px solid #b7b7b7;
+ width:4px;
+ background:#ededed;
+ height:4px;
+ position:absolute;
+ top:4px;
+ left:4px;
+ border-radius: 3px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+}
+
+.dojoxScrollWrapper {
+}
diff --git a/js/dojo/dojox/layout/resources/ScrollPane.html b/js/dojo/dojox/layout/resources/ScrollPane.html
new file mode 100644
index 0000000..4b3df77
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/ScrollPane.html
@@ -0,0 +1,6 @@
+<div class="dojoxScrollWindow" dojoAttachEvent="onmouseenter: _enter, onmouseleave: _leave">
+ <div class="dojoxScrollWrapper" style="${style}" dojoAttachPoint="wrapper" dojoAttachEvent="onmousemove: _calc">
+ <div class="dojoxScrollPane" dojoAttachPoint="containerNode"></div>
+ </div>
+ <div dojoAttachPoint="helper" class="dojoxScrollHelper"><span class="helperInner">|</span></div>
+</div> \ No newline at end of file
diff --git a/js/dojo/dojox/layout/resources/ToggleSplitter.css b/js/dojo/dojox/layout/resources/ToggleSplitter.css
new file mode 100644
index 0000000..2f18625
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/ToggleSplitter.css
@@ -0,0 +1,87 @@
+.dijitBorderContainer .dijitSplitterH {
+ height: 6px;
+}
+
+.dijitBorderContainer .dijitSplitterV {
+ width: 6px;
+}
+
+.dijitBorderContainer .dijitSplitterH .dojoxToggleSplitterIcon {
+ background-image: url('icons/splitterToggleH.png');
+ background-repeat: no-repeat;
+ width: 71px;
+ height: 6px;
+ top: 0;
+ left: 45%;
+ cursor: pointer;
+}
+
+.dijitBorderContainer .dijitSplitterV .dojoxToggleSplitterIcon {
+ background-image: url('icons/splitterToggleV.png');
+ background-repeat: no-repeat;
+ vertical-align: middle;
+ width: 6px;
+ height: 71px;
+ left: 0;
+ top: 45%;
+ cursor: pointer;
+}
+
+.dojoxToggleSplitterTop .dojoxToggleSplitterIconOpen,
+.dojoxToggleSplitterBottom .dojoxToggleSplitterIconClosed {
+ background-position: 0 -12px !important;
+}
+
+.dojoxToggleSplitterBottom .dojoxToggleSplitterIconOpen,
+.dojoxToggleSplitterTop .dojoxToggleSplitterIconClosed {
+ background-position: 0 0 !important;
+}
+
+.dojoxToggleSplitterLeft .dojoxToggleSplitterIconOpen,
+.dojoxToggleSplitterRight .dojoxToggleSplitterIconClosed {
+ background-position: -12px 0 !important;
+}
+
+.dojoxToggleSplitterRight .dojoxToggleSplitterIconOpen,
+.dojoxToggleSplitterLeft .dojoxToggleSplitterIconClosed {
+ background-position: 0 0 !important;
+}
+
+.dojoxToggleSplitterTop .dojoxToggleSplitterIconOpenHover,
+.dojoxToggleSplitterBottom .dojoxToggleSplitterIconClosedHover {
+ background-position: 0 -18px !important;
+}
+
+.dojoxToggleSplitterBottom .dojoxToggleSplitterIconOpenHover,
+.dojoxToggleSplitterTop .dojoxToggleSplitterIconClosedHover {
+ background-position: 0 -6px !important;
+}
+
+.dojoxToggleSplitterLeft .dojoxToggleSplitterIconOpenHover,
+.dojoxToggleSplitterRight .dojoxToggleSplitterIconClosedHover {
+ background-position: -18px 0 !important;
+}
+
+.dojoxToggleSplitterRight .dojoxToggleSplitterIconOpenHover,
+.dojoxToggleSplitterLeft .dojoxToggleSplitterIconClosedHover {
+ background-position: -6px 0 !important;
+}
+
+.dojoxToggleSplitterTop .dojoxToggleSplitterA11y,
+.dojoxToggleSplitterBottom .dojoxToggleSplitterA11y {
+ display: none;
+ font-size: 6px;
+ text-align: center;
+}
+
+.dojoxToggleSplitterRight .dojoxToggleSplitterA11y,
+.dojoxToggleSplitterLeft .dojoxToggleSplitterA11y {
+ display: none;
+ font-size: 8px;
+ position: relative;
+ top: 48%;
+}
+
+.dijit_a11y .dojoxToggleSplitterA11y {
+ display: block;
+}
diff --git a/js/dojo/dojox/layout/resources/icons/gridcontainer_grip.gif b/js/dojo/dojox/layout/resources/icons/gridcontainer_grip.gif
new file mode 100644
index 0000000..2eb05e8
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/icons/gridcontainer_grip.gif
Binary files differ
diff --git a/js/dojo/dojox/layout/resources/icons/grip_bg.gif b/js/dojo/dojox/layout/resources/icons/grip_bg.gif
new file mode 100644
index 0000000..45f76ce
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/icons/grip_bg.gif
Binary files differ
diff --git a/js/dojo/dojox/layout/resources/icons/pixel.gif b/js/dojo/dojox/layout/resources/icons/pixel.gif
new file mode 100644
index 0000000..3be2119
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/icons/pixel.gif
Binary files differ
diff --git a/js/dojo/dojox/layout/resources/icons/resize.png b/js/dojo/dojox/layout/resources/icons/resize.png
new file mode 100644
index 0000000..17f39d0
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/icons/resize.png
Binary files differ
diff --git a/js/dojo/dojox/layout/resources/icons/resizeRtl.png b/js/dojo/dojox/layout/resources/icons/resizeRtl.png
new file mode 100644
index 0000000..c3f97c6
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/icons/resizeRtl.png
Binary files differ
diff --git a/js/dojo/dojox/layout/resources/icons/rotator.png b/js/dojo/dojox/layout/resources/icons/rotator.png
new file mode 100644
index 0000000..ad93ee5
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/icons/rotator.png
Binary files differ
diff --git a/js/dojo/dojox/layout/resources/icons/splitterToggleH.png b/js/dojo/dojox/layout/resources/icons/splitterToggleH.png
new file mode 100644
index 0000000..72a3723
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/icons/splitterToggleH.png
Binary files differ
diff --git a/js/dojo/dojox/layout/resources/icons/splitterToggleV.png b/js/dojo/dojox/layout/resources/icons/splitterToggleV.png
new file mode 100644
index 0000000..55ecf04
--- /dev/null
+++ b/js/dojo/dojox/layout/resources/icons/splitterToggleV.png
Binary files differ