blob: c44e685953f873c9b997ee92955b099c59f5a5ff [file] [log] [blame]
/*
Copyright (c) 2004-2006, 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.Button");
dojo.require("dojo.lang.extras");
dojo.require("dojo.html.*");
dojo.require("dojo.html.selection");
dojo.require("dojo.widget.*");
/*
* usage
* <button dojoType="button" onClick="...">Hello world</button>
*
* var button1 = dojo.widget.createWidget("Button", {caption: "hello world", onClick: foo});
* document.body.appendChild(button1.domNode);
*/
dojo.widget.defineWidget(
"dojo.widget.Button",
dojo.widget.HtmlWidget,
{
// summary
// Basically the same thing as a normal HTML button, but with special styling.
isContainer: true,
// caption: String
// text to display in button
caption: "",
templatePath: dojo.uri.dojoUri("src/widget/templates/ButtonTemplate.html"),
templateCssPath: dojo.uri.dojoUri("src/widget/templates/ButtonTemplate.css"),
// inactiveImg: Url
// prefix of filename holding images (left, center, right) for button in normal state
inactiveImg: "src/widget/templates/images/soriaButton-",
// activeImg: Url
// prefix of filename holding images (left, center, right) for button when it's being hovered over
activeImg: "src/widget/templates/images/soriaActive-",
// pressedImg: Url
// prefix of filename holding images (left, center, right) for button between mouse-down and mouse-up
pressedImg: "src/widget/templates/images/soriaPressed-",
// disabledImg: Url
// prefix of filename holding images (left, center, right) for button when it's disabled (aka, grayed-out)
disabledImg: "src/widget/templates/images/soriaDisabled-",
// widget2height: Number
// shape of the button's end pieces;
// the height of the end pieces is a function of the button's height (which in turn is a function of the button's content),
// and then the width of the end pieces is relative to their height.
width2height: 1.0/3.0,
fillInTemplate: function(){
if(this.caption){
this.containerNode.appendChild(document.createTextNode(this.caption));
}
dojo.html.disableSelection(this.containerNode);
},
postCreate: function(){
this._sizeMyself();
},
_sizeMyself: function(){
// we cannot size correctly if any of our ancestors are hidden (display:none),
// so temporarily attach to document.body
if(this.domNode.parentNode){
var placeHolder = document.createElement("span");
dojo.html.insertBefore(placeHolder, this.domNode);
}
dojo.body().appendChild(this.domNode);
this._sizeMyselfHelper();
// Put this.domNode back where it was originally
if(placeHolder){
dojo.html.insertBefore(this.domNode, placeHolder);
dojo.html.removeNode(placeHolder);
}
},
_sizeMyselfHelper: function(){
var mb = dojo.html.getMarginBox(this.containerNode);
this.height = mb.height;
this.containerWidth = mb.width;
var endWidth= this.height * this.width2height;
this.containerNode.style.left=endWidth+"px";
this.leftImage.height = this.rightImage.height = this.centerImage.height = this.height;
this.leftImage.width = this.rightImage.width = endWidth+1;
this.centerImage.width = this.containerWidth;
this.centerImage.style.left=endWidth+"px";
this._setImage(this.disabled ? this.disabledImg : this.inactiveImg);
if ( this.disabled ) {
dojo.html.prependClass(this.domNode, "dojoButtonDisabled");
this.domNode.removeAttribute("tabIndex");
dojo.widget.wai.setAttr(this.domNode, "waiState", "disabled", true);
} else {
dojo.html.removeClass(this.domNode, "dojoButtonDisabled");
this.domNode.setAttribute("tabIndex", "0");
dojo.widget.wai.setAttr(this.domNode, "waiState", "disabled", false);
}
this.domNode.style.height=this.height + "px";
this.domNode.style.width= (this.containerWidth+2*endWidth) + "px";
},
onMouseOver: function(/*Event*/ e){
// summary: callback when user mouses-over the button
if( this.disabled ){ return; }
dojo.html.prependClass(this.buttonNode, "dojoButtonHover");
this._setImage(this.activeImg);
},
onMouseDown: function(/*Event*/ e){
// summary: callback when user starts to click the button
if( this.disabled ){ return; }
dojo.html.prependClass(this.buttonNode, "dojoButtonDepressed");
dojo.html.removeClass(this.buttonNode, "dojoButtonHover");
this._setImage(this.pressedImg);
},
onMouseUp: function(/*Event*/ e){
// summary: callback when the user finishes clicking
if( this.disabled ){ return; }
dojo.html.prependClass(this.buttonNode, "dojoButtonHover");
dojo.html.removeClass(this.buttonNode, "dojoButtonDepressed");
this._setImage(this.activeImg);
},
onMouseOut: function(/*Event*/ e){
// summary: callback when the user moves the mouse off the button
if( this.disabled ){ return; }
if( e.toElement && dojo.html.isDescendantOf(e.toElement, this.buttonNode) ){
return; // Ignore IE mouseOut events that dont actually leave button - Prevents hover image flicker in IE
}
dojo.html.removeClass(this.buttonNode, "dojoButtonHover");
dojo.html.removeClass(this.buttonNode, "dojoButtonDepressed");
this._setImage(this.inactiveImg);
},
onKey: function(/*Event*/ e){
// summary: callback when the user presses a key (on key-down)
if (!e.key) { return; }
var menu = dojo.widget.getWidgetById(this.menuId);
if (e.key == e.KEY_ENTER || e.key == " "){
this.onMouseDown(e);
this.buttonClick(e);
dojo.lang.setTimeout(this, "onMouseUp", 75, e);
dojo.event.browser.stopEvent(e);
}
if(menu && menu.isShowingNow && e.key == e.KEY_DOWN_ARROW){
// disconnect onBlur when focus moves into menu
dojo.event.disconnect(this.domNode, "onblur", this, "onBlur");
// allow event to propagate to menu
}
},
onFocus: function(/*Event*/ e){
// summary: callback on focus to the button
var menu = dojo.widget.getWidgetById(this.menuId);
if (menu){
dojo.event.connectOnce(this.domNode, "onblur", this, "onBlur");
}
},
onBlur: function(/*Event*/ e){
// summary: callback when button loses focus
var menu = dojo.widget.getWidgetById(this.menuId);
if ( !menu ) { return; }
if ( menu.close && menu.isShowingNow ){
menu.close();
}
},
buttonClick: function(/*Event*/ e){
// summary: internal function for handling button clicks
if(!this.disabled){
// focus may fail when tabIndex is not supported on div's
// by the browser, or when the node is disabled
try { this.domNode.focus(); } catch(e2) {};
this.onClick(e);
}
},
onClick: function(/*Event*/ e) {
// summary: callback for when button is clicked; user can override this function
},
_setImage: function(/*String*/ prefix){
this.leftImage.src=dojo.uri.dojoUri(prefix + "l.gif");
this.centerImage.src=dojo.uri.dojoUri(prefix + "c.gif");
this.rightImage.src=dojo.uri.dojoUri(prefix + "r.gif");
},
_toggleMenu: function(/*String*/ menuId){
var menu = dojo.widget.getWidgetById(menuId);
if ( !menu ) { return; }
if ( menu.open && !menu.isShowingNow) {
var pos = dojo.html.getAbsolutePosition(this.domNode, false);
menu.open(pos.x, pos.y+this.height, this);
} else if ( menu.close && menu.isShowingNow ){
menu.close();
} else {
menu.toggle();
}
},
setCaption: function(/*String*/ content){
// summary: reset the caption (text) of the button; takes an HTML string
this.caption=content;
this.containerNode.innerHTML=content;
this._sizeMyself();
},
setDisabled: function(/*Boolean*/ disabled){
// summary: set disabled state of button
this.disabled=disabled;
this._sizeMyself();
}
});
/*
* usage
* <button dojoType="DropDownButton" menuId="mymenu">Hello world</button>
*
* var button1 = dojo.widget.createWidget("DropDownButton", {caption: "hello world", menuId: foo});
* document.body.appendChild(button1.domNode);
*/
dojo.widget.defineWidget(
"dojo.widget.DropDownButton",
dojo.widget.Button,
{
// summary
// push the button and a menu shows up
// menuId: String
// widget id of the menu that this button should activate
menuId: "",
// downArrow: Url
// path of arrow image to display to the right of the button text
downArrow: "src/widget/templates/images/whiteDownArrow.gif",
// disabledDownArray: Url
// path of arrow image to display to the right of the button text, when the button is disabled
disabledDownArrow: "src/widget/templates/images/whiteDownArrow.gif",
fillInTemplate: function(){
dojo.widget.DropDownButton.superclass.fillInTemplate.apply(this, arguments);
this.arrow = document.createElement("img");
dojo.html.setClass(this.arrow, "downArrow");
dojo.widget.wai.setAttr(this.domNode, "waiState", "haspopup", this.menuId);
},
_sizeMyselfHelper: function(){
// draw the arrow (todo: why is the arror in containerNode rather than outside it?)
this.arrow.src = dojo.uri.dojoUri(this.disabled ? this.disabledDownArrow : this.downArrow);
this.containerNode.appendChild(this.arrow);
dojo.widget.DropDownButton.superclass._sizeMyselfHelper.call(this);
},
onClick: function(/*Event*/ e){
// summary: callback when button is clicked; user shouldn't override this function or else the menu won't toggle
this._toggleMenu(this.menuId);
}
});
/*
* usage
* <button dojoType="ComboButton" onClick="..." menuId="mymenu">Hello world</button>
*
* var button1 = dojo.widget.createWidget("DropDownButton", {caption: "hello world", onClick: foo, menuId: "myMenu"});
* document.body.appendChild(button1.domNode);
*/
dojo.widget.defineWidget(
"dojo.widget.ComboButton",
dojo.widget.Button,
{
// summary
// left side is normal button, right side displays menu
// menuId: String
// widget id of the menu that this button should activate
menuId: "",
templatePath: dojo.uri.dojoUri("src/widget/templates/ComboButtonTemplate.html"),
// splitWidth: Integer
// # of pixels between left & right part of button
splitWidth: 2,
// arrowWidth: Integer
// width of segment holding down arrow
arrowWidth: 5,
_sizeMyselfHelper: function(/*Event*/ e){
var mb = dojo.html.getMarginBox(this.containerNode);
this.height = mb.height;
this.containerWidth = mb.width;
var endWidth= this.height/3;
if(this.disabled){
dojo.widget.wai.setAttr(this.domNode, "waiState", "disabled", true);
this.domNode.removeAttribute("tabIndex");
}
else {
dojo.widget.wai.setAttr(this.domNode, "waiState", "disabled", false);
this.domNode.setAttribute("tabIndex", "0");
}
// left part
this.leftImage.height = this.rightImage.height = this.centerImage.height =
this.arrowBackgroundImage.height = this.height;
this.leftImage.width = endWidth+1;
this.centerImage.width = this.containerWidth;
this.buttonNode.style.height = this.height + "px";
this.buttonNode.style.width = endWidth + this.containerWidth + "px";
this._setImage(this.disabled ? this.disabledImg : this.inactiveImg);
// right part
this.arrowBackgroundImage.width=this.arrowWidth;
this.rightImage.width = endWidth+1;
this.rightPart.style.height = this.height + "px";
this.rightPart.style.width = this.arrowWidth + endWidth + "px";
this._setImageR(this.disabled ? this.disabledImg : this.inactiveImg);
// outer container
this.domNode.style.height=this.height + "px";
var totalWidth = this.containerWidth+this.splitWidth+this.arrowWidth+2*endWidth;
this.domNode.style.width= totalWidth + "px";
},
_setImage: function(prefix){
this.leftImage.src=dojo.uri.dojoUri(prefix + "l.gif");
this.centerImage.src=dojo.uri.dojoUri(prefix + "c.gif");
},
/*** functions on right part of button ***/
rightOver: function(/*Event*/ e){
// summary:
// callback when mouse-over right part of button;
// onMouseOver() is the callback for the left side of the button.
if( this.disabled ){ return; }
dojo.html.prependClass(this.rightPart, "dojoButtonHover");
this._setImageR(this.activeImg);
},
rightDown: function(/*Event*/ e){
// summary:
// callback when mouse-down right part of button;
// onMouseDown() is the callback for the left side of the button.
if( this.disabled ){ return; }
dojo.html.prependClass(this.rightPart, "dojoButtonDepressed");
dojo.html.removeClass(this.rightPart, "dojoButtonHover");
this._setImageR(this.pressedImg);
},
rightUp: function(/*Event*/ e){
// summary:
// callback when mouse-up right part of button;
// onMouseUp() is the callback for the left side of the button.
if( this.disabled ){ return; }
dojo.html.prependClass(this.rightPart, "dojoButtonHover");
dojo.html.removeClass(this.rightPart, "dojoButtonDepressed");
this._setImageR(this.activeImg);
},
rightOut: function(/*Event*/ e){
// summary:
// callback when moving the mouse off of the right part of button;
// onMouseOut() is the callback for the left side of the button.
if( this.disabled ){ return; }
dojo.html.removeClass(this.rightPart, "dojoButtonHover");
dojo.html.removeClass(this.rightPart, "dojoButtonDepressed");
this._setImageR(this.inactiveImg);
},
rightClick: function(/*Event*/ e){
// summary:
// callback when clicking the right part of button;
// onClick() is the callback for the left side of the button.
if( this.disabled ){ return; }
// focus may fail when tabIndex is not supported on div's
// by the browser, or when the node is disabled
try { this.domNode.focus(); } catch(e2) {};
this._toggleMenu(this.menuId);
},
_setImageR: function(prefix){
this.arrowBackgroundImage.src=dojo.uri.dojoUri(prefix + "c.gif");
this.rightImage.src=dojo.uri.dojoUri(prefix + "r.gif");
},
/*** keyboard functions ***/
onKey: function(/*Event*/ e){
if (!e.key) { return; }
var menu = dojo.widget.getWidgetById(this.menuId);
if(e.key== e.KEY_ENTER || e.key == " "){
this.onMouseDown(e);
this.buttonClick(e);
dojo.lang.setTimeout(this, "onMouseUp", 75, e);
dojo.event.browser.stopEvent(e);
} else if (e.key == e.KEY_DOWN_ARROW && e.altKey){
this.rightDown(e);
this.rightClick(e);
dojo.lang.setTimeout(this, "rightUp", 75, e);
dojo.event.browser.stopEvent(e);
} else if(menu && menu.isShowingNow && e.key == e.KEY_DOWN_ARROW){
// disconnect onBlur when focus moves into menu
dojo.event.disconnect(this.domNode, "onblur", this, "onBlur");
// allow event to propagate to menu
}
}
});