BarGauge.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.widget.BarGauge"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.widget.BarGauge"] = true;
  8. dojo.provide("dojox.widget.BarGauge");
  9. dojo.require("dojox.gfx");
  10. dojo.require("dojox.widget.gauge._Gauge");
  11. dojo.experimental("dojox.widget.BarGauge");
  12. dojo.declare("dojox.widget.gauge.BarLineIndicator",[dojox.widget.gauge._Indicator],{
  13. width: 1,
  14. _getShapes: function(){
  15. // summary:
  16. // Private function for generating the shapes for this indicator. An indicator that behaves the
  17. // same might override this one and simply replace the shapes (such as BarIndicator).
  18. if(!this._gauge){
  19. return null;
  20. }
  21. var v = this.value;
  22. if(v < this._gauge.min){v = this._gauge.min;}
  23. if(v > this._gauge.max){v = this._gauge.max;}
  24. var pos = this._gauge._getPosition(v);
  25. var shapes = [];
  26. if(this.width > 1){
  27. shapes[0] = this._gauge.surface.createRect({
  28. x:pos,
  29. y:this._gauge.dataY + this.offset,
  30. width:this.width,
  31. height:this.length
  32. });
  33. shapes[0].setStroke({color: this.color});
  34. shapes[0].setFill(this.color);
  35. }else{
  36. shapes[0] = this._gauge.surface.createLine({
  37. x1:pos,
  38. y1:this._gauge.dataY + this.offset,
  39. x2:pos,
  40. y2:this._gauge.dataY + this.offset + this.length
  41. });
  42. shapes[0].setStroke({color: this.color});
  43. }
  44. return shapes;
  45. },
  46. draw: function(/*Boolean?*/ dontAnimate){
  47. // summary:
  48. // Override of dojox.widget.gauge._Indicator.draw
  49. // dontAnimate: Boolean
  50. // Indicates if the drawing should not be animated (vs. the default of doing an animation)
  51. var i;
  52. if(this.shapes){
  53. this._move(dontAnimate);
  54. }else{
  55. if(this.shapes){
  56. for(i=0; i<this.shapes.length; i++){
  57. this._gauge.surface.remove(this.shapes[i]);
  58. }
  59. this.shapes = null;
  60. }
  61. if(this.text){
  62. this._gauge.surface.rawNode.removeChild(this.text);
  63. this.text = null;
  64. }
  65. this.color = this.color || '#000000';
  66. this.length = this.length || this._gauge.dataHeight;
  67. this.width = this.width || 3;
  68. this.offset = this.offset || 0;
  69. this.highlight = this.highlight || '#4D4D4D';
  70. this.highlight2 = this.highlight2 || '#A3A3A3';
  71. this.shapes = this._getShapes(this._gauge, this);
  72. if(this.label){
  73. var v = this.value;
  74. if(v < this._gauge.min){v = this._gauge.min;}
  75. if(v > this._gauge.max){v = this._gauge.max;}
  76. var pos = this._gauge._getPosition(v);
  77. this.text = this._gauge.drawText(''+this.label, pos, this._gauge.dataY + this.offset - 5, 'middle','top', this.color, this.font);
  78. }
  79. for(i=0; i<this.shapes.length; i++){
  80. if(this.hover){
  81. this.shapes[i].getEventSource().setAttribute('hover',this.hover);
  82. }
  83. if(this.onDragMove && !this.noChange){
  84. this._gauge.connect(this.shapes[i].getEventSource(), 'onmousedown', this._gauge.handleMouseDown);
  85. this.shapes[i].getEventSource().style.cursor = 'pointer';
  86. }
  87. }
  88. this.currentValue = this.value;
  89. }
  90. },
  91. _move: function(/*Boolean?*/ dontAnimate){
  92. // summary:
  93. // Moves this indicator (since it's already been drawn once)
  94. // dontAnimate: Boolean
  95. // Indicates if the drawing should not be animated (vs. the default of doing an animation)
  96. var v = this.value ;
  97. if(v < this.min){v = this.min;}
  98. if(v > this.max){v = this.max;}
  99. var c = this._gauge._getPosition(this.currentValue);
  100. this.currentValue = v;
  101. v = this._gauge._getPosition(v)-this._gauge.dataX;
  102. if(dontAnimate){
  103. this.shapes[0].applyTransform(dojox.gfx.matrix.translate(v-(this.shapes[0].matrix?this.shapes[0].matrix.dx:0),0));
  104. }else{
  105. var anim = new dojo.Animation({curve: [c, v], duration: this.duration, easing: this.easing});
  106. dojo.connect(anim, "onAnimate", dojo.hitch(this, function(jump){
  107. this.shapes[0].applyTransform(dojox.gfx.matrix.translate(jump-(this.shapes[0].matrix?this.shapes[0].matrix.dx:0),0));
  108. }));
  109. anim.play();
  110. }
  111. }
  112. });
  113. dojo.declare("dojox.widget.BarGauge",dojox.widget.gauge._Gauge,{
  114. // summary:
  115. // a bar graph built using the dojox.gfx package.
  116. //
  117. // description:
  118. // using dojo.gfx (and thus either SVG or VML based on what is supported), this widget
  119. // builds a bar graph component, used to display numerical data in a familiar format.
  120. //
  121. // usage:
  122. // <script type="text/javascript">
  123. // dojo.require("dojox.widget.BarGauge");
  124. // dojo.require("dijit.util.parser");
  125. // </script>
  126. // ...
  127. // <div dojoType="dojox.widget.BarGauge"
  128. // id="testBarGauge"
  129. // barGaugeHeight="55"
  130. // dataY="25"
  131. // dataHeight="25"
  132. // dataWidth="225">
  133. // </div>
  134. // dataX: Number
  135. // x position of data area (default 5)
  136. dataX: 5,
  137. // dataY: Number
  138. // y position of data area (default 5)
  139. dataY: 5,
  140. // dataWidth: Number
  141. // width of data area (default is bar graph width - 10)
  142. dataWidth: 0,
  143. // dataHeight: Number
  144. // height of data area (default is bar graph width - 10)
  145. dataHeight: 0,
  146. // _defaultIndicator: override of dojox.widget._Gauge._defaultIndicator
  147. _defaultIndicator: dojox.widget.gauge.BarLineIndicator,
  148. startup: function(){
  149. // handle settings from HTML by making sure all the options are
  150. // converted correctly to numbers
  151. //
  152. // also connects mouse handling events
  153. if(this.getChildren){
  154. dojo.forEach(this.getChildren(), function(child){ child.startup(); });
  155. }
  156. if(!this.dataWidth){this.dataWidth = this.gaugeWidth - 10;}
  157. if(!this.dataHeight){this.dataHeight = this.gaugeHeight - 10;}
  158. this.inherited(arguments);
  159. },
  160. _getPosition: function(/*Number*/value){
  161. // summary:
  162. // This is a helper function used to determine the position that represents
  163. // a given value on the bar graph
  164. // value: Number
  165. // A value to be converted to a position for this bar graph.
  166. return this.dataX + Math.floor((value - this.min)/(this.max - this.min)*this.dataWidth);
  167. },
  168. _getValueForPosition: function(/*Number*/pos){
  169. // summary:
  170. // This is a helper function used to determine the value represented by
  171. // a position on the bar graph
  172. // pos: Number
  173. // A position to be converted to a value.
  174. return (pos - this.dataX)*(this.max - this.min)/this.dataWidth + this.min;
  175. },
  176. draw: function(){
  177. // summary:
  178. // This function is used to draw (or redraw) the bar graph
  179. // description:
  180. // Draws the bar graph by drawing the surface, the ranges, and the indicators.
  181. if(!this.surface){this.createSurface();}
  182. var i;
  183. if(this._rangeData){
  184. for(i=0; i<this._rangeData.length; i++){
  185. this.drawRange(this._rangeData[i]);
  186. }
  187. if(this._img && this.image.overlay){
  188. this._img.moveToFront();
  189. }
  190. }
  191. if(this._indicatorData){
  192. for(i=0; i<this._indicatorData.length; i++){
  193. this._indicatorData[i].draw();
  194. }
  195. }
  196. },
  197. drawRange: function(/*Object*/range){
  198. // summary:
  199. // This function is used to draw (or redraw) a range
  200. // description:
  201. // Draws a range (colored area on the background of the gauge)
  202. // based on the given arguments.
  203. // range:
  204. // A range is either a dojox.widget.gauge.Range or an object
  205. // with similar parameters (low, high, hover, etc.).
  206. if(range.shape){
  207. this.surface.remove(range.shape);
  208. range.shape = null;
  209. }
  210. var x1 = this._getPosition(range.low);
  211. var x2 = this._getPosition(range.high);
  212. var path = this.surface.createRect({x:x1,
  213. y:this.dataY,
  214. width:x2-x1,
  215. height:this.dataHeight});
  216. if(dojo.isArray(range.color) || dojo.isString(range.color)){
  217. path.setStroke({color: range.color});
  218. path.setFill(range.color);
  219. }else if(range.color.type){
  220. // Color is a gradient
  221. var y = this.dataY + this.dataHeight/2;
  222. range.color.x1 = x1;
  223. range.color.x2 = x2;
  224. range.color.y1 = y;
  225. range.color.y2 = y;
  226. path.setFill(range.color);
  227. path.setStroke({color: range.color.colors[0].color});
  228. }else{
  229. // We've defined a style rather than an explicit color
  230. path.setStroke({color: "green"}); // Arbitrary color, just have to indicate
  231. path.setFill("green"); // that we want it filled
  232. path.getEventSource().setAttribute("class", range.color.style);
  233. }
  234. if(range.hover){
  235. path.getEventSource().setAttribute('hover',range.hover);
  236. }
  237. range.shape = path;
  238. },
  239. getRangeUnderMouse: function(/*Object*/event){
  240. // summary:
  241. // Determines which range the mouse is currently over
  242. // event: Object
  243. // The event object as received by the mouse handling functions below.
  244. var range = null;
  245. var pos = dojo.coords(this.gaugeContent);
  246. var x = event.clientX - pos.x;
  247. var value = this._getValueForPosition(x);
  248. if(this._rangeData){
  249. for(var i=0; (i<this._rangeData.length) && !range; i++){
  250. if((Number(this._rangeData[i].low) <= value) && (Number(this._rangeData[i].high) >= value)){
  251. range = this._rangeData[i];
  252. }
  253. }
  254. }
  255. return range;
  256. },
  257. _dragIndicator: function(/*Object*/ widget, /*Object*/ event){
  258. // summary:
  259. // Handles the dragging of an indicator, including moving/re-drawing
  260. // get new value based on mouse position
  261. var pos = dojo.coords(widget.gaugeContent);
  262. var x = event.clientX - pos.x;
  263. var value = widget._getValueForPosition(x);
  264. if(value < widget.min){value = widget.min;}
  265. if(value > widget.max){value = widget.max;}
  266. // update the indicator
  267. widget._drag.value = value;
  268. // callback
  269. widget._drag.onDragMove(widget._drag);
  270. // redraw/move indicator(s)
  271. widget._drag.draw(true);
  272. dojo.stopEvent(event);
  273. }
  274. });
  275. }