/* 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.ProgressBar"); dojo.require("dojo.widget.*"); dojo.require("dojo.event"); dojo.require("dojo.dom"); dojo.require("dojo.html.style"); dojo.require("dojo.string.*"); dojo.require("dojo.lfx.*"); dojo.widget.defineWidget( "dojo.widget.ProgressBar", dojo.widget.HtmlWidget, { // summary: // a progress widget, with some calculation and server polling capabilities // // description: // (implementation) four overlapped divs: // (1) lower z-index // (4) higher z-index // back and front percent label have the same content: when the vertical line (*) // partially hides the backPercentLabel, the frontPercentLabel becomes visible // // ________________________(1)_containerNode_________________________________ // |__(3)_internalProgress____________ | // | | <--- (*) | // | (4) frontPercentLabel | (2) backPercentLabel | // |__________________________________| | // |__________________________________________________________________________| // // usage: //
// progressValue: String // initial progress value. // with "%": percentual value, 0% <= progressValue <= 100% // or without "%": absolute value, 0 <= progressValue <= maxProgressValue progressValue: 0, // maxProgressValue: Float // max sample number maxProgressValue: 100, // width: Integer // ProgressBar width (pixel) width: 300, // height: Integer // ProgressBar height, (pixel) height: 30, // frontPercentClass: String // css class for frontPercentLabel (4) frontPercentClass: "frontPercent", // backPercentClass: String // css class for backPercentLabel (2) backPercentClass: "backPercent", // frontBarClass: String // css class for containerNode (1) frontBarClass: "frontBar", // backBarClass: String // css class for internalProgress (3) backBarClass: "backBar", // hasText: Boolean // if true, the percent label is visible hasText: false, // isVertical: Boolean // if true, the widget is vertical isVertical: false, // showOnlyIntegers: Boolean // if true, the percent label shows only integer values showOnlyIntegers: false, // dataSource: String // dataSource uri for server polling dataSource: "", // pollInterval: Integer // server poll interval pollInterval: 3000, // duration: Integer // duration of the animation duration: 1000, templatePath: dojo.uri.dojoUri("src/widget/templates/ProgressBar.html"), templateCssPath: dojo.uri.dojoUri("src/widget/templates/ProgressBar.css"), // attach points containerNode: null, internalProgress: null, // private members _pixelUnitRatio: 0.0, _pixelPercentRatio: 0.0, _unitPercentRatio: 0.0, _unitPixelRatio: 0.0, _floatDimension: 0.0, _intDimension: 0, _progressPercentValue: "0%", _floatMaxProgressValue: 0.0, _dimension: "width", _pixelValue: 0, _oInterval: null, _animation: null, _animationStopped: true, _progressValueBak: false, _hasTextBak: false, // public functions fillInTemplate: function(args, frag){ this.internalProgress.className = this.frontBarClass; this.containerNode.className = this.backBarClass; if (this.isVertical){ this.internalProgress.style.bottom="0px"; this.internalProgress.style.left="0px"; this._dimension = "height"; } else { this.internalProgress.style.top="0px"; this.internalProgress.style.left="0px"; this._dimension = "width"; } this.frontPercentLabel.className = this.frontPercentClass; this.backPercentLabel.className = this.backPercentClass; this.progressValue = "" + this.progressValue; this.domNode.style.height = this.height + "px"; this.domNode.style.width = this.width + "px"; this._intDimension = parseInt("0" + eval("this." + this._dimension)); this._floatDimension = parseFloat("0" + eval("this."+this._dimension)); this._pixelPercentRatio = this._floatDimension/100; this.setMaxProgressValue(this.maxProgressValue, true); this.setProgressValue(dojo.string.trim(this.progressValue), true); dojo.debug("float dimension: " + this._floatDimension); dojo.debug("this._unitPixelRatio: " + this._unitPixelRatio); this.showText(this.hasText); }, showText: function(visible){ // summary: shows or hides the labels if (visible){ this.backPercentLabel.style.display="block"; this.frontPercentLabel.style.display="block"; } else { this.backPercentLabel.style.display="none"; this.frontPercentLabel.style.display="none"; } this.hasText = visible; }, postCreate: function(args, frag){ this.render(); }, _backupValues: function(){ this._progressValueBak = this.progressValue; this._hasTextBak = this.hasText; }, _restoreValues: function(){ this.setProgressValue(this._progressValueBak); this.showText(this._hasTextBak); }, _setupAnimation: function(){ var _self = this; dojo.debug("internalProgress width: " + this.internalProgress.style.width); this._animation = dojo.lfx.html.slideTo(this.internalProgress, {top: 0, left: parseInt(this.width)-parseInt(this.internalProgress.style.width)}, parseInt(this.duration), null, function(){ var _backAnim = dojo.lfx.html.slideTo(_self.internalProgress, { top: 0, left: 0 }, parseInt(_self.duration)); dojo.event.connect(_backAnim, "onEnd", function(){ if (!_self._animationStopped){ _self._animation.play(); } }); if (!_self._animationStopped){ _backAnim.play(); } _backAnim = null; // <-- to avoid memory leaks in IE } ); }, getMaxProgressValue: function(){ // summary: returns the maxProgressValue return this.maxProgressValue; }, setMaxProgressValue: function(maxValue, noRender){ // summary: sets the maxProgressValue // if noRender is true, only sets the internal max progress value if (!this._animationStopped){ return; } this.maxProgressValue = maxValue; this._floatMaxProgressValue = parseFloat("0" + this.maxProgressValue); this._pixelUnitRatio = this._floatDimension/this.maxProgressValue; this._unitPercentRatio = this._floatMaxProgressValue/100; this._unitPixelRatio = this._floatMaxProgressValue/this._floatDimension; this.setProgressValue(this.progressValue, true); if (!noRender){ this.render(); } }, setProgressValue: function(value, noRender){ // summary: sets the progressValue // if value ends width "%", does a normalization // if noRender is true, only sets the internal value: useful if // there is a setMaxProgressValue call if (!this._animationStopped){ return; } // transformations here this._progressPercentValue = "0%"; var _value=dojo.string.trim("" + value); var _floatValue = parseFloat("0" + _value); var _intValue = parseInt("0" + _value); var _pixelValue = 0; if (dojo.string.endsWith(_value, "%", false)){ this._progressPercentValue = Math.min(_floatValue.toFixed(1), 100) + "%"; _value = Math.min((_floatValue)*this._unitPercentRatio, this.maxProgressValue); _pixelValue = Math.min((_floatValue)*this._pixelPercentRatio, eval("this."+this._dimension)); } else { this.progressValue = Math.min(_floatValue, this.maxProgressValue); this._progressPercentValue = Math.min((_floatValue/this._unitPercentRatio).toFixed(1), 100) + "%"; _pixelValue = Math.min(_floatValue/this._unitPixelRatio, eval("this."+this._dimension)); } this.progressValue = dojo.string.trim(_value); this._pixelValue = _pixelValue; if (!noRender){ this.render(); } }, getProgressValue: function(){ // summary: returns the progressValue return this.progressValue; }, getProgressPercentValue: function(){ // summary: returns the percentual progressValue return this._progressPercentValue; }, setDataSource: function(dataSource){ // summary: sets the dataSource this.dataSource = dataSource; }, setPollInterval: function(pollInterval){ // summary: sets the pollInterval this.pollInterval = pollInterval; }, start: function(){ // summary: starts the server polling var _showFunction = dojo.lang.hitch(this, this._showRemoteProgress); this._oInterval = setInterval(_showFunction, this.pollInterval); }, startAnimation: function(){ // summary: starts the left-right animation, useful when // the user doesn't know how much time the operation will last if (this._animationStopped) { this._backupValues(); this.setProgressValue("10%"); this._animationStopped = false; this._setupAnimation(); this.showText(false); this.internalProgress.style.height="105%"; this._animation.play(); } }, stopAnimation: function(){ // summary: stops the left-right animation if (this._animation) { this._animationStopped = true; this._animation.stop(); this.internalProgress.style.height="100%"; this.internalProgress.style.left = "0px"; this._restoreValues(); this._setLabelPosition(); } }, _showRemoteProgress: function(){ var _self = this; if ( (this.getMaxProgressValue() == this.getProgressValue()) && this._oInterval){ clearInterval(this._oInterval); this._oInterval = null; this.setProgressValue("100%"); return; } var bArgs = { url: _self.dataSource, method: "POST", mimetype: "text/json", error: function(type, errorObj){ dojo.debug("[ProgressBar] showRemoteProgress error"); }, load: function(type, data, evt){ _self.setProgressValue( (_self._oInterval ? data["progress"] : "100%") ); } }; dojo.io.bind(bArgs); }, render: function(){ // summary: renders the ProgressBar, based on current values this._setPercentLabel(dojo.string.trim(this._progressPercentValue)); this._setPixelValue(this._pixelValue); this._setLabelPosition(); }, _setLabelPosition: function(){ var _widthFront = dojo.html.getContentBox(this.frontPercentLabel).width; var _heightFront = dojo.html.getContentBox(this.frontPercentLabel).height; var _widthBack = dojo.html.getContentBox(this.backPercentLabel).width; var _heightBack = dojo.html.getContentBox(this.backPercentLabel).height; var _leftFront = (parseInt(this.width) - _widthFront)/2 + "px"; var _bottomFront = (parseInt(this.height) - parseInt(_heightFront))/2 + "px"; var _leftBack = (parseInt(this.width) - _widthBack)/2 + "px"; var _bottomBack = (parseInt(this.height) - parseInt(_heightBack))/2 + "px"; this.frontPercentLabel.style.left = _leftFront; this.backPercentLabel.style.left = _leftBack; this.frontPercentLabel.style.bottom = _bottomFront; this.backPercentLabel.style.bottom = _bottomBack; }, _setPercentLabel: function(percentValue){ dojo.dom.removeChildren(this.frontPercentLabel); dojo.dom.removeChildren(this.backPercentLabel); var _percentValue = this.showOnlyIntegers == false ? percentValue : parseInt(percentValue) + "%"; this.frontPercentLabel. appendChild(document.createTextNode(_percentValue)); this.backPercentLabel. appendChild(document.createTextNode(_percentValue)); }, _setPixelValue: function(value){ eval("this.internalProgress.style." + this._dimension + " = " + value + " + 'px'"); this.onChange(); }, onChange: function(){ } });