// ========================================================================== // 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) // ========================================================================== /** @class Renders and updates the HTML representation of a group of radio buttons. Expects Properties ------------------------------- - `items` -- a collection of data sources for radioRenderDelegates - `layoutDirection` - `isEnabled` Extended API -------------------------------- As this encompasses an entire group, it must provide a way to determine which radio button is the target of an event. The indexForEvent method does exactly this, and all radioGroupRenderDelegates _must_ support it. Also, as it would be low-performance to update any but the changed radio button, there is a method to update a specific index. */ SC.BaseTheme.radioGroupRenderDelegate = SC.RenderDelegate.create({ className: 'radio-group', render: function(dataSource, context) { this.addSizeClassName(dataSource, context); var theme = dataSource.get('theme'), name = SC.guidFor(this), items = dataSource.get('items'), idx, len = items.length, item; context.addClass(dataSource.get('layoutDirection')); context.attr('role', 'radiogroup'); context.attr('aria-disabled', dataSource.get('isEnabled') ? 'false' : 'true'); for (idx = 0; idx < len; idx++) { item = items[idx]; context = context.begin('div') .addClass('radio-' + idx) .attr('index', idx) .addClass(theme.classNames) .addClass(theme.radioRenderDelegate.className) // so we can identify it in event handling .addClass('sc-radio-button'); theme.radioRenderDelegate.render(item, context); context = context.end(); } // store the radio count so we can know when to regenerate in update dataSource.get('renderState').radioCount = idx; }, update: function(dataSource, jquery) { this.updateSizeClassName(dataSource, jquery); var theme = dataSource.get('theme'), name = SC.guidFor(this), items = dataSource.get('items'), idx, len = items.length, item; jquery.addClass(dataSource.get('layoutDirection')); jquery.attr('aria-disabled', dataSource.get('isEnabled') ? 'false' : 'true'); if (dataSource.get('renderState').radioCount !== len) { // just regenerate if the count has changed. It would be better // to be intelligent, but that would also be rather complex // for such a rare case. var context = SC.RenderContext(jquery[0]); this.render(dataSource, context); context.update(); return; } for (idx = 0; idx < len; idx++) { item = items[idx]; theme.radioRenderDelegate.update(item, jquery.find('.radio-' + idx)); } }, /** Updates the radio button at the specified index. @param {Object} dataSource The RenderDelegate data source. @param {jQuery} jquery A jQuery instance with the DOM for this radio group. @param {Number} index The index of the radio to update. */ updateRadioAtIndex: function(dataSource, jquery, index) { var item = dataSource.get('items')[index]; dataSource.get('theme').radioRenderDelegate.update(item, jquery.find('.radio-' + index)); }, /** Returns the index of the radio button that was the target of the supplied event. @param {Object} dataSource The RenderDelegate data source. @param {jQuery} jquery A jQuery instance with the DOM for this radio group. @param {SC.Event SC.Touch} event The event or SC.Touch object. */ indexForEvent: function(dataSource, jquery, evt) { var index = $(evt.target).closest('.sc-radio-button').attr('index'); if (isNaN(index)) return undefined; return parseInt(index, 0); } });