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
|
@method selectText
|
||||||
**/
|
**/
|
||||||
selectText: function(e) {
|
selectText: function(postId) {
|
||||||
// anonymous users cannot "quote-reply"
|
// anonymous users cannot "quote-reply"
|
||||||
if (!Discourse.get('currentUser')) return;
|
if (!Discourse.get('currentUser')) return;
|
||||||
// don't display the "quote-reply" button if we can't create a post
|
// don't display the "quote-reply" button if we can't create a post
|
||||||
if (!this.get('controllers.topic.content.can_create_post')) return;
|
if (!this.get('controllers.topic.content.can_create_post')) return;
|
||||||
|
|
||||||
var selection = window.getSelection();
|
var selection = window.getSelection();
|
||||||
|
|
||||||
// no selections
|
// no selections
|
||||||
if (selection.rangeCount === 0) return;
|
if (selection.rangeCount === 0) return;
|
||||||
|
|
||||||
// retrieve the selected range
|
// retrieve the selected range
|
||||||
var range = selection.getRangeAt(0),
|
var range = selection.getRangeAt(0),
|
||||||
cloned = range.cloneRange(),
|
cloned = range.cloneRange(),
|
||||||
|
@ -51,9 +49,17 @@ Discourse.QuoteButtonController = Discourse.Controller.extend({
|
||||||
|
|
||||||
var selectedText = Discourse.Utilities.selectedText();
|
var selectedText = Discourse.Utilities.selectedText();
|
||||||
if (this.get('buffer') === selectedText) return;
|
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);
|
this.set('buffer', selectedText);
|
||||||
|
|
||||||
// collapse the range at the beginning of the selection
|
// collapse the range at the beginning of the selection
|
||||||
|
@ -117,6 +123,18 @@ Discourse.QuoteButtonController = Discourse.Controller.extend({
|
||||||
}
|
}
|
||||||
this.set('buffer', '');
|
this.set('buffer', '');
|
||||||
return false;
|
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'));
|
this.set('context', this.get('content'));
|
||||||
},
|
},
|
||||||
|
|
||||||
mouseDown: function(e) {
|
|
||||||
this.set('isMouseDown', true);
|
|
||||||
},
|
|
||||||
|
|
||||||
mouseUp: function(e) {
|
mouseUp: function(e) {
|
||||||
if (this.get('controller.multiSelect') && (e.metaKey || e.ctrlKey)) {
|
if (this.get('controller.multiSelect') && (e.metaKey || e.ctrlKey)) {
|
||||||
this.toggleProperty('post.selected');
|
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');
|
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');
|
return !this.get('repliesShown');
|
||||||
}).property('repliesShown'),
|
}.property('repliesShown'),
|
||||||
|
|
||||||
// Click on the replies button
|
// Click on the replies button
|
||||||
showReplies: function() {
|
showReplies: function() {
|
||||||
|
@ -262,30 +247,5 @@ Discourse.PostView = Discourse.View.extend({
|
||||||
if (controller && controller.postRendered) {
|
if (controller && controller.postRendered) {
|
||||||
controller.postRendered(post);
|
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({
|
Discourse.QuoteButtonView = Discourse.View.extend({
|
||||||
classNames: ['quote-button'],
|
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) {
|
render: function(buffer) {
|
||||||
buffer.push('<i class="icon-quote-right"></i> ');
|
buffer.push('<i class="icon-quote-right"></i> ');
|
||||||
buffer.push(Em.String.i18n("post.quote_reply"));
|
buffer.push(Em.String.i18n("post.quote_reply"));
|
||||||
},
|
},
|
||||||
|
|
||||||
hasBuffer: function() {
|
/**
|
||||||
return this.present('controller.buffer') ? 'visible' : null;
|
Binds to the following global events:
|
||||||
}.property('controller.buffer'),
|
- `mousedown` to clear the quote button if they click elsewhere.
|
||||||
|
- `mouseup` to trigger the display of the quote button.
|
||||||
willDestroyElement: function() {
|
- `selectionchange` to make the selection work under iOS
|
||||||
$(document).off("mousedown.quote-button");
|
|
||||||
},
|
|
||||||
|
|
||||||
|
@method didInsertElement
|
||||||
|
**/
|
||||||
didInsertElement: function() {
|
didInsertElement: function() {
|
||||||
// Clear quote button if they click elsewhere
|
var controller = this.get('controller'),
|
||||||
var quoteButtonView = this;
|
view = this;
|
||||||
$(document).on("mousedown.quote-button", function(e) {
|
|
||||||
if ($(e.target).hasClass('quote-button')) return;
|
$(document)
|
||||||
if ($(e.target).hasClass('create')) return;
|
.on("mousedown.quote-button", function(e) {
|
||||||
quoteButtonView.set('controller.lastSelected', quoteButtonView.get('controller.buffer'));
|
view.set('isMouseDown', true);
|
||||||
quoteButtonView.set('controller.buffer', '');
|
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) {
|
click: function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
return this.get('controller').quoteText(e);
|
return this.get('controller').quoteText(e);
|
||||||
|
|
Loading…
Reference in New Issue