From ddcaa5bf242dd547a357fe4e5cba1cc3df5713c0 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 17 Apr 2018 14:40:06 -0300 Subject: [PATCH] [FIX] render popover to other side on RTL (#10428) [FIX] Wrong positioning of popover when using RTL languages --- .../client/lib/EmojiPicker.js | 32 +++++----- .../client/views/pushNotificationsFlexTab.js | 12 +--- .../components/sidebar/sidebar-header.css | 9 ++- .../client/flexTabBar.js | 15 ++--- .../client/tabs/membersList.js | 12 +--- .../client/tabs/userInfo.js | 15 ++--- .../client/messageBox.js | 14 ++--- .../client/sidebarHeader.js | 43 +++----------- .../client/sidebarItem.js | 8 +-- .../rocketchat-ui/client/views/app/popover.js | 58 +++++++++++++------ .../rocketchat-ui/client/views/app/room.js | 9 +-- 11 files changed, 90 insertions(+), 137 deletions(-) diff --git a/packages/rocketchat-emoji/client/lib/EmojiPicker.js b/packages/rocketchat-emoji/client/lib/EmojiPicker.js index d5d275952049..9e2b3e363fcb 100644 --- a/packages/rocketchat-emoji/client/lib/EmojiPicker.js +++ b/packages/rocketchat-emoji/client/lib/EmojiPicker.js @@ -2,8 +2,8 @@ import _ from 'underscore'; RocketChat.EmojiPicker = { - width: 390, - height: 238, + width: 365, + height: 290, initiated: false, input: null, source: null, @@ -54,27 +54,23 @@ RocketChat.EmojiPicker = { return this.recent; }, setPosition() { + const windowHeight = window.innerHeight; + const windowBorder = 10; const sourcePos = $(this.source).offset(); const left = sourcePos.left; - const top = sourcePos.top - this.height - 60; - const cssProperties = { - top, - left - }; - - if (top < 0) { - cssProperties.top = 10; + const top = sourcePos.top; + const cssProperties = {top, left}; + + if (top + this.height >= windowHeight) { + cssProperties.top = windowHeight - this.height - windowBorder; } - if (left < 35) { - cssProperties.left = 0; - } else { - const windowSize = $(window).width(); - const pickerWidth = $('.emoji-picker').outerWidth(); + if (left < windowBorder) { + cssProperties.left = windowBorder; + } - if (left + pickerWidth > windowSize) { - cssProperties.left = left - pickerWidth; - } + if (left + this.width >= window.innerWidth) { + cssProperties.left = left - this.width - windowBorder; } return $('.emoji-picker').css(cssProperties); diff --git a/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.js b/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.js index 70f65e81ef12..46a8f6a75473 100644 --- a/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.js +++ b/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.js @@ -309,21 +309,15 @@ Template.pushNotificationsFlexTab.events({ const config = { popoverClass: 'notifications-preferences', template: 'pushNotificationsPopover', - mousePosition: () => ({ - x: e.currentTarget.getBoundingClientRect().left, - y: e.currentTarget.getBoundingClientRect().bottom + 50 - }), - customCSSProperties: () => ({ - top: `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`, - left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px` - }), data: { change : (value) => { return instance.form[key].set(key === 'desktopNotificationDuration' ? parseInt(value) : value); }, value: instance.form[key].get(), options - } + }, + currentTarget: e.currentTarget, + offsetVertical: e.currentTarget.clientHeight + 10 }; popover.open(config); } diff --git a/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-header.css b/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-header.css index b5cacef8ef19..0e0981fe07d9 100644 --- a/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-header.css +++ b/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-header.css @@ -1,5 +1,6 @@ .sidebar__header { position: relative; + display: flex; margin: 0 -10px; @@ -31,11 +32,11 @@ width: var(--sidebar-account-status-bullet-size); height: var(--sidebar-account-status-bullet-size); - border-width: 2px; + pointer-events: none; + border-width: 2px; border-style: solid; border-color: var(--sidebar-background); - border-radius: var(--sidebar-account-status-bullet-radius); &--online { @@ -77,9 +78,11 @@ &-search { position: absolute; right: calc(10px + var(--sidebar-default-padding)); - width: 200px; + display: none; + width: 200px; + & .rc-input__element { background-color: var(--sidebar-background); } diff --git a/packages/rocketchat-ui-flextab/client/flexTabBar.js b/packages/rocketchat-ui-flextab/client/flexTabBar.js index acfc43bec6dc..cc74a979a527 100644 --- a/packages/rocketchat-ui-flextab/client/flexTabBar.js +++ b/packages/rocketchat-ui-flextab/client/flexTabBar.js @@ -1,4 +1,4 @@ -/* globals popover, isRtl */ +/* globals popover */ import _ from 'underscore'; const commonHelpers = { @@ -149,22 +149,15 @@ Template.RoomsActionTab.events({ columns[0] = {groups}; const config = { columns, - // template: 'RoomsActionMore', popoverClass: 'message-box', - mousePosition: () => ({ - x: e.currentTarget.getBoundingClientRect().right + 10, - y: e.currentTarget.getBoundingClientRect().bottom + 100 - }), - customCSSProperties: () => ({ - top: `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`, - left: isRtl() ? `${ e.currentTarget.getBoundingClientRect().left - 10 }px` : undefined - }), data: { rid: this._id, buttons: instance.small.get() ? buttons : buttons.slice(4), tabBar: instance.tabBar }, - activeElement: e.currentTarget + currentTarget: e.currentTarget, + offsetHorizontal: -e.currentTarget.clientWidth, + offsetVertical: e.currentTarget.clientHeight + 10 }; popover.open(config); diff --git a/packages/rocketchat-ui-flextab/client/tabs/membersList.js b/packages/rocketchat-ui-flextab/client/tabs/membersList.js index a17fa52ddb79..21f27367f521 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/membersList.js +++ b/packages/rocketchat-ui-flextab/client/tabs/membersList.js @@ -1,4 +1,4 @@ -/* globals WebRTC popover isRtl */ +/* globals WebRTC popover */ import _ from 'underscore'; import {getActions} from './userActions'; @@ -216,20 +216,12 @@ Template.membersList.events({ e.preventDefault(); const config = { columns, - mousePosition: () => ({ - x: e.currentTarget.getBoundingClientRect().right + 10, - y: e.currentTarget.getBoundingClientRect().bottom + 100 - }), - customCSSProperties: () => ({ - top: `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`, - left: isRtl() ? `${ e.currentTarget.getBoundingClientRect().left - 10 }px` : undefined - }), data: { rid: this._id, username: instance.data.username, instance }, - activeElement: e.currentTarget, + currentTarget: e.currentTarget, onDestroyed:() => { e.currentTarget.parentElement.classList.remove('active'); } diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index 25fa6d560315..b579079733ff 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -1,4 +1,4 @@ -/* globals RoomRoles, UserRoles*/ +/* globals RoomRoles UserRoles popover */ import _ from 'underscore'; import s from 'underscore.string'; import moment from 'moment'; @@ -168,7 +168,7 @@ Template.userInfo.helpers({ return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false && user.reason; } }); -/* globals isRtl popover */ + Template.userInfo.events({ 'click .js-more'(e, instance) { const actions = more.call(this); @@ -193,20 +193,13 @@ Template.userInfo.events({ e.preventDefault(); const config = { columns, - mousePosition: () => ({ - x: e.currentTarget.getBoundingClientRect().right + 10, - y: e.currentTarget.getBoundingClientRect().bottom + 100 - }), - customCSSProperties: () => ({ - top: `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`, - left: isRtl() ? `${ e.currentTarget.getBoundingClientRect().left - 10 }px` : undefined - }), data: { rid: this._id, username: instance.data.username, instance }, - activeElement: e.currentTarget + currentTarget: e.currentTarget, + offsetVertical: e.currentTarget.clientHeight + 10 }; popover.open(config); }, diff --git a/packages/rocketchat-ui-message/client/messageBox.js b/packages/rocketchat-ui-message/client/messageBox.js index fe5fafedacb3..3f7d1e0806ad 100644 --- a/packages/rocketchat-ui-message/client/messageBox.js +++ b/packages/rocketchat-ui-message/client/messageBox.js @@ -1,4 +1,4 @@ -/* globals fileUpload KonchatNotification chatMessages popover isRtl AudioRecorder chatMessages fileUploadHandler*/ +/* globals fileUpload KonchatNotification chatMessages popover AudioRecorder chatMessages fileUploadHandler*/ import toastr from 'toastr'; import moment from 'moment'; import _ from 'underscore'; @@ -449,8 +449,6 @@ Template.messageBox.events({ }, 'click .rc-message-box__action-menu'(e) { const groups = RocketChat.messageBox.actions.get(); - const textArea = document.querySelector('.rc-message-box__textarea'); - const config = { popoverClass: 'message-box', columns: [ @@ -472,13 +470,9 @@ Template.messageBox.events({ }) } ], - mousePosition: { - x: document.querySelector('.rc-message-box__textarea').getBoundingClientRect().right + 40, - y: document.querySelector('.rc-message-box__textarea').getBoundingClientRect().top - }, - customCSSProperties: { - left: isRtl() ? `${ textArea.getBoundingClientRect().left - 10 }px` : undefined - }, + offsetVertical: 10, + direction: 'top-inverted', + currentTarget: e.currentTarget.firstElementChild.firstElementChild, data: { rid: this._id }, diff --git a/packages/rocketchat-ui-sidenav/client/sidebarHeader.js b/packages/rocketchat-ui-sidenav/client/sidebarHeader.js index 3b6900c2932c..c36dcc66abf3 100644 --- a/packages/rocketchat-ui-sidenav/client/sidebarHeader.js +++ b/packages/rocketchat-ui-sidenav/client/sidebarHeader.js @@ -105,14 +105,8 @@ const toolbarButtons = (user) => { ] } ], - mousePosition: () => ({ - x: e.currentTarget.getBoundingClientRect().left, - y: e.currentTarget.getBoundingClientRect().bottom + 50 - }), - customCSSProperties: () => ({ - top: `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`, - left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px` - }) + currentTarget: e.currentTarget, + offsetVertical: e.currentTarget.clientHeight + 10 }; popover.open(config); @@ -125,18 +119,11 @@ const toolbarButtons = (user) => { const options = []; const config = { template: 'sortlist', - mousePosition: () => ({ - x: e.currentTarget.getBoundingClientRect().left, - y: e.currentTarget.getBoundingClientRect().bottom + 50 - }), - customCSSProperties: () => ({ - top: `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`, - left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px` - }), + currentTarget: e.currentTarget, data: { - // value: instance.form[key].get(), options - } + }, + offsetVertical: e.currentTarget.clientHeight + 10 }; popover.open(config); } @@ -209,14 +196,8 @@ const toolbarButtons = (user) => { ] } ], - mousePosition: () => ({ - x: e.currentTarget.getBoundingClientRect().left, - y: e.currentTarget.getBoundingClientRect().bottom + 50 - }), - customCSSProperties: () => ({ - top: `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`, - left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px` - }) + currentTarget: e.currentTarget, + offsetVertical: e.currentTarget.clientHeight + 10 }; popover.open(config); @@ -323,14 +304,8 @@ Template.sidebarHeader.events({ ] } ], - mousePosition: () => ({ - x: e.currentTarget.getBoundingClientRect().left, - y: e.currentTarget.getBoundingClientRect().bottom + 50 - }), - customCSSProperties: () => ({ - top: `${ e.currentTarget.getBoundingClientRect().bottom + 10 }px`, - left: `${ e.currentTarget.getBoundingClientRect().left - 10 }px` - }) + currentTarget: e.currentTarget, + offsetVertical: e.currentTarget.clientHeight + 10 }; popover.open(config); diff --git a/packages/rocketchat-ui-sidenav/client/sidebarItem.js b/packages/rocketchat-ui-sidenav/client/sidebarItem.js index 24eed132bf47..86664ad00591 100644 --- a/packages/rocketchat-ui-sidenav/client/sidebarItem.js +++ b/packages/rocketchat-ui-sidenav/client/sidebarItem.js @@ -159,15 +159,13 @@ Template.sidebarItem.events({ ] } ], - mousePosition: { - x: e.clientX, - y: e.clientY - }, data: { template: this.t, rid: this.rid, name: this.name - } + }, + currentTarget: e.currentTarget, + offsetHorizontal: -e.currentTarget.clientWidth }; popover.open(config); diff --git a/packages/rocketchat-ui/client/views/app/popover.js b/packages/rocketchat-ui/client/views/app/popover.js index 1a04ec3171cb..30e2897c626c 100644 --- a/packages/rocketchat-ui/client/views/app/popover.js +++ b/packages/rocketchat-ui/client/views/app/popover.js @@ -38,40 +38,62 @@ Template.popover.onRendered(function() { popover.close(); } }); + const { offsetVertical = 0, offsetHorizontal = 0 } = this.data; const activeElement = this.data.activeElement; const popoverContent = this.firstNode.children[0]; const position = _.throttle(() => { + + const direction = typeof this.data.direction === 'function' ? this.data.direction() : this.data.direction; + + const verticalDirection = /top/.test(direction) ? 'top' : 'bottom'; + const horizontalDirection = /left/.test(direction) ? 'left' : /right/.test(direction) ? 'right' : isRtl() ^ /inverted/.test(direction) ? 'left' : 'right'; + const position = typeof this.data.position === 'function' ? this.data.position() : this.data.position; const customCSSProperties = typeof this.data.customCSSProperties === 'function' ? this.data.customCSSProperties() : this.data.customCSSProperties; - const mousePosition = typeof this.data.mousePosition === 'function' ? this.data.mousePosition() : this.data.mousePosition; + + const mousePosition = typeof this.data.mousePosition === 'function' ? this.data.mousePosition() : this.data.mousePosition || { + x: this.data.currentTarget.getBoundingClientRect()[horizontalDirection === 'left'? 'right' : 'left'], + y: this.data.currentTarget.getBoundingClientRect()[verticalDirection] + }; + const offsetWidth = offsetHorizontal * (horizontalDirection === 'left' ? 1 : -1); + const offsetHeight = offsetVertical * (verticalDirection === 'bottom' ? 1 : -1); + if (position) { popoverContent.style.top = `${ position.top }px`; popoverContent.style.left = `${ position.left }px`; } else { + const clientHeight = this.data.currentTarget.clientHeight; const popoverWidth = popoverContent.offsetWidth; const popoverHeight = popoverContent.offsetHeight; - const popoverHeightHalf = popoverHeight / 2; const windowWidth = window.innerWidth; const windowHeight = window.innerHeight; - let top; - if (mousePosition.y <= popoverHeightHalf) { - top = 10; - } else if (mousePosition.y + popoverHeightHalf > windowHeight) { - top = windowHeight - popoverHeight - 10; - } else { - top = mousePosition.y - popoverHeightHalf; + let top = mousePosition.y - clientHeight + offsetHeight; + + if (verticalDirection === 'top') { + top = mousePosition.y - popoverHeight + offsetHeight; + + if (top < 0) { + top = 10 + offsetHeight; + } + } + + if (top + popoverHeight > windowHeight) { + top = windowHeight - 10 - popoverHeight - offsetHeight; + } + + let left = mousePosition.x - popoverWidth + offsetWidth; + + if (horizontalDirection === 'right') { + left = mousePosition.x + offsetWidth; + } + + if (left + popoverWidth >= windowWidth) { + left = mousePosition.x - popoverWidth + offsetWidth; } - let left; - if (mousePosition.x + popoverWidth >= windowWidth) { - left = mousePosition.x - popoverWidth; - } else if (mousePosition.x <= popoverWidth) { - left = isRtl() ? mousePosition.x + 10 : 10; - } else if (mousePosition.x <= windowWidth / 2) { - left = mousePosition.x; - } else { - left = mousePosition.x - popoverWidth; + if (left <= 0) { + left = mousePosition.x + offsetWidth; } popoverContent.style.top = `${ top }px`; diff --git a/packages/rocketchat-ui/client/views/app/room.js b/packages/rocketchat-ui/client/views/app/room.js index 507e5ad2f8ae..0acf393a14df 100644 --- a/packages/rocketchat-ui/client/views/app/room.js +++ b/packages/rocketchat-ui/client/views/app/room.js @@ -112,10 +112,6 @@ const mountPopover = (e, i, outerContext) => { ], instance: i, data: outerContext, - mousePosition: { - x: e.clientX, - y: e.clientY - }, activeElement: $(e.currentTarget).parents('.message')[0], onRendered: () => new Clipboard('.rc-popover__item') }; @@ -582,10 +578,7 @@ Template.room.events({ ], instance: i, data: this, - mousePosition: { - x: e.clientX, - y: e.clientY - }, + currentTarget: e.currentTarget, activeElement: $(e.currentTarget).parents('.message')[0], onRendered: () => new Clipboard('.rc-popover__item') };