Fix: cannot select names in hovercards in the reply dialog

Change-Id: I8756ea57f7db68d98e9ffbfb9b49474670a78b9f
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.ts b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.ts
index 7ad7223..48de78e 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.ts
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.ts
@@ -35,6 +35,26 @@
 const HIDE_CLASS = 'hide';
 
 /**
+ * ID for the container element.
+ */
+const containerId = 'gr-hovercard-container';
+
+export function getHovercardContainer(
+  options: {createIfNotExists: boolean} = {createIfNotExists: false}
+): HTMLElement | null {
+  let container = getRootElement().querySelector<HTMLElement>(
+    `#${containerId}`
+  );
+  if (!container && options.createIfNotExists) {
+    // If it does not exist, create and initialize the hovercard container.
+    container = document.createElement('div');
+    container.setAttribute('id', containerId);
+    getRootElement().appendChild(container);
+  }
+  return container;
+}
+
+/**
  * How long should we wait before showing the hovercard when the user hovers
  * over the element?
  */
@@ -99,12 +119,6 @@
       @property({type: Object})
       container: HTMLElement | null = null;
 
-      /**
-       * ID for the container element.
-       */
-      @property({type: String})
-      containerId = 'gr-hovercard-container';
-
       private hideTask?: DelayedTask;
 
       private showTask?: DelayedTask;
@@ -147,16 +161,7 @@
       ready() {
         super.ready();
         // First, check to see if the container has already been created.
-        this.container = getRootElement().querySelector('#' + this.containerId);
-
-        if (this.container) {
-          return;
-        }
-
-        // If it does not exist, create and initialize the hovercard container.
-        this.container = document.createElement('div');
-        this.container.setAttribute('id', this.containerId);
-        getRootElement().appendChild(this.container);
+        this.container = getHovercardContainer({createIfNotExists: true});
       }
 
       removeListeners() {
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
index 100d5cc..2c48ec0f 100644
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
@@ -22,6 +22,7 @@
 import {IronOverlayBehavior} from '@polymer/iron-overlay-behavior/iron-overlay-behavior';
 import {findActiveElement} from '../../../utils/dom-util';
 import {fireEvent} from '../../../utils/event-util';
+import {getHovercardContainer} from '../gr-hovercard/gr-hovercard-behavior';
 
 const AWAIT_MAX_ITERS = 10;
 const AWAIT_STEP = 5;
@@ -118,6 +119,20 @@
     }
   }
 
+  _onCaptureFocus(e: Event) {
+    const hovercardContainer = getHovercardContainer();
+    if (hovercardContainer) {
+      // Hovercard container is not a child of an overlay.
+      // When an overlay is opened and a user clicks inside hovercard,
+      // the IronOverlayBehavior doesn't allow to set focus inside a hovercard.
+      // As a result, user can't select a text (username) in the hovercard
+      // in a dialog. We should skip default _onCaptureFocus for hovercards.
+      const path = e.composedPath();
+      if (path.indexOf(hovercardContainer) >= 0) return;
+    }
+    super._onCaptureFocus(e);
+  }
+
   /**
    * Override the focus stops that iron-overlay-behavior tries to find.
    */