if (!dojo._hasResource["dojox.layout.RadioGroup"]) { // _hasResource checks
// added by build. Do
// not use _hasResource
// directly in your
// code.
dojo._hasResource["dojox.layout.RadioGroup"] = true;
dojo.provide("dojox.layout.RadioGroup");
dojo.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?
//
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dijit._Container");
dojo.require("dijit.layout.StackContainer");
dojo.require("dojox.fx.easing");
dojo.declare("dojox.layout.RadioGroup", [dijit.layout.StackContainer,
dijit._Templated], {
// summary: A Container that turns its Layout Children into a
// single Pane and transitions between states
// onHover of the button
//
// duration: Int
// 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 : true,
// templateString: String
// the template for our container
templateString : '
',
startup : function() {
// summary: scan the container for children, and make "tab
// buttons" for them
this.inherited("startup", arguments);
this._children = this.getChildren();
this._buttons = this._children.length;
this._size = dojo.coords(this.containerNode);
if (this.hasButtons) {
dojo.style(this.buttonHolder, "display", "block");
dojo.forEach(this._children, this._makeButton, this);
}
},
// private:
_makeButton : function(/* DomNode */n) {
// summary: creates a hover button for a child node of the
// RadioGroup
dojo.style(n.domNode, "position", "absolute");
var tmp = document.createElement('td');
this.buttonNode.appendChild(tmp);
var tmpt = tmp.appendChild(document.createElement('div'));
var tmpw = new dojox.layout._RadioButton({
label : n.title,
page : n
}, tmpt);
tmpw.startup();
},
// 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(/* Widget */newWidget, /* 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(/* 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._loadCheck) {
page._loadCheck(); // trigger load in ContentPane
}
if (page.onShow) {
page.onShow();
}
},
_hideChild : function(/* Widget */page) {
// summary: hide the specified child widget
page.selected = false;
page.domNode.style.display = "none";
if (page.onHide) {
page.onHide();
}
}
});
dojo.declare("dojox.layout.RadioGroupFade", dojox.layout.RadioGroup, {
// summary: An extension on a stock RadioGroup, that fades the
// panes.
_hideChild : function(page) {
// summary: hide the specified child widget
dojo.fadeOut({
node : page.domNode,
duration : this.duration,
onEnd : this.inherited("_hideChild", arguments)
}).play();
},
_showChild : function(page) {
// summary: show the specified child widget
this.inherited("_showChild", arguments);
dojo.style(page.domNode, "opacity", 0);
dojo.fadeIn({
node : page.domNode,
duration : this.duration
}).play();
}
});
dojo.declare("dojox.layout.RadioGroupSlide", dojox.layout.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: dojo._Animation.easing
// A hook to override the default easing of the pane slides.
easing : dojox.fx.easing.easeOut,
startup : function() {
// summary: on startup, set each of the panes off-screen
// (_showChild is called later)
this.inherited("startup", arguments);
dojo.forEach(this._children, this._positionChild, this);
},
_positionChild : function(page) {
// summary: randomly set the child out of view
// description:
var rA = Math.round(Math.random());
var rB = Math.round(Math.random());
dojo.style(page.domNode, rA ? "top" : "left", (rB
? "-"
: "")
+ this._size[rA ? "h" : "w"] + "px");
},
_showChild : function(page) {
// summary: Slide in the selected child widget
this.inherited("_showChild", arguments);
if (this._anim && this._anim.status() == "playing") {
this._anim.gotoPercent(100, true);
}
this._anim = dojo.animateProperty({
node : page.domNode,
properties : {
// take a performance hit determinging one
// of these doesn't get modified
// but it's better this way than an extra
// call to mixin in think?
left : {
end : 0,
unit : "px"
},
top : {
end : 0,
unit : "px"
}
},
duration : this.duration,
easing : this.easing
});
this._anim.play();
},
_hideChild : function(page) {
// summary: reset the position of the hidden pane out of
// sight
this.inherited("_hideChild", arguments);
this._positionChild(page);
}
});
dojo.declare("dojox.layout._RadioButton", [dijit._Widget, dijit._Templated,
dijit._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 : '${label}
',
startup : function() {
// summary: start listening to mouseOver
this.connect(this.domNode, "onmouseover", "_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();
dojo.addClass(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]
dojo.query(".dojoxRadioButtonSelected",
this.domNode.parentNode.parentNode).forEach(
function(n) {
dojo.removeClass(n, "dojoxRadioButtonSelected");
});
}
});
}