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('views/collection'); 9 10 /** 11 @class 12 13 A StackedView is a CollectionView that expects its content to use static 14 layout to stack vertically. This type of collection view is not designed 15 for use with large size collections, but it can be very useful for 16 collections with complex displays and variable heights such as comments or 17 small notification queues. 18 19 ## Static Layout 20 21 This view makes no attempt to size or position your child views. It assumes 22 you are using StaticLayout for your child views. If you don't enable static 23 layout your views will probably overlay on top of each other and will look 24 incorrect. 25 26 Note also that the default layout for this view set's the height to "auto". 27 This is usually the behavior you will want. 28 29 @extends SC.CollectionView 30 @since SproutCore 0.9 31 */ 32 SC.StackedView = SC.CollectionView.extend( 33 /** @scope SC.StackedView.prototype */ { 34 35 /** 36 @type Array 37 @default ['sc-stacked-view'] 38 @see SC.View#classNames 39 */ 40 classNames: ['sc-stacked-view'], 41 42 /** 43 Default layout for a stacked view will fill the parent view but auto- 44 adjust the height of the view. 45 46 @type Hash 47 @default `{ top: 0, left: 0, right: 0, height: 1 }` 48 @see SC.View#layout 49 */ 50 layout: { top: 0, left: 0, right: 0, height: 1 }, 51 52 /** 53 Return full range of its indexes for nowShowing 54 55 @param {Rect} rect 56 @returns {SC.IndexSet} full range of indexes 57 */ 58 computeNowShowing: function () { 59 return this.get('allContentIndexes'); 60 }, 61 62 /** 63 Updates the height of the stacked view to reflect the current content of 64 the view. This is called automatically whenever an item view is reloaded. 65 You can also call this method directly if the height of one of your views 66 has changed. 67 68 The height will be recomputed based on the actual location and dimensions 69 of the last child view. 70 71 Note that normally this method will defer actually updating the height 72 of the view until the end of the run loop. You can force an immediate 73 update by passing YES to the "immediately" parameter. 74 75 @param {Boolean} immediately YES to update immediately 76 @returns {SC.StackedView} receiver 77 */ 78 updateHeight: function (immediately) { 79 if (immediately) this._updateHeight(); 80 else this.invokeLast(this._updateHeight); 81 // ^ use invokeLast() here because we need to wait until all rendering has 82 // completed. 83 84 return this; 85 }, 86 87 /** @private */ 88 _updateHeight: function () { 89 90 var childViews = this.get('childViews'), 91 len = childViews.get('length'), 92 view, layer, height; 93 94 if (len === 0) { 95 height = 1; 96 } else { 97 view = childViews.objectAt(len - 1); 98 layer = view ? view.get('layer') : null; 99 height = layer ? (layer.offsetTop + layer.offsetHeight) : 1; 100 layer = null; // avoid memory leaks 101 } 102 this.adjust('minHeight', height); 103 this.set('calculatedHeight', height); 104 }, 105 106 // .......................................................... 107 // INTERNAL SUPPORT 108 // 109 110 /** @private 111 Whenever the collection view reloads some views, reset the cache on the 112 frame as well so that it will recalculate. 113 */ 114 reloadIfNeeded: function () { 115 sc_super(); 116 117 return this.updateHeight(); 118 }, 119 120 /** @private 121 When layer is first created, make sure we update the height using the 122 newly calculated value. 123 */ 124 didCreateLayer: function () { return this.updateHeight(); } 125 126 }); 127