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: Licened under MIT license (see license.js) 6 // ========================================================================== 7 8 /** 9 Renders and updates the DOM representation of a slider. 10 11 Parameters 12 ------------------------- 13 Requires the following parameters: 14 15 - `value` -- a value from 0 to 1. 16 - `frame` -- containing the frame in which the slider is being drawn. 17 */ 18 19 SC.BaseTheme.sliderRenderDelegate = SC.RenderDelegate.create({ 20 21 className: 'slider', 22 23 render: function(dataSource, context) { 24 this.addSizeClassName(dataSource, context); 25 26 var valueMax = dataSource.get('maximum'), 27 valueMin = dataSource.get('minimum'), 28 valueNow = dataSource.get('ariaValue'); 29 30 // Add accessibility values. 31 context.setAttr('aria-valuemax', valueMax); 32 context.setAttr('aria-valuemin', valueMin); 33 context.setAttr('aria-valuenow', valueNow); 34 if(valueMin !== 0 || valueMax !== 100) context.setAttr('aria-valuetext', valueNow); 35 context.setAttr('aria-orientation', 'horizontal'); 36 37 // Begin the track element. 38 context = context.begin('span').addClass('track'); 39 40 // Draw the track's visual elements ("beginning", "middle" and "end"). 41 this.includeSlices(dataSource, context, SC.THREE_SLICE); 42 43 // If desired, draw the step choinks. 44 if (dataSource.get('markSteps')) { 45 var stepPositions = dataSource.get('stepPositions'); 46 if (stepPositions) { 47 var i, len = stepPositions.length; 48 for (i = 0; i < len; i++) { 49 context.begin() 50 .setStyle('left', '%@%'.fmt(stepPositions[i] * 100)) 51 .addClass(['sc-slider-step-mark', 'sc-slider-step-mark-%@'.fmt(i)]) 52 .setClass({ 53 'sc-slider-step-mark-first': i === 0, 54 'sc-slider-step-mark-last': i === len - 1 55 }).end(); 56 } 57 } 58 } 59 60 // Draw the handle. 61 context.begin('img') 62 .setAttr('src', SC.BLANK_IMAGE_URL) 63 .addClass('sc-handle') 64 .setStyle('left', '%@%'.fmt(dataSource.get('value'))) 65 .end(); 66 67 // End the track element. 68 context = context.end(); 69 70 dataSource.get('renderState')._cachedHandle = null; 71 }, 72 73 update: function(dataSource, jquery) { 74 this.updateSizeClassName(dataSource, jquery); 75 76 var valueMax = dataSource.get('maximum'), 77 valueMin = dataSource.get('minimum'), 78 valueNow = dataSource.get('ariaValue'), 79 handle = dataSource.get('renderState')._cachedHandle; 80 81 // Snag the handle if we haven't cached it yet. 82 if (!handle) { 83 handle = dataSource.get('renderState')._cachedHandle = jquery.find('.sc-handle'); 84 } 85 86 // Update accessibility values. 87 jquery.attr('aria-valuemax', valueMax); 88 jquery.attr('aria-valuemin', valueMin); 89 jquery.attr('aria-valuenow', valueNow); 90 if(valueMin !== 0 || valueMax !== 100) jquery.attr('aria-valuetext', valueNow); 91 jquery.attr('aria-orientation', 'horizontal'); 92 93 // If the minimum, maximum, step, or markSteps have changed, repoint the choinks. 94 if (dataSource.didChangeFor('sliderRenderDelegateMinimumMaximumStepMarkSteps', 'minimum', 'maximum', 'step', 'markSteps')) { 95 var marks = jquery.find('.sc-slider-step-mark'), 96 markSteps = dataSource.get('markSteps'), 97 stepPositions; 98 // Ten years ago we had no marks, no steps and 99 if (!markSteps || !(stepPositions = dataSource.get('stepPositions'))) { 100 marks.remove(); 101 } 102 // Otherwise, reposition them, adding new ones as needed. 103 else { 104 var choinkVal, 105 i, len = stepPositions.length, 106 firstLastClass, 107 choinkTemplate = '<div style="left:%@%" class="sc-slider-step-mark sc-slider-step-mark-%@ %@"></div>', 108 choinkMarkup; 109 110 for (i = 0; i < len; i++) { 111 if (marks[i]) { 112 marks.eq(i).css('left', '%@%'.fmt(stepPositions[i] * 100)).setClass({ 113 'sc-slider-step-mark-first': i === 0, 114 'sc-slider-step-mark-last': i === len - 1 115 }); 116 } 117 else { 118 if (i === 0) firstLastClass = 'sc-slider-step-mark-first'; 119 else if (i === len - 1) firstLastClass = 'sc-slider-step-mark-last'; 120 else firstLastClass = ''; 121 choinkMarkup = choinkTemplate.fmt(stepPositions[i] * 100, i, firstLastClass); 122 handle.before(choinkMarkup); 123 } 124 } 125 // Remove any remaining. 126 marks.slice(i).remove(); 127 } 128 } 129 130 // Update the value, if needed. 131 if (dataSource.didChangeFor('sliderRenderDelegateValue', 'value')) { 132 var value = dataSource.get('value'); 133 handle.css('left', value + "%"); 134 } 135 } 136 }); 137