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