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 8 9 /** 10 @class 11 Renders and updates the HTML representation of a group of radio buttons. 12 13 Expects Properties 14 ------------------------------- 15 16 - `items` -- a collection of data sources for radioRenderDelegates 17 - `layoutDirection` 18 - `isEnabled` 19 20 Extended API 21 -------------------------------- 22 As this encompasses an entire group, it must provide a way to determine 23 which radio button is the target of an event. The indexForEvent method 24 does exactly this, and all radioGroupRenderDelegates _must_ support it. 25 26 Also, as it would be low-performance to update any but the changed radio 27 button, there is a method to update a specific index. 28 */ 29 SC.BaseTheme.radioGroupRenderDelegate = SC.RenderDelegate.create({ 30 className: 'radio-group', 31 32 render: function(dataSource, context) { 33 this.addSizeClassName(dataSource, context); 34 35 var theme = dataSource.get('theme'), 36 name = SC.guidFor(this), 37 items = dataSource.get('items'), idx, len = items.length, item; 38 39 40 context.addClass(dataSource.get('layoutDirection')); 41 context.setAttr('role', 'radiogroup'); 42 context.setAttr('aria-disabled', dataSource.get('isEnabled') ? 'false' : 'true'); 43 44 for (idx = 0; idx < len; idx++) { 45 item = items[idx]; 46 context = context.begin('div') 47 .addClass('radio-' + idx) 48 .setAttr('index', idx) 49 .addClass(theme.classNames) 50 .addClass(theme.radioRenderDelegate.className) 51 52 // so we can identify it in event handling 53 .addClass('sc-radio-button'); 54 55 theme.radioRenderDelegate.render(item, context); 56 57 context = context.end(); 58 } 59 60 // store the radio count so we can know when to regenerate in update 61 dataSource.get('renderState').radioCount = idx; 62 }, 63 64 update: function(dataSource, jquery) { 65 this.updateSizeClassName(dataSource, jquery); 66 67 var theme = dataSource.get('theme'), 68 name = SC.guidFor(this), 69 items = dataSource.get('items'), idx, len = items.length, item; 70 71 jquery.addClass(dataSource.get('layoutDirection')); 72 jquery.attr('aria-disabled', dataSource.get('isEnabled') ? 'false' : 'true'); 73 74 if (dataSource.get('renderState').radioCount !== len) { 75 // just regenerate if the count has changed. It would be better 76 // to be intelligent, but that would also be rather complex 77 // for such a rare case. 78 var context = SC.RenderContext(jquery[0]); 79 this.render(dataSource, context); 80 context.update(); 81 return; 82 } 83 84 for (idx = 0; idx < len; idx++) { 85 item = items[idx]; 86 theme.radioRenderDelegate.update(item, jquery.find('.radio-' + idx)); 87 } 88 }, 89 90 /** 91 Updates the radio button at the specified index. 92 93 @param {Object} dataSource The RenderDelegate data source. 94 @param {jQuery} jquery A jQuery instance with the DOM for this radio group. 95 @param {Number} index The index of the radio to update. 96 */ 97 updateRadioAtIndex: function(dataSource, jquery, index) { 98 var item = dataSource.get('items')[index]; 99 dataSource.get('theme').radioRenderDelegate.update(item, jquery.find('.radio-' + index)); 100 }, 101 102 /** 103 Returns the index of the radio button that was the target of the 104 supplied event. 105 106 @param {Object} dataSource The RenderDelegate data source. 107 @param {jQuery} jquery A jQuery instance with the DOM for this radio group. 108 @param {SC.Event SC.Touch} event The event or SC.Touch object. 109 */ 110 111 indexForEvent: function(dataSource, jquery, evt) { 112 var index = $(evt.target).closest('.sc-radio-button').attr('index'); 113 if (isNaN(index)) return undefined; 114 return parseInt(index, 0); 115 } 116 }); 117