// ========================================================================== // Project: SproutCore
- JavaScript Application Framework // Copyright: ©2006-2011 Strobe Inc. and contributors. // Portions ©2008-2011 Apple Inc. All rights reserved. // License: Licensed under MIT license (see license.js) // ==========================================================================
SC
.BaseTheme.PROGRESS_OFFSET = 0.5; SC
.BaseTheme.PROGRESS_OFFSET_RANGE = 42;
/**
Renders and updates DOM representations of progress bars. Parameters -------------------------- Expects these properties on the data source: - `isIndeterminate` - `isRunning` - `isVisibleInWindow` - `value` Theme Constants ------------------------------------- Ace's `progressRenderDelegate`'s rendering process is not affected by any theme constants. */
SC
.BaseTheme.progressRenderDelegate = SC
.RenderDelegate.create({
className:'progress', render:function (dataSource, context) { this.addSizeClassName(dataSource, context); var isIndeterminate = dataSource.get('isIndeterminate'), theme = dataSource.get('theme'), valueMax = dataSource.get('maximum'), valueMin = dataSource.get('minimum'), valueNow = dataSource.get('ariaValue'); var value; if (isIndeterminate) { value = 1; } else { value = dataSource.get('value'); } // make accessible context.setAttr('aria-valuemax', valueMax); context.setAttr('aria-valuemin', valueMin); context.setAttr('aria-valuenow', valueNow); context.setAttr('aria-valuetext', valueNow); context.setClass({ indeterminate:isIndeterminate, running:dataSource.get('isRunning') && isIndeterminate, 'sc-empty':(value <= 0), 'sc-complete':(value >= 1 && !isIndeterminate) }); context = context.begin('div').addClass('track'); this.includeSlices(dataSource, context, SC.THREE_SLICE); context = context.end(); context = context.begin('div').addClass('content'); context.setStyle('width', (value * 100) + "%"); this.includeSlices(dataSource, context, SC.THREE_SLICE); context = context.end(); }, update:function (dataSource, jQuery) { this.updateSizeClassName(dataSource, jQuery); var theme = dataSource.get('theme'), value, valueMax = dataSource.get('maximum'), valueMin = dataSource.get('minimum'), valueNow = dataSource.get('ariaValue'), isIndeterminate = dataSource.get('isIndeterminate'), isRunning = dataSource.get('isRunning'), isVisibleInWindow = dataSource.get('isVisibleInWindow'); // make accessible jQuery.attr('aria-valuemax', valueMax); jQuery.attr('aria-valuemin', valueMin); jQuery.attr('aria-valuenow', valueNow); jQuery.attr('aria-valuetext', valueNow); if (isIndeterminate) { value = 1; } else { value = dataSource.get('value'); } jQuery.setClass({ indeterminate:isIndeterminate, running:isRunning && isIndeterminate, 'sc-empty':(value <= 0), 'sc-complete':(value >= 1 && !isIndeterminate) }); jQuery.find('.content').css('width', (value * 100) + "%"); // fallback for browsers that don't support css transitions if(!SC.platform.supportsCSSTransitions) { if (!this._queue[jQuery[0].id]) { this._queue[jQuery[0].id] = { offset:0, element:SC.$(jQuery).find('.content .middle'), shouldAnimate:false }; } if (isIndeterminate && isRunning && isVisibleInWindow) { // save offset in the queue and request animation this._queue[jQuery[0].id].shouldAnimate = true; this.animate(dataSource); } else if (!isIndeterminate) { // Clear out our custom background-position when isIndeterminate toggles. this._queue[jQuery[0].id].element.css('background-position', ''); } else { this._queue[jQuery[0].id].shouldAnimate = false; } } }, /** @private Queue of objects to animate: { id, offset, element } */ _queue: {}, /** @private Catch double calls to _animate */ _animating: false, /** Animates the indeterminate progress view's middle background using JavaScript and requestAnimationFrame(). */ animate: function (dataSource) { var self = this; // avoid invoking the animation code multiple times if more than // one progress bar needs animating *and* one has already started the loop if (this._animating) { return; } function _animate() { var offset, lastOffset, roundedOffset, viewsToAnimate = self._queue, animations = 0, params; var id; for (id in viewsToAnimate) { if (viewsToAnimate.hasOwnProperty(id)) { params=viewsToAnimate[id]; if (params.shouldAnimate) { self._animating = true; animations++; lastOffset = params.offset || 0; offset = (lastOffset + SC.BaseTheme.PROGRESS_OFFSET) % SC.BaseTheme.PROGRESS_OFFSET_RANGE; // Only update the style when the offset changes (this avoids making // the browser recalculate style in each frame). roundedOffset = Math.round(offset); if (roundedOffset > Math.round(lastOffset)) { params.element.css('background-position', roundedOffset + "px 0px"); } params.offset = offset; } } } if (animations === 0) { self._animating = false; } else { window.requestAnimationFrame(_animate); } } // Start the animation. _animate(); }
});