User stream now uses eyeline for loading more content.

This commit is contained in:
Robin Ward 2013-07-23 16:06:26 -04:00
parent 44bebf255d
commit c9c6a8fd9d
6 changed files with 63 additions and 74 deletions

View File

@ -18,31 +18,31 @@ Discourse.Eyeline = function Eyeline(selector) {
/** /**
Call this to analyze the positions of all the nodes in a set Call this to analyze the positions of all the nodes in a set
returns: a hash with top, bottom and onScreen items returns: a hash with top, bottom and onScreen items
{top: , bottom:, onScreen:} {top: , bottom:, onScreen:}
**/ **/
Discourse.Eyeline.analyze = function(rows) { Discourse.Eyeline.analyze = function(rows) {
var current, goingUp, i, increment, offset, var current, goingUp, i, increment, offset,
winHeight, winOffset, detected, onScreen, winHeight, winOffset, detected, onScreen,
bottom, top, outerHeight; bottom, top, outerHeight;
if (rows.length === 0) return; if (rows.length === 0) return;
i = parseInt(rows.length / 2, 10); i = parseInt(rows.length / 2, 10);
increment = parseInt(rows.length / 4, 10); increment = parseInt(rows.length / 4, 10);
goingUp = undefined; goingUp = undefined;
winOffset = window.pageYOffset || $('html').scrollTop(); winOffset = window.pageYOffset || $('html').scrollTop();
winHeight = window.innerHeight || $(window).height(); winHeight = window.innerHeight || $(window).height();
while (true) { while (true) {
if (i === 0 || (i >= rows.length - 1)) { if (i === 0 || (i >= rows.length - 1)) {
break; break;
} }
current = $(rows[i]); current = $(rows[i]);
offset = current.offset(); offset = current.offset();
if (offset.top - winHeight < winOffset) { if (offset.top - winHeight < winOffset) {
if (offset.top + current.outerHeight() - window.innerHeight > winOffset) { if (offset.top + current.outerHeight() - window.innerHeight > winOffset) {
break; break;
@ -69,22 +69,22 @@ Discourse.Eyeline.analyze = function(rows) {
goingUp = undefined; goingUp = undefined;
} }
} }
onScreen = []; onScreen = [];
bottom = i; bottom = i;
// quick analysis of whats on screen // quick analysis of whats on screen
while(true) { while(true) {
if(i < 0) { break;} if(i < 0) { break;}
current = $(rows[i]); current = $(rows[i]);
offset = current.offset(); offset = current.offset();
outerHeight = current.outerHeight(); outerHeight = current.outerHeight();
// on screen // on screen
if(offset.top > winOffset && offset.top + outerHeight < winOffset + winHeight) { if(offset.top > winOffset && offset.top + outerHeight < winOffset + winHeight) {
onScreen.unshift(i); onScreen.unshift(i);
} else { } else {
if(offset.top < winOffset) { if(offset.top < winOffset) {
top = i; top = i;
break; break;
@ -94,7 +94,7 @@ Discourse.Eyeline.analyze = function(rows) {
} }
i -=1; i -=1;
} }
return({top: top, bottom: bottom, onScreen: onScreen}); return({top: top, bottom: bottom, onScreen: onScreen});
}; };
@ -169,11 +169,10 @@ Discourse.Eyeline.prototype.update = function() {
@method flushRest @method flushRest
**/ **/
Discourse.Eyeline.prototype.flushRest = function() { Discourse.Eyeline.prototype.flushRest = function() {
var _this = this; var eyeline = this;
return $(this.selector).each(function(i, elem) { return $(this.selector).each(function(i, elem) {
var $elem; var $elem = $(elem);
$elem = $(elem); return eyeline.trigger('saw', { detail: $elem });
return _this.trigger('saw', { detail: $elem });
}); });
}; };

View File

@ -35,7 +35,7 @@ Discourse.Scrolling = Em.Mixin.create({
}, },
/** /**
Begin watching for scroll events. They will be called at max every 100ms. Stop watching for scroll events.
@method unbindScrolling @method unbindScrolling
*/ */

View File

@ -1,27 +1,24 @@
<div id='user-stream'> {{#each view.stream.content}}
{{#each view.stream.content}} <div {{bindAttr class=":item hidden deleted moderator_action"}}>
<div {{bindAttr class=":item hidden deleted moderator_action"}}> <div class='clearfix info'>
<div class='clearfix info'> <a href="{{unbound userUrl}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a>
<a href="{{unbound userUrl}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a> <span class='time'>{{date path="created_at" leaveAgo="true"}}</span>
<span class='time'>{{date path="created_at" leaveAgo="true"}}</span> <span class="title">
<span class="title"> <a href="{{unbound postUrl}}">{{unbound title}}</a>
<a href="{{unbound postUrl}}">{{unbound title}}</a> </span>
</span> <span class="type">{{unbound descriptionHtml}}</span>
<span class="type">{{unbound descriptionHtml}}</span>
</div>
<p class='excerpt'>
{{{unbound excerpt}}}
</p>
{{#each children}}
<div class='child-actions'>
<i class="icon {{unbound icon}}"></i>
{{#each items}}
<a href="{{unbound userUrl}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}</div></a>
{{/each}}
</div>
{{/each}}
</div> </div>
{{/each}} <p class='excerpt'>
{{{unbound excerpt}}}
</p>
{{#each children}}
<div class='child-actions'>
<i class="icon {{unbound icon}}"></i>
{{#each items}}
<a href="{{unbound userUrl}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}</div></a>
{{/each}}
</div>
{{/each}}
</div>
{{/each}}
</div>
<div id="user-stream-bottom"></div>

View File

@ -76,9 +76,9 @@ Discourse.ListTopicsView = Discourse.View.extend(Discourse.Scrolling, {
// When the topic list is scrolled // When the topic list is scrolled
scrolled: function(e) { scrolled: function(e) {
var _ref;
this.saveScrollPos(); this.saveScrollPos();
return (_ref = this.get('eyeline')) ? _ref.update() : void 0; var eyeline = this.get('eyeline');
if (eyeline) { eyeline.update(); }
} }

View File

@ -9,34 +9,23 @@
**/ **/
Discourse.UserStreamView = Discourse.View.extend(Discourse.Scrolling, { Discourse.UserStreamView = Discourse.View.extend(Discourse.Scrolling, {
templateName: 'user/stream', templateName: 'user/stream',
loading: false,
elementId: 'user-stream',
scrolled: function(e) { scrolled: function(e) {
var eyeline = this.get('eyeline');
if (eyeline) { eyeline.update(); }
},
var $userStreamBottom = $('#user-stream-bottom'); loadMore: function() {
if ($userStreamBottom.data('loading')) return; var userStreamView = this;
if (userStreamView.get('loading')) { return; }
var position = $userStreamBottom.position(); var stream = this.get('stream');
if (!($userStreamBottom && position)) return; stream.findItems().then(function() {
userStreamView.set('loading', false);
var docViewTop = $(window).scrollTop(); userStreamView.get('eyeline').flushRest();
var windowHeight = $(window).height(); });
var docViewBottom = docViewTop + windowHeight;
if (position.top < docViewBottom) {
$userStreamBottom.data('loading', true);
this.set('loading', true);
var userStreamView = this;
var user = this.get('stream.user');
var stream = this.get('stream');
stream.findItems().then(function() {
userStreamView.set('loading', false);
Em.run.schedule('afterRender', function() {
$userStreamBottom.data('loading', null);
});
});
}
}, },
willDestroyElement: function() { willDestroyElement: function() {
@ -45,8 +34,15 @@ Discourse.UserStreamView = Discourse.View.extend(Discourse.Scrolling, {
didInsertElement: function() { didInsertElement: function() {
this.bindScrolling(); this.bindScrolling();
}
var eyeline = new Discourse.Eyeline('#user-stream .item');
this.set('eyeline', eyeline);
var userStreamView = this;
eyeline.on('sawBottom', function() {
userStreamView.loadMore();
});
}
}); });

View File

@ -237,14 +237,11 @@
} }
} }
#user-stream-bottom {
margin-bottom: 50px;
clear: both;
}
#user-stream { #user-stream {
width: 840px; width: 840px;
float: left; float: left;
margin-bottom: 50px;
.excerpt { .excerpt {
margin: 5px 0px; margin: 5px 0px;
font-size: 13px; font-size: 13px;