Displaying the markdown editor on publisher
This commit is contained in:
parent
8deef544dc
commit
5c2e241106
29 changed files with 927 additions and 210 deletions
1
Gemfile
1
Gemfile
|
|
@ -106,6 +106,7 @@ source "https://rails-assets.org" do
|
|||
gem "rails-assets-markdown-it-sub", "1.0.0"
|
||||
gem "rails-assets-markdown-it-sup", "1.0.0"
|
||||
gem "rails-assets-highlightjs", "9.4.0"
|
||||
gem "rails-assets-bootstrap-markdown", "2.9.0"
|
||||
|
||||
# jQuery plugins
|
||||
|
||||
|
|
|
|||
|
|
@ -646,6 +646,10 @@ GEM
|
|||
sprockets-rails
|
||||
rails-assets-autosize (3.0.15)
|
||||
rails-assets-blueimp-gallery (2.21.2)
|
||||
rails-assets-bootstrap (3.3.6)
|
||||
rails-assets-jquery (>= 1.9.1, < 3)
|
||||
rails-assets-bootstrap-markdown (2.9.0)
|
||||
rails-assets-bootstrap (~> 3)
|
||||
rails-assets-diaspora_jsxc (0.1.5.develop.1)
|
||||
rails-assets-favico.js (~> 0.3.9)
|
||||
rails-assets-jquery (>= 1.11)
|
||||
|
|
@ -994,6 +998,7 @@ DEPENDENCIES
|
|||
rails (= 4.2.7.1)
|
||||
rails-assets-autosize (= 3.0.15)!
|
||||
rails-assets-blueimp-gallery (= 2.21.2)!
|
||||
rails-assets-bootstrap-markdown (= 2.9.0)!
|
||||
rails-assets-diaspora_jsxc (= 0.1.5.develop.1)!
|
||||
rails-assets-highlightjs (= 9.4.0)!
|
||||
rails-assets-jasmine-ajax (= 3.2.0)!
|
||||
|
|
|
|||
41
app/assets/javascripts/app/views/preview_post_view.js
Normal file
41
app/assets/javascripts/app/views/preview_post_view.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
||||
|
||||
app.views.PreviewPost = app.views.Post.extend({
|
||||
templateName: "stream-element",
|
||||
className: "stream_element loaded",
|
||||
|
||||
subviews: {
|
||||
".feedback": "feedbackView",
|
||||
".post-content": "postContentView",
|
||||
".oembed": "oEmbedView",
|
||||
".opengraph": "openGraphView",
|
||||
".poll": "pollView",
|
||||
".status-message-location": "postLocationStreamView"
|
||||
},
|
||||
|
||||
tooltipSelector: [
|
||||
".timeago",
|
||||
".delete",
|
||||
".permalink"
|
||||
].join(", "),
|
||||
|
||||
initialize: function() {
|
||||
this.model.set("preview", true);
|
||||
this.oEmbedView = new app.views.OEmbed({model: this.model});
|
||||
this.openGraphView = new app.views.OpenGraph({model: this.model});
|
||||
this.pollView = new app.views.Poll({model: this.model});
|
||||
},
|
||||
|
||||
feedbackView: function() {
|
||||
return new app.views.Feedback({model: this.model});
|
||||
},
|
||||
|
||||
postContentView: function() {
|
||||
return new app.views.StatusMessage({model: this.model});
|
||||
},
|
||||
|
||||
postLocationStreamView: function() {
|
||||
return new app.views.LocationStream({model: this.model});
|
||||
}
|
||||
});
|
||||
// @license-end
|
||||
|
|
@ -18,6 +18,7 @@ app.views.PublisherGettingStarted = Backbone.View.extend({
|
|||
|
||||
// initiate all the popover message boxes
|
||||
show: function() {
|
||||
app.publisher.open();
|
||||
this._addPopover(this.firstMessage, {
|
||||
trigger: "manual",
|
||||
id: "first_message_explain",
|
||||
|
|
|
|||
|
|
@ -20,10 +20,8 @@ app.views.Publisher = Backbone.View.extend({
|
|||
events : {
|
||||
"keydown #status_message_fake_text" : "keyDown",
|
||||
"focus textarea" : "open",
|
||||
"click #hide_publisher" : "clear",
|
||||
"submit form" : "createStatusMessage",
|
||||
"click #submit" : "createStatusMessage",
|
||||
"click .post_preview_button" : "createPostPreview",
|
||||
"textchange #status_message_fake_text": "handleTextchange",
|
||||
"click #locator" : "showLocation",
|
||||
"click #poll_creator" : "togglePollCreator",
|
||||
|
|
@ -41,12 +39,12 @@ app.views.Publisher = Backbone.View.extend({
|
|||
this.hiddenInputEl = this.$("#status_message_text");
|
||||
this.wrapperEl = this.$("#publisher_textarea_wrapper");
|
||||
this.submitEl = this.$("input[type=submit], button#submit");
|
||||
this.previewEl = this.$("button.post_preview_button");
|
||||
this.photozoneEl = this.$("#photodropzone");
|
||||
|
||||
// if there is data in the publisher we ask for a confirmation
|
||||
// before the user is able to leave the page
|
||||
$(window).on("beforeunload", _.bind(this._beforeUnload, this));
|
||||
$(window).unload(this.clear.bind(this));
|
||||
|
||||
// sync textarea content
|
||||
if( this.hiddenInputEl.val() === "" ) {
|
||||
|
|
@ -60,8 +58,6 @@ app.views.Publisher = Backbone.View.extend({
|
|||
// in case publisher is standalone
|
||||
// (e.g. bookmarklet, mentions popup)
|
||||
if( this.standalone ) {
|
||||
this.$("#hide_publisher").hide();
|
||||
this.previewEl.hide();
|
||||
this.$(".question_mark").hide();
|
||||
}
|
||||
|
||||
|
|
@ -130,6 +126,36 @@ app.views.Publisher = Backbone.View.extend({
|
|||
});
|
||||
this.viewUploader.on("change", this.checkSubmitAvailability, this);
|
||||
|
||||
var self = this;
|
||||
var mdEditorOptions = {
|
||||
onPreview: function() {
|
||||
self.wrapperEl.addClass("markdown-preview");
|
||||
return self.createPostPreview();
|
||||
},
|
||||
|
||||
onHidePreview: function() {
|
||||
self.wrapperEl.removeClass("markdown-preview");
|
||||
},
|
||||
|
||||
onPostPreview: function() {
|
||||
var photoAttachments = self.wrapperEl.find(".photo_attachments");
|
||||
if (photoAttachments.length > 0) {
|
||||
new app.views.Gallery({el: photoAttachments});
|
||||
}
|
||||
},
|
||||
|
||||
onChange: function() {
|
||||
self.inputEl.trigger("textchange");
|
||||
}
|
||||
};
|
||||
|
||||
if (!this.standalone) {
|
||||
mdEditorOptions.onClose = function() {
|
||||
self.clear();
|
||||
};
|
||||
}
|
||||
this.markdownEditor = new Diaspora.MarkdownEditor(this.inputEl, mdEditorOptions);
|
||||
|
||||
this.viewPollCreator = new app.views.PublisherPollCreator({
|
||||
el: this.$("#poll_creator_container")
|
||||
});
|
||||
|
|
@ -251,7 +277,7 @@ app.views.Publisher = Backbone.View.extend({
|
|||
},
|
||||
|
||||
togglePollCreator: function(){
|
||||
this.viewPollCreator.$el.toggle();
|
||||
this.wrapperEl.toggleClass("with-poll");
|
||||
this.inputEl.focus();
|
||||
},
|
||||
|
||||
|
|
@ -300,17 +326,14 @@ app.views.Publisher = Backbone.View.extend({
|
|||
return poll;
|
||||
},
|
||||
|
||||
createPostPreview : function(evt) {
|
||||
if(evt){ evt.preventDefault(); }
|
||||
if(!app.stream) { return; }
|
||||
|
||||
createPostPreview: function() {
|
||||
//add missing mentions at end of post:
|
||||
this.handleTextchange();
|
||||
|
||||
var serializedForm = $(evt.target).closest("form").serializeObject();
|
||||
var serializedForm = $("#new_status_message").serializeObject();
|
||||
var text = this.mention.getTextForSubmit();
|
||||
var photos = this.getUploadedPhotos();
|
||||
var mentionedPeople = this.mention.mentionedPeople;
|
||||
var date = (new Date()).toISOString();
|
||||
var poll = this.getPollData(serializedForm);
|
||||
var locationCoords = serializedForm["location[coords]"];
|
||||
if(!locationCoords || locationCoords === "") {
|
||||
|
|
@ -326,11 +349,10 @@ app.views.Publisher = Backbone.View.extend({
|
|||
|
||||
var previewMessage = {
|
||||
"id": 0,
|
||||
"text" : serializedForm["status_message[text]"],
|
||||
"text": text,
|
||||
"public": serializedForm["aspect_ids[]"] === "public",
|
||||
"created_at" : date,
|
||||
"interacted_at" : date,
|
||||
"post_type" : "StatusMessage",
|
||||
"created_at": new Date().toISOString(),
|
||||
"interacted_at": new Date().toISOString(),
|
||||
"author": app.currentUser ? app.currentUser.attributes : {},
|
||||
"mentioned_people": mentionedPeople,
|
||||
"photos": photos,
|
||||
|
|
@ -340,29 +362,8 @@ app.views.Publisher = Backbone.View.extend({
|
|||
"poll": poll
|
||||
};
|
||||
|
||||
this.removePostPreview();
|
||||
app.stream.addNow(previewMessage);
|
||||
this.recentPreview=previewMessage;
|
||||
this.modifyPostPreview($(".stream_element:first",$(".stream_container")));
|
||||
},
|
||||
|
||||
modifyPostPreview : function(post) {
|
||||
post.addClass("post_preview");
|
||||
$(".collapsible",post).removeClass("collapsed").addClass("opened");
|
||||
$("a.delete.remove_post",post).hide();
|
||||
$("a.like, a.focus_comment_textarea",post).removeAttr("href");
|
||||
$("a.like",post).addClass("like_preview")
|
||||
.removeClass("like");
|
||||
$("a.focus_comment_textarea",post).addClass("focus_comment_textarea_preview")
|
||||
.removeClass("focus_comment_textarea");
|
||||
$("a",$("span.details.grey",post)).removeAttr("href");
|
||||
},
|
||||
|
||||
removePostPreview : function() {
|
||||
if(app.stream && this.recentPreview) {
|
||||
app.stream.items.remove(this.recentPreview);
|
||||
delete this.recentPreview;
|
||||
}
|
||||
var previewPost = new app.views.PreviewPost({model: new app.models.Post(previewMessage)}).render().el;
|
||||
return $("<div/>").append(previewPost).html();
|
||||
},
|
||||
|
||||
keyDown : function(evt) {
|
||||
|
|
@ -392,12 +393,10 @@ app.views.Publisher = Backbone.View.extend({
|
|||
// empty upload-photo
|
||||
this.$("#fileInfo").empty();
|
||||
|
||||
// close publishing area (CSS)
|
||||
// remove preview and close publishing area (CSS)
|
||||
this.markdownEditor.hidePreview();
|
||||
this.close();
|
||||
|
||||
// remove preview
|
||||
this.removePostPreview();
|
||||
|
||||
// disable submitting
|
||||
this.checkSubmitAvailability();
|
||||
|
||||
|
|
@ -445,7 +444,7 @@ app.views.Publisher = Backbone.View.extend({
|
|||
$(this.el).addClass("closed");
|
||||
this.wrapperEl.removeClass("active");
|
||||
this.inputEl.css("height", "");
|
||||
this.viewPollCreator.$el.hide();
|
||||
this.wrapperEl.removeClass("with-poll");
|
||||
return this;
|
||||
},
|
||||
|
||||
|
|
@ -476,10 +475,8 @@ app.views.Publisher = Backbone.View.extend({
|
|||
setButtonsEnabled: function(bool) {
|
||||
if (bool) {
|
||||
this.submitEl.removeAttr("disabled");
|
||||
this.previewEl.removeAttr("disabled");
|
||||
} else {
|
||||
this.submitEl.prop("disabled", true);
|
||||
this.previewEl.prop("disabled", true);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -503,8 +500,6 @@ app.views.Publisher = Backbone.View.extend({
|
|||
},
|
||||
|
||||
handleTextchange: function() {
|
||||
var self = this;
|
||||
|
||||
this.checkSubmitAvailability();
|
||||
this.hiddenInputEl.val(this.mention.getTextForSubmit());
|
||||
},
|
||||
|
|
|
|||
162
app/assets/javascripts/helpers/markdown_editor.js
Normal file
162
app/assets/javascripts/helpers/markdown_editor.js
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
Diaspora.MarkdownEditor = function(element, opts) {
|
||||
this.initialize(element, opts);
|
||||
};
|
||||
|
||||
Diaspora.MarkdownEditor.prototype = {
|
||||
constructor: Diaspora.MarkdownEditor,
|
||||
|
||||
initialize: function(element, opts) {
|
||||
this.options = {
|
||||
resize: "none",
|
||||
onHidePreview: $.noop,
|
||||
onPostPreview: $.noop
|
||||
};
|
||||
|
||||
$.extend(this.options, opts);
|
||||
|
||||
this.options.fullscreen = {enable: false, icons: {}};
|
||||
this.options.language = this.localize();
|
||||
this.options.hiddenButtons = ["cmdPreview"];
|
||||
this.options.onShow = this.onShow.bind(this);
|
||||
|
||||
$(element).markdown(this.options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach the $.fn.markdown instance to the current MarkdownEditor instance
|
||||
* and initializes the preview and edit tabs after the editor is shown.
|
||||
* @param instance
|
||||
*/
|
||||
onShow: function(instance) {
|
||||
this.instance = instance;
|
||||
|
||||
if (_.isFunction(this.options.onPreview)) {
|
||||
instance.$editor.find(".md-header").remove(".write-preview-tabs").prepend(this.createTabsElement());
|
||||
}
|
||||
|
||||
if (_.isFunction(this.options.onClose)) {
|
||||
instance.$editor.find(".md-header").remove(".md-cancel").append(this.createCloseElement());
|
||||
}
|
||||
|
||||
// Monkey patch to change icons. Will have to PR upstream
|
||||
var icons = {
|
||||
cmdUrl: ["glyphicon-link", "entypo-link"],
|
||||
cmdImage: ["glyphicon-picture", "entypo-picture"],
|
||||
cmdList: ["glyphicon-list", "entypo-list"],
|
||||
cmdListO: ["glyphicon-th-list", "entypo-numbered-list"],
|
||||
cmdCode: ["glyphicon-asterisk", "entypo-code"],
|
||||
cmdQuote: ["glyphicon-comment", "entypo-comment"]
|
||||
};
|
||||
|
||||
Object.keys(icons).forEach(function(key) {
|
||||
instance.$editor.find("[data-handler='bootstrap-markdown-" + key + "']").find(".glyphicon")
|
||||
.removeClass("glyphicon").removeClass(icons[key][0])
|
||||
.addClass(icons[key][1]);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates write and preview tabs inside the markdown editor header.
|
||||
* @returns {jQuery} The created tabs
|
||||
*/
|
||||
createTabsElement: function() {
|
||||
var self = this;
|
||||
|
||||
var tabElement = $("<ul class='nav nav-tabs btn-group write-preview-tabs'></ul>");
|
||||
|
||||
var writeTab = $("<li class='active full-height' role='presentation'></li>");
|
||||
this.writeLink = $("<a class='full-height md-write-tab' href='#'></a>")
|
||||
.attr("title", Diaspora.I18n.t("publisher.markdown_editor.tooltips.write"));
|
||||
|
||||
this.writeLink.append($("<i class='visible-sm visible-xs visible-md diaspora-custom-compose'></i>"));
|
||||
this.writeLink.append($("<span class='hidden-sm hidden-xs hidden-md tab-help-text'></span>")
|
||||
.text(Diaspora.I18n.t("publisher.markdown_editor.write")));
|
||||
|
||||
this.writeLink.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
self.hidePreview();
|
||||
});
|
||||
|
||||
writeTab.append(this.writeLink);
|
||||
|
||||
var previewTab = $("<li class='full-height' role='presentation'></li>");
|
||||
this.previewLink = $("<a class='full-height md-preview-tab' href='#'></a>")
|
||||
.attr("title", Diaspora.I18n.t("publisher.markdown_editor.tooltips.preview"));
|
||||
|
||||
this.previewLink.append($("<i class='visible-sm visible-xs visible-md entypo-search'>"));
|
||||
this.previewLink.append($("<span class='hidden-sm hidden-xs hidden-md tab-help-text'></span>")
|
||||
.text(Diaspora.I18n.t("publisher.markdown_editor.preview")));
|
||||
|
||||
this.previewLink.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
self.showPreview();
|
||||
});
|
||||
|
||||
previewTab.append(this.previewLink);
|
||||
|
||||
return tabElement.append(writeTab).append(previewTab);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a cancel button that executes {options#onClose} on click.
|
||||
* @returns {jQuery} The created cancel button
|
||||
*/
|
||||
createCloseElement: function() {
|
||||
var self = this;
|
||||
var button = $("<a class='md-cancel btn btn-sm btn-link hidden-xs pull-right'></a>")
|
||||
.attr("title", Diaspora.I18n.t("publisher.markdown_editor.tooltips.cancel"));
|
||||
|
||||
button.click(function() {
|
||||
self.hidePreview();
|
||||
self.options.onClose();
|
||||
});
|
||||
|
||||
return button.append($("<i class='entypo-cross'></i>"));
|
||||
},
|
||||
|
||||
hidePreview: function() {
|
||||
if (this.writeLink) {
|
||||
this.writeLink.tab("show");
|
||||
this.instance.hidePreview();
|
||||
this.options.onHidePreview();
|
||||
}
|
||||
},
|
||||
|
||||
showPreview: function() {
|
||||
if (this.previewLink) {
|
||||
this.previewLink.tab("show");
|
||||
this.instance.showPreview();
|
||||
this.options.onPostPreview();
|
||||
}
|
||||
},
|
||||
|
||||
localize: function() {
|
||||
var locale = Diaspora.I18n.language;
|
||||
|
||||
$.fn.markdown.messages[locale] = {
|
||||
"Bold": Diaspora.I18n.t("publisher.markdown_editor.tooltips.bold"),
|
||||
"Italic": Diaspora.I18n.t("publisher.markdown_editor.tooltips.italic"),
|
||||
"Heading": Diaspora.I18n.t("publisher.markdown_editor.tooltips.heading"),
|
||||
"URL/Link": Diaspora.I18n.t("publisher.markdown_editor.tooltips.insert_link"),
|
||||
"Image": Diaspora.I18n.t("publisher.markdown_editor.tooltips.insert_image"),
|
||||
"Ordered List": Diaspora.I18n.t("publisher.markdown_editor.tooltips.insert_ordered_list"),
|
||||
"Unordered List": Diaspora.I18n.t("publisher.markdown_editor.tooltips.insert_unordered_list"),
|
||||
"Preview": Diaspora.I18n.t("publisher.markdown_editor.tooltips.preview"),
|
||||
"Quote": Diaspora.I18n.t("publisher.markdown_editor.tooltips.quote"),
|
||||
"Code": Diaspora.I18n.t("publisher.markdown_editor.tooltips.code"),
|
||||
"strong text": Diaspora.I18n.t("publisher.markdown_editor.texts.strong"),
|
||||
"emphasized text": Diaspora.I18n.t("publisher.markdown_editor.texts.italic"),
|
||||
"heading text": Diaspora.I18n.t("publisher.markdown_editor.texts.heading"),
|
||||
"enter link description here": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_link_description_text"),
|
||||
"Insert Hyperlink": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_link_help_text"),
|
||||
"enter image description here": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_image_description_text"),
|
||||
"Insert Image Hyperlink": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_image_help_text"),
|
||||
"enter image title here": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_image_title"),
|
||||
"list text here": Diaspora.I18n.t("publisher.markdown_editor.texts.list"),
|
||||
"quote here": Diaspora.I18n.t("publisher.markdown_editor.texts.quote"),
|
||||
"code text here": Diaspora.I18n.t("publisher.markdown_editor.texts.code")
|
||||
};
|
||||
|
||||
return locale;
|
||||
}
|
||||
};
|
||||
|
|
@ -43,3 +43,5 @@
|
|||
//= require blueimp-gallery/blueimp-gallery-indicator
|
||||
//= require leaflet
|
||||
//= require api/authorization_page
|
||||
// = require bootstrap-markdown/bootstrap-markdown
|
||||
// = require helpers/markdown_editor
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
// publisher
|
||||
@import 'publisher';
|
||||
@import 'aspects';
|
||||
@import 'markdown-editor';
|
||||
|
||||
// bookmarklet
|
||||
@import 'bookmarklet';
|
||||
|
|
|
|||
|
|
@ -17,13 +17,6 @@ body {
|
|||
color: fade-out($link-color, 0.4);
|
||||
}
|
||||
|
||||
#main_stream .stream_element {
|
||||
&.post_preview {
|
||||
background-color: $main-color-essence;
|
||||
border-color: darken($main-color-essence, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
.left-navbar .hoverable:hover { background-color: $main-color-essence; }
|
||||
|
||||
.poll_form .progress .bar { background-color: $main-color-dark; }
|
||||
|
|
|
|||
141
app/assets/stylesheets/markdown-editor.scss
Normal file
141
app/assets/stylesheets/markdown-editor.scss
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
.md-footer,
|
||||
.md-header {
|
||||
background: $sidebars-background;
|
||||
border: 0;
|
||||
display: block;
|
||||
height: 42px;
|
||||
margin: 0;
|
||||
padding: 6px 6px 0;
|
||||
|
||||
[class^="entypo-"],
|
||||
[class*="entypo-"],
|
||||
.glyphicon {
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
|
||||
.md-header,
|
||||
.nav-tabs {
|
||||
border-bottom: 0;
|
||||
margin: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.md-header.btn-toolbar {
|
||||
background-color: $background-grey;
|
||||
overflow: hidden;
|
||||
|
||||
.btn-group {
|
||||
margin-bottom: 8px;
|
||||
|
||||
[class^="entypo-"],
|
||||
[class*="entypo-"] {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
[data-handler="bootstrap-markdown-cmdUrl"],
|
||||
[data-handler="bootstrap-markdown-cmdImage"],
|
||||
[data-handler="bootstrap-markdown-cmdList"],
|
||||
[data-handler="bootstrap-markdown-cmdListO"],
|
||||
[data-handler="bootstrap-markdown-cmdCode"],
|
||||
[data-handler="bootstrap-markdown-cmdQuote"] {
|
||||
height: 28.5px;
|
||||
line-height: 1.25;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: $screen-xs) {
|
||||
[data-handler="bootstrap-markdown-cmdList"],
|
||||
[data-handler="bootstrap-markdown-cmdListO"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-handler="bootstrap-markdown-cmdCode"] {
|
||||
// !important is needed to override BS' specific rules
|
||||
// scss-lint:disable ImportantRule
|
||||
border-bottom-left-radius: $border-radius-small !important;
|
||||
border-top-left-radius: $border-radius-small !important;
|
||||
// scss-lint:enable ImportantRule
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.md-cancel {
|
||||
box-sizing: content-box;
|
||||
|
||||
&,
|
||||
.entypo-cross {
|
||||
color: $text-grey;
|
||||
font-size: 18px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
&:hover .entypo-cross { color: $text; }
|
||||
}
|
||||
|
||||
|
||||
.md-preview {
|
||||
background: $white;
|
||||
color: $text-color;
|
||||
// !important is needed to override the CSS rules dynamically added to the element
|
||||
// scss-lint:disable ImportantRule
|
||||
height: auto !important;
|
||||
// scss-lint:enable ImportantRule
|
||||
min-height: 90px;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
// !important is needed to override the CSS rules dynamically added to the element
|
||||
// scss-lint:disable ImportantRule
|
||||
width: 100% !important;
|
||||
// scss-lint:enable ImportantRule
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.md-controls {
|
||||
float: right;
|
||||
padding: 3px;
|
||||
|
||||
.md-control {
|
||||
color: $text-grey;
|
||||
padding: 3px;
|
||||
padding-left: 10px;
|
||||
right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.write-preview-tabs {
|
||||
&,
|
||||
& .full-height {
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
> li {
|
||||
> a { padding: 7px 15px; }
|
||||
|
||||
&:not(.active) * { color: $brand-primary; }
|
||||
|
||||
&.active * { color: $black; }
|
||||
}
|
||||
|
||||
a:focus { outline: none; }
|
||||
|
||||
li {
|
||||
&:not(.active) a:focus,
|
||||
&:not(.active) a:hover {
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
&.active:focus { color: $black; }
|
||||
}
|
||||
|
||||
.diaspora-custom-compose::before {
|
||||
bottom: -2px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.publisher-textarea-wrapper:not(.active) .md-header { display: none; }
|
||||
|
|
@ -78,7 +78,6 @@
|
|||
color: white;
|
||||
font-size: $font-size-base;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
line-height: normal;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
white-space: pre-wrap;
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@
|
|||
}
|
||||
|
||||
textarea {
|
||||
border: none;
|
||||
border: 0 solid $light-grey;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
resize: none;
|
||||
|
|
@ -101,16 +101,11 @@
|
|||
a { color: lighten($blue,20%); }
|
||||
}
|
||||
|
||||
.mentions-input-box .mentions {
|
||||
line-height: $line-height-base !important;
|
||||
}
|
||||
|
||||
&.with_attachments #photodropzone_container {
|
||||
border-top: 1px dashed $border-grey;
|
||||
}
|
||||
|
||||
#poll_creator_container {
|
||||
display: none;
|
||||
border-top: 1px dashed $border-grey;
|
||||
padding:4px 6px 4px 6px;
|
||||
box-sizing: border-box;
|
||||
|
|
@ -212,7 +207,14 @@
|
|||
}
|
||||
|
||||
.publisher-textarea-wrapper {
|
||||
&:not(.with-location) .location-container { display: none; }
|
||||
&:not(.with-location) .location-container,
|
||||
&.markdown-preview .location-container,
|
||||
&:not(.with-poll) .poll-creator-container,
|
||||
&.markdown-preview .poll-creator-container,
|
||||
&.markdown-preview .photodropzone-container,
|
||||
&.markdown-preview .publisher-buttonbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.with-location .loader {
|
||||
height: 20px;
|
||||
|
|
@ -259,7 +261,15 @@
|
|||
|
||||
.twitter-typeahead {
|
||||
left: -1px;
|
||||
position: absolute;
|
||||
// Override inline rule of Typeahead
|
||||
// scss-lint:disable ImportantRule
|
||||
position: absolute !important;
|
||||
// scss-lint:enable ImportantRule
|
||||
}
|
||||
|
||||
.mentions-box {
|
||||
// Leave space for markdown editor header
|
||||
margin-top: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#main_stream .stream_element,
|
||||
.stream_element,
|
||||
.photo {
|
||||
& > .media {
|
||||
margin: 0px;
|
||||
|
|
@ -61,12 +61,20 @@
|
|||
}
|
||||
|
||||
#main_stream .stream_element {
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
background-color: $white;
|
||||
border: 1px solid $light-grey;
|
||||
box-shadow: $card-shadow;
|
||||
|
||||
&.highlighted {
|
||||
border-left: 3px solid $brand-primary;
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.stream_element {
|
||||
background-color: $white;
|
||||
padding: 10px;
|
||||
|
||||
& > .media {
|
||||
&.shield-active .nsfw-hidden { display: none; }
|
||||
&:not(.shield-active) .nsfw-shield { display: none; }
|
||||
|
|
@ -146,18 +154,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.highlighted {
|
||||
padding-left: 8px;
|
||||
border-left: 3px solid $brand-primary;
|
||||
}
|
||||
|
||||
&.post_preview {
|
||||
background-color: lighten($brand-primary,45%);
|
||||
border: 1px solid $brand-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.stream_element {
|
||||
.likes,
|
||||
.reshares {
|
||||
font-size: 12px;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@
|
|||
</span>
|
||||
|
||||
|
||||
{{#if preview}}
|
||||
<span>{{t "stream.like"}}</span>
|
||||
{{else}}
|
||||
<a href="#" class="like" rel='nofollow'>
|
||||
{{#if userLike}}
|
||||
{{t "stream.unlike"}}
|
||||
|
|
@ -21,15 +24,18 @@
|
|||
{{t "stream.like"}}
|
||||
{{/if}}
|
||||
</a>
|
||||
{{/if}}
|
||||
·
|
||||
|
||||
{{#if userCanReshare}}
|
||||
<a href="#" class="reshare" rel='nofollow'>
|
||||
{{t "stream.reshare"}}
|
||||
</a>
|
||||
{{#if preview}}
|
||||
<span>{{t "stream.reshare"}}</span>
|
||||
·
|
||||
{{else if userCanReshare}}
|
||||
<a href="#" class="reshare" rel='nofollow'>{{t "stream.reshare"}}</a>
|
||||
·
|
||||
{{/if}}
|
||||
|
||||
<a href="#" class="focus_comment_textarea" rel="nofollow">
|
||||
{{t "stream.comment"}}
|
||||
</a>
|
||||
{{#if preview}}
|
||||
<span>{{t "stream.comment"}}</span>
|
||||
{{else}}
|
||||
<a href="#" class="focus_comment_textarea" rel="nofollow">{{t "stream.comment"}}</a>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,11 @@
|
|||
{{/poll.poll_answers}}
|
||||
{{#if show_form}}
|
||||
<div class="toggle-result-wrapper">
|
||||
{{#if preview}}
|
||||
<span>{{t "poll.show_result"}}</span>
|
||||
{{else}}
|
||||
<a class="toggle_result" href="#">{{t "poll.show_result"}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
<input type="submit" class="submit pull-right btn btn-default" value="{{t "poll.vote"}}"/>
|
||||
<div class="clearfix"></div>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
<div class="bd">
|
||||
{{#if loggedIn}}
|
||||
<div class="control-icons">
|
||||
{{#unless preview}}
|
||||
{{#if authorIsCurrentUser}}
|
||||
<a href="#" rel="nofollow" class="delete remove_post" title="{{t "delete"}}">
|
||||
<i class="entypo-trash"></i>
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
<i class="entypo-cross"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
|
@ -42,6 +44,9 @@
|
|||
|
||||
<span class="details gray">
|
||||
-
|
||||
{{#if preview}}
|
||||
<time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" />
|
||||
{{else}}
|
||||
<a href="/posts/{{id}}">
|
||||
<time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" />
|
||||
</a>
|
||||
|
|
@ -49,6 +54,7 @@
|
|||
<a href="/posts/{{id}}" class="permalink" title="{{t "stream.permalink"}}">
|
||||
<i class="entypo-link"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
%input.typeahead-mention-box.hidden{type: "text"}
|
||||
= status.hidden_field :text, value: h(publisher_hidden_text), class: "clear_on_submit"
|
||||
|
||||
.container-fluid#photodropzone_container
|
||||
.container-fluid.photodropzone-container#photodropzone_container
|
||||
%ul#photodropzone
|
||||
.location-container.form-group{style: "padding: 4px 6px;"}
|
||||
= hidden_field :location, :coords
|
||||
#poll_creator_container
|
||||
.poll-creator-container#poll_creator_container
|
||||
-# handlebars template
|
||||
#button_container
|
||||
.publisher-buttonbar#publisher-images
|
||||
|
|
@ -59,12 +59,8 @@
|
|||
.spinner
|
||||
.options_and_submit.col-sm-12
|
||||
.public_toggle.clearfix
|
||||
.btn.btn-default.pull-left.hidden-xs#hide_publisher{title: t("shared.publisher.discard_post")}
|
||||
%span.text= t("cancel")
|
||||
|
||||
.btn-toolbar.pull-right
|
||||
= render partial: "publisher/aspect_dropdown", locals: {selected_aspects: selected_aspects}
|
||||
%button.btn.btn-default.btn-group.post_preview_button= t("shared.publisher.preview")
|
||||
%button.btn.btn-group.btn-primary#submit= t("shared.publisher.share")
|
||||
|
||||
.btn-toolbar.pull-right#publisher-service-icons
|
||||
|
|
|
|||
|
|
@ -2,6 +2,13 @@
|
|||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
# bootstrap-markdown plugin relies on rails-assets-bootstrap gem but we use
|
||||
# bootstrap-sass this line makes sure we exclude every asset comming
|
||||
# from rails-assets-bootstrap to prevent conflicts with bootstrap-sass
|
||||
Rails.configuration.assets.paths.reject! do |path|
|
||||
path.include?("rails-assets-bootstrap") && !path.include?("rails-assets-bootstrap-markdown")
|
||||
end
|
||||
|
||||
Diaspora::Application.configure do
|
||||
config.serve_static_files = AppConfig.environment.assets.serve?
|
||||
# config.static_cache_control = "public, max-age=3600" if AppConfig[:serve_static_assets].to_s == 'true'
|
||||
|
|
|
|||
|
|
@ -1031,7 +1031,6 @@ en:
|
|||
formatWithMarkdown: "You can use %{markdown_link} to format your post"
|
||||
posting: "Posting..."
|
||||
share: "Share"
|
||||
preview: "Preview"
|
||||
upload_photos: "Upload photos"
|
||||
get_location: "Get your location"
|
||||
remove_location: "Remove location"
|
||||
|
|
|
|||
|
|
@ -138,6 +138,35 @@ en:
|
|||
option: "Answer"
|
||||
add_option: "Add an answer"
|
||||
question: "Question"
|
||||
markdown_editor:
|
||||
preview: "Preview"
|
||||
write: "Write"
|
||||
tooltips:
|
||||
bold: "Bold"
|
||||
italic: "Italic"
|
||||
heading: "Heading"
|
||||
insert_link: "Insert link"
|
||||
insert_image: "Insert image"
|
||||
insert_ordered_list: "Insert ordered list"
|
||||
insert_unordered_list: "Insert unordered list"
|
||||
preview: "Preview message"
|
||||
write: "Edit message"
|
||||
cancel: "Cancel message"
|
||||
quote: "Insert quotation"
|
||||
code: "Insert code"
|
||||
texts:
|
||||
strong: "strong text"
|
||||
italic: "italic text"
|
||||
heading: "heading text"
|
||||
insert_link_description_text: "enter link description here"
|
||||
insert_link_help_text: "Insert link here"
|
||||
insert_image_description_text: "enter image description here"
|
||||
insert_image_help_text: "Insert image link here"
|
||||
insert_image_title: "enter image title here"
|
||||
list: "list text here"
|
||||
quote: "quotation text here"
|
||||
code: "code here"
|
||||
|
||||
bookmarklet:
|
||||
post_something: "Post to diaspora*"
|
||||
post_submit: "Submitting post..."
|
||||
|
|
|
|||
|
|
@ -16,26 +16,27 @@ Feature: preview posts in the stream
|
|||
Scenario: preview and post a text-only message
|
||||
Given I expand the publisher
|
||||
When I write the status message "I am eating yogurt"
|
||||
And I press "Preview"
|
||||
Then "I am eating yogurt" should be post 1
|
||||
And the first post should be a preview
|
||||
And I preview the post
|
||||
Then I should see "I am eating yogurt" in the preview
|
||||
|
||||
Given I edit the post
|
||||
When I write the status message "This preview rocks"
|
||||
And I press "Preview"
|
||||
Then "This preview rocks" should be post 1
|
||||
And I should not see "I am eating a yogurt"
|
||||
And I preview the post
|
||||
Then I should see "This preview rocks" in the preview
|
||||
And I should not see "I am eating a yogurt" in the preview
|
||||
|
||||
Given I edit the post
|
||||
When I write the status message "I like rocks"
|
||||
And I press "Share"
|
||||
Then "I like rocks" should be post 1
|
||||
And I should not see "This preview rocks"
|
||||
When I expand the publisher
|
||||
Then I should not be in preview mode
|
||||
|
||||
Scenario: preview a very long message
|
||||
Given I expand the publisher
|
||||
When I insert an extremely long status message
|
||||
And I press "Preview"
|
||||
And I preview the post
|
||||
Then the preview should not be collapsed
|
||||
|
||||
When I press "Share"
|
||||
Then the post should be collapsed
|
||||
|
||||
|
|
@ -44,15 +45,15 @@ Feature: preview posts in the stream
|
|||
And I attach "spec/fixtures/button.png" to the publisher
|
||||
When I fill in the following:
|
||||
| status_message_fake_text | Look at this dog |
|
||||
And I press "Preview"
|
||||
Then I should see a "img" within ".stream_element div.photo_attachments"
|
||||
And I should see "Look at this dog" within ".stream_element"
|
||||
And I preview the post
|
||||
Then I should see a "img" within ".md-preview .stream_element .photo_attachments"
|
||||
And I should see "Look at this dog" within ".md-preview .stream_element"
|
||||
And I close the publisher
|
||||
|
||||
Scenario: preview a post with mentions
|
||||
Given I expand the publisher
|
||||
And I mention Alice in the publisher
|
||||
And I press "Preview"
|
||||
And I preview the post
|
||||
And I confirm the alert after I follow "Alice Smith"
|
||||
Then I should see "Alice Smith"
|
||||
|
||||
|
|
@ -63,9 +64,8 @@ Feature: preview posts in the stream
|
|||
When I expand the publisher
|
||||
And I fill in the following:
|
||||
| status_message_fake_text | This preview rocks |
|
||||
And I press "Preview"
|
||||
Then "This preview rocks" should be post 1
|
||||
And the first post should be a preview
|
||||
And I preview the post
|
||||
Then I should see "This preview rocks" in the preview
|
||||
And I close the publisher
|
||||
|
||||
Scenario: preview a post with the poll
|
||||
|
|
@ -79,9 +79,9 @@ Feature: preview posts in the stream
|
|||
And I fill in the following for the options:
|
||||
| normal |
|
||||
| not normal |
|
||||
And I press "Preview"
|
||||
Then I should see a ".poll_form" within ".stream_element"
|
||||
And I should see a "form" within ".stream_element"
|
||||
And I preview the post
|
||||
Then I should see a ".poll_form" within ".md-preview .stream_element"
|
||||
And I should see a "form" within ".md-preview .stream_element"
|
||||
And I close the publisher
|
||||
|
||||
Scenario: preview a post with location
|
||||
|
|
@ -93,7 +93,7 @@ Feature: preview posts in the stream
|
|||
When I fill in the following:
|
||||
| status_message_fake_text | I am eating yogurt |
|
||||
| location_address | Some cool place |
|
||||
And I press "Preview"
|
||||
Then I should see a ".near-from" within ".stream_element"
|
||||
And I should see "Some cool place" within ".stream_element .near-from"
|
||||
And I preview the post
|
||||
Then I should see a ".near-from" within ".md-preview .stream_element"
|
||||
And I should see "Some cool place" within ".md-preview .stream_element .near-from"
|
||||
And I close the publisher
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ Feature: posting from the main page
|
|||
When I expand the publisher
|
||||
Then I should see "You can use Markdown to format your post" within ".markdownIndications"
|
||||
Then I should see "All aspects" within ".options_and_submit"
|
||||
Then I should see "Preview" within ".options_and_submit"
|
||||
Then I should see a ".md-write-tab" within ".md-header"
|
||||
Then I should see a ".md-preview-tab" within ".md-header"
|
||||
|
||||
Scenario: post a text-only message to all aspects
|
||||
Given I expand the publisher
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ And /^I expand the publisher$/ do
|
|||
end
|
||||
|
||||
And /^I close the publisher$/ do
|
||||
find("#publisher #hide_publisher").click
|
||||
find("#publisher .md-cancel").click
|
||||
end
|
||||
|
||||
Then /^the publisher should be expanded$/ do
|
||||
|
|
|
|||
|
|
@ -1,9 +1,35 @@
|
|||
Then /^the first post should be a preview$/ do
|
||||
find(".post_preview .post-content").text.should == first_post_text
|
||||
And /^I edit the post$/ do
|
||||
with_scope(".publisher-textarea-wrapper") do
|
||||
find(".md-write-tab").click
|
||||
end
|
||||
end
|
||||
|
||||
Then /^the preview should not be collapsed$/ do
|
||||
find(".post_preview").should_not have_selector('.collapsed')
|
||||
find(".post_preview").should have_selector('.opened')
|
||||
with_scope(".publisher-textarea-wrapper .collapsible") do
|
||||
expect(current_scope).not_to have_css(".collapsed")
|
||||
end
|
||||
end
|
||||
|
||||
And /^I preview the post$/ do
|
||||
with_scope(".publisher-textarea-wrapper") do
|
||||
find(".md-preview-tab").click
|
||||
end
|
||||
end
|
||||
|
||||
Then /^I should see "([^"]*)" in the preview$/ do |text|
|
||||
with_scope(".publisher-textarea-wrapper .md-preview") do
|
||||
expect(current_scope).to have_content(text)
|
||||
end
|
||||
end
|
||||
|
||||
Then /^I should not see "([^"]*)" in the preview$/ do |text|
|
||||
with_scope(".publisher-textarea-wrapper .md-preview") do
|
||||
expect(current_scope).to_not have_content(text)
|
||||
end
|
||||
end
|
||||
|
||||
Then /^I should not be in preview mode$/ do
|
||||
with_scope(".publisher-textarea-wrapper") do
|
||||
expect(current_scope).to_not have_css(".md-preview")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -45,10 +45,8 @@ module PublishingCukeHelpers
|
|||
end
|
||||
|
||||
def click_publisher
|
||||
page.execute_script('
|
||||
$("#publisher").removeClass("closed");
|
||||
$("#publisher").find("#status_message_fake_text").focus();
|
||||
')
|
||||
find("#status_message_fake_text").click
|
||||
expect(find("#publisher")).to have_css(".publisher-textarea-wrapper.active")
|
||||
end
|
||||
|
||||
def publisher_submittable?
|
||||
|
|
|
|||
81
spec/javascripts/app/views/preview_post_view_spec.js
Normal file
81
spec/javascripts/app/views/preview_post_view_spec.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
describe("app.views.PreviewPost", function() {
|
||||
beforeEach(function() {
|
||||
this.model = new app.models.Post(factory.postAttrs());
|
||||
this.view = new app.views.PreviewPost({model: this.model});
|
||||
});
|
||||
|
||||
describe("initialize", function() {
|
||||
it("sets preview property in model", function() {
|
||||
this.view.initialize();
|
||||
expect(this.view.model.get("preview")).toBe(true);
|
||||
});
|
||||
|
||||
it("calls app.views.OEmbed.initialize", function() {
|
||||
spyOn(app.views.OEmbed.prototype, "initialize");
|
||||
this.view.initialize();
|
||||
expect(app.views.OEmbed.prototype.initialize).toHaveBeenCalledWith({model: this.model});
|
||||
});
|
||||
|
||||
it("calls app.views.OpenGraph.initialize", function() {
|
||||
spyOn(app.views.OpenGraph.prototype, "initialize");
|
||||
this.view.initialize();
|
||||
expect(app.views.OpenGraph.prototype.initialize).toHaveBeenCalledWith({model: this.model});
|
||||
});
|
||||
|
||||
it("calls app.views.Poll.initialize", function() {
|
||||
spyOn(app.views.Poll.prototype, "initialize");
|
||||
this.view.initialize();
|
||||
expect(app.views.Poll.prototype.initialize).toHaveBeenCalledWith({model: this.model});
|
||||
});
|
||||
|
||||
it("calls app.views.Poll.initialize", function() {
|
||||
spyOn(app.views.Poll.prototype, "initialize");
|
||||
this.view.initialize();
|
||||
expect(app.views.Poll.prototype.initialize).toHaveBeenCalledWith({model: this.model});
|
||||
});
|
||||
});
|
||||
|
||||
describe("render", function() {
|
||||
it("calls feedbackView", function() {
|
||||
spyOn(app.views.PreviewPost.prototype, "feedbackView");
|
||||
this.view.render();
|
||||
expect(app.views.PreviewPost.prototype.feedbackView).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls postContentView", function() {
|
||||
spyOn(app.views.PreviewPost.prototype, "postContentView");
|
||||
this.view.render();
|
||||
expect(app.views.PreviewPost.prototype.postContentView).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls postLocationStreamView", function() {
|
||||
spyOn(app.views.PreviewPost.prototype, "postLocationStreamView");
|
||||
this.view.render();
|
||||
expect(app.views.PreviewPost.prototype.postLocationStreamView).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("feedbackView", function() {
|
||||
it("calls app.views.Feedback.initialise", function() {
|
||||
spyOn(app.views.Feedback.prototype, "initialize");
|
||||
this.view.feedbackView();
|
||||
expect(app.views.Feedback.prototype.initialize).toHaveBeenCalledWith({model: this.model});
|
||||
});
|
||||
});
|
||||
|
||||
describe("postContentView", function() {
|
||||
it("calls app.views.Feedback.initialise", function() {
|
||||
spyOn(app.views.StatusMessage.prototype, "initialize");
|
||||
this.view.postContentView();
|
||||
expect(app.views.StatusMessage.prototype.initialize).toHaveBeenCalledWith({model: this.model});
|
||||
});
|
||||
});
|
||||
|
||||
describe("postLocationStreamView", function() {
|
||||
it("calls app.views.Feedback.initialise", function() {
|
||||
spyOn(app.views.LocationStream.prototype, "initialize");
|
||||
this.view.postLocationStreamView();
|
||||
expect(app.views.LocationStream.prototype.initialize).toHaveBeenCalledWith({model: this.model});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -12,14 +12,11 @@ describe("app.views.Publisher", function() {
|
|||
this.view = new app.views.Publisher({
|
||||
standalone: true
|
||||
});
|
||||
this.view.open();
|
||||
});
|
||||
|
||||
it("hides the close button in standalone mode", function() {
|
||||
expect(this.view.$("#hide_publisher").is(":visible")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("hides the post preview button in standalone mode", function() {
|
||||
expect(this.view.$(".post_preview_button").is(":visible")).toBeFalsy();
|
||||
expect(this.view.$(".md-cancel").is(":visible")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("hides the manage services link in standalone mode", function() {
|
||||
|
|
@ -89,6 +86,21 @@ describe("app.views.Publisher", function() {
|
|||
this.view.close($.Event());
|
||||
expect($(this.view.el).find("#status_message_fake_text").attr("style")).not.toContain("height");
|
||||
});
|
||||
|
||||
it("should hide the poll container correctly", function() {
|
||||
this.view.$el.find(".poll-creator").click();
|
||||
expect(this.view.$el.find(".publisher-textarea-wrapper")).toHaveClass("with-poll");
|
||||
expect(this.view.$el.find(".poll-creator-container")).toBeVisible();
|
||||
this.view.close();
|
||||
expect(this.view.$el.find(".publisher-textarea-wrapper")).not.toHaveClass("with-poll");
|
||||
expect(this.view.$el.find(".poll-creator-container")).not.toBeVisible();
|
||||
this.view.open();
|
||||
expect(this.view.$el.find(".publisher-textarea-wrapper")).not.toHaveClass("with-poll");
|
||||
expect(this.view.$el.find(".poll-creator-container")).not.toBeVisible();
|
||||
this.view.$el.find(".poll-creator").click();
|
||||
expect(this.view.$el.find(".publisher-textarea-wrapper")).toHaveClass("with-poll");
|
||||
expect(this.view.$el.find(".poll-creator-container")).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe("#clear", function() {
|
||||
|
|
@ -99,11 +111,11 @@ describe("app.views.Publisher", function() {
|
|||
expect(this.view.close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls removePostPreview", function(){
|
||||
spyOn(this.view, "removePostPreview");
|
||||
it("calls hidePreview", function() {
|
||||
spyOn(this.view.markdownEditor, "hidePreview");
|
||||
|
||||
this.view.clear($.Event());
|
||||
expect(this.view.removePostPreview).toHaveBeenCalled();
|
||||
expect(this.view.markdownEditor.hidePreview).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("clears all textareas", function(){
|
||||
|
|
@ -179,39 +191,11 @@ describe("app.views.Publisher", function() {
|
|||
});
|
||||
|
||||
describe("createPostPreview", function(){
|
||||
beforeEach(function() {
|
||||
app.stream = { addNow: $.noop };
|
||||
});
|
||||
|
||||
it("calls handleTextchange to complete missing mentions", function(){
|
||||
spyOn(this.view, "handleTextchange");
|
||||
this.view.createPostPreview($.Event());
|
||||
this.view.createPostPreview();
|
||||
expect(this.view.handleTextchange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls removePostPreview to remove the last preview", function(){
|
||||
spyOn(this.view, "removePostPreview");
|
||||
this.view.createPostPreview($.Event());
|
||||
expect(this.view.removePostPreview).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("adds the status message to the stream", function() {
|
||||
spyOn(app.stream, "addNow");
|
||||
this.view.createPostPreview($.Event());
|
||||
expect(app.stream.addNow).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sets recentPreview", function(){
|
||||
expect(this.view.recentPreview).toBeUndefined();
|
||||
this.view.createPostPreview($.Event());
|
||||
expect(this.view.recentPreview).toBeDefined();
|
||||
});
|
||||
|
||||
it("calls modifyPostPreview to apply the preview style to the post", function(){
|
||||
spyOn(this.view, "modifyPostPreview");
|
||||
this.view.createPostPreview($.Event());
|
||||
expect(this.view.modifyPostPreview).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setText', function() {
|
||||
|
|
@ -236,11 +220,9 @@ describe("app.views.Publisher", function() {
|
|||
it("disables submitting", function() {
|
||||
this.view.setText("TESTING");
|
||||
expect(this.view.submitEl.prop("disabled")).toBeFalsy();
|
||||
expect(this.view.previewEl.prop("disabled")).toBeFalsy();
|
||||
|
||||
this.view.setEnabled(false);
|
||||
expect(this.view.submitEl.prop("disabled")).toBeTruthy();
|
||||
expect(this.view.previewEl.prop("disabled")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -491,7 +473,6 @@ describe("app.views.Publisher", function() {
|
|||
' <div id="publisher_textarea_wrapper"></div>'+
|
||||
' <div id="photodropzone"></div>'+
|
||||
' <input type="submit" />'+
|
||||
' <button class="post_preview_button" />'+
|
||||
' </form></div>'+
|
||||
'</div>'
|
||||
);
|
||||
|
|
@ -540,7 +521,6 @@ describe("app.views.Publisher", function() {
|
|||
|
||||
it('disables the publisher buttons', function() {
|
||||
expect(this.view.submitEl.prop("disabled")).toBeTruthy();
|
||||
expect(this.view.previewEl.prop("disabled")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -577,7 +557,6 @@ describe("app.views.Publisher", function() {
|
|||
|
||||
it('re-enables the buttons', function() {
|
||||
expect(this.view.submitEl.prop("disabled")).toBeFalsy();
|
||||
expect(this.view.previewEl.prop("disabled")).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
237
spec/javascripts/helpers/markdown_editor_spec.js
Normal file
237
spec/javascripts/helpers/markdown_editor_spec.js
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
describe("Diaspora.MarkdownEditor", function() {
|
||||
beforeEach(function() {
|
||||
spec.content().html("<textarea id='fake-textarea'></textarea>");
|
||||
this.$el = $("#fake-textarea");
|
||||
});
|
||||
|
||||
describe("constructor", function() {
|
||||
it("calls initialize", function() {
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "initialize");
|
||||
new Diaspora.MarkdownEditor(this.$el, {});
|
||||
expect(Diaspora.MarkdownEditor.prototype.initialize).toHaveBeenCalledWith(this.$el, {});
|
||||
});
|
||||
});
|
||||
|
||||
describe("initialize", function() {
|
||||
beforeEach(function() {
|
||||
this.target = new Diaspora.MarkdownEditor($("<textarea></textarea>"), {});
|
||||
});
|
||||
|
||||
it("calls localize", function() {
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "localize");
|
||||
this.target.initialize(this.$el, {});
|
||||
expect(Diaspora.MarkdownEditor.prototype.localize).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls onShow", function() {
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "onShow");
|
||||
this.target.initialize(this.$el, {});
|
||||
expect(Diaspora.MarkdownEditor.prototype.onShow).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("call $.fn.markdown with correct default options", function() {
|
||||
spyOn($.fn, "markdown");
|
||||
this.target.initialize(this.$el, {});
|
||||
expect($.fn.markdown).toHaveBeenCalled();
|
||||
var args = $.fn.markdown.calls.mostRecent().args[0];
|
||||
expect(args.resize).toBe("none");
|
||||
expect(args.language).toBe("en");
|
||||
expect(args.onHidePreview).toBe($.noop);
|
||||
expect(args.onPostPreview).toBe($.noop);
|
||||
expect(args.fullscreen).toEqual({enable: false, icons: {}});
|
||||
expect(args.hiddenButtons).toEqual(["cmdPreview"]);
|
||||
});
|
||||
|
||||
it("overrides fullscreen, hiddenButtons, language and onShow options", function() {
|
||||
spyOn($.fn, "markdown").and.callThrough();
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "onShow");
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "localize").and.callThrough();
|
||||
this.target.initialize(this.$el, {
|
||||
fullscreen: {enabled: true, icons: {somekey: "somevalue"}},
|
||||
hiddenButtons: [],
|
||||
language: "fr",
|
||||
onShow: $.noop
|
||||
});
|
||||
var args = $.fn.markdown.calls.mostRecent().args[0];
|
||||
expect(args.fullscreen).toEqual({enable: false, icons: {}});
|
||||
expect(args.hiddenButtons).toEqual(["cmdPreview"]);
|
||||
expect(args.language).toBe("en");
|
||||
expect(args.onShow).not.toBe($.noop);
|
||||
expect(Diaspora.MarkdownEditor.prototype.onShow).toHaveBeenCalled();
|
||||
expect(Diaspora.MarkdownEditor.prototype.localize).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("onShow", function() {
|
||||
beforeEach(function() {
|
||||
this.target = new Diaspora.MarkdownEditor(this.$el, {});
|
||||
this.$el.find(".md-header").remove(".write-preview-tabs");
|
||||
this.$el.find(".md-header").remove(".md-cancel");
|
||||
});
|
||||
|
||||
it("retreives the $.fn.markdown instance back", function() {
|
||||
var fakeInstance = {$editor: $("body")};
|
||||
this.target.onShow(fakeInstance);
|
||||
expect(this.target.instance).toBe(fakeInstance);
|
||||
});
|
||||
|
||||
it("calls createTabsElement createCloseElement if preview and close functions are given", function() {
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "createTabsElement");
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "createCloseElement");
|
||||
this.target.options.onPreview = $.noop;
|
||||
this.target.options.onClose = $.noop;
|
||||
this.target.onShow(this.target.instance);
|
||||
expect(Diaspora.MarkdownEditor.prototype.createTabsElement).toHaveBeenCalled();
|
||||
expect(Diaspora.MarkdownEditor.prototype.createCloseElement).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not call createTabsElement createCloseElement if no preview and close functions are given", function() {
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "createTabsElement");
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "createCloseElement");
|
||||
delete this.target.options.onPreview;
|
||||
delete this.target.options.onClose;
|
||||
this.target.onShow(this.target.instance);
|
||||
expect(Diaspora.MarkdownEditor.prototype.createCloseElement).not.toHaveBeenCalled();
|
||||
expect(Diaspora.MarkdownEditor.prototype.createTabsElement).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("creates the preview and write tabs", function() {
|
||||
this.target.options.onPreview = $.noop;
|
||||
this.target.onShow(this.target.instance);
|
||||
expect($(".md-header .write-preview-tabs").length).toBe(1);
|
||||
});
|
||||
|
||||
it("removes preview tabs if already existing", function() {
|
||||
this.target.options.onPreview = $.noop;
|
||||
this.$el.find(".md-header").prepend("<div id='fake-write-preview-tabs' class='write-preview-tabs'/>");
|
||||
this.target.onShow(this.target.instance);
|
||||
expect($(".md-header .write-preview-tabs").length).toBe(1);
|
||||
expect($("#fake-write-preview-tabs").length).toBe(0);
|
||||
});
|
||||
|
||||
it("creates the cancel button", function() {
|
||||
this.target.options.onClose = $.noop;
|
||||
this.target.onShow(this.target.instance);
|
||||
expect($(".md-header .md-cancel").length).toBe(1);
|
||||
});
|
||||
|
||||
it("removes cancel button if already existing", function() {
|
||||
this.target.options.onClose = $.noop;
|
||||
this.$el.find(".md-header").prepend("<div id='fake-md-cancel' class='md-cancel'/>");
|
||||
this.target.onShow(this.target.instance);
|
||||
expect($(".md-header .md-cancel").length).toBe(1);
|
||||
expect($("#fake-md-cancel").length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createTabsElement", function() {
|
||||
beforeEach(function() {
|
||||
this.target = new Diaspora.MarkdownEditor(this.$el, {});
|
||||
});
|
||||
|
||||
it("correctly creates the preview tabs", function() {
|
||||
var tabsElement = this.target.createTabsElement();
|
||||
expect(tabsElement).toHaveClass("write-preview-tabs");
|
||||
expect(tabsElement.find("> li > a.md-write-tab").attr("title")).toBe("Edit message");
|
||||
expect(tabsElement.find("> li > a.md-write-tab > i.diaspora-custom-compose").length).toBe(1);
|
||||
expect(tabsElement.find("> li > a.md-write-tab > span.tab-help-text").length).toBe(1);
|
||||
expect(tabsElement.find("> li > a.md-write-tab > span.tab-help-text").text()).toBe("Write");
|
||||
expect(tabsElement.find("> li > a.md-preview-tab").attr("title")).toBe("Preview message");
|
||||
expect(tabsElement.find("> li > a.md-preview-tab > i.entypo-search").length).toBe(1);
|
||||
expect(tabsElement.find("> li > a.md-preview-tab > span.tab-help-text").length).toBe(1);
|
||||
expect(tabsElement.find("> li > a.md-preview-tab > span.tab-help-text").text()).toBe("Preview");
|
||||
});
|
||||
|
||||
it("correctly binds onclick events", function() {
|
||||
var tabsElement = this.target.createTabsElement();
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "hidePreview");
|
||||
spyOn(Diaspora.MarkdownEditor.prototype, "showPreview");
|
||||
tabsElement.find("> li > a.md-write-tab").click();
|
||||
expect(Diaspora.MarkdownEditor.prototype.hidePreview).toHaveBeenCalled();
|
||||
tabsElement.find("> li > a.md-preview-tab").click();
|
||||
expect(Diaspora.MarkdownEditor.prototype.showPreview).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("createCloseElement", function() {
|
||||
beforeEach(function() {
|
||||
this.target = new Diaspora.MarkdownEditor(this.$el, {});
|
||||
});
|
||||
|
||||
it("correctly creates the close button", function() {
|
||||
var closeElement = this.target.createCloseElement();
|
||||
expect(closeElement).toHaveClass("md-cancel");
|
||||
expect(closeElement.get(0).tagName).toBe("A");
|
||||
expect(closeElement.attr("title")).toBe("Cancel message");
|
||||
expect(closeElement.find("> i.entypo-cross").length).toBe(1);
|
||||
});
|
||||
|
||||
it("correctly binds onclick events", function() {
|
||||
this.target.options.onClose = jasmine.createSpy();
|
||||
var closeElement = this.target.createCloseElement();
|
||||
closeElement.click();
|
||||
expect(this.target.options.onClose).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("hidePreview", function() {
|
||||
beforeEach(function() {
|
||||
this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onHidePreview: jasmine.createSpy()});
|
||||
spyOn(this.target.instance, "hidePreview");
|
||||
spyOn(this.target.writeLink, "tab");
|
||||
});
|
||||
|
||||
it("calls writeLink.tab", function() {
|
||||
this.target.hidePreview();
|
||||
expect(this.target.writeLink.tab).toHaveBeenCalledWith("show");
|
||||
});
|
||||
|
||||
it("calls instance.hidePreview", function() {
|
||||
this.target.hidePreview();
|
||||
expect(this.target.instance.hidePreview).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls instance.onHidePreview", function() {
|
||||
this.target.hidePreview();
|
||||
expect(this.target.options.onHidePreview).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("showPreview", function() {
|
||||
beforeEach(function() {
|
||||
this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onPostPreview: jasmine.createSpy()});
|
||||
spyOn(this.target.instance, "showPreview");
|
||||
spyOn(this.target.previewLink, "tab");
|
||||
});
|
||||
|
||||
it("calls previewLink.tab", function() {
|
||||
this.target.showPreview();
|
||||
expect(this.target.previewLink.tab).toHaveBeenCalledWith("show");
|
||||
});
|
||||
|
||||
it("calls instance.showPreview", function() {
|
||||
this.target.showPreview();
|
||||
expect(this.target.instance.showPreview).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls instance.onPostPreview", function() {
|
||||
this.target.showPreview();
|
||||
expect(this.target.options.onPostPreview).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("localize", function() {
|
||||
beforeEach(function() {
|
||||
this.target = new Diaspora.MarkdownEditor(this.$el, {});
|
||||
});
|
||||
|
||||
it("returns the correct locale", function() {
|
||||
expect(this.target.localize()).toBe(Diaspora.I18n.language);
|
||||
});
|
||||
|
||||
it("creates translation messages for the current locale", function() {
|
||||
this.target.localize();
|
||||
expect($.fn.markdown.messages[Diaspora.I18n.language]).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -76,6 +76,7 @@ var factory = {
|
|||
|
||||
postAttrs : function(){
|
||||
return {
|
||||
"author": {},
|
||||
"provider_display_name" : null,
|
||||
"created_at" : "2012-01-03T19:53:13Z",
|
||||
"interacted_at" : '2012-01-03T19:53:13Z',
|
||||
|
|
|
|||
Loading…
Reference in a new issue