1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2011 Strobe Inc. and contributors. 4 // Portions ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 sc_require("theme"); 8 SC.LegacyTheme.PROGRESS_ANIMATED_BACKGROUND_MATRIX = []; 9 SC.LegacyTheme.PROGRESS_OFFSET_RANGE = 24; 10 11 /** 12 @class 13 Renders and updates DOM representations of progress bars. 14 15 Parameters 16 -------------------------- 17 Expects these properties on the data source: 18 19 - isIndeterminate 20 - isRunning 21 - isEnabled 22 - value (from 0 to 1) 23 24 There are a few other properties supported for backwards-compatibility 25 with certain ProgressView implementations; these ProgressViews should 26 be updated to match the new API. These properties will trigger deprecation 27 warnings. 28 29 Theme Constants 30 ------------------------------------- 31 Note that, unlike render delegate parameters, which are mostly standardized, 32 the theme constants can vary by the theme and the theme's method of rendering 33 the control. 34 35 - PROGRESS_ANIMATED_BACKGROUND_MATRIX: Set to the matrix used for 36 background image position for animation. 37 [1st image y-location, offset, total number of images] 38 39 - PROGRESS_OFFSET_RANGE: The value of the progress inner offset range. 40 Should be the same as width of image. Default it to 24. 41 42 */ 43 SC.LegacyTheme.progressRenderDelegate = SC.RenderDelegate.create({ 44 className: 'progress', 45 46 render: function(dataSource, context) { 47 this.addSizeClassName(dataSource, context); 48 49 var theme = dataSource.get('theme'), 50 valueMax = dataSource.get('maximum'), 51 valueMin = dataSource.get('minimum'), 52 valueNow = dataSource.get('ariaValue'); 53 54 var inner, animatedBackground, value = dataSource.get('value') * 100, 55 cssString, backPosition, 56 isIndeterminate = dataSource.get('isIndeterminate'), 57 isRunning = dataSource.get('isRunning'), 58 isEnabled = dataSource.get('isEnabled'), 59 offsetRange = theme.PROGRESS_OFFSET_RANGE, 60 offset = (isIndeterminate && isRunning) ? 61 (Math.floor(Date.now()/75)%offsetRange-offsetRange) : 0; 62 63 //addressing accessibility 64 context.setAttr('aria-valuemax', valueMax); 65 context.setAttr('aria-valuemin', valueMin); 66 context.setAttr('aria-valuenow', valueNow); 67 context.setAttr('aria-valuetext', valueNow); 68 69 // offsetRange from dataSource only supported for backwards-compatibility 70 if (dataSource.get('offsetRange')) { 71 if (!this._hasGivenOffsetRangeDeprecationWarning) { 72 console.warn( 73 "The 'offsetRange' property for progressRenderDelegate is deprecated. " + 74 "Please override the value on your theme, instead, by setting " + 75 "its PROGRESS_OFFSET_RANGE property." 76 ); 77 } 78 this._hasGivenOffsetRangeDeprecationWarning = YES; 79 80 offsetRange = dataSource.get('offsetRange'); 81 } 82 83 var classNames = { 84 'sc-indeterminate': isIndeterminate, 85 'sc-empty': (value <= 0), 86 'sc-complete': (value >= 100) 87 }; 88 89 // compute value for setting the width of the inner progress 90 if (!isEnabled) { 91 value = "0%" ; 92 } else if (isIndeterminate) { 93 value = "120%"; 94 } else { 95 value = value + "%"; 96 } 97 98 var classString = this._createClassNameString(classNames); 99 context.push('<div class="sc-inner ', classString, '" style="width: ', 100 value, ';left: ', offset, 'px;">', 101 '<div class="sc-inner-head">','</div>', 102 '<div class="sc-inner-tail"></div></div>', 103 '<div class="sc-outer-head"></div>', 104 '<div class="sc-outer-tail"></div>'); 105 }, 106 107 update: function(dataSource, $) { 108 this.updateSizeClassName(dataSource, $); 109 110 var theme = dataSource.get('theme'), 111 valueMax = dataSource.get('maximum'), 112 valueMin = dataSource.get('minimum'), 113 valueNow = dataSource.get('ariaValue'); 114 115 // make accessible 116 $.attr('aria-valuemax', valueMax); 117 $.attr('aria-valuemin', valueMin); 118 $.attr('aria-valuenow', valueNow); 119 $.attr('aria-valuetext', valueNow); 120 121 var inner, value, cssString, backPosition, 122 animatedBackground = theme.PROGRESS_ANIMATED_BACKGROUND_MATRIX, 123 isIndeterminate = dataSource.get('isIndeterminate'), 124 isRunning = dataSource.get('isRunning'), 125 isEnabled = dataSource.get('isEnabled'), 126 offsetRange = dataSource.get('offsetRange'), 127 offset = (isIndeterminate && isRunning) ? 128 (Math.floor(Date.now()/75)%offsetRange-offsetRange) : 0; 129 130 // compute value for setting the width of the inner progress 131 if (!isEnabled) { 132 value = "0%" ; 133 } else if (isIndeterminate) { 134 value = "120%"; 135 } else { 136 value = (dataSource.get('value') * 100) + "%"; 137 } 138 139 var classNames = { 140 'sc-indeterminate': isIndeterminate, 141 'sc-empty': (value <= 0), 142 'sc-complete': (value >= 100) 143 }; 144 145 $.setClass(classNames); 146 inner = $.find('.sc-inner'); 147 148 // animatedBackground from dataSource only supported for backwards-compatibility 149 if (dataSource.get('animatedBackgroundMatrix')) { 150 if (!this._hasGivenAnimatedBackgroundDeprecationWarning) { 151 console.warn( 152 "The 'animatedBackgroundMatrix' property for progressRenderDelegate " + 153 "is deprecated. Please override the value on your theme by setting " + 154 "its PROGRESS_ANIMATED_BACKGROUND_MATRIX property." 155 ); 156 } 157 158 this._hasGivenAnimatedBackgroundDeprecationWarning = YES; 159 160 animatedBackground = dataSource.get('animatedBackgroundMatrix'); 161 } 162 163 if (!animatedBackground) { 164 animatedBackground = theme.PROGRESS_ANIMATED_BACKGROUND_MATRIX; 165 } 166 167 cssString = "width: "+value+"; "; 168 cssString = cssString + "left: "+offset+"px; "; 169 if (animatedBackground.length === 3 ) { 170 inner.css('backgroundPosition', '0px -'+ 171 (animatedBackground[0] + 172 animatedBackground[1]*this._currentBackground)+'px'); 173 if(this._currentBackground===animatedBackground[2]-1 174 || this._currentBackground===0){ 175 this._nextBackground *= -1; 176 } 177 this._currentBackground += this._nextBackground; 178 179 cssString = cssString + "backgroundPosition: "+backPosition+"px; "; 180 //Instead of using css() set attr for faster perf. 181 inner.attr('style', cssString); 182 }else{ 183 inner.attr('style', cssString); 184 } 185 }, 186 187 188 _createClassNameString: function(classNames) { 189 var classNameArray = [], key; 190 for(key in classNames) { 191 if(!classNames.hasOwnProperty(key)) continue; 192 if(classNames[key]) classNameArray.push(key); 193 } 194 return classNameArray.join(" "); 195 } 196 }); 197