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 sc_require('mixins/collection_group'); 9 sc_require('views/disclosure'); 10 11 /** 12 @class 13 14 Displays a group view in a source list. Handles displaying a disclosure 15 triangle which can be used to show/hide children. 16 17 @extends SC.View 18 @extends SC.Control 19 @extends SC.CollectionGroup 20 @author Charles Jolley 21 @author Erich Ocean 22 @version 1.0 23 @since 0.9 24 */ 25 SC.SourceListGroupView = SC.View.extend(SC.Control, SC.CollectionGroup, 26 /** @scope SC.SourceListGroupView.prototype */ { 27 28 /** 29 @type Array 30 @default ['sc-source-list-group'] 31 @see SC.View#classNames 32 */ 33 classNames: ['sc-source-list-group'], 34 35 // .......................................................... 36 // KEY PROPERTIES 37 // 38 39 /** 40 The content object the source list group will display. 41 42 @type SC.Object 43 @default null 44 */ 45 content: null, 46 47 /** 48 The current group visibility. Used by the source list to determine the 49 layout size of the group. 50 51 @type Boolean 52 @default YES 53 */ 54 isGroupVisible: YES, 55 56 /** 57 YES if group is showing its titlebar. 58 59 Group views will typically hide their header if the content is set to 60 null. You can also override this method to always hide the header if 61 you want and the SourceListView will not leave room for it. 62 63 @type Boolean 64 @default YES 65 */ 66 hasGroupTitle: YES, 67 68 /** 69 The content property key to use as the group view's title. 70 71 @type String 72 @default null 73 */ 74 groupTitleKey: null, 75 76 /** 77 The content property key to use to determine if the group's children are 78 visible or not. 79 80 @type String 81 @default null 82 */ 83 groupVisibleKey: null, 84 85 /** @private */ 86 render: function(context, firstTime) { 87 context.push('<div role="button" class="sc-source-list-label sc-disclosure-view sc-button-view button disclosure no-disclosure">', 88 '<img src="'+SC.BLANK_IMAGE_URL+'" class="button" />', 89 '<span class="label"></span></div>') ; 90 }, 91 92 /** @private */ 93 createChildViews: function() { 94 95 }, 96 97 /** @private */ 98 contentPropertyDidChange: function(target, key) { 99 var content = this.get('content') ; 100 var labelView = this.outlet('labelView') ; 101 102 // hide labelView if content is null. 103 if (content === null) { 104 labelView.setIfChanged('isVisible', NO) ; 105 this.setIfChanged('hasGroupTitle', NO) ; 106 return ; 107 } else { 108 labelView.setIfChanged('isVisible', YES) ; 109 this.setIfChanged('hasGroupTitle', YES) ; 110 } 111 112 // set the title if that changed. 113 var groupTitleKey = this.getDelegateProperty('groupTitleKey', this.displayDelegate) ; 114 if ((key == '*') || (groupTitleKey && (key == groupTitleKey))) { 115 var title = (content && content.get && groupTitleKey) ? content.get(groupTitleKey) : content; 116 if (title != this._title) { 117 this._title = title ; 118 if (title) title = title.capitalize() ; 119 labelView.set('title', title) ; 120 } 121 } 122 123 // set the group visibility if changed 124 var groupVisibleKey = this.getDelegateProperty('groupVisibleKey', this.displayDelegate) ; 125 if ((key == '*') || (groupVisibleKey && (key == groupVisibleKey))) { 126 if (groupVisibleKey) { 127 labelView.removeClassName('no-disclosure') ; 128 129 var isVisible = (content && content.get) ? 130 !!content.get(groupVisibleKey) : 131 YES ; 132 if (isVisible != this.get('isGroupVisible')) { 133 this.set('isGroupVisible', isVisible) ; 134 labelView.set('value', isVisible) ; 135 } 136 } else labelView.addClassName('no-disclosure') ; 137 } 138 }, 139 140 /** @private 141 Called when the user clicks on the disclosure triangle 142 */ 143 disclosureValueDidChange: function(newValue) { 144 if (newValue == this.get('isGroupVisible')) return; // nothing to do 145 146 // update group if necessary 147 var group = this.get('content') ; 148 var groupVisibleKey = this.getDelegateProperty('groupVisibleKey', this.displayDelegate) ; 149 if (group && group.set && groupVisibleKey) { 150 group.set(groupVisibleKey, newValue) ; 151 } 152 153 // update my own value and then update my collection view. 154 this.set('isGroupVisible', newValue) ; 155 if (this.owner && this.owner.updateChildren) this.owner.updateChildren(true) ; 156 157 }, 158 159 /** @private */ 160 labelView: SC.DisclosureView.extend({ 161 162 /** @private */ 163 value: YES, 164 165 /** @private 166 If the disclosure value changes, call the owner's method. Note 167 normally you would do this with a binding, but since this is a semi- 168 private class anyway, there is no reason to go to all that trouble. 169 */ 170 _valueObserver: function() { 171 if (this.owner) this.owner.disclosureValueDidChange(this.get('value')) ; 172 }.observes('value') 173 174 }) 175 176 }); 177