Fix tooltips when chat view is shown as the main view

By default, "tooltip()" adds the tooltip element to the element in which
the function is called. If a "container" option is provided the tooltip
is added instead to the given element, although visually it will be
shown for the element in which the function is called.

The positioning context (the element that an absolute element is
relative to) of the tooltips shown for the date of messages was the
author row, and thus they were visible only were the author row would be
visible. The author row would be clipped outside the list of messages
(due to its "overflow-y" CSS property), so the tooltip shown for the
date of the newest message was clipped at the top of the list of
messages.

Now the ChatView provides a method to specify to which element append
the tooltip elements, so they can be appended to another element that
does not cause clipping problems.

Although right now it would be enough to add the tooltips to the chat
view itself, once the chat view layout is modified to show the input
field at the bottom then the same problem would arise when the chat view
is shown as the main view, as the tooltips would be clipped by
"#app-content". Thus, to be prepared for that change, they are added to
"#app" instead.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
Daniel Calviño Sánchez 2017-12-01 12:34:21 +01:00
Родитель be934f1364
Коммит 38d866bf14
2 изменённых файлов: 25 добавлений и 2 удалений

Просмотреть файл

@ -396,10 +396,12 @@
if (this.activeRoom.get('participantInCall') && this._chatViewInMainView === true) { if (this.activeRoom.get('participantInCall') && this._chatViewInMainView === true) {
this._chatView.$el.detach(); this._chatView.$el.detach();
this._sidebarView.addTab('chat', { label: t('spreed', 'Chat') }, this._chatView); this._sidebarView.addTab('chat', { label: t('spreed', 'Chat') }, this._chatView);
this._chatView.setTooltipContainer(undefined);
this._chatViewInMainView = false; this._chatViewInMainView = false;
} else if (!this.activeRoom.get('participantInCall') && !this._chatViewInMainView) { } else if (!this.activeRoom.get('participantInCall') && !this._chatViewInMainView) {
this._sidebarView.removeTab('chat'); this._sidebarView.removeTab('chat');
this._chatView.$el.prependTo('#app-content-wrapper'); this._chatView.$el.prependTo('#app-content-wrapper');
this._chatView.setTooltipContainer($('#app'));
this._chatViewInMainView = true; this._chatViewInMainView = true;
} }
}, },

Просмотреть файл

@ -98,7 +98,7 @@
delete this._lastAddedMessageModel; delete this._lastAddedMessageModel;
this.$el.find('.comments').before(this.addCommentTemplate({})); this.$el.find('.comments').before(this.addCommentTemplate({}));
this.$el.find('.has-tooltip').tooltip(); this.$el.find('.has-tooltip').tooltip({container: this._tooltipContainer});
this.$container = this.$el.find('ul.comments'); this.$container = this.$el.find('ul.comments');
// FIXME handle guest users // FIXME handle guest users
this.$el.find('.avatar').avatar(OC.getCurrentUser().uid, 32); this.$el.find('.avatar').avatar(OC.getCurrentUser().uid, 32);
@ -108,6 +108,27 @@
autosize(this.$el.find('.newCommentRow .message')); autosize(this.$el.find('.newCommentRow .message'));
}, },
/**
* Set the tooltip container.
*
* Depending on the parent elements of the chat view the tooltips may
* need to be appended to a specific element to be properly shown (due
* to how CSS overflows, clipping areas and positioning contexts work).
* If no specific container is ever set, or if it is set to "undefined",
* the tooltip elements will be appended as siblings of the element for
* which they are shown.
*
* @param jQuery tooltipContainer the element to append the tooltip
* elements to
*/
setTooltipContainer: function(tooltipContainer) {
this._tooltipContainer = tooltipContainer;
// Update tooltips
this.$el.find('.has-tooltip').tooltip('destroy');
this.$el.find('.has-tooltip').tooltip({container: this._tooltipContainer});
},
_formatItem: function(commentModel) { _formatItem: function(commentModel) {
// PHP timestamp is second-based; JavaScript timestamp is // PHP timestamp is second-based; JavaScript timestamp is
// millisecond based. // millisecond based.
@ -197,7 +218,7 @@
}, },
_postRenderItem: function($el) { _postRenderItem: function($el) {
$el.find('.has-tooltip').tooltip(); $el.find('.has-tooltip').tooltip({container: this._tooltipContainer});
$el.find('.avatar').each(function() { $el.find('.avatar').each(function() {
var $this = $(this); var $this = $(this);
$this.avatar($this.attr('data-username'), 32); $this.avatar($this.attr('data-username'), 32);