diff options
Diffstat (limited to 'js/dojo/dojox/layout')
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\"> </span>\n\t\t<span dojoAttachPoint=\"restoreNode\" dojoAttachEvent=\"onclick: _restore\" class=\"dojoxFloatingRestoreIcon\"> </span>\t\n\t\t<span dojoAttachPoint=\"dockNode\" dojoAttachEvent=\"onclick: minimize\" class=\"dojoxFloatingMinimizeIcon\"> </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 = "▴", 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 = "▲"; + }else if(region == "top" && !on || region == "bottom" && on){ + arrow = "▼"; + }else if(region == "right" && on || region == "left" && !on){ + arrow = "▶"; + }else if(region == "right" && !on || region == "left" && on){ + arrow = "◀"; + } + + 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"> </span> + <span dojoAttachPoint="restoreNode" dojoAttachEvent="onclick: _restore" class="dojoxFloatingRestoreIcon"> </span> + <span dojoAttachPoint="dockNode" dojoAttachEvent="onclick: minimize" class="dojoxFloatingMinimizeIcon"> </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 Binary files differnew file mode 100644 index 0000000..2eb05e8 --- /dev/null +++ b/js/dojo/dojox/layout/resources/icons/gridcontainer_grip.gif diff --git a/js/dojo/dojox/layout/resources/icons/grip_bg.gif b/js/dojo/dojox/layout/resources/icons/grip_bg.gif Binary files differnew file mode 100644 index 0000000..45f76ce --- /dev/null +++ b/js/dojo/dojox/layout/resources/icons/grip_bg.gif diff --git a/js/dojo/dojox/layout/resources/icons/pixel.gif b/js/dojo/dojox/layout/resources/icons/pixel.gif Binary files differnew file mode 100644 index 0000000..3be2119 --- /dev/null +++ b/js/dojo/dojox/layout/resources/icons/pixel.gif diff --git a/js/dojo/dojox/layout/resources/icons/resize.png b/js/dojo/dojox/layout/resources/icons/resize.png Binary files differnew file mode 100644 index 0000000..17f39d0 --- /dev/null +++ b/js/dojo/dojox/layout/resources/icons/resize.png diff --git a/js/dojo/dojox/layout/resources/icons/resizeRtl.png b/js/dojo/dojox/layout/resources/icons/resizeRtl.png Binary files differnew file mode 100644 index 0000000..c3f97c6 --- /dev/null +++ b/js/dojo/dojox/layout/resources/icons/resizeRtl.png diff --git a/js/dojo/dojox/layout/resources/icons/rotator.png b/js/dojo/dojox/layout/resources/icons/rotator.png Binary files differnew file mode 100644 index 0000000..ad93ee5 --- /dev/null +++ b/js/dojo/dojox/layout/resources/icons/rotator.png diff --git a/js/dojo/dojox/layout/resources/icons/splitterToggleH.png b/js/dojo/dojox/layout/resources/icons/splitterToggleH.png Binary files differnew file mode 100644 index 0000000..72a3723 --- /dev/null +++ b/js/dojo/dojox/layout/resources/icons/splitterToggleH.png diff --git a/js/dojo/dojox/layout/resources/icons/splitterToggleV.png b/js/dojo/dojox/layout/resources/icons/splitterToggleV.png Binary files differnew file mode 100644 index 0000000..55ecf04 --- /dev/null +++ b/js/dojo/dojox/layout/resources/icons/splitterToggleV.png |
