You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by he...@apache.org on 2006/11/13 23:55:14 UTC
svn commit: r474551 [30/49] - in
/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo:
./ src/ src/alg/ src/animation/ src/cal/ src/charting/ src/charting/svg/
src/charting/vml/ src/collections/ src/crypto/ src/data/ src/data/cs...
Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Button.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Button.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Button.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Button.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004-2005, The Dojo Foundation
+ Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
@@ -9,15 +9,424 @@
*/
dojo.provide("dojo.widget.Button");
-dojo.require("dojo.widget.Widget");
-dojo.widget.tags.addParseTreeHandler("dojo:button");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.html.*");
+dojo.require("dojo.html.selection");
+dojo.require("dojo.widget.*");
-dojo.widget.Button = function(){
- dojo.widget.Widget.call(this);
+/*
+ * summary
+ * Basically the same thing as a normal HTML button, but with special styling.
+ * 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,
+ {
+ isContainer: true,
- this.widgetType = "Button";
- this.isContainer = true;
-}
-dojo.inherits(dojo.widget.Button, dojo.widget.Widget);
-dojo.requireAfterIf("html", "dojo.widget.html.Button");
+ // String
+ // text to display in button
+ caption: "",
+
+ // Boolean
+ // if true, cannot click button
+ disabled: false,
+
+ templatePath: dojo.uri.dojoUri("src/widget/templates/ButtonTemplate.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/ButtonTemplate.css"),
+
+ // Url
+ // prefix of filename holding images (left, center, right) for button in normal state
+ inactiveImg: "src/widget/templates/images/soriaButton-",
+
+ // Url
+ // prefix of filename holding images (left, center, right) for button when it's being hovered over
+ activeImg: "src/widget/templates/images/soriaActive-",
+
+ // Url
+ // prefix of filename holding images (left, center, right) for button between mouse-down and mouse-up
+ pressedImg: "src/widget/templates/images/soriaPressed-",
+
+ // Url
+ // prefix of filename holding images (left, center, right) for button when it's disabled (aka, grayed-out)
+ disabledImg: "src/widget/templates/images/soriaDisabled-",
+
+ // 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");
+ 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();
+ }
+ });
+
+/*
+ * summary
+ * push the button and a menu shows up
+ * 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,
+ {
+ // String
+ // widget id of the menu that this button should activate
+ menuId: "",
+
+ // Url
+ // path of arrow image to display to the right of the button text
+ downArrow: "src/widget/templates/images/whiteDownArrow.gif",
+
+ // 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);
+ }
+ });
+
+/*
+ * summary
+ * left side is normal button, right side displays menu
+ * 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,
+ {
+ // String
+ // widget id of the menu that this button should activate
+ menuId: "",
+
+ templatePath: dojo.uri.dojoUri("src/widget/templates/ComboButtonTemplate.html"),
+
+ // Integer
+ // # of pixels between left & right part of button
+ splitWidth: 2,
+
+ // 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");
+ 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
+ }
+ }
+ });
Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Chart.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Chart.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Chart.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Chart.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004-2005, The Dojo Foundation
+ Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
@@ -9,108 +9,187 @@
*/
dojo.provide("dojo.widget.Chart");
-dojo.provide("dojo.widget.Chart.DataSeries");
dojo.require("dojo.widget.*");
-dojo.require("dojo.widget.Widget");
-dojo.require("dojo.graphics.color");
-dojo.widget.tags.addParseTreeHandler("dojo:chart");
-
-dojo.requireAfterIf(dojo.render.svg.support.builtin, "dojo.widget.svg.Chart");
-
-dojo.widget.Chart=function(){
- dojo.widget.Widget.call(this);
- this.widgetType="Chart";
- this.isContainer=false;
- this.series=[];
- this.assignColors=function(){
- var hue=30, sat=120, lum=120;
+dojo.require("dojo.gfx.color");
+dojo.require("dojo.gfx.color.hsl");
+
+// Base class for svg and vml implementations of Chart
+dojo.declare(
+ "dojo.widget.Chart",
+ null,
+ function(){
+ this.series = [];
+ },
+{
+ isContainer: false,
+
+ assignColors: function(){
+ // summary
+ // Assigns/generates a color for a data series.
+ var hue=30;
+ var sat=120;
+ var lum=120;
var steps = Math.round(330/this.series.length);
- for (var i=0; i<this.series.length; i++){
- var c=dojo.graphics.color.hsl2rgb(hue,sat,lum);
- if (!this.series[i].color)
- this.series[i].color=dojo.graphics.color.rgb2hex(c[0],c[1],c[2]);
- hue+=steps;
- }
- };
-}
-dojo.inherits(dojo.widget.Chart, dojo.widget.Widget);
-
-/* Every chart has a set of data series; this is the series.
- Note that each member of value is an object and in the
- minimum has 2 properties: .x and .value.
+
+ for(var i=0; i<this.series.length; i++){
+ var c=dojo.gfx.color.hsl2rgb(hue,sat,lum);
+ if(!this.series[i].color){
+ this.series[i].color = dojo.gfx.color.rgb2hex(c[0],c[1],c[2]);
+ }
+ hue += steps;
+ }
+ },
+ parseData: function(table){
+ var thead=table.getElementsByTagName("thead")[0];
+ var tbody=table.getElementsByTagName("tbody")[0];
+ if(!(thead&&tbody)) dojo.raise("dojo.widget.Chart: supplied table must define a head and a body.");
+
+ // set up the series.
+ var columns=thead.getElementsByTagName("tr")[0].getElementsByTagName("th"); // should be <tr><..>
+
+ // assume column 0 == X
+ for (var i=1; i<columns.length; i++){
+ var key="column"+i;
+ var label=columns[i].innerHTML;
+ var plotType=columns[i].getAttribute("plotType")||"line";
+ var color=columns[i].getAttribute("color");
+ var ds=new dojo.widget.Chart.DataSeries(key,label,plotType,color);
+ this.series.push(ds);
+ }
+
+ // ok, get the values.
+ var rows=tbody.rows;
+ var xMin=Number.MAX_VALUE,xMax=Number.MIN_VALUE;
+ var yMin=Number.MAX_VALUE,yMax=Number.MIN_VALUE;
+ var ignore = [
+ "accesskey","align","bgcolor","class",
+ "colspan","height","id","nowrap",
+ "rowspan","style","tabindex","title",
+ "valign","width"
+ ];
+
+ for(var i=0; i<rows.length; i++){
+ var row=rows[i];
+ var cells=row.cells;
+ var x=Number.MIN_VALUE;
+ for (var j=0; j<cells.length; j++){
+ if (j==0){
+ x=parseFloat(cells[j].innerHTML);
+ xMin=Math.min(xMin, x);
+ xMax=Math.max(xMax, x);
+ } else {
+ var ds=this.series[j-1];
+ var y=parseFloat(cells[j].innerHTML);
+ yMin=Math.min(yMin,y);
+ yMax=Math.max(yMax,y);
+ var o={x:x, value:y};
+ var attrs=cells[j].attributes;
+ for(var k=0; k<attrs.length; k++){
+ var attr=attrs.item(k);
+ var bIgnore=false;
+ for (var l=0; l<ignore.length; l++){
+ if (attr.nodeName.toLowerCase()==ignore[l]){
+ bIgnore=true;
+ break;
+ }
+ }
+ if(!bIgnore) o[attr.nodeName]=attr.nodeValue;
+ }
+ ds.add(o);
+ }
+ }
+ }
+ return { x:{ min:xMin, max:xMax}, y:{ min:yMin, max:yMax} };
+ }
+});
+
+/*
+ * Every chart has a set of data series; this is the series. Note that each
+ * member of value is an object and in the minimum has 2 properties: .x and
+ * .value.
*/
-dojo.widget.Chart.DataSeries=function(key, label, plotType, color){
- this.id="DataSeries"+dojo.widget.Chart.DataSeries.count++;
- this.key=key;
- this.label=label||this.id;
- this.plotType=plotType||0;
- this.color=color;
- this.values=[];
-};
-dojo.widget.Chart.DataSeries.prototype={
- add:function(v){
+dojo.declare(
+ "dojo.widget.Chart.DataSeries",
+ null,
+ function(key, label, plotType, color){
+ this.id = "DataSeries"+dojo.widget.Chart.DataSeries.count++;
+ this.key = key;
+ this.label = label||this.id;
+ this.plotType = plotType||"line"; // let line be the default.
+ this.color = color;
+ this.values = [];
+ },
+{
+ add: function(v){
if(v.x==null||v.value==null){
dojo.raise("dojo.widget.Chart.DataSeries.add: v must have both an 'x' and 'value' property.");
}
this.values.push(v);
},
- clear:function(){
+
+ clear: function(){
this.values=[];
},
- createRange:function(len){
- var idx=this.values.length-1;
- var length=len||this.values.length;
- return {index:idx, length:length, start:Math.max(idx-length,0)};
+
+ createRange: function(len){
+ var idx = this.values.length-1;
+ var length = (len||this.values.length);
+ return { "index": idx, "length": length, "start":Math.max(idx-length,0) };
},
+
// trend values
- getMean:function(len){
- var range=this.createRange(len);
- if (range.index<0) return 0;
- var t=0, c=0;
- for (var i=range.index; i>=range.start; i--){
- var n=parseFloat(this.values[i].value);
- if (!isNaN(n)){
- t+=n; c++;
- }
+ getMean: function(len){
+ var range = this.createRange(len);
+ if(range.index<0){ return 0; }
+ var t = 0;
+ var c = 0;
+ for(var i=range.index; i>=range.start; i--){
+ var n = parseFloat(this.values[i].value);
+ if(!isNaN(n)){ t += n; c++; }
}
- t/=Math.max(c,1);
+ t /= Math.max(c,1);
return t;
},
- getMovingAverage:function(len){
- var range=this.createRange(len);
- if (range.index<0) return 0;
- var t=0, c=0;
- for (var i=range.index; i>=range.start; i--){
- var n=parseFloat(this.values[i].value);
- if (!isNaN(n)){
- t+=n; c++;
- }
+
+ getMovingAverage: function(len){
+ var range = this.createRange(len);
+ if(range.index<0){ return 0; }
+ var t = 0;
+ var c = 0;
+ for(var i=range.index; i>=range.start; i--){
+ var n = parseFloat(this.values[i].value);
+ if(!isNaN(n)){ t += n; c++; }
}
- t/=Math.max(c,1);
+ t /= Math.max(c,1);
return t;
},
- getVariance:function(len){
- var range=this.createRange(len);
- if (range.index < 0) return 0;
- var t=0, s=0, c=0;
- for (var i=range.index; i>=range.start; i--){
- var n=parseFloat(this.values[i].value);
- if (!isNaN(n)){
- t+=n;
- s+=Math.pow(n,2);
+
+ getVariance: function(len){
+ var range = this.createRange(len);
+ if(range.index < 0){ return 0; }
+ var t = 0; // FIXME: for tom: wtf are t, c, and s?
+ var s = 0;
+ var c = 0;
+ for(var i=range.index; i>=range.start; i--){
+ var n = parseFloat(this.values[i].value);
+ if(!isNaN(n)){
+ t += n;
+ s += Math.pow(n,2);
c++;
}
}
return (s/c)-Math.pow(t/c,2);
},
- getStandardDeviation:function(len){
+
+ getStandardDeviation: function(len){
return Math.sqrt(this.getVariance(len));
},
- getMax:function(len){
- var range=this.createRange(len);
- if (range.index < 0) return 0;
- var t=0;
+
+ getMax: function(len){
+ var range = this.createRange(len);
+ if(range.index < 0){ return 0; }
+ var t = 0;
for (var i=range.index; i>=range.start; i--){
var n=parseFloat(this.values[i].value);
if (!isNaN(n)){
@@ -119,22 +198,26 @@
}
return t;
},
- getMin:function(len){
+
+ getMin: function(len){
var range=this.createRange(len);
- if (range.index < 0) return 0;
- var t=0;
- for (var i=range.index; i>=range.start; i--){
- var n=parseFloat(this.values[i].value);
- if (!isNaN(n)){
+ if(range.index < 0){ return 0; }
+ var t = 0;
+ for(var i=range.index; i>=range.start; i--){
+ var n = parseFloat(this.values[i].value);
+ if(!isNaN(n)){
t=Math.min(n,t);
}
}
return t;
},
- getMedian:function(len){
- var range=this.createRange(len);
- if (range.index<0) return 0;
- var a=[];
+
+ getMedian: function(len){
+ var range = this.createRange(len);
+
+ if(range.index<0){ return 0; }
+
+ var a = [];
for (var i=range.index; i>=range.start; i--){
var n=parseFloat(this.values[i].value);
if (!isNaN(n)){
@@ -142,29 +225,33 @@
for(var j=0; j<a.length&&!b; j++){
if (n==a[j]) b=true;
}
- if(!b) a.push(n);
+ if(!b){ a.push(n); }
}
}
a.sort();
- if(a.length>0) return a[Math.ceil(a.length/2)];
+ if(a.length>0){ return a[Math.ceil(a.length/2)]; }
return 0;
},
- getMode:function(len){
+
+ getMode: function(len){
var range=this.createRange(len);
- if (range.index<0) return 0;
- var o={}, ret=0, m=0;
- for (var i=range.index; i>=range.start; i--){
+ if(range.index<0){ return 0; }
+ var o = {};
+ var ret = 0
+ var m = 0;
+ for(var i=range.index; i>=range.start; i--){
var n=parseFloat(this.values[i].value);
- if (!isNaN(n)){
+ if(!isNaN(n)){
if (!o[this.values[i].value]) o[this.values[i].value] = 1;
else o[this.values[i].value]++;
}
}
- for (var p in o){
- if(m<o[p]){
- m=o[p]; ret=p;
- }
+ for(var p in o){
+ if(m<o[p]){ m=o[p]; ret=p; }
}
return parseFloat(ret);
}
-};
+});
+
+dojo["requireIf"](dojo.render.svg.capable, "dojo.widget.svg.Chart");
+dojo["requireIf"](!dojo.render.svg.capable && dojo.render.vml.capable, "dojo.widget.vml.Chart");
Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Checkbox.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Checkbox.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Checkbox.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Checkbox.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004-2005, The Dojo Foundation
+ Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
@@ -11,18 +11,172 @@
dojo.provide("dojo.widget.Checkbox");
dojo.require("dojo.widget.*");
-dojo.require("dojo.event");
-dojo.require("dojo.html");
-
-dojo.widget.tags.addParseTreeHandler("dojo:Checkbox");
-
-dojo.widget.Checkbox = function(){
- dojo.widget.Widget.call(this);
-};
-dojo.inherits(dojo.widget.Checkbox, dojo.widget.Widget);
-
-dojo.lang.extend(dojo.widget.Checkbox, {
- widgetType: "Checkbox"
-});
-
-dojo.requireAfterIf("html", "dojo.widget.html.Checkbox");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html.style");
+dojo.require("dojo.html.selection");
+
+// summary
+// Same as an HTML checkbox, but with fancy styling
+dojo.widget.defineWidget(
+ "dojo.widget.Checkbox",
+ dojo.widget.HtmlWidget,
+ {
+ templatePath: dojo.uri.dojoUri('src/widget/templates/Checkbox.html'),
+ templateCssPath: dojo.uri.dojoUri('src/widget/templates/Checkbox.css'),
+
+ // Boolean
+ // if true, clicking will not change the state of the checkbox.
+ // in markup, this is specified as "disabled='disabled'", or just "disabled",
+ disabled: false,
+
+ // String
+ // name used when submitting form; same as "name" attribute or plain HTML elements
+ name: "",
+
+ // String
+ // id attached to the checkbox, used when submitting form
+ id: "",
+
+ // Boolean
+ // if true, checkbox is initially marked turned on;
+ // in markup, specified as "checked='checked'" or just "checked"
+ checked: false,
+
+ // Integer
+ // order fields are traversed when user hits the tab key
+ tabIndex: "",
+
+ // Value
+ // equivalent to value field on normal checkbox (if checked, the value is passed as
+ // the value when form is submitted)
+ value: "on",
+
+ postMixInProperties: function(){
+ dojo.widget.Checkbox.superclass.postMixInProperties.apply(this, arguments);
+
+ // set tabIndex="0" because if tabIndex=="" user won't be able to tab to the field
+ if(!this.disabled && this.tabIndex==""){ this.tabIndex="0"; }
+ },
+
+ fillInTemplate: function(){
+ this._setInfo();
+ },
+
+ postCreate: function(){
+ // find any associated label and create a labelled-by relationship
+ // assumes <label for="inputId">label text </label> rather than
+ // <label><input type="xyzzy">label text</label>
+ var notcon = true;
+ this.id = this.id !="" ? this.id : this.widgetId;
+ if(this.id != ""){
+ var labels = document.getElementsByTagName("label");
+ if (labels != null && labels.length > 0){
+ for(var i=0; i<labels.length; i++){
+ if (labels[i].htmlFor == this.id){
+ labels[i].id = (labels[i].htmlFor + "label");
+ this._connectEvents(labels[i]);
+ dojo.widget.wai.setAttr(this.domNode, "waiState", "labelledby", labels[i].id);
+ break;
+ }
+ }
+ }
+ }
+ this._connectEvents(this.domNode);
+ // this is needed here for IE
+ this.inputNode.checked=this.checked;
+ },
+
+ _connectEvents: function(/*DomNode*/ node){
+ dojo.event.connect(node, "onmouseover", this, "mouseOver");
+ dojo.event.connect(node, "onmouseout", this, "mouseOut");
+ dojo.event.connect(node, "onkey", this, "onKey");
+ dojo.event.connect(node, "onclick", this, "_onClick");
+ dojo.html.disableSelection(node);
+ },
+
+ _onClick: function(/*Event*/ e){
+ if(this.disabled == false){
+ this.checked = !this.checked;
+ this._setInfo();
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ this.onClick();
+ },
+
+ onClick: function(){
+ // summary: user overridable callback function for checkbox being clicked
+ },
+
+ onKey: function(/*Event*/ e){
+ // summary: callback when user hits a key
+ var k = dojo.event.browser.keys;
+ if(e.key == " "){
+ this._onClick(e);
+ }
+ },
+
+ mouseOver: function(/*Event*/ e){
+ // summary: callback when user moves mouse over checkbox
+ this._hover(e, true);
+ },
+
+ mouseOut: function(/*Event*/ e){
+ // summary: callback when user moves mouse off of checkbox
+ this._hover(e, false);
+ },
+
+ _hover: function(/*Event*/ e, /*Boolean*/ isOver){
+ if (this.disabled == false){
+ var state = this.checked ? "On" : "Off";
+ var style = "dojoHtmlCheckbox" + state + "Hover";
+ if (isOver){
+ dojo.html.addClass(this.imageNode, style);
+ }else{
+ dojo.html.removeClass(this.imageNode,style);
+ }
+ }
+ },
+
+ _setInfo: function(){
+ // summary:
+ // set state of hidden checkbox node to correspond to displayed value.
+ // also set CSS class string according to checked/unchecked and disabled/enabled state
+ var state = "dojoHtmlCheckbox" + (this.disabled ? "Disabled" : "") + (this.checked ? "On" : "Off");
+ dojo.html.setClass(this.imageNode, "dojoHtmlCheckbox " + state);
+ this.inputNode.checked = this.checked;
+ if(this.disabled){
+ this.inputNode.setAttribute("disabled",true);
+ }else{
+ this.inputNode.removeAttribute("disabled");
+ }
+ dojo.widget.wai.setAttr(this.domNode, "waiState", "checked", this.checked);
+ }
+ }
+);
+
+// summary
+// variation on Checkbox widget to be display on monitors in high-contrast mode (that don't display CSS background images)
+dojo.widget.defineWidget(
+ "dojo.widget.a11y.Checkbox",
+ dojo.widget.Checkbox,
+ {
+ templatePath: dojo.uri.dojoUri('src/widget/templates/CheckboxA11y.html'),
+
+ fillInTemplate: function(){
+ },
+
+ postCreate: function(args, frag){
+ this.inputNode.checked=this.checked;
+ //only set disabled if true since FF interprets any value for disabled as true
+ if (this.disabled){
+ this.inputNode.setAttribute("disabled",true);
+ }
+ },
+
+ _onClick: function(){
+ this.onClick();
+ }
+ }
+);
\ No newline at end of file
Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Clock.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Clock.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Clock.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Clock.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,211 @@
+/*
+ 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.Clock");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.gfx.*");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.lang.timing.Timer");
+
+dojo.widget.defineWidget(
+ "dojo.widget.Clock",
+ dojo.widget.HtmlWidget,
+ function(){
+ var self=this;
+ this.timeZoneOffset=0; // this is fun.
+ this.label=""; // optional label.
+
+ this.date=new Date();
+
+ this.handColor="#788598";
+ this.handStroke="#6f7b8c";
+ // this.secondHandColor="#c90405";
+ this.secondHandColor=[201, 4, 5, 0.8];
+ this.topLabelColor="#efefef";
+ this.labelColor="#fff";
+
+ // timer
+ this.timer = new dojo.lang.timing.Timer(1000);
+
+ // shapes
+ this.center={ x:75, y:75 };
+ this.hands={
+ hour:null,
+ minute:null,
+ second:null
+ };
+ this.shadows={
+ hour:{ shadow:null, shift:{ dx:2, dy:2} },
+ minute:{ shadow:null, shift:{ dx:2, dy:3} },
+ second:{ shadow:null, shift:{ dx:4, dy:4} }
+ };
+ this.image = dojo.uri.dojoUri("src/widget/templates/images/clock.png");
+ this.surface=null;
+ this.labelNode=null;
+ this.topLabelNode=null;
+
+ this.draw=function(){
+ self.date=new Date();
+ var h=(self.date.getHours()+self.timeZoneOffset) % 12;
+ var m=self.date.getMinutes();
+ var s=self.date.getSeconds();
+
+ self.placeHour(h, m, s);
+ self.placeMinute(m, s);
+ self.placeSecond(s);
+
+ self.topLabelNode.innerHTML=((self.date.getHours()+self.timeZoneOffset)>11)?"PM":"AM";
+ };
+
+ this.timer.onTick=self.draw;
+ },
+ {
+ set:function(/* Date */dt){
+ this.date=dt;
+ if(!this.timer.isRunning){
+ this.draw();
+ }
+ },
+ start:function(){ this.timer.start(); },
+ stop:function(){ this.timer.stop(); },
+
+ _initPoly:function(parent, points){
+ var path = parent.createPath();
+ var first = true;
+ dojo.lang.forEach(points, function(c){
+ if(first){
+ path.moveTo(c.x, c.y);
+ first=false;
+ } else {
+ path.lineTo(c.x, c.y);
+ }
+ });
+ return path;
+ },
+ _placeHand:function(shape, angle, shift){
+ var move = { dx:this.center.x + (shift?shift.dx:0), dy:this.center.y+(shift?shift.dy:0) };
+ return shape.setTransform([move, dojo.gfx.matrix.rotateg(-angle)]);
+ },
+ placeHour:function(h, m, s){
+ var angle=30 *(h + m/60 + s/3600);
+ this._placeHand(this.hands.hour, angle);
+ this._placeHand(this.shadows.hour.shadow, angle, this.shadows.hour.shift);
+ },
+ placeMinute:function(m, s){
+ var angle=6 * (m + s/60);
+ this._placeHand(this.hands.minute, angle);
+ this._placeHand(this.shadows.minute.shadow, angle, this.shadows.minute.shift);
+ },
+ placeSecond:function(s){
+ var angle=6 * s;
+ this._placeHand(this.hands.second, angle);
+ this._placeHand(this.shadows.second.shadow, angle, this.shadows.second.shift);
+ },
+
+ init:function(){
+ // start by setting up the domNode
+ if(this.domNode.style.position != "absolute"){
+ this.domNode.style.position = "relative";
+ }
+
+ // clean out any children
+ while(this.domNode.childNodes.length>0){
+ this.domNode.removeChild(this.domNode.childNodes[0]);
+ }
+
+ // set ourselves up.
+ this.domNode.style.width="150px";
+ this.domNode.style.height="150px";
+
+ this.surface=dojo.gfx.createSurface(this.domNode, 150, 150);
+ this.surface.createRect({width: 150, height: 150});
+ this.surface.createImage({width: 150, height: 150, src: this.image+""});
+
+ var hP=[ {x: -3, y: -4}, {x: 3, y: -4}, {x: 1, y: -27}, { x:-1, y:-27}, {x: -3, y: -4} ];
+ var mP=[ {x: -3, y: -4}, {x: 3, y: -4}, {x: 1, y: -38}, {x:-1, y:-38}, {x: -3, y: -4} ];
+ var sP=[ {x: -2, y: -2}, {x: 2, y: -2}, {x: 1, y: -45}, {x: -1, y: -45}, {x: -2, y: -2} ];
+
+ this.shadows.hour.shadow = this._initPoly(this.surface, hP)
+ .setFill([0, 0, 0, 0.1]);
+ this.hands.hour = this._initPoly(this.surface, hP)
+ .setStroke({color: this.handStroke, width:1 })
+ .setFill({
+ type:"linear",
+ x1:0, y1:0, x2:0, y2:-27,
+ colors:[{offset:0, color:"#fff"}, {offset:0.33, color:this.handColor}]
+ });
+ this.shadows.minute.shadow = this._initPoly(this.surface, mP)
+ .setFill([0, 0, 0, 0.1]);
+ this.hands.minute = this._initPoly(this.surface, mP)
+ .setStroke({color: this.handStroke, width:1 })
+ .setFill({
+ type:"linear",
+ x1:0, y1:0, x2:0, y2:-38,
+ colors:[{offset:0, color:"#fff"}, {offset:0.33, color:this.handColor}]
+ });
+
+ this.surface.createCircle({r: 6})
+ .setStroke({color: this.handStroke, width:2 })
+ .setFill("#fff")
+ .setTransform({dx: 75, dy: 75});
+
+ this.shadows.second.shadow = this._initPoly(this.surface, sP)
+ .setFill([0, 0, 0, 0.1]);
+ this.hands.second = this._initPoly(this.surface, sP)
+ .setFill(this.secondHandColor);
+
+ // clock centers, doesn't move.
+ this.surface.createCircle({r: 4})
+ .setFill(this.secondHandColor)
+ .setTransform({dx: 75, dy: 75});
+
+ // labels
+ this.topLabelNode=document.createElement("div");
+ with(this.topLabelNode.style){
+ position="absolute";
+ top="3px";
+ left="0px";
+ color=this.topLabelColor;
+ textAlign="center";
+ width="150px";
+ fontFamily="sans-serif";
+ fontSize="11px";
+ textTransform="uppercase";
+ fontWeight="bold";
+ }
+ this.topLabelNode.innerHTML=((this.date.getHours()+this.timeZoneOffset)>11)?"PM":"AM";
+ this.domNode.appendChild(this.topLabelNode);
+
+ this.labelNode=document.createElement("div");
+ with(this.labelNode.style){
+ position="absolute";
+ top="134px";
+ left="0px";
+ color=this.labelColor;
+ textAlign="center";
+ width="150px";
+ fontFamily="sans-serif";
+ fontSize="10px";
+ textTransform="uppercase";
+ fontWeight="bold";
+ }
+ this.labelNode.innerHTML=this.label||" ";
+ this.domNode.appendChild(this.labelNode);
+
+ this.draw();
+ },
+ postCreate:function(){
+ this.init();
+ this.start();
+ }
+ }
+);
Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ColorPalette.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ColorPalette.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ColorPalette.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ColorPalette.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004-2005, The Dojo Foundation
+ Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
@@ -9,73 +9,19 @@
*/
dojo.provide("dojo.widget.ColorPalette");
-dojo.provide("dojo.widget.html.ColorPalette");
dojo.require("dojo.widget.*");
-dojo.require("dojo.widget.Toolbar");
-dojo.require("dojo.html");
-
-dojo.widget.tags.addParseTreeHandler("dojo:ToolbarColorDialog");
-
-dojo.widget.html.ToolbarColorDialog = function () {
- dojo.widget.html.ToolbarDialog.call(this);
-
- for (var method in this.constructor.prototype) {
- this[method] = this.constructor.prototype[method];
- }
-}
-
-dojo.inherits(dojo.widget.html.ToolbarColorDialog, dojo.widget.html.ToolbarDialog);
-
-dojo.lang.extend(dojo.widget.html.ToolbarColorDialog, {
-
- widgetType: "ToolbarColorDialog",
-
- palette: "7x10",
-
- fillInTemplate: function (args, frag) {
- dojo.widget.html.ToolbarColorDialog.superclass.fillInTemplate.call(this, args, frag);
- this.dialog = dojo.widget.createWidget("ColorPalette", {palette: this.palette});
- this.dialog.domNode.style.position = "absolute";
-
- dojo.event.connect(this.dialog, "onColorSelect", this, "_setValue");
- },
-
- _setValue: function(color) {
- this._value = color;
- this._fireEvent("onSetValue", color);
- },
-
- showDialog: function (e) {
- dojo.widget.html.ToolbarColorDialog.superclass.showDialog.call(this, e);
- var x = dojo.html.getAbsoluteX(this.domNode);
- var y = dojo.html.getAbsoluteY(this.domNode) + dojo.html.getInnerHeight(this.domNode);
- this.dialog.showAt(x, y);
- },
-
- hideDialog: function (e) {
- dojo.widget.html.ToolbarColorDialog.superclass.hideDialog.call(this, e);
- this.dialog.hide();
- }
-});
-
-
-
-dojo.widget.tags.addParseTreeHandler("dojo:colorpalette");
-
-dojo.widget.html.ColorPalette = function () {
- dojo.widget.HtmlWidget.call(this);
-}
-
-dojo.inherits(dojo.widget.html.ColorPalette, dojo.widget.HtmlWidget);
-
-dojo.lang.extend(dojo.widget.html.ColorPalette, {
-
- widgetType: "colorpalette",
-
+dojo.require("dojo.html.layout");
+dojo.require("dojo.html.display");
+dojo.require("dojo.html.selection");
+
+dojo.widget.defineWidget(
+ "dojo.widget.ColorPalette",
+ dojo.widget.HtmlWidget,
+{
palette: "7x10",
bgIframe: null,
-
+
palettes: {
"7x10": [["fff", "fcc", "fc9", "ff9", "ffc", "9f9", "9ff", "cff", "ccf", "fcf"],
["ccc", "f66", "f96", "ff6", "ff3", "6f9", "3ff", "6ff", "99f", "f9f"],
@@ -84,7 +30,7 @@
["666", "900", "c60", "c93", "990", "090", "399", "33f", "60c", "939"],
["333", "600", "930", "963", "660", "060", "366", "009", "339", "636"],
["000", "300", "630", "633", "330", "030", "033", "006", "309", "303"]],
-
+
"3x4": [["ffffff"/*white*/, "00ff00"/*lime*/, "008000"/*green*/, "0000ff"/*blue*/],
["c0c0c0"/*silver*/, "ffff00"/*yellow*/, "ff00ff"/*fuchsia*/, "000080"/*navy*/],
["808080"/*gray*/, "ff0000"/*red*/, "800080"/*purple*/, "000000"/*black*/]]
@@ -92,8 +38,8 @@
},
buildRendering: function () {
-
this.domNode = document.createElement("table");
+// dojo.body().appendChild(this.domNode);
dojo.html.disableSelection(this.domNode);
dojo.event.connect(this.domNode, "onmousedown", function (e) {
e.preventDefault();
@@ -102,45 +48,41 @@
cellPadding = "0"; cellSpacing = "1"; border = "1";
style.backgroundColor = "white"; //style.position = "absolute";
}
- var tbody = document.createElement("tbody");
- this.domNode.appendChild(tbody);
var colors = this.palettes[this.palette];
for (var i = 0; i < colors.length; i++) {
- var tr = document.createElement("tr");
+ var tr = this.domNode.insertRow(-1);
for (var j = 0; j < colors[i].length; j++) {
if (colors[i][j].length == 3) {
colors[i][j] = colors[i][j].replace(/(.)(.)(.)/, "$1$1$2$2$3$3");
}
-
- var td = document.createElement("td");
+
+ var td = tr.insertCell(-1);
with (td.style) {
backgroundColor = "#" + colors[i][j];
border = "1px solid gray";
width = height = "15px";
fontSize = "1px";
}
-
+
td.color = "#" + colors[i][j];
-
+
td.onmouseover = function (e) { this.style.borderColor = "white"; }
td.onmouseout = function (e) { this.style.borderColor = "gray"; }
dojo.event.connect(td, "onmousedown", this, "click");
-
+
td.innerHTML = " ";
- tr.appendChild(td);
}
- tbody.appendChild(tr);
}
if(dojo.render.html.ie){
- this.bgIframe = document.createElement("<iframe frameborder='0' src='about:blank'>");
+ this.bgIframe = document.createElement("<iframe frameborder='0' src='javascript:void(0);'>");
with(this.bgIframe.style){
position = "absolute";
left = top = "0px";
display = "none";
}
- dojo.html.body().appendChild(this.bgIframe);
- dojo.style.setOpacity(this.bgIframe, 0);
+ dojo.body().appendChild(this.bgIframe);
+ dojo.html.setOpacity(this.bgIframe, 0);
}
},
@@ -157,25 +99,25 @@
this.bgIframe.style.display = "none";
}
},
-
+
showAt: function (x, y) {
with(this.domNode.style){
top = y + "px";
left = x + "px";
zIndex = 999;
}
- dojo.html.body().appendChild(this.domNode);
+ dojo.body().appendChild(this.domNode);
if(this.bgIframe){
with(this.bgIframe.style){
display = "block";
top = y + "px";
left = x + "px";
zIndex = 998;
- width = dojo.html.getOuterWidth(this.domNode) + "px";
- height = dojo.html.getOuterHeight(this.domNode) + "px";
+ var s = dojo.html.getMarginBox(this.domNode);
+ width = s.width + "px";
+ height = s.height + "px";
}
}
}
-
});
Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ComboBox.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ComboBox.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ComboBox.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ComboBox.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004-2005, The Dojo Foundation
+ Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
@@ -12,42 +12,63 @@
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
+dojo.require("dojo.io.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.html.*");
+dojo.require("dojo.html.display");
+dojo.require("dojo.html.layout");
+dojo.require("dojo.html.iframe");
+dojo.require("dojo.string");
+dojo.require("dojo.widget.html.stabile");
+dojo.require("dojo.widget.PopupContainer");
-dojo.widget.incrementalComboBoxDataProvider = function(url, limit, timeout){
+dojo.widget.incrementalComboBoxDataProvider = function(/*String*/ url, /*Number*/ limit, /*Number*/ timeout){
this.searchUrl = url;
this.inFlight = false;
this.activeRequest = null;
this.allowCache = false;
this.cache = {};
- this.addToCache = function(keyword, data){
+
+ this.init = function(/*Widget*/ cbox){
+ this.searchUrl = cbox.dataUrl;
+ };
+
+ this.addToCache = function(/*String*/ keyword, /*Array*/ data){
if(this.allowCache){
this.cache[keyword] = data;
}
- }
+ };
- this.startSearch = function(searchStr, type, ignoreLimit){
+ this.startSearch = function(/*String*/ searchStr, /*String*/ type, /*Boolean*/ ignoreLimit){
if(this.inFlight){
// FIXME: implement backoff!
}
var tss = encodeURIComponent(searchStr);
- var realUrl = dojo.string.paramString(this.searchUrl, {"searchString": tss});
+ var realUrl = dojo.string.substituteParams(this.searchUrl, {"searchString": tss});
var _this = this;
var request = dojo.io.bind({
url: realUrl,
method: "get",
- mimetype: "text/javascript",
+ mimetype: "text/json",
load: function(type, data, evt){
_this.inFlight = false;
+ if(!dojo.lang.isArray(data)){
+ var arrData = [];
+ for(var key in data){
+ arrData.push([data[key], key]);
+ }
+ data = arrData;
+ }
_this.addToCache(searchStr, data);
_this.provideSearchResults(data);
}
});
this.inFlight = true;
- }
-}
+ };
+};
-dojo.widget.ComboBoxDataProvider = function(dataPairs, limit, timeout){
+dojo.widget.ComboBoxDataProvider = function(/*Array*/ dataPairs, /*Number*/ limit, /*Number*/ timeout){
// NOTE: this data provider is designed as a naive reference
// implementation, and as such it is written more for readability than
// speed. A deployable data provider would implement lookups, search
@@ -55,23 +76,63 @@
// structure for storage of items.
this.data = [];
- this.searchTimeout = 500;
- this.searchLimit = 30;
+ this.searchTimeout = timeout || 500;
+ this.searchLimit = limit || 30;
this.searchType = "STARTSTRING"; // may also be "STARTWORD" or "SUBSTRING"
this.caseSensitive = false;
// for caching optimizations
this._lastSearch = "";
this._lastSearchResults = null;
- this.startSearch = function(searchStr, type, ignoreLimit){
+ this.init = function(/*Widget*/ cbox, /*DomNode*/ node){
+ if(!dojo.string.isBlank(cbox.dataUrl)){
+ this.getData(cbox.dataUrl);
+ }else{
+ // check to see if we can populate the list from <option> elements
+ if((node)&&(node.nodeName.toLowerCase() == "select")){
+ // NOTE: we're not handling <optgroup> here yet
+ var opts = node.getElementsByTagName("option");
+ var ol = opts.length;
+ var data = [];
+ for(var x=0; x<ol; x++){
+ var text = opts[x].textContent || opts[x].innerText || opts[x].innerHTML;
+ var keyValArr = [String(text), String(opts[x].value)];
+ data.push(keyValArr);
+ if(opts[x].selected){
+ cbox.setAllValues(keyValArr[0], keyValArr[1]);
+ }
+ }
+ this.setData(data);
+ }
+ }
+ };
+
+ this.getData = function(/*String*/ url){
+ dojo.io.bind({
+ url: url,
+ load: dojo.lang.hitch(this, function(type, data, evt){
+ if(!dojo.lang.isArray(data)){
+ var arrData = [];
+ for(var key in data){
+ arrData.push([data[key], key]);
+ }
+ data = arrData;
+ }
+ this.setData(data);
+ }),
+ mimetype: "text/json"
+ });
+ };
+
+ this.startSearch = function(/*String*/ searchStr, /*String*/ type, /*Boolean*/ ignoreLimit){
// FIXME: need to add timeout handling here!!
this._preformSearch(searchStr, type, ignoreLimit);
- }
+ };
- this._preformSearch = function(searchStr, type, ignoreLimit){
+ this._preformSearch = function(/*String*/ searchStr, /*String*/ type, /*Boolean*/ ignoreLimit){
//
// NOTE: this search is LINEAR, which means that it exhibits perhaps
- // the worst possible speed charachteristics of any search type. It's
+ // the worst possible speed characteristics of any search type. It's
// written this way to outline the responsibilities and interfaces for
// a search.
//
@@ -95,8 +156,6 @@
}
if(st == "STARTSTRING"){
- // jum.debug(dataLabel.substr(0, searchStr.length))
- // jum.debug(searchStr);
if(searchStr == dataLabel.substr(0, searchStr.length)){
ret.push(this.data[x]);
}
@@ -129,7 +188,7 @@
// FIXME: what about tab chars?
matches = true; break;
}
- idx = dataLabel.indexOf(searchStr, tti+1);
+ idx = dataLabel.indexOf(searchStr, idx+1);
}
if(!matches){
continue;
@@ -139,59 +198,643 @@
}
}
this.provideSearchResults(ret);
- }
+ };
- this.provideSearchResults = function(resultsDataPairs){
- }
+ this.provideSearchResults = function(/*Array*/ resultsDataPairs){
+ };
- this.addData = function(pairs){
+ this.addData = function(/*Array*/ pairs){
// FIXME: incredibly naive and slow!
this.data = this.data.concat(pairs);
- }
+ };
- this.setData = function(pdata){
+ this.setData = function(/*Array*/ pdata){
// populate this.data and initialize lookup structures
this.data = pdata;
- }
+ };
if(dataPairs){
this.setData(dataPairs);
}
-}
-
-dojo.widget.ComboBox = function(){
- dojo.widget.Widget.call(this);
-}
-
-dojo.inherits(dojo.widget.ComboBox, dojo.widget.Widget);
-
-dojo.widget.ComboBox.defaults = {
- widgetType: "ComboBox",
- isContainer: false,
-
- forceValidOption: false,
- searchType: "stringstart",
- dataProvider: null,
-
- startSearch: function(searchString){},
- openResultList: function(results){},
- clearResultList: function(){},
- hideResultList: function(){},
- selectNextResult: function(){},
- selectPrevResult: function(){},
- setSelectedResult: function(){}
};
-dojo.lang.extend(dojo.widget.ComboBox, dojo.widget.ComboBox.defaults);
+dojo.widget.defineWidget(
+ "dojo.widget.ComboBox",
+ dojo.widget.HtmlWidget,
+ {
+ // Applies to any renderer
+ isContainer: false,
+
+ forceValidOption: false,
+ searchType: "stringstart",
+ dataProvider: null,
+
+ startSearch: function(/*String*/ searchString){},
+ selectNextResult: function(){},
+ selectPrevResult: function(){},
+ setSelectedResult: function(){},
+
+ // HTML specific stuff
+ autoComplete: true,
+ name: "", // clone in the name from the DOM node
+ textInputNode: null,
+ comboBoxValue: null,
+ comboBoxSelectionValue: null,
+ optionsListWrapper: null,
+ optionsListNode: null,
+ downArrowNode: null,
+ searchTimer: null,
+ searchDelay: 100,
+ dataUrl: "",
+ fadeTime: 200,
+ disabled: false,
+ // maxListLength limits list to X visible rows, scroll on rest
+ maxListLength: 8,
+ // mode can also be "remote" for JSON-returning live search or "html" for
+ // dumber live search
+ mode: "local",
+ selectedResult: null,
+ _highlighted_option: null,
+ _prev_key_backspace: false,
+ _prev_key_esc: false,
+ _gotFocus: false,
+ _mouseover_list: false,
+ dataProviderClass: "dojo.widget.ComboBoxDataProvider",
+ buttonSrc: dojo.uri.dojoUri("src/widget/templates/images/combo_box_arrow.png"),
+
+ //the old implementation has builtin fade toggle, so we mimic it here
+ dropdownToggle: "fade",
+
+ templatePath: dojo.uri.dojoUri("src/widget/templates/ComboBox.html"),
+ templateCssPath: dojo.uri.dojoUri("src/widget/templates/ComboBox.css"),
+
+
+ setValue: function(/*String*/ value){
+ this.comboBoxValue.value = value;
+ if (this.textInputNode.value != value){ // prevent mucking up of selection
+ this.textInputNode.value = value;
+ // only change state and value if a new value is set
+ dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);
+ this.onValueChanged(value);
+ }
+ },
+
+ // for user to override
+ onValueChanged: function(){ },
+
+ getValue: function(){
+ return this.comboBoxValue.value;
+ },
+
+ getState: function(){
+ return {value: this.getValue()};
+ },
+
+ setState: function(/*Object*/ state){
+ this.setValue(state.value);
+ },
+
+ enable:function(){
+ this.disabled=false;
+ this.isEnabled = true;
+ this.textInputNode.removeAttribute("disabled");
+ },
+
+ disable: function(){
+ this.disabled = true;
+ this.isEnabled = false;
+ this.textInputNode.setAttribute("disabled",true);
+ },
+
+ getCaretPos: function(/*DomNode*/ element){
+ // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
+ if(dojo.lang.isNumber(element.selectionStart)){
+ // FIXME: this is totally borked on Moz < 1.3. Any recourse?
+ return element.selectionStart;
+ }else if(dojo.render.html.ie){
+ // in the case of a mouse click in a popup being handled,
+ // then the document.selection is not the textarea, but the popup
+ // var r = document.selection.createRange();
+ // hack to get IE 6 to play nice. What a POS browser.
+ var tr = document.selection.createRange().duplicate();
+ var ntr = element.createTextRange();
+ tr.move("character",0);
+ ntr.move("character",0);
+ try {
+ // If control doesnt have focus, you get an exception.
+ // Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
+ // There appears to be no workaround for this - googled for quite a while.
+ ntr.setEndPoint("EndToEnd", tr);
+ return String(ntr.text).replace(/\r/g,"").length;
+ } catch (e){
+ return 0; // If focus has shifted, 0 is fine for caret pos.
+ }
+
+ }
+ },
+
+ setCaretPos: function(/*DomNode*/ element, /*Number*/ location){
+ location = parseInt(location);
+ this.setSelectedRange(element, location, location);
+ },
+
+ setSelectedRange: function(/*DomNode*/ element, /*Number*/ start, /*Number*/ end){
+ if(!end){ end = element.value.length; } // NOTE: Strange - should be able to put caret at start of text?
+ // Mozilla
+ // parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130
+ if(element.setSelectionRange){
+ element.focus();
+ element.setSelectionRange(start, end);
+ }else if(element.createTextRange){ // IE
+ var range = element.createTextRange();
+ with(range){
+ collapse(true);
+ moveEnd('character', end);
+ moveStart('character', start);
+ select();
+ }
+ }else{ //otherwise try the event-creation hack (our own invention)
+ // do we need these?
+ element.value = element.value;
+ element.blur();
+ element.focus();
+ // figure out how far back to go
+ var dist = parseInt(element.value.length)-end;
+ var tchar = String.fromCharCode(37);
+ var tcc = tchar.charCodeAt(0);
+ for(var x = 0; x < dist; x++){
+ var te = document.createEvent("KeyEvents");
+ te.initKeyEvent("keypress", true, true, null, false, false, false, false, tcc, tcc);
+ element.dispatchEvent(te);
+ }
+ }
+ },
-dojo.widget.DomComboBox = function(){
- dojo.widget.ComboBox.call(this);
- dojo.widget.DomWidget.call(this, true);
-}
+ // does the keyboard related stuff
+ _handleKeyEvents: function(/*Event*/ evt){
+ if(evt.ctrlKey || evt.altKey || !evt.key){ return; }
+
+ // reset these
+ this._prev_key_backspace = false;
+ this._prev_key_esc = false;
+
+ var k = dojo.event.browser.keys;
+ var doSearch = true;
+
+ switch(evt.key){
+ case k.KEY_DOWN_ARROW:
+ if(!this.popupWidget.isShowingNow){
+ this.startSearchFromInput();
+ }
+ this.highlightNextOption();
+ dojo.event.browser.stopEvent(evt);
+ return;
+ case k.KEY_UP_ARROW:
+ this.highlightPrevOption();
+ dojo.event.browser.stopEvent(evt);
+ return;
+ case k.KEY_TAB:
+ // using linux alike tab for autocomplete
+ if(!this.autoComplete && this.popupWidget.isShowingNow && this._highlighted_option){
+ dojo.event.browser.stopEvent(evt);
+ this.selectOption({ 'target': this._highlighted_option, 'noHide': false});
+
+ // put caret last
+ this.setSelectedRange(this.textInputNode, this.textInputNode.value.length, null);
+ }else{
+ this.selectOption();
+ return;
+ }
+ break;
+ case k.KEY_ENTER:
+ // prevent submitting form if we press enter with list open
+ if(this.popupWidget.isShowingNow){
+ dojo.event.browser.stopEvent(evt);
+ }
+ if(this.autoComplete){
+ this.selectOption();
+ return;
+ }
+ // fallthrough
+ case " ":
+ if(this.popupWidget.isShowingNow && this._highlighted_option){
+ dojo.event.browser.stopEvent(evt);
+ this.selectOption();
+ this.hideResultList();
+ return;
+ }
+ break;
+ case k.KEY_ESCAPE:
+ this.hideResultList();
+ this._prev_key_esc = true;
+ return;
+ case k.KEY_BACKSPACE:
+ this._prev_key_backspace = true;
+ if(!this.textInputNode.value.length){
+ this.setAllValues("", "");
+ this.hideResultList();
+ doSearch = false;
+ }
+ break;
+ case k.KEY_RIGHT_ARROW: // fall through
+ case k.KEY_LEFT_ARROW: // fall through
+ doSearch = false;
+ break;
+ default:// non char keys (F1-F12 etc..) shouldn't open list
+ if(evt.charCode==0){
+ doSearch = false;
+ }
+ }
-dojo.inherits(dojo.widget.DomComboBox, dojo.widget.DomWidget);
-dojo.widget.tags.addParseTreeHandler("dojo:combobox");
+ if(this.searchTimer){
+ clearTimeout(this.searchTimer);
+ }
+ if(doSearch){
+ // if we have gotten this far we dont want to keep our highlight
+ this.blurOptionNode();
+
+ // need to wait a tad before start search so that the event bubbles through DOM and we have value visible
+ this.searchTimer = setTimeout(dojo.lang.hitch(this, this.startSearchFromInput), this.searchDelay);
+ }
+ },
+
+ // When inputting characters using an input method, such as Asian
+ // languages, it will generate this event instead of onKeyDown event
+ compositionEnd: function(/*Event*/ evt){
+ evt.key = evt.keyCode;
+ this._handleKeyEvents(evt);
+ },
+
+ onKeyUp: function(/*Event*/ evt){
+ this.setValue(this.textInputNode.value);
+ },
+
+ setSelectedValue: function(/*String*/ value){
+ // FIXME, not sure what to do here!
+ this.comboBoxSelectionValue.value = value;
+ },
+
+ setAllValues: function(/*String*/ value1, /*String*/ value2){
+ this.setSelectedValue(value2);
+ this.setValue(value1);
+ },
+
+ // does the actual highlight
+ focusOptionNode: function(/*DomNode*/ node){
+ if(this._highlighted_option != node){
+ this.blurOptionNode();
+ this._highlighted_option = node;
+ dojo.html.addClass(this._highlighted_option, "dojoComboBoxItemHighlight");
+ }
+ },
+
+ // removes highlight on highlighted
+ blurOptionNode: function(){
+ if(this._highlighted_option){
+ dojo.html.removeClass(this._highlighted_option, "dojoComboBoxItemHighlight");
+ this._highlighted_option = null;
+ }
+ },
+
+ highlightNextOption: function(){
+ if((!this._highlighted_option) || !this._highlighted_option.parentNode){
+ this.focusOptionNode(this.optionsListNode.firstChild);
+ }else if(this._highlighted_option.nextSibling){
+ this.focusOptionNode(this._highlighted_option.nextSibling);
+ }
+ dojo.html.scrollIntoView(this._highlighted_option);
+ },
+
+ highlightPrevOption: function(){
+ if(this._highlighted_option && this._highlighted_option.previousSibling){
+ this.focusOptionNode(this._highlighted_option.previousSibling);
+ }else{
+ this._highlighted_option = null;
+ this.hideResultList();
+ return;
+ }
+ dojo.html.scrollIntoView(this._highlighted_option);
+ },
-// render-specific includes
-dojo.requireAfterIf("html", "dojo.widget.html.ComboBox");
+ itemMouseOver: function(/*Event*/ evt){
+ if (evt.target === this.optionsListNode){ return; }
+ this.focusOptionNode(evt.target);
+ dojo.html.addClass(this._highlighted_option, "dojoComboBoxItemHighlight");
+ },
+
+ itemMouseOut: function(/*Event*/ evt){
+ if (evt.target === this.optionsListNode){ return; }
+ this.blurOptionNode();
+ },
+
+ // reset button size; this function is called when the input area has changed size
+ onResize: function(){
+ var inputSize = dojo.html.getContentBox(this.textInputNode);
+ if( inputSize.height == 0 ){
+ // need more time to calculate size
+ dojo.lang.setTimeout(this, "onResize", 50);
+ return;
+ }
+ var buttonSize = { width: inputSize.height, height: inputSize.height};
+ dojo.html.setContentBox(this.downArrowNode, buttonSize);
+ },
+
+ fillInTemplate: function(/*Object*/ args, /*Object*/ frag){
+ // For inlining a table we need browser specific CSS
+ dojo.html.applyBrowserClass(this.domNode);
+
+ var source = this.getFragNodeRef(frag);
+ if (! this.name && source.name){ this.name = source.name; }
+ this.comboBoxValue.name = this.name;
+ this.comboBoxSelectionValue.name = this.name+"_selected";
+
+ /* different nodes get different parts of the style */
+ dojo.html.copyStyle(this.domNode, source);
+ dojo.html.copyStyle(this.textInputNode, source);
+ dojo.html.copyStyle(this.downArrowNode, source);
+ with (this.downArrowNode.style){ // calculate these later
+ width = "0px";
+ height = "0px";
+ }
+
+ var dpClass;
+ if(this.mode == "remote"){
+ dpClass = dojo.widget.incrementalComboBoxDataProvider;
+ }else if(typeof this.dataProviderClass == "string"){
+ dpClass = dojo.evalObjPath(this.dataProviderClass)
+ }else{
+ dpClass = this.dataProviderClass;
+ }
+ this.dataProvider = new dpClass();
+ this.dataProvider.init(this, this.getFragNodeRef(frag));
+ this.popupWidget = new dojo.widget.createWidget("PopupContainer",
+ {toggle: this.dropdownToggle, toggleDuration: this.toggleDuration});
+ dojo.event.connect(this, 'destroy', this.popupWidget, 'destroy');
+ this.optionsListNode = this.popupWidget.domNode;
+ this.domNode.appendChild(this.optionsListNode);
+ dojo.html.addClass(this.optionsListNode, 'dojoComboBoxOptions');
+ dojo.event.connect(this.optionsListNode, 'onclick', this, 'selectOption');
+ dojo.event.connect(this.optionsListNode, 'onmouseover', this, '_onMouseOver');
+ dojo.event.connect(this.optionsListNode, 'onmouseout', this, '_onMouseOut');
+
+ dojo.event.connect(this.optionsListNode, "onmouseover", this, "itemMouseOver");
+ dojo.event.connect(this.optionsListNode, "onmouseout", this, "itemMouseOut");
+ },
+
+ focus: function(){
+ // summary
+ // set focus to input node from code
+ this.tryFocus();
+ },
+
+ openResultList: function(/*Array*/ results){
+ if (!this.isEnabled){
+ return;
+ }
+ this.clearResultList();
+ if(!results.length){
+ this.hideResultList();
+ }
+
+ if( (this.autoComplete)&&
+ (results.length)&&
+ (!this._prev_key_backspace)&&
+ (this.textInputNode.value.length > 0)){
+ var cpos = this.getCaretPos(this.textInputNode);
+ // only try to extend if we added the last character at the end of the input
+ if((cpos+1) > this.textInputNode.value.length){
+ // only add to input node as we would overwrite Capitalisation of chars
+ this.textInputNode.value += results[0][0].substr(cpos);
+ // build a new range that has the distance from the earlier
+ // caret position to the end of the first string selected
+ this.setSelectedRange(this.textInputNode, cpos, this.textInputNode.value.length);
+ }
+ }
+
+ var even = true;
+ while(results.length){
+ var tr = results.shift();
+ if(tr){
+ var td = document.createElement("div");
+ td.appendChild(document.createTextNode(tr[0]));
+ td.setAttribute("resultName", tr[0]);
+ td.setAttribute("resultValue", tr[1]);
+ td.className = "dojoComboBoxItem "+((even) ? "dojoComboBoxItemEven" : "dojoComboBoxItemOdd");
+ even = (!even);
+ this.optionsListNode.appendChild(td);
+ }
+ }
+
+ // show our list (only if we have content, else nothing)
+ this.showResultList();
+ },
+
+ onFocusInput: function(){
+ this._hasFocus = true;
+ },
+
+ onBlurInput: function(){
+ this._hasFocus = false;
+ this._handleBlurTimer(true, 500);
+ },
+
+ // collect all blur timers issues here
+ _handleBlurTimer: function(/*Boolean*/clear, /*Number*/ millisec){
+ if(this.blurTimer && (clear || millisec)){
+ clearTimeout(this.blurTimer);
+ }
+ if(millisec){ // we ignore that zero is false and never sets as that never happens in this widget
+ this.blurTimer = dojo.lang.setTimeout(this, "checkBlurred", millisec);
+ }
+ },
+
+ // these 2 are needed in IE and Safari as inputTextNode loses focus when scrolling optionslist
+ _onMouseOver: function(/*Event*/ evt){
+ if(!this._mouseover_list){
+ this._handleBlurTimer(true, 0);
+ this._mouseover_list = true;
+ }
+ },
+
+ _onMouseOut:function(/*Event*/ evt){
+ var relTarget = evt.relatedTarget;
+ if(!relTarget || relTarget.parentNode!=this.optionsListNode){
+ this._mouseover_list = false;
+ this._handleBlurTimer(true, 100);
+ this.tryFocus();
+ }
+ },
+
+ _isInputEqualToResult: function(/*String*/ result){
+ var input = this.textInputNode.value;
+ if(!this.dataProvider.caseSensitive){
+ input = input.toLowerCase();
+ result = result.toLowerCase();
+ }
+ return (input == result);
+ },
+
+ _isValidOption: function(){
+ var tgt = dojo.html.firstElement(this.optionsListNode);
+ var isValidOption = false;
+ while(!isValidOption && tgt){
+ if(this._isInputEqualToResult(tgt.getAttribute("resultName"))){
+ isValidOption = true;
+ }else{
+ tgt = dojo.html.nextElement(tgt);
+ }
+ }
+ return isValidOption;
+ },
+
+ checkBlurred: function(){
+ if(!this._hasFocus && !this._mouseover_list){
+ this.hideResultList();
+ // clear the list if the user empties field and moves away.
+ if(!this.textInputNode.value.length){
+ this.setAllValues("", "");
+ return;
+ }
+
+ var isValidOption = this._isValidOption();
+ // enforce selection from option list
+ if(this.forceValidOption && !isValidOption){
+ this.setAllValues("", "");
+ return;
+ }
+ if(!isValidOption){// clear
+ this.setSelectedValue("");
+ }
+ }
+ },
+
+ sizeBackgroundIframe: function(){
+ var mb = dojo.html.getMarginBox(this.optionsListNode);
+ if( mb.width==0 || mb.height==0 ){
+ // need more time to calculate size
+ dojo.lang.setTimeout(this, "sizeBackgroundIframe", 100);
+ return;
+ }
+ },
+
+ selectOption: function(/*Event*/ evt){
+ var tgt = null;
+ if(!evt){
+ evt = { target: this._highlighted_option };
+ }
+
+ if(!dojo.html.isDescendantOf(evt.target, this.optionsListNode)){
+ // handle autocompletion where the the user has hit ENTER or TAB
+
+ // if the input is empty do nothing
+ if(!this.textInputNode.value.length){
+ return;
+ }
+ tgt = dojo.html.firstElement(this.optionsListNode);
+
+ // user has input value not in option list
+ if(!tgt || !this._isInputEqualToResult(tgt.getAttribute("resultName"))){
+ return;
+ }
+ // otherwise the user has accepted the autocompleted value
+ }else{
+ tgt = evt.target;
+ }
+
+ while((tgt.nodeType!=1)||(!tgt.getAttribute("resultName"))){
+ tgt = tgt.parentNode;
+ if(tgt === dojo.body()){
+ return false;
+ }
+ }
+
+ this.selectedResult = [tgt.getAttribute("resultName"), tgt.getAttribute("resultValue")];
+ this.setAllValues(tgt.getAttribute("resultName"), tgt.getAttribute("resultValue"));
+ if(!evt.noHide){
+ this.hideResultList();
+ this.setSelectedRange(this.textInputNode, 0, null);
+ }
+ this.tryFocus();
+ },
+
+ clearResultList: function(){
+ if(this.optionsListNode.innerHTML){
+ this.optionsListNode.innerHTML = ""; // browser natively knows how to collect this memory
+ }
+ },
+
+ hideResultList: function(){
+ this.popupWidget.close();
+ },
+
+ showResultList: function(){
+ // Our dear friend IE doesnt take max-height so we need to calculate that on our own every time
+ var childs = this.optionsListNode.childNodes;
+ if(childs.length){
+ var visibleCount = this.maxListLength;
+ if(childs.length < visibleCount){
+ visibleCount = childs.length;
+ }
+
+ with(this.optionsListNode.style)
+ {
+ display = "";
+ if(visibleCount == childs.length){
+ //no scrollbar is required, so unset height to let browser calcuate it,
+ //as in css, overflow is already set to auto
+ height = "";
+ }else{
+ //show it first to get the correct dojo.style.getOuterHeight(childs[0])
+ //FIXME: shall we cache the height of the item?
+ height = visibleCount * dojo.html.getMarginBox(childs[0]).height +"px";
+ }
+ width = (dojo.html.getMarginBox(this.domNode).width-2)+"px";
+
+ }
+ this.popupWidget.open(this.domNode, this, this.downArrowNode);
+ }else{
+ this.hideResultList();
+ }
+ },
+
+ handleArrowClick: function(){
+ this._handleBlurTimer(true, 0);
+ this.tryFocus();
+ if(this.popupWidget.isShowingNow){
+ this.hideResultList();
+ }else{
+ // forces full population of results, if they click
+ // on the arrow it means they want to see more options
+ this.startSearch("");
+ }
+ },
+
+ tryFocus: function(){
+ try {
+ this.textInputNode.focus();
+ } catch (e){
+ // element isn't focusable if disabled, or not visible etc - not easy to test for.
+ };
+ },
+
+ startSearchFromInput: function(){
+ this.startSearch(this.textInputNode.value);
+ },
+
+ postCreate: function(){
+ this.onResize();
+ dojo.event.connect(this, "startSearch", this.dataProvider, "startSearch");
+ dojo.event.connect(this.dataProvider, "provideSearchResults", this, "openResultList");
+ dojo.event.connect(this.textInputNode, "onblur", this, "onBlurInput");
+ dojo.event.connect(this.textInputNode, "onfocus", this, "onFocusInput");
+ if (this.disabled){
+ this.disable();
+ }
+ var s = dojo.widget.html.stabile.getState(this.widgetId);
+ if (s){
+ this.setState(s);
+ }
+ }
+ }
+);