Commit 05e87b31 authored by Jonne Haß's avatar Jonne Haß
Browse files

Merge pull request #6363 from svbergerem/mobile-view-multiple-reaction-boxes

Mobile view multiple reaction boxes
parents 1dee5429 696eebbe
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ With the port to Bootstrap 3, app/views/terms/default.haml has a new structure.
* Improve accessibility of a couple pages [#6227](https://github.com/diaspora/diaspora/pull/6227)
* Capitalize "Powered by diaspora" [#6254](https://github.com/diaspora/diaspora/pull/6254)
* Display username and avatar for NSFW posts in mobile view [#6245](https://github.com/diaspora/diaspora/6245)
* Prevent multiple comment boxes on mobile [#6363](https://github.com/diaspora/diaspora/pull/6363)

## Features
* Support color themes [#6033](https://github.com/diaspora/diaspora/pull/6033)
+4 −1
Original line number Diff line number Diff line
@@ -77,9 +77,12 @@ Diaspora.I18n = {

  reset: function() {
    this.locale.data = {};
    this.locale.fallback.data = {};

    if( arguments.length > 0 && !(_.isEmpty(arguments[0])) )
    if(arguments.length > 0 && !(_.isEmpty(arguments[0]))) {
      this.locale.data = arguments[0];
      this.locale.fallback.data = arguments[0];
    }
  }
};
// @license-end
+167 −149
Original line number Diff line number Diff line
@@ -4,8 +4,11 @@
 *   the COPYRIGHT file.
 */

$(document).ready(function() {

(function() {
  Diaspora.Mobile = {};
  Diaspora.Mobile.Comments = {
    initialize: function() {
      var self = this;
      $(".stream").on("tap click", "a.back_to_stream_element_top", function() {
        var bottomBar = $(this).closest(".bottom_bar").first();
        var streamElement = bottomBar.parent();
@@ -16,71 +19,87 @@ $(document).ready(function() {

      $(".stream").on("tap click", "a.show_comments", function(evt){
        evt.preventDefault();
    toggleComments($(this));
        self.toggleComments($(this));
      });

      $(".stream").on("tap click", "a.comment-action", function(evt) {
        evt.preventDefault();
        self.showCommentBox($(this));
        var bottomBar = $(this).closest(".bottom_bar").first();
        var commentContainer = bottomBar.find(".comment_container").first();
        self.scrollToOffset(commentContainer);
      });

      $(".stream").on("submit", ".new_comment", function(evt) {
        evt.preventDefault();
        var form = $(this);
        $.post(form.attr("action")+"?format=mobile", form.serialize(), function(data) {
          self.updateStream(form, data);
        }, "html");
      });
    },

  function toggleComments(toggleReactionsLink) {
    toggleComments: function(toggleReactionsLink) {
      if(toggleReactionsLink.hasClass("loading")) { return; }
      if (toggleReactionsLink.hasClass("active")) {
      hideComments(toggleReactionsLink);
        this.hideComments(toggleReactionsLink);
      } else {
      showComments(toggleReactionsLink);
    }
        this.showComments(toggleReactionsLink);
      }
    },

  function hideComments(toggleReactionsLink) {
    hideComments: function(toggleReactionsLink) {
      var bottomBar = toggleReactionsLink.closest(".bottom_bar").first(),
        commentsContainer = commentsContainerLazy(bottomBar),
          commentsContainer = this.commentsContainerLazy(bottomBar),
          existingCommentsContainer = commentsContainer();
      existingCommentsContainer.hide();
      toggleReactionsLink.removeClass("active");
  }
    },

  function showComments(toggleReactionsLink) {
    showComments: function(toggleReactionsLink) {
      var bottomBar = toggleReactionsLink.closest(".bottom_bar").first(),
        commentsContainer = commentsContainerLazy(bottomBar),
          commentsContainer = this.commentsContainerLazy(bottomBar),
          existingCommentsContainer = commentsContainer(),
          commentActionLink = bottomBar.find("a.comment-action");
      if (existingCommentsContainer.length > 0) {
      showLoadedComments(toggleReactionsLink, existingCommentsContainer, commentActionLink);
        this.showLoadedComments(toggleReactionsLink, existingCommentsContainer, commentActionLink);
      } else {
      showUnloadedComments(toggleReactionsLink, bottomBar, commentActionLink);
    }
        this.showUnloadedComments(toggleReactionsLink, bottomBar, commentActionLink);
      }
    },

  function showLoadedComments(toggleReactionsLink, existingCommentsContainer, commentActionLink) {
    existingCommentsContainer.show();
    showCommentBox(commentActionLink);
    showLoadedComments: function(toggleReactionsLink, existingCommentsContainer, commentActionLink) {
      toggleReactionsLink.addClass("active");
      existingCommentsContainer.show();
      this.showCommentBox(commentActionLink);
      existingCommentsContainer.find("time.timeago").timeago();
  }
    },

  function showUnloadedComments(toggleReactionsLink, bottomBar, commentActionLink) {
    var commentsContainer = commentsContainerLazy(bottomBar);
    showUnloadedComments: function(toggleReactionsLink, bottomBar, commentActionLink) {
      toggleReactionsLink.addClass("loading");
      var commentsContainer = this.commentsContainerLazy(bottomBar);
      var self = this;
      $.ajax({
        url: toggleReactionsLink.attr("href"),
        success: function (data) {
          toggleReactionsLink.addClass("active").removeClass("loading");
          $(data).insertAfter(bottomBar.children(".show_comments").first());
        showCommentBox(commentActionLink);
        toggleReactionsLink.addClass("active");
          self.showCommentBox(commentActionLink);
          commentsContainer().find("time.timeago").timeago();
        },
        error: function() {
          toggleReactionsLink.removeClass("loading");
        }
      });
  }
    },

  function commentsContainerLazy(bottomBar) {
    commentsContainerLazy: function(bottomBar) {
      return function() {
        return bottomBar.find(".comment_container").first();
      };
  }
    },

  $(".stream").on("tap click", "a.comment-action", function(evt) {
    evt.preventDefault();
    showCommentBox(this);
    var bottomBar = $(this).closest(".bottom_bar").first();
    var commentContainer = bottomBar.find(".comment_container").first();
    scrollToOffset(commentContainer);
  });
  var scrollToOffset = function(commentsContainer){
    scrollToOffset: function(commentsContainer){
      var commentCount = commentsContainer.find("li.comment").length;
      if ( commentCount > 3 ) {
        var lastComment = commentsContainer.find("li:nth-child("+(commentCount-3)+")");
@@ -88,78 +107,77 @@ $(document).ready(function() {
          scrollTop: lastComment.offset().top
        }, 1000);
      }
  };
    },

  function showCommentBox(link){
    var commentActionLink = $(link);
    if(commentActionLink.hasClass("inactive")) {
    showCommentBox: function(link){
      if(!link.hasClass("inactive") || link.hasClass("loading")) { return; }
      var self = this;
      $.ajax({
        url: commentActionLink.attr("href"),
        url: link.attr("href"),
        beforeSend: function(){
          commentActionLink.addClass("loading");
          link.addClass("loading");
        },
        context: commentActionLink,
        context: link,
        success: function(data) {
          appendCommentBox.call(this, commentActionLink, data);
          self.appendCommentBox.call(this, link, data);
        },
        error: function() {
          link.removeClass("loading");
        }
      });
    }
  }
    },

  function appendCommentBox(link, data) {
    appendCommentBox: function(link, data) {
      link.removeClass("loading");
      link.removeClass("inactive");
      var bottomBar = link.closest(".bottom_bar").first();
      bottomBar.append(data);
      var textArea = bottomBar.find("textarea.comment_box").first()[0];
      autosize(textArea);
  }

  $(".stream").on("submit", ".new_comment", function(evt) {
    evt.preventDefault();
    var form = $(this);
    $.post(form.attr("action")+"?format=mobile", form.serialize(), function(data) {
      updateStream(form, data);
    }, "html");
  });
    },

  function updateStream(form, data) {
    updateStream: function(form, data) {
      var bottomBar = form.closest(".bottom_bar").first();
    addNewComments(bottomBar, data);
    updateCommentCount(bottomBar);
    updateReactionCount(bottomBar);
    handleCommentShowing(form, bottomBar);
      this.addNewComments(bottomBar, data);
      this.updateCommentCount(bottomBar);
      this.updateReactionCount(bottomBar);
      this.handleCommentShowing(form, bottomBar);
      bottomBar.find("time.timeago").timeago();
  }
    },

  function addNewComments(bottomBar, data) {
    addNewComments: function(bottomBar, data) {
      var commentsContainer = bottomBar.find(".comment_container").first();
      var comments = commentsContainer.find(".comments").first();
      comments.append(data);
  }
    },

    // Fix for no comments
  function updateCommentCount(bottomBar) {
    updateCommentCount: function(bottomBar) {
      var commentCount = bottomBar.find(".comment_count");
      commentCount.text(commentCount.text().replace(/(\d+)/, function (match) {
        return parseInt(match) + 1;
      }));
  }
    },

    // Fix for no reactions
  function updateReactionCount(bottomBar) {
    updateReactionCount: function(bottomBar) {
      var toggleReactionsLink = bottomBar.find(".show_comments").first();
      toggleReactionsLink.text(toggleReactionsLink.text().replace(/(\d+)/, function (match) {
        return parseInt(match) + 1;
      }));
  }
    },

  function handleCommentShowing(form, bottomBar) {
    handleCommentShowing: function(form, bottomBar) {
      var formContainer = form.parent();
      formContainer.remove();
      var commentActionLink = bottomBar.find("a.comment-action").first();
      commentActionLink.addClass("inactive");
      var toggleReactionsLink = bottomBar.find(".show_comments").first();
    showComments(toggleReactionsLink);
      this.showComments(toggleReactionsLink);
    }
  };
})();

$(document).ready(function() {
  Diaspora.Mobile.Comments.initialize();
});
+7 −0
Original line number Diff line number Diff line
@@ -58,6 +58,13 @@ describe StreamsController, :type => :controller do
        save_fixture(html_for("body"), "aspects_index_post_with_comments")
      end

      it "generates a mobile jasmine fixture with a post with comments", fixture: true do
        message = bob.post(:status_message, text: "HALO WHIRLED", to: @bob.aspects.where(name: "generic").first.id)
        5.times { bob.comment!(message, "what") }
        get :aspects, format: :mobile
        save_fixture(html_for("body"), "aspects_index_mobile_post_with_comments")
      end

      it 'generates a jasmine fixture with a followed tag', :fixture => true do
        @tag = ActsAsTaggableOn::Tag.create!(:name => "partytimeexcellent")
        TagFollowing.create!(:tag => @tag, :user => alice)
+119 −0
Original line number Diff line number Diff line
describe("Diaspora.Mobile.Comments", function(){
  describe("toggleComments", function() {
    beforeEach(function() {
      spec.loadFixture("aspects_index_mobile_post_with_comments");
      this.link = $(".stream .show_comments").first();
      spyOn(Diaspora.Mobile.Comments, "showComments");
      spyOn(Diaspora.Mobile.Comments, "hideComments");
    });

    it("calls showComments", function() {
      Diaspora.Mobile.Comments.toggleComments(this.link);
      expect(Diaspora.Mobile.Comments.showComments).toHaveBeenCalled();
      expect(Diaspora.Mobile.Comments.hideComments).not.toHaveBeenCalled();
    });

    it("calls hideComments if the link class is 'active'", function() {
      this.link.addClass("active");
      Diaspora.Mobile.Comments.toggleComments(this.link);
      expect(Diaspora.Mobile.Comments.showComments).not.toHaveBeenCalled();
      expect(Diaspora.Mobile.Comments.hideComments).toHaveBeenCalled();
    });

    it("doesn't call any function if the link class is 'loading'", function() {
      this.link.addClass("loading");
      Diaspora.Mobile.Comments.toggleComments(this.link);
      expect(Diaspora.Mobile.Comments.showComments).not.toHaveBeenCalled();
      expect(Diaspora.Mobile.Comments.hideComments).not.toHaveBeenCalled();
    });
  });

  describe("showUnloadedComments", function() {
    beforeEach(function() {
      spec.loadFixture("aspects_index_mobile_post_with_comments");
      this.link = $(".stream .show_comments").first();
      this.bottomBar = this.link.closest(".bottom_bar").first();
      this.commentActionLink = this.bottomBar.find("a.comment-action");
    });

    it("adds the 'loading' class to the link", function() {
      Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink);
      expect($(".show_comments").first()).toHaveClass("loading");
    });

    it("removes the 'loading' class if the request failed", function() {
      Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink);
      jasmine.Ajax.requests.mostRecent().respondWith({status: 400});
      expect($(".show_comments").first()).not.toHaveClass("loading");
    });

    it("adds the 'active' class if the request succeeded", function() {
      Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink);
      jasmine.Ajax.requests.mostRecent().respondWith({status: 200, contentType: "text/plain", responseText: "test"});
      expect($(".show_comments").first()).toHaveClass("active");
      expect($(".show_comments").first()).not.toHaveClass("loading");
    });

    it("calls showCommentBox", function() {
      spyOn(Diaspora.Mobile.Comments, "showCommentBox");
      Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink);
      jasmine.Ajax.requests.mostRecent().respondWith({status: 200, contentType: "text/plain", responseText: "test"});
      expect(Diaspora.Mobile.Comments.showCommentBox).toHaveBeenCalledWith(this.commentActionLink);
    });

    it("adds the response text to the comments list", function() {
      Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink);
      jasmine.Ajax.requests.mostRecent().respondWith({
        status: 200,
        contentType: "text/plain",
        responseText: "<div class=\"commentContainerForTest\">new comments</div>"
      });
      expect($(".stream .stream_element").first()).toContainElement(".commentContainerForTest");
    });
  });

  describe("showCommentBox", function() {
    beforeEach(function() {
      spec.loadFixture("aspects_index_mobile_post_with_comments");
      this.link = $(".stream .comment-action").first();
    });

    it("adds the 'loading' class to the link", function() {
      Diaspora.Mobile.Comments.showCommentBox(this.link);
      expect($(".comment-action").first()).toHaveClass("loading");
    });

    it("removes the 'loading' class if the request failed", function() {
      Diaspora.Mobile.Comments.showCommentBox(this.link);
      jasmine.Ajax.requests.mostRecent().respondWith({status: 400});
      expect($(".comment-action").first()).not.toHaveClass("loading");
    });

    it("fires an AJAX call", function() {
      spyOn(jQuery, "ajax");
      Diaspora.Mobile.Comments.showCommentBox(this.link);
      expect(jQuery.ajax).toHaveBeenCalled();
    });

    it("calls appendCommentBox", function() {
      spyOn(Diaspora.Mobile.Comments, "appendCommentBox");
      Diaspora.Mobile.Comments.showCommentBox(this.link);
      jasmine.Ajax.requests.mostRecent().respondWith({status: 200, contentType: "text/plain", responseText: "test"});
      expect(Diaspora.Mobile.Comments.appendCommentBox).toHaveBeenCalledWith(this.link, "test");
    });

    it("doesn't do anything if the link class is 'loading'", function() {
      spyOn(jQuery, "ajax");
      this.link.addClass("loading");
      Diaspora.Mobile.Comments.showCommentBox(this.link);
      expect(jQuery.ajax).not.toHaveBeenCalled();
    });

    it("doesn't do anything if the link class is not 'inactive'", function() {
      spyOn(jQuery, "ajax");
      this.link.removeClass("inactive");
      Diaspora.Mobile.Comments.showCommentBox(this.link);
      expect(jQuery.ajax).not.toHaveBeenCalled();
    });
  });
});
Loading