App = Ember.Application.create(); App.Router.map(function() { // put your routes here }); App.IndexRoute = Ember.Route.extend({ model: function() { var people = [ 'Bill', 'Zach', 'Seung', 'Kapil', 'Tom', 'Ren', 'George', 'Ed', 'Ben', 'Curtis', 'Allie', 'Tao', 'David', 'Gian', 'Clifton', 'Richard', 'Max', 'Tony', 'Kiran', 'Mike', 'Brian', 'Joe', 'Matt', 'Alex', 'Jeremy', 'Travis' ]; var items = []; for (var i = 0; i < 1000; i++) { var person = people[Math.floor(Math.random() * people.length)]; items.push((i+1) + ". " + person); } return items; } }); App.XVirtualListComponent = Ember.Component.extend({ rowHeight: 40, scrollOffset: 0, containerHeight: 0, visibleItems: function() { var rowHeight = this.get('rowHeight'); var startIndex = this.get('startIndex'); var endIndex = this.get('endIndex'); return this.get('items').slice(startIndex, endIndex).map(function(name, i) { var index = i + startIndex; var top = (rowHeight * index); return { name: name, style: new Ember.Handlebars.SafeString("top: " + top + "px;") }; }); }.property('items', 'rowHeight', 'startIndex', 'endIndex'), startOffset: function() { return Math.abs(this.get('scrollOffset')) / this.get('rowHeight'); }.property('scrollOffset', 'containerHeight', 'rowHeight'), endOffset: function() { return (Math.abs(this.get('scrollOffset')) + this.getWithDefault('containerHeight', 0)) / this.get('rowHeight'); }.property('scrollOffset', 'containerHeight', 'rowHeight'), startIndex: function() { return Math.floor(this.get('startOffset')); }.property('startOffset'), endIndex: function() { return Math.ceil(this.get('endOffset')); }.property('endOffset'), scrollerStyle: function() { var height = this.get('items.length') * this.get('rowHeight'); var style = "height: " + height + "px"; return new Ember.Handlebars.SafeString(style); }.property('items.length', 'rowHeight'), hookupScroll: function() { var view = this; $('#container').bind('scroll', function() { Ember.run.once(view, function() { var containerOffset = $('#container').offset().top; var scrollerOffset = $('#scroller').offset().top; var scrollOffset = scrollerOffset - containerOffset; view.set('scrollOffset', scrollOffset); }); }); }.on('didInsertElement'), readySetGo: function() { Ember.run.later(this, function() { this.set('containerHeight', Ember.$('#container').height()); }); }.on('didInsertElement'), });