MD editor coversations&comments: refactorings

Javascript refactorings for better maintainability:
* simplePreview function to avoid code duplication
* Preloaded conversation is processed in a slightly different way
* Split isPreviewOrTexareaNotEmpty function since it has more than one responsibility
This commit is contained in:
cmrd Senya 2017-07-10 04:28:16 +03:00 committed by Steffen van Bergerem
parent 8f4498506d
commit 621d269760
No known key found for this signature in database
GPG key ID: 315C9787D548DC6B
10 changed files with 105 additions and 39 deletions

View file

@ -9,7 +9,7 @@ app.Router = Backbone.Router.extend({
"commented(/)": "stream", "commented(/)": "stream",
"community_spotlight(/)": "spotlight", "community_spotlight(/)": "spotlight",
"contacts(/)": "contacts", "contacts(/)": "contacts",
"conversations(/)(:id)(/)": "conversations", "conversations(/)(:id)(?conversation_id=:conversation_id)(/)": "conversations",
"followed_tags(/)": "followed_tags", "followed_tags(/)": "followed_tags",
"getting_started(/)": "gettingStarted", "getting_started(/)": "gettingStarted",
"help(/)": "help", "help(/)": "help",
@ -93,8 +93,8 @@ app.Router = Backbone.Router.extend({
app.page = new app.pages.Contacts({stream: stream}); app.page = new app.pages.Contacts({stream: stream});
}, },
conversations: function(id) { conversations: function(id, conversationId) {
app.conversations = app.conversations || new app.views.ConversationsInbox(); app.conversations = app.conversations || new app.views.ConversationsInbox(conversationId);
if (parseInt("" + id, 10)) { if (parseInt("" + id, 10)) {
app.conversations.renderConversation(id); app.conversations.renderConversation(id);
} }

View file

@ -31,9 +31,7 @@ app.views.CommentStream = app.views.Base.extend({
new app.views.CommentMention({el: this.$el, postId: this.model.get("id")}); new app.views.CommentMention({el: this.$el, postId: this.model.get("id")});
this.mdEditor = new Diaspora.MarkdownEditor(this.$(".comment_box"), { this.mdEditor = new Diaspora.MarkdownEditor(this.$(".comment_box"), {
onPreview: function($mdInstance) { onPreview: Diaspora.MarkdownEditor.simplePreview,
return "<div class='preview-content'>" + app.helpers.textFormatter($mdInstance.getContent()) + "</div>";
},
onFocus: this.openForm.bind(this) onFocus: this.openForm.bind(this)
}); });
}, },
@ -156,8 +154,15 @@ app.views.CommentStream = app.views.Base.extend({
autosize.update(this.commentBox); autosize.update(this.commentBox);
}, },
isCloseAllowed: function() {
if (this.mdEditor === undefined) {
return true;
}
return !this.mdEditor.isPreviewMode() && this.mdEditor.userInputEmpty();
},
onFormBlur: function(evt) { onFormBlur: function(evt) {
if (this.mdEditor !== undefined && this.mdEditor.isPreviewOrTexareaNotEmpty()) { if (!this.isCloseAllowed()) {
return; return;
} }

View file

@ -26,12 +26,6 @@ app.views.ConversationsForm = app.views.Base.extend({
this.newConversationMdEditor = this.renderMarkdownEditor("#new-message-text"); this.newConversationMdEditor = this.renderMarkdownEditor("#new-message-text");
// Creates another markdown editor in case of displaying conversation
var responseTextarea = $("#conversation-show .conversation-message-text");
if (responseTextarea.length === 1) {
this.renderMarkdownEditor(responseTextarea);
}
this.bindTypeaheadEvents(); this.bindTypeaheadEvents();
this.tagListElement.empty(); this.tagListElement.empty();
@ -45,9 +39,7 @@ app.views.ConversationsForm = app.views.Base.extend({
renderMarkdownEditor: function(element) { renderMarkdownEditor: function(element) {
return new Diaspora.MarkdownEditor($(element), { return new Diaspora.MarkdownEditor($(element), {
onPreview: function($mdInstance) { onPreview: Diaspora.MarkdownEditor.simplePreview
return "<div class='preview-content'>" + app.helpers.textFormatter($mdInstance.getContent()) + "</div>";
}
}); });
}, },

View file

@ -8,11 +8,21 @@ app.views.ConversationsInbox = app.views.Base.extend({
"click .new-conversation-btn": "displayNewConversation" "click .new-conversation-btn": "displayNewConversation"
}, },
initialize: function() { initialize: function(conversationId) {
this.conversationForm = new app.views.ConversationsForm(); this.conversationForm = new app.views.ConversationsForm();
// Creates markdown editor in case of displaying preloaded conversation
if (conversationId != null) {
this.renderMarkdownEditor();
}
this.setupConversation(); this.setupConversation();
}, },
renderMarkdownEditor: function() {
this.conversationForm.renderMarkdownEditor("#conversation-show .conversation-message-text");
},
renderConversation: function(conversationId) { renderConversation: function(conversationId) {
var self = this; var self = this;
$.ajax({ $.ajax({
@ -23,7 +33,7 @@ app.views.ConversationsInbox = app.views.Base.extend({
self.$el.find("#conversation-show").removeClass("hidden").html(data); self.$el.find("#conversation-show").removeClass("hidden").html(data);
self.selectConversation(conversationId); self.selectConversation(conversationId);
self.setupConversation(); self.setupConversation();
self.conversationForm.renderMarkdownEditor("#conversation-show .conversation-message-text"); self.renderMarkdownEditor();
autosize(self.$("#conversation-show textarea")); autosize(self.$("#conversation-show textarea"));
} }
}); });

View file

@ -130,11 +130,12 @@ Diaspora.MarkdownEditor.prototype = {
} }
}, },
isPreviewOrTexareaNotEmpty: function() { isPreviewMode: function() {
if (this.instance === undefined) { return this.instance !== undefined && this.instance.$editor.find(".md-preview").length > 0;
return false; },
}
return (this.instance.$editor.find(".md-preview").length > 0) || (this.instance.getContent().length > 0); userInputEmpty: function() {
return this.instance === undefined || this.instance.getContent().length === 0;
}, },
localize: function() { localize: function() {
@ -167,3 +168,7 @@ Diaspora.MarkdownEditor.prototype = {
return locale; return locale;
} }
}; };
Diaspora.MarkdownEditor.simplePreview = function($mdInstance) {
return "<div class='preview-content'>" + app.helpers.textFormatter($mdInstance.getContent()) + "</div>";
};

View file

@ -112,6 +112,13 @@ describe('app.Router', function () {
this.router.conversations("12"); this.router.conversations("12");
expect(app.views.ConversationsInbox.prototype.renderConversation).toHaveBeenCalledWith("12"); expect(app.views.ConversationsInbox.prototype.renderConversation).toHaveBeenCalledWith("12");
}); });
it("passes conversation_id parameter to ConversationsInbox initializer when passed in URL", function() {
app.conversations = undefined;
spyOn(app.views.ConversationsInbox.prototype, "initialize");
this.router.navigate("/conversations?conversation_id=45", {trigger: true});
expect(app.views.ConversationsInbox.prototype.initialize).toHaveBeenCalledWith("45");
});
}); });
describe("stream", function() { describe("stream", function() {

View file

@ -368,16 +368,26 @@ describe("app.views.CommentStream", function(){
spec.content().html("<div class='new-comment'/><div class='focus_comment_textarea'/>"); spec.content().html("<div class='new-comment'/><div class='focus_comment_textarea'/>");
}); });
it("does not call closeForm if markdown editor contains text or is in preview mode", function() { it("does not call closeForm if markdown editor is in preview mode", function() {
spyOn(this.view, "closeForm"); spyOn(this.view, "closeForm");
spyOn(this.view.mdEditor, "isPreviewOrTexareaNotEmpty").and.returnValue(true); spyOn(this.view.mdEditor, "isPreviewMode").and.returnValue(true);
spyOn(this.view.mdEditor, "userInputEmpty").and.returnValue(true);
this.view.onFormBlur();
expect(this.view.closeForm).not.toHaveBeenCalled();
});
it("does not call closeForm if markdown editor contains text", function() {
spyOn(this.view, "closeForm");
spyOn(this.view.mdEditor, "isPreviewMode").and.returnValue(false);
spyOn(this.view.mdEditor, "userInputEmpty").and.returnValue(false);
this.view.onFormBlur(); this.view.onFormBlur();
expect(this.view.closeForm).not.toHaveBeenCalled(); expect(this.view.closeForm).not.toHaveBeenCalled();
}); });
it("does not call closeForm when the form is clicked", function() { it("does not call closeForm when the form is clicked", function() {
spyOn(this.view, "closeForm"); spyOn(this.view, "closeForm");
spyOn(this.view.mdEditor, "isPreviewOrTexareaNotEmpty").and.returnValue(false); spyOn(this.view.mdEditor, "isPreviewMode").and.returnValue(false);
spyOn(this.view.mdEditor, "userInputEmpty").and.returnValue(true);
this.view.onFormBlur($.Event("click", {target: $(".new-comment")})); this.view.onFormBlur($.Event("click", {target: $(".new-comment")}));
expect(this.view.closeForm).not.toHaveBeenCalled(); expect(this.view.closeForm).not.toHaveBeenCalled();
this.view.onFormBlur($.Event("click", {target: $(".focus_comment_textarea")})); this.view.onFormBlur($.Event("click", {target: $(".focus_comment_textarea")}));
@ -386,7 +396,8 @@ describe("app.views.CommentStream", function(){
it("calls closeForm when the user clicks outside of the form", function() { it("calls closeForm when the user clicks outside of the form", function() {
spyOn(this.view, "closeForm"); spyOn(this.view, "closeForm");
spyOn(this.view.mdEditor, "isPreviewOrTexareaNotEmpty").and.returnValue(false); spyOn(this.view.mdEditor, "isPreviewMode").and.returnValue(false);
spyOn(this.view.mdEditor, "userInputEmpty").and.returnValue(true);
this.view.onFormBlur($.Event("click", {target: $("body")})); this.view.onFormBlur($.Event("click", {target: $("body")}));
expect(this.view.closeForm).toHaveBeenCalled(); expect(this.view.closeForm).toHaveBeenCalled();
}); });

View file

@ -41,13 +41,6 @@ describe("app.views.ConversationsForm", function() {
this.target.initialize(); this.target.initialize();
expect(this.target.renderMarkdownEditor).toHaveBeenCalledWith("#new-message-text"); expect(this.target.renderMarkdownEditor).toHaveBeenCalledWith("#new-message-text");
}); });
it("creates markdown editor for an existing conversation", function() {
spyOn(this.target, "renderMarkdownEditor");
this.target.initialize();
expect(this.target.renderMarkdownEditor).toHaveBeenCalledWith(
$("#conversation-show .conversation-message-text"));
});
}); });
describe("renderMarkdownEditor", function() { describe("renderMarkdownEditor", function() {

View file

@ -17,6 +17,14 @@ describe("app.views.ConversationsInbox", function() {
new app.views.ConversationsInbox(); new app.views.ConversationsInbox();
expect(app.views.ConversationsInbox.prototype.setupConversation).toHaveBeenCalled(); expect(app.views.ConversationsInbox.prototype.setupConversation).toHaveBeenCalled();
}); });
it("creates markdown editor for an existing conversation", function() {
spyOn(app.views.ConversationsForm.prototype, "renderMarkdownEditor");
new app.views.ConversationsInbox(1);
expect(app.views.ConversationsForm.prototype.renderMarkdownEditor).toHaveBeenCalledWith(
"#conversation-show .conversation-message-text"
);
});
}); });
describe("renderConversation", function() { describe("renderConversation", function() {

View file

@ -220,24 +220,45 @@ describe("Diaspora.MarkdownEditor", function() {
}); });
}); });
describe("isPreviewOrTexareaNotEmpty", function() { describe("isPreviewMode", function() {
beforeEach(function() { beforeEach(function() {
this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onPostPreview: $.noop()}); this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onPostPreview: $.noop()});
}); });
it("return false if editor is not visible yet", function() { it("return false if editor is not visible yet", function() {
this.target.instance = undefined; this.target.instance = undefined;
expect(this.target.isPreviewOrTexareaNotEmpty()).toBe(false); expect(this.target.isPreviewMode()).toBe(false);
});
it("returns false if the editor is in write (default) mode", function() {
expect(this.target.instance).toBeDefined();
expect(this.target.isPreviewMode()).toBe(false);
}); });
it("returns true if editor is in preview mode", function() { it("returns true if editor is in preview mode", function() {
this.target.showPreview(); this.target.showPreview();
expect(this.target.isPreviewOrTexareaNotEmpty()).toBe(true); expect(this.target.isPreviewMode()).toBe(true);
});
});
describe("userInputEmpty", function() {
beforeEach(function() {
this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onPostPreview: $.noop()});
}); });
it("returns true if editor has content", function() { it("return true if editor is not visible yet", function() {
this.target.instance = undefined;
expect(this.target.userInputEmpty()).toBe(true);
});
it("returns true if editor has no content", function() {
$("textarea").text("");
expect(this.target.userInputEmpty()).toBe(true);
});
it("returns false if editor has content", function() {
$("textarea").text("Yolo"); $("textarea").text("Yolo");
expect(this.target.isPreviewOrTexareaNotEmpty()).toBe(true); expect(this.target.userInputEmpty()).toBe(false);
}); });
}); });
@ -255,4 +276,18 @@ describe("Diaspora.MarkdownEditor", function() {
expect($.fn.markdown.messages[Diaspora.I18n.language]).toBeDefined(); expect($.fn.markdown.messages[Diaspora.I18n.language]).toBeDefined();
}); });
}); });
describe("simplePreview", function() {
beforeEach(function() {
this.target = new Diaspora.MarkdownEditor(this.$el, {});
});
it("generates HTML for preview", function() {
spyOn(app.helpers, "textFormatter").and.callThrough();
this.$el[0].value = "<p>hello</p>";
var res = Diaspora.MarkdownEditor.simplePreview(this.target.instance);
expect(app.helpers.textFormatter).toHaveBeenCalledWith("<p>hello</p>");
expect(res).toBe("<div class='preview-content'><p>hello</p></div>");
});
});
}); });