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