Merge pull request #767 from ZogStriP/refactor-quote-reply
improve & refactor quote reply
This commit is contained in:
commit
0a13b78c05
|
@ -29,17 +29,15 @@ Discourse.QuoteButtonController = Discourse.Controller.extend({
|
|||
|
||||
@method selectText
|
||||
**/
|
||||
selectText: function(e) {
|
||||
selectText: function(postId) {
|
||||
// anonymous users cannot "quote-reply"
|
||||
if (!Discourse.get('currentUser')) return;
|
||||
// don't display the "quote-reply" button if we can't create a post
|
||||
if (!this.get('controllers.topic.content.can_create_post')) return;
|
||||
|
||||
var selection = window.getSelection();
|
||||
|
||||
// no selections
|
||||
if (selection.rangeCount === 0) return;
|
||||
|
||||
// retrieve the selected range
|
||||
var range = selection.getRangeAt(0),
|
||||
cloned = range.cloneRange(),
|
||||
|
@ -51,9 +49,17 @@ Discourse.QuoteButtonController = Discourse.Controller.extend({
|
|||
|
||||
var selectedText = Discourse.Utilities.selectedText();
|
||||
if (this.get('buffer') === selectedText) return;
|
||||
if (this.get('lastSelected') === selectedText) return;
|
||||
|
||||
this.set('post', e.context);
|
||||
// we need to retrieve the post data from the posts collection in the topic controller
|
||||
var posts = this.get('controllers.topic.posts'),
|
||||
length = posts.length,
|
||||
post;
|
||||
|
||||
for (var p = 0; p < length; p++) {
|
||||
if (posts[p].id === postId) { post = posts[p]; break; }
|
||||
}
|
||||
|
||||
this.set('post', post);
|
||||
this.set('buffer', selectedText);
|
||||
|
||||
// collapse the range at the beginning of the selection
|
||||
|
@ -117,6 +123,18 @@ Discourse.QuoteButtonController = Discourse.Controller.extend({
|
|||
}
|
||||
this.set('buffer', '');
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
Deselect the currently selected text
|
||||
|
||||
@method deselectText
|
||||
**/
|
||||
deselectText: function() {
|
||||
// clear selected text
|
||||
window.getSelection().removeAllRanges();
|
||||
// clean up the buffer
|
||||
this.set('buffer', '');
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -43,34 +43,19 @@ Discourse.PostView = Discourse.View.extend({
|
|||
this.set('context', this.get('content'));
|
||||
},
|
||||
|
||||
mouseDown: function(e) {
|
||||
this.set('isMouseDown', true);
|
||||
},
|
||||
|
||||
mouseUp: function(e) {
|
||||
if (this.get('controller.multiSelect') && (e.metaKey || e.ctrlKey)) {
|
||||
this.toggleProperty('post.selected');
|
||||
}
|
||||
|
||||
if (!Discourse.get('currentUser.enable_quoting')) return;
|
||||
if ($(e.target).closest('.topic-body').length === 0) return;
|
||||
|
||||
var qbc = this.get('controller.controllers.quoteButton');
|
||||
if (qbc) {
|
||||
e.context = this.get('post');
|
||||
qbc.selectText(e);
|
||||
}
|
||||
|
||||
this.set('isMouseDown', false);
|
||||
},
|
||||
|
||||
selectText: (function() {
|
||||
selectText: function() {
|
||||
return this.get('post.selected') ? Em.String.i18n('topic.multi_select.selected', { count: this.get('controller.selectedCount') }) : Em.String.i18n('topic.multi_select.select');
|
||||
}).property('post.selected', 'controller.selectedCount'),
|
||||
}.property('post.selected', 'controller.selectedCount'),
|
||||
|
||||
repliesHidden: (function() {
|
||||
repliesHidden: function() {
|
||||
return !this.get('repliesShown');
|
||||
}).property('repliesShown'),
|
||||
}.property('repliesShown'),
|
||||
|
||||
// Click on the replies button
|
||||
showReplies: function() {
|
||||
|
@ -262,30 +247,5 @@ Discourse.PostView = Discourse.View.extend({
|
|||
if (controller && controller.postRendered) {
|
||||
controller.postRendered(post);
|
||||
}
|
||||
|
||||
// make the selection work under iOS
|
||||
// "selectionchange" event is only supported in IE, Safari & Chrome
|
||||
var postView = this;
|
||||
$(document).on('selectionchange', function(e) {
|
||||
// quoting as been disabled by the user
|
||||
if (!Discourse.get('currentUser.enable_quoting')) return;
|
||||
// there is no need to handle this event when the mouse is down
|
||||
if (postView.get('isMouseDown')) return;
|
||||
// find out whether we currently are selecting inside a post
|
||||
var closestPosts = $(window.getSelection().anchorNode).closest('.topic-post');
|
||||
if (closestPosts.length === 0) return;
|
||||
// this event is bound for every posts in the topic, but is triggered on "document"
|
||||
// we should therefore filter the event to only the right post
|
||||
if (closestPosts[0].id !== postView.elementId) return;
|
||||
var qbc = postView.get('controller.controllers.quoteButton');
|
||||
if (qbc) {
|
||||
e.context = postView.get('post');
|
||||
qbc.selectText(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
willDestroyElement: function() {
|
||||
$(document).off('selectionchange');
|
||||
}
|
||||
});
|
||||
|
|
|
@ -8,32 +8,92 @@
|
|||
**/
|
||||
Discourse.QuoteButtonView = Discourse.View.extend({
|
||||
classNames: ['quote-button'],
|
||||
classNameBindings: ['hasBuffer'],
|
||||
classNameBindings: ['visible'],
|
||||
isMouseDown: false,
|
||||
|
||||
/**
|
||||
Determines whether the pop-up quote button should be visible.
|
||||
The button is visible whenever there is something in the buffer
|
||||
(ie. something has been selected)
|
||||
|
||||
@property visible
|
||||
**/
|
||||
visible: function() {
|
||||
return this.present('controller.buffer');
|
||||
}.property('controller.buffer'),
|
||||
|
||||
/**
|
||||
Renders the pop-up quote button.
|
||||
|
||||
@method render
|
||||
**/
|
||||
render: function(buffer) {
|
||||
buffer.push('<i class="icon-quote-right"></i> ');
|
||||
buffer.push(Em.String.i18n("post.quote_reply"));
|
||||
},
|
||||
|
||||
hasBuffer: function() {
|
||||
return this.present('controller.buffer') ? 'visible' : null;
|
||||
}.property('controller.buffer'),
|
||||
|
||||
willDestroyElement: function() {
|
||||
$(document).off("mousedown.quote-button");
|
||||
},
|
||||
/**
|
||||
Binds to the following global events:
|
||||
- `mousedown` to clear the quote button if they click elsewhere.
|
||||
- `mouseup` to trigger the display of the quote button.
|
||||
- `selectionchange` to make the selection work under iOS
|
||||
|
||||
@method didInsertElement
|
||||
**/
|
||||
didInsertElement: function() {
|
||||
// Clear quote button if they click elsewhere
|
||||
var quoteButtonView = this;
|
||||
$(document).on("mousedown.quote-button", function(e) {
|
||||
if ($(e.target).hasClass('quote-button')) return;
|
||||
if ($(e.target).hasClass('create')) return;
|
||||
quoteButtonView.set('controller.lastSelected', quoteButtonView.get('controller.buffer'));
|
||||
quoteButtonView.set('controller.buffer', '');
|
||||
var controller = this.get('controller'),
|
||||
view = this;
|
||||
|
||||
$(document)
|
||||
.on("mousedown.quote-button", function(e) {
|
||||
view.set('isMouseDown', true);
|
||||
if ($(e.target).hasClass('quote-button') || $(e.target).hasClass('create')) return;
|
||||
controller.deselectText();
|
||||
})
|
||||
.on('mouseup.quote-button', function(e) {
|
||||
view.selectText(e.target, controller);
|
||||
view.set('isMouseDown', false);
|
||||
})
|
||||
.on('selectionchange', function() {
|
||||
// there is no need to handle this event when the mouse is down
|
||||
if (view.get('isMouseDown')) return;
|
||||
// `selection.anchorNode` is used as a target
|
||||
view.selectText(window.getSelection().anchorNode, controller);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Selects the text
|
||||
|
||||
@method selectText
|
||||
**/
|
||||
selectText: function(target, controller) {
|
||||
var $target = $(target);
|
||||
// quoting as been disabled by the user
|
||||
if (!Discourse.get('currentUser.enable_quoting')) return;
|
||||
// retrieve the post id from the DOM
|
||||
var postId = $target.closest('.boxed').data('post-id');
|
||||
// select the text
|
||||
if (postId) controller.selectText(postId);
|
||||
},
|
||||
|
||||
/**
|
||||
Unbinds from global `mouseup, mousedown, selectionchange` events
|
||||
|
||||
@method willDestroyElement
|
||||
**/
|
||||
willDestroyElement: function() {
|
||||
$(document)
|
||||
.off("mousedown.quote-button")
|
||||
.off("mouseup.quote-button")
|
||||
.off("selectionchange");
|
||||
},
|
||||
|
||||
/**
|
||||
Quote the selected text when clicking on the quote button.
|
||||
|
||||
@method click
|
||||
**/
|
||||
click: function(e) {
|
||||
e.stopPropagation();
|
||||
return this.get('controller').quoteText(e);
|
||||
|
|
Loading…
Reference in New Issue