blob: 9833fca5aff82de457bc3fc8ae8ee5fc5b3d50da [file] [log] [blame]
/*
Copyright (c) 2004-2005, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
dojo.provide("dojo.widget.Dialog");
dojo.provide("dojo.widget.HtmlDialog");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
dojo.require("dojo.graphics.color");
dojo.require("dojo.fx.*");
dojo.require("dojo.html");
dojo.widget.tags.addParseTreeHandler("dojo:dialog");
dojo.widget.HtmlDialog = function(){
dojo.widget.HtmlWidget.call(this);
this.resizeConnectArgs = {
srcObj: window,
srcFunc: "onresize",
adviceObj: this,
adviceFunc: "onResize",
rate: 500
}
}
dojo.inherits(dojo.widget.HtmlDialog, dojo.widget.HtmlWidget);
dojo.lang.extend(dojo.widget.HtmlDialog, {
templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlDialog.html"),
widgetType: "Dialog",
isContainer: true,
_scrollConnected: false,
_resizeConnected: false,
// provide a focusable element or element id if you need to
// work around FF's tendency to send focus into outer space on hide
focusElement: "",
// Only supports fade right now
effect: "fade",
effectDuration: 250,
bg: null,
bgIframe: null,
bgColor: "black",
bgOpacity: 0.4,
followScroll: 1,
_fromTrap: false,
anim: null,
trapTabs: function(e){
if(e.target == this.tabStart) {
if(this._fromTrap) {
this._fromTrap = false;
} else {
this._fromTrap = true;
this.tabEnd.focus();
}
} else if(e.target == this.tabEnd) {
if(this._fromTrap) {
this._fromTrap = false;
} else {
this._fromTrap = true;
this.tabStart.focus();
}
}
},
clearTrap: function(e) {
var _this = this;
setTimeout(function() {
_this._fromTrap = false;
}, 100);
},
postCreate: function(args, frag, parentComp) {
with(this.domNode.style) {
position = "absolute";
zIndex = 999;
display = "none";
}
var b = dojo.html.body();
b.appendChild(this.domNode);
this.nodeRef = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
if(this.nodeRef) {
this.setContent(this.nodeRef);
}
this.bgIframe = new dojo.html.BackgroundIframe();
this.bg = document.createElement("div");
this.bg.className = "dialogUnderlay";
with(this.bg.style) {
position = "absolute";
left = top = "0px";
zIndex = 998;
display = "none";
}
this.setBackgroundColor(this.bgColor);
b.appendChild(this.bg);
this.bgIframe.setZIndex(this.bg);
},
setContent: function(content) {
if(typeof content == "string") {
this.containerNode.innerHTML = content;
} else if(content.nodeType != undefined) {
// dojo.dom.removeChildren(this.containerNode);
this.containerNode.appendChild(content);
} else {
dojo.raise("Tried to setContent with unknown content (" + content + ")");
}
},
setBackgroundColor: function(color) {
if(arguments.length >= 3) {
color = new dojo.graphics.color.Color(arguments[0], arguments[1], arguments[2]);
} else {
color = new dojo.graphics.color.Color(color);
}
this.bg.style.backgroundColor = color.toString();
return this.bgColor = color;
},
setBackgroundOpacity: function(op) {
if(arguments.length == 0) { op = this.bgOpacity; }
dojo.style.setOpacity(this.bg, op);
try {
this.bgOpacity = dojo.style.getOpacity(this.bg);
} catch (e) {
this.bgOpacity = op;
}
return this.bgOpacity;
},
sizeBackground: function() {
if(this.bgOpacity > 0) {
var h = document.documentElement.scrollHeight || dojo.html.body().scrollHeight;
var w = dojo.html.getViewportWidth();
this.bg.style.width = w + "px";
this.bg.style.height = h + "px";
this.bgIframe.size([0, 0, w, h]);
} else {
this.bgIframe.size(this.domNode);
}
},
showBackground: function() {
this.sizeBackground();
this.bgIframe.show();
if(this.bgOpacity > 0) {
this.bg.style.display = "block";
}
},
placeDialog: function() {
var scroll_offset = dojo.html.getScrollOffset();
var viewport_size = dojo.html.getViewportSize();
// find the size of the dialog
// we should really be using dojo.style but i'm not sure
// which (inner, outer, box, content, client) --cal
this.domNode.style.display = "block";
var w = this.domNode.offsetWidth;
var h = this.domNode.offsetHeight;
this.domNode.style.display = "none";
var x = scroll_offset[0] + (viewport_size[0] - w)/2;
var y = scroll_offset[1] + (viewport_size[1] - h)/2;
with(this.domNode.style) {
left = x + "px";
top = y + "px";
}
// tied to domNode, so we need to update the position
if(this.bgOpacity == 0) {
this.bgIframe.size([x, y, w, h]);
}
},
show: function() {
this.setBackgroundOpacity();
this.placeDialog();
this.showBackground();
switch((this.effect||"").toLowerCase()){
case "fade":
this.domNode.style.display = "block";
var _this = this;
if(this.anim){ this.anim.stop(); }
// FIXME: we should be supporting other effect types here!
this.anim = dojo.fx.fade(this.domNode,
this.effectDuration,
0,
1,
dojo.lang.hitch(this,
function(node){
if(dojo.lang.isFunction(_this.onShow)) {
_this.onShow(node);
}
}
)
);
break;
default:
this.domNode.style.display = "block";
if(dojo.lang.isFunction(this.onShow)){
this.onShow(this.domNode);
}
break;
}
// FIXME: moz doesn't generate onscroll events for mouse or key scrolling (wtf)
// we should create a fake event by polling the scrolltop/scrollleft every X ms.
// this smells like it should be a dojo feature rather than just for this widget.
if (this.followScroll && !this._scrollConnected){
this._scrollConnected = true;
dojo.event.connect(window, "onscroll", this, "onScroll");
}
if(!this._resizeConnected) {
this._resizeConnected = true;
dojo.event.kwConnect(this.resizeConnectArgs);
}
},
hide: function(){
// workaround for FF focus going into outer space
if (this.focusElement) {
dojo.byId(this.focusElement).focus();
dojo.byId(this.focusElement).blur();
}
switch((this.effect||"").toLowerCase()) {
case "fade":
this.bg.style.display = "none";
this.bgIframe.hide();
var _this = this;
if(this.anim){ this.anim.stop(); }
this.anim = dojo.fx.fadeOut(this.domNode, this.effectDuration, function(node) {
node.style.display = "none";
if(dojo.lang.isFunction(_this.onHide)) {
_this.onHide(node);
}
_this.anim = null;
});
break;
default:
this.bg.style.display = "none";
this.bgIframe.hide();
this.domNode.style.display = "none";
if(dojo.lang.isFunction(this.onHide)) {
this.onHide(node);
}
break;
}
this.bg.style.width = this.bg.style.height = "1px";
if (this._scrollConnected){
this._scrollConnected = false;
dojo.event.disconnect(window, "onscroll", this, "onScroll");
}
if(this._resizeConnected) {
this._resizeConnected = false;
dojo.event.kwDisconnect(this.resizeConnectArgs);
}
},
setCloseControl: function(node) {
dojo.event.connect(node, "onclick", this, "hide");
},
setShowControl: function(node) {
dojo.event.connect(node, "onclick", this, "show");
},
onScroll: function(){
this.placeDialog();
this.domNode.style.display = "block";
},
onResize: function(e) {
this.sizeBackground();
}
});