From 9aa0a7ed58a615c96a35d0716b73bba3344ad69e Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Mon, 12 Mar 2012 21:32:22 +0100 Subject: [PATCH 1/4] extracted "show more" part from #2941, tests still WIP --- public/javascripts/app/views/comment_view.js | 6 +- public/javascripts/app/views/content_view.js | 11 +++- .../app/views/stream_object_view.js | 29 --------- public/javascripts/app/views/stream_view.js | 30 +++++++++ public/stylesheets/sass/application.sass | 20 ++++++ .../javascripts/app/views/stream_view_spec.js | 63 +++---------------- 6 files changed, 74 insertions(+), 85 deletions(-) diff --git a/public/javascripts/app/views/comment_view.js b/public/javascripts/app/views/comment_view.js index 5c04227cb..c85faf7a2 100644 --- a/public/javascripts/app/views/comment_view.js +++ b/public/javascripts/app/views/comment_view.js @@ -4,8 +4,10 @@ app.views.Comment = app.views.Content.extend({ className : "comment media", - events : { - "click .comment_delete": "destroyModel" + events : function() { + return _.extend(app.views.Content.prototype.events, { + "click .comment_delete": "destroyModel" + }); }, presenter : function() { diff --git a/public/javascripts/app/views/content_view.js b/public/javascripts/app/views/content_view.js index d8cde6e45..0037e3eee 100644 --- a/public/javascripts/app/views/content_view.js +++ b/public/javascripts/app/views/content_view.js @@ -1,7 +1,8 @@ app.views.Content = app.views.StreamObject.extend({ events: { - "click .oembed .thumb": "showOembedContent" + "click .oembed .thumb": "showOembedContent", + "click .expander": "expandPost" }, presenter : function(){ @@ -41,7 +42,15 @@ app.views.Content = app.views.StreamObject.extend({ var paramSeparator = ( /\\?/.test(embedHTML.attr("href")) ) ? "&" : "?"; embedHTML.attr("src", embedHTML.attr("src") + paramSeparator + "autoplay=1"); oembed.html( embedHTML ); + }, + + expandPost: function(evt) { + var el = $(this.el).find('.collapsible'); + el.removeClass('collapsed').addClass('opened'); + el.animate({'height':el.data('orig-height')}, 550); + $(evt.currentTarget).hide(); } + }); app.views.StatusMessage = app.views.Content.extend({ diff --git a/public/javascripts/app/views/stream_object_view.js b/public/javascripts/app/views/stream_object_view.js index 054cdee88..1f46e732b 100644 --- a/public/javascripts/app/views/stream_object_view.js +++ b/public/javascripts/app/views/stream_object_view.js @@ -1,34 +1,5 @@ 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) { if (evt) { evt.preventDefault(); diff --git a/public/javascripts/app/views/stream_view.js b/public/javascripts/app/views/stream_view.js index 0c3b71d74..b3095b540 100644 --- a/public/javascripts/app/views/stream_view.js +++ b/public/javascripts/app/views/stream_view.js @@ -16,6 +16,7 @@ app.views.Stream = Backbone.View.extend({ setupEvents : function(){ this.stream.bind("fetched", this.removeLoader, this) + this.stream.bind("fetched", this.postRender, this) this.stream.bind("allPostsLoaded", this.unbindInfScroll, this) this.collection.bind("add", this.addPost, this); if(window.app.user()) { @@ -52,6 +53,35 @@ app.views.Stream = Backbone.View.extend({ 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( + $('
') + .addClass('expander') + .text( Diaspora.I18n.t("show_more") ) + ); + } + }); + }, appendLoader: function(){ $("#paginate").html($("", { diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass index 7c8622063..73850a289 100644 --- a/public/stylesheets/sass/application.sass +++ b/public/stylesheets/sass/application.sass @@ -1828,6 +1828,26 @@ ul#press_logos :color #777 .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 :background url('/images/ajax-loader2.gif') no-repeat center center diff --git a/spec/javascripts/app/views/stream_view_spec.js b/spec/javascripts/app/views/stream_view_spec.js index b1b8b1630..68cd67f1c 100644 --- a/spec/javascripts/app/views/stream_view_spec.js +++ b/spec/javascripts/app/views/stream_view_spec.js @@ -45,64 +45,21 @@ describe("app.views.Stream", function() { beforeEach(function() { this.statusMessage = this.stream.posts.models[0]; this.statusElement = $(this.view.$(".stream_element")[0]); - readMoreLink = this.statusElement.find('.read-more a'); + readMoreLink = this.statusElement.find('.expander'); readMoreLink.text("read more"); + + $(this.view.el).find('.collapsible').css('width', 400); // make content narrow like in real stream + setFixtures(this.view.el); + this.view.postRender(); }); it('expands the post', function() { - expect(this.statusElement.find('.collapsible .details').attr('style')).toContain('display: none;'); + // TODO + var textElement = this.statusElement.find('.collapsible'); + expect(textElement.hasClass('collapsed')).toBeTruthy(); 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); - } - }); + expect(textElement.hasClass('collapsed')).toBeFalsy(); + expect(textElement.hasClass('opened')).toBeTruthy(); }); }); From 813b706f8efdc3534bb81e6a168b972f20d1eed2 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Wed, 14 Mar 2012 01:50:24 +0100 Subject: [PATCH 2/4] added little fix for extra long content --- public/javascripts/app/views/content_view.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/javascripts/app/views/content_view.js b/public/javascripts/app/views/content_view.js index 0037e3eee..0f1aa2fc2 100644 --- a/public/javascripts/app/views/content_view.js +++ b/public/javascripts/app/views/content_view.js @@ -47,10 +47,12 @@ app.views.Content = app.views.StreamObject.extend({ expandPost: function(evt) { var el = $(this.el).find('.collapsible'); el.removeClass('collapsed').addClass('opened'); - el.animate({'height':el.data('orig-height')}, 550); + el.animate({'height':el.data('orig-height')}, 550, function() { + el.css('height','auto'); + }); $(evt.currentTarget).hide(); } - + }); app.views.StatusMessage = app.views.Content.extend({ From 5dae27c1706033f20d1939371ee4cc04d9cc7812 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Fri, 16 Mar 2012 02:00:50 +0100 Subject: [PATCH 3/4] finally some working tests for "show more" --- features/show_more.feature | 24 +++++++++++++++++++ features/step_definitions/posts_steps.rb | 21 +++++++++++++++- .../javascripts/app/views/stream_view_spec.js | 24 ------------------- 3 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 features/show_more.feature diff --git a/features/show_more.feature b/features/show_more.feature new file mode 100644 index 000000000..e842267e7 --- /dev/null +++ b/features/show_more.feature @@ -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 + diff --git a/features/step_definitions/posts_steps.rb b/features/step_definitions/posts_steps.rb index 3e81c8840..bae24539a 100644 --- a/features/step_definitions/posts_steps.rb +++ b/features/step_definitions/posts_steps.rb @@ -2,6 +2,17 @@ Then /^the post "([^"]*)" should be marked nsfw$/ do |text| assert_nsfw(text) end +Then /^the post should be collapsed$/ do + find(".collapsible").should have_css(".expander") + find(".collapsible").has_selector?(".collapsed") +end + +Then /^the post should be expanded$/ do + find(".expander").should_not be_visible + find(".collapsible").has_no_selector?(".collapsed") + find(".collapsible").has_selector?(".opened") +end + Then /^I should see an uploaded image within the photo drop zone$/ do find("#photodropzone img")["src"].should include("uploads/images") end @@ -32,6 +43,10 @@ When /^I click on the first block button/ do find(".block_user").click end +When /^I expand the post$/ do + find(".expander").click + wait_until{ !find(".expander").visible? } +end Then /^I should see "([^"]*)" as the first post in my stream$/ do |text| first_post_text.should include(text) @@ -43,4 +58,8 @@ end When /^I click the publisher and post "([^"]*)"$/ do |text| click_and_post(text) -end \ No newline at end of file +end + +When /^I post an extremely long status message$/ do + click_and_post("I am a very interesting message " * 64) +end diff --git a/spec/javascripts/app/views/stream_view_spec.js b/spec/javascripts/app/views/stream_view_spec.js index 68cd67f1c..7f14ae523 100644 --- a/spec/javascripts/app/views/stream_view_spec.js +++ b/spec/javascripts/app/views/stream_view_spec.js @@ -39,30 +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('.expander'); - readMoreLink.text("read more"); - - $(this.view.el).find('.collapsible').css('width', 400); // make content narrow like in real stream - setFixtures(this.view.el); - this.view.postRender(); - }); - - it('expands the post', function() { - // TODO - var textElement = this.statusElement.find('.collapsible'); - expect(textElement.hasClass('collapsed')).toBeTruthy(); - readMoreLink.click(); - expect(textElement.hasClass('collapsed')).toBeFalsy(); - expect(textElement.hasClass('opened')).toBeTruthy(); - }); - }); - describe("infScroll", function() { // NOTE: inf scroll happens at 500px From 27997e95250675056bafce417b1f39fcb05b85f8 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Fri, 16 Mar 2012 22:25:53 +0100 Subject: [PATCH 4/4] refactored test method into helpers --- features/step_definitions/posts_steps.rb | 10 +++------- features/support/publishing_cuke_helpers.rb | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/features/step_definitions/posts_steps.rb b/features/step_definitions/posts_steps.rb index bae24539a..ee7e2854f 100644 --- a/features/step_definitions/posts_steps.rb +++ b/features/step_definitions/posts_steps.rb @@ -3,14 +3,11 @@ Then /^the post "([^"]*)" should be marked nsfw$/ do |text| end Then /^the post should be collapsed$/ do - find(".collapsible").should have_css(".expander") - find(".collapsible").has_selector?(".collapsed") + first_post_collapsed? end Then /^the post should be expanded$/ do - find(".expander").should_not be_visible - find(".collapsible").has_no_selector?(".collapsed") - find(".collapsible").has_selector?(".opened") + first_post_expanded? end Then /^I should see an uploaded image within the photo drop zone$/ do @@ -44,8 +41,7 @@ When /^I click on the first block button/ do end When /^I expand the post$/ do - find(".expander").click - wait_until{ !find(".expander").visible? } + expand_first_post end Then /^I should see "([^"]*)" as the first post in my stream$/ do |text| diff --git a/features/support/publishing_cuke_helpers.rb b/features/support/publishing_cuke_helpers.rb index 9895813a4..8f1762434 100644 --- a/features/support/publishing_cuke_helpers.rb +++ b/features/support/publishing_cuke_helpers.rb @@ -17,6 +17,22 @@ module PublishingCukeHelpers ') 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 find('.stream_element:first .post-content').text() end