Merge branch 'show-more' of https://github.com/Raven24/diaspora into Raven24-show-more
Conflicts: public/javascripts/app/views/content_view.js
This commit is contained in:
commit
2e1f353ac4
9 changed files with 122 additions and 100 deletions
24
features/show_more.feature
Normal file
24
features/show_more.feature
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
@javascript
|
||||||
|
Feature: collapsing and expanding long posts
|
||||||
|
In order to tame the lengths of posts in my stream
|
||||||
|
As a rocket scientist
|
||||||
|
I want long posts to be collapsed and expand on click
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given a user with username "bob"
|
||||||
|
And I sign in as "bob@bob.bob"
|
||||||
|
And I am on the home page
|
||||||
|
|
||||||
|
Scenario: post a very long message
|
||||||
|
Given I post an extremely long status message
|
||||||
|
And I go to the home page
|
||||||
|
|
||||||
|
Then the post should be collapsed
|
||||||
|
|
||||||
|
Scenario: expand a very long message
|
||||||
|
Given I post an extremely long status message
|
||||||
|
And I go to the home page
|
||||||
|
And I expand the post
|
||||||
|
|
||||||
|
Then the post should be expanded
|
||||||
|
|
||||||
|
|
@ -2,6 +2,14 @@ Then /^the post "([^"]*)" should be marked nsfw$/ do |text|
|
||||||
assert_nsfw(text)
|
assert_nsfw(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Then /^the post should be collapsed$/ do
|
||||||
|
first_post_collapsed?
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the post should be expanded$/ do
|
||||||
|
first_post_expanded?
|
||||||
|
end
|
||||||
|
|
||||||
Then /^I should see an uploaded image within the photo drop zone$/ do
|
Then /^I should see an uploaded image within the photo drop zone$/ do
|
||||||
find("#photodropzone img")["src"].should include("uploads/images")
|
find("#photodropzone img")["src"].should include("uploads/images")
|
||||||
end
|
end
|
||||||
|
|
@ -32,6 +40,9 @@ When /^I click on the first block button/ do
|
||||||
find(".block_user").click
|
find(".block_user").click
|
||||||
end
|
end
|
||||||
|
|
||||||
|
When /^I expand the post$/ do
|
||||||
|
expand_first_post
|
||||||
|
end
|
||||||
|
|
||||||
Then /^I should see "([^"]*)" as the first post in my stream$/ do |text|
|
Then /^I should see "([^"]*)" as the first post in my stream$/ do |text|
|
||||||
first_post_text.should include(text)
|
first_post_text.should include(text)
|
||||||
|
|
@ -43,4 +54,8 @@ end
|
||||||
|
|
||||||
When /^I click the publisher and post "([^"]*)"$/ do |text|
|
When /^I click the publisher and post "([^"]*)"$/ do |text|
|
||||||
click_and_post(text)
|
click_and_post(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
When /^I post an extremely long status message$/ do
|
||||||
|
click_and_post("I am a very interesting message " * 64)
|
||||||
|
end
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,22 @@ module PublishingCukeHelpers
|
||||||
')
|
')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def expand_first_post
|
||||||
|
find(".stream_element:first .expander").click
|
||||||
|
wait_until{ !find(".expander").visible? }
|
||||||
|
end
|
||||||
|
|
||||||
|
def first_post_collapsed?
|
||||||
|
find(".stream_element:first .collapsible").should have_css(".expander")
|
||||||
|
find(".stream_element:first .collapsible").has_selector?(".collapsed")
|
||||||
|
end
|
||||||
|
|
||||||
|
def first_post_expanded?
|
||||||
|
find(".stream_element:first .expander").should_not be_visible
|
||||||
|
find(".stream_element:first .collapsible").has_no_selector?(".collapsed")
|
||||||
|
find(".stream_element:first .collapsible").has_selector?(".opened")
|
||||||
|
end
|
||||||
|
|
||||||
def first_post_text
|
def first_post_text
|
||||||
find('.stream_element:first .post-content').text()
|
find('.stream_element:first .post-content').text()
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@ app.views.Comment = app.views.Content.extend({
|
||||||
|
|
||||||
className : "comment media",
|
className : "comment media",
|
||||||
|
|
||||||
events : {
|
events : function() {
|
||||||
"click .comment_delete": "destroyModel"
|
return _.extend(app.views.Content.prototype.events, {
|
||||||
|
"click .comment_delete": "destroyModel"
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
presenter : function() {
|
presenter : function() {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
app.views.Content = app.views.StreamObject.extend({
|
app.views.Content = app.views.StreamObject.extend({
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
"click .oembed .thumb": "showOembedContent"
|
"click .oembed .thumb": "showOembedContent",
|
||||||
|
"click .expander": "expandPost"
|
||||||
},
|
},
|
||||||
|
|
||||||
presenter : function(){
|
presenter : function(){
|
||||||
|
|
@ -41,7 +42,17 @@ app.views.Content = app.views.StreamObject.extend({
|
||||||
var paramSeparator = ( /\?/.test(insertHTML.attr("src")) ) ? "&" : "?";
|
var paramSeparator = ( /\?/.test(insertHTML.attr("src")) ) ? "&" : "?";
|
||||||
insertHTML.attr("src", insertHTML.attr("src") + paramSeparator + "autoplay=1");
|
insertHTML.attr("src", insertHTML.attr("src") + paramSeparator + "autoplay=1");
|
||||||
oembed.html( insertHTML );
|
oembed.html( insertHTML );
|
||||||
|
},
|
||||||
|
|
||||||
|
expandPost: function(evt) {
|
||||||
|
var el = $(this.el).find('.collapsible');
|
||||||
|
el.removeClass('collapsed').addClass('opened');
|
||||||
|
el.animate({'height':el.data('orig-height')}, 550, function() {
|
||||||
|
el.css('height','auto');
|
||||||
|
});
|
||||||
|
$(evt.currentTarget).hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.views.StatusMessage = app.views.Content.extend({
|
app.views.StatusMessage = app.views.Content.extend({
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,5 @@
|
||||||
app.views.StreamObject = app.views.Base.extend({
|
app.views.StreamObject = app.views.Base.extend({
|
||||||
|
|
||||||
postRenderTemplate : function() {
|
|
||||||
// collapse long posts
|
|
||||||
this.$(".collapsible").expander({
|
|
||||||
slicePoint: 400,
|
|
||||||
widow: 12,
|
|
||||||
expandPrefix: "",
|
|
||||||
expandText: Diaspora.I18n.t("show_more"),
|
|
||||||
userCollapse: false,
|
|
||||||
beforeExpand: function() {
|
|
||||||
if ($(this).find('.summary').length == 0) { // Sigh. See comments in the spec.
|
|
||||||
var readMoreDiv = $(this).find('.read-more');
|
|
||||||
var lastElementBeforeReadMore = readMoreDiv.prev();
|
|
||||||
var firstElementAfterReadMore = readMoreDiv.next().children().first();
|
|
||||||
|
|
||||||
if (lastElementBeforeReadMore.is('p')) {
|
|
||||||
lastElementBeforeReadMore.append(firstElementAfterReadMore.html());
|
|
||||||
firstElementAfterReadMore.remove();
|
|
||||||
|
|
||||||
} else if (lastElementBeforeReadMore.is('ul') && firstElementAfterReadMore.is('ul')) {
|
|
||||||
var firstBullet = firstElementAfterReadMore.children().first();
|
|
||||||
lastElementBeforeReadMore.find('li').last().append(firstBullet.html());
|
|
||||||
firstBullet.remove();
|
|
||||||
}
|
|
||||||
readMoreDiv.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
destroyModel: function(evt) {
|
destroyModel: function(evt) {
|
||||||
if (evt) {
|
if (evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ app.views.Stream = Backbone.View.extend({
|
||||||
|
|
||||||
setupEvents : function(){
|
setupEvents : function(){
|
||||||
this.stream.bind("fetched", this.removeLoader, this)
|
this.stream.bind("fetched", this.removeLoader, this)
|
||||||
|
this.stream.bind("fetched", this.postRender, this)
|
||||||
this.stream.bind("allPostsLoaded", this.unbindInfScroll, this)
|
this.stream.bind("allPostsLoaded", this.unbindInfScroll, this)
|
||||||
this.collection.bind("add", this.addPost, this);
|
this.collection.bind("add", this.addPost, this);
|
||||||
if(window.app.user()) {
|
if(window.app.user()) {
|
||||||
|
|
@ -52,6 +53,35 @@ app.views.Stream = Backbone.View.extend({
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
postRender : function() {
|
||||||
|
// collapse long posts
|
||||||
|
var collHeight = 190,
|
||||||
|
collElem = $(this.el).find(".collapsible");
|
||||||
|
|
||||||
|
_.each(collElem, function(elem) {
|
||||||
|
var elem = $(elem),
|
||||||
|
oembed = elem.find(".oembed"),
|
||||||
|
addHeight = 0;
|
||||||
|
|
||||||
|
if( $.trim(oembed.html()) != "" ) {
|
||||||
|
addHeight = oembed.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
// only collapse if height exceeds collHeight+20%
|
||||||
|
if( elem.height() > ((collHeight*1.2)+addHeight) && !elem.is(".opened") ) {
|
||||||
|
elem.data("orig-height", elem.height() );
|
||||||
|
elem
|
||||||
|
.height( Math.max(collHeight, addHeight) )
|
||||||
|
.addClass("collapsed")
|
||||||
|
.append(
|
||||||
|
$('<div />')
|
||||||
|
.addClass('expander')
|
||||||
|
.text( Diaspora.I18n.t("show_more") )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
appendLoader: function(){
|
appendLoader: function(){
|
||||||
$("#paginate").html($("<img>", {
|
$("#paginate").html($("<img>", {
|
||||||
|
|
|
||||||
|
|
@ -1828,6 +1828,26 @@ ul#press_logos
|
||||||
:color #777
|
:color #777
|
||||||
|
|
||||||
.collapsible
|
.collapsible
|
||||||
|
:overflow hidden
|
||||||
|
:position relative
|
||||||
|
|
||||||
|
.expander
|
||||||
|
:position absolute
|
||||||
|
:bottom 0
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:height 30px
|
||||||
|
:text-align center
|
||||||
|
:line-height 48px
|
||||||
|
:font-size .8em
|
||||||
|
:color $grey
|
||||||
|
:text-shadow 0 0 7px #FFF
|
||||||
|
:cursor pointer
|
||||||
|
:border-bottom 2px solid #DDD
|
||||||
|
@include border-radius(0, 0, 3px, 3px)
|
||||||
|
@include linear-gradient(rgba(255,255,255,0) , #EEE, 0%, 95%)
|
||||||
|
:background-color transparent
|
||||||
|
|
||||||
.oembed
|
.oembed
|
||||||
:background url('/images/ajax-loader2.gif') no-repeat center center
|
:background url('/images/ajax-loader2.gif') no-repeat center center
|
||||||
:display inline-block
|
:display inline-block
|
||||||
|
|
|
||||||
|
|
@ -39,73 +39,6 @@ describe("app.views.Stream", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('clicking read more', function() {
|
|
||||||
var readMoreLink;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
this.statusMessage = this.stream.posts.models[0];
|
|
||||||
this.statusElement = $(this.view.$(".stream_element")[0]);
|
|
||||||
readMoreLink = this.statusElement.find('.read-more a');
|
|
||||||
readMoreLink.text("read more");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('expands the post', function() {
|
|
||||||
expect(this.statusElement.find('.collapsible .details').attr('style')).toContain('display: none;');
|
|
||||||
readMoreLink.click();
|
|
||||||
expect(this.statusElement.find('.collapsible .details').attr('style')).not.toContain('display: none;');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('differences between firefox and webkit/IE', function() {
|
|
||||||
// Firefox creates 2 divs - one with the summary and one with the whole post.
|
|
||||||
// It hides the summary and shows the whole post when you click show more. Works great!
|
|
||||||
// Webkit and IE also create 2 divs, but they split the post - the 1st has the summary and the 2nd has the rest
|
|
||||||
// of the post. When you click read more, it just shows the 2nd div. This leaves whitespace in odd places.
|
|
||||||
// So there's a callback that this is testing, that fixes the whitespace on webkit & IE.
|
|
||||||
var weAreOnFirefox;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
weAreOnFirefox = this.statusElement.find('.collapsible .summary').length > 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('removes the read-more div on webkit/IE but leaves it on firefox', function() {
|
|
||||||
expect(this.statusElement.find('.read-more').length).toEqual(1);
|
|
||||||
readMoreLink.click();
|
|
||||||
if (weAreOnFirefox === true) {
|
|
||||||
expect(this.statusElement.find('.read-more').length).toEqual(1);
|
|
||||||
} else {
|
|
||||||
expect(this.statusElement.find('.read-more').length).toEqual(0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('collapses p elements on webkit/IE but leaves them alone on firefox', function() {
|
|
||||||
expect(this.statusElement.find('.collapsible p').length).toEqual(2);
|
|
||||||
readMoreLink.click();
|
|
||||||
if (weAreOnFirefox === true) {
|
|
||||||
expect(this.statusElement.find('.collapsible p').length).toEqual(2);
|
|
||||||
} else {
|
|
||||||
expect(this.statusElement.find('.collapsible p').length).toEqual(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('collapses li elements on webkit/IE but leaves them alone on firefox', function() {
|
|
||||||
this.statusMessage = this.stream.posts.models[3];
|
|
||||||
this.statusElement = $(this.view.$(".stream_element")[3]);
|
|
||||||
readMoreLink = this.statusElement.find('.read-more a');
|
|
||||||
readMoreLink.text("read more");
|
|
||||||
|
|
||||||
if (weAreOnFirefox === true) {
|
|
||||||
expect(this.statusElement.find('.collapsible li').length).toEqual(12);
|
|
||||||
readMoreLink.click();
|
|
||||||
expect(this.statusElement.find('.collapsible li').length).toEqual(12);
|
|
||||||
} else {
|
|
||||||
expect(this.statusElement.find('.collapsible li').length).toEqual(9);
|
|
||||||
readMoreLink.click();
|
|
||||||
expect(this.statusElement.find('.collapsible li').length).toEqual(8);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("infScroll", function() {
|
describe("infScroll", function() {
|
||||||
// NOTE: inf scroll happens at 500px
|
// NOTE: inf scroll happens at 500px
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue