You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
319 lines
9.1 KiB
319 lines
9.1 KiB
define(["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", "dojo/touch", |
|
"dijit/_TemplatedMixin", "dijit/_Widget", "dijit/BackgroundIframe", |
|
"dijit/registry", "dojo/dnd/Moveable", "./ContentPane", "./ResizeHandle", "dojo/text!./resources/FloatingPane.html","./Dock" |
|
], function( |
|
kernel, lang, winUtil, declare, baseFx, connectUtil, arrayUtil, |
|
has, windowLib, dom, domClass, domGeom, domConstruct, touch, TemplatedMixin, Widget, BackgroundIframe, |
|
registry, Moveable, ContentPane, ResizeHandle, template, Dock){ |
|
|
|
kernel.experimental("dojox.layout.FloatingPane"); |
|
|
|
return 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 = registry.byId(this.dockTo); |
|
}else{ |
|
this.dockTo = registry.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, touch.press,"bringToTop"); |
|
this.connect(this.domNode, touch.press,"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(); |
|
// use w / h from content box dimensions and x / y from position |
|
var contentBox = domGeom.getContentBox(this.domNode); |
|
this.resize(lang.mixin(domGeom.position(this.domNode), {w: contentBox.w, h: contentBox.h})); |
|
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._naturalState = 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); |
|
} |
|
}); |
|
|
|
});
|
|
|