/* 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 * * * 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 * * * 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 * * * 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 } } });