Переглянути джерело

Merge pull request #2703 from afshin/issues/2702

Bug fix: when a notebook's tooltip is dismissed, the prompt loses focus.
Steven Silvester 7 роки тому
батько
коміт
510bf9a967

+ 21 - 1
packages/shortcuts-extension/schema/jupyter.extensions.shortcuts.json

@@ -288,7 +288,9 @@
       "properties": {
         "command": { "default": "notebook:enter-command-mode" },
         "keys": { "default": ["Escape"] },
-        "selector": { "default": ".jp-Notebook.jp-mod-editMode" }
+        "selector": {
+          "default": ".jp-Notebook.jp-mod-editMode"
+        }
       },
       "type": "object"
     },
@@ -544,6 +546,24 @@
       },
       "type": "object"
     },
+    "tooltip:dismiss-console": {
+      "default": { },
+      "properties": {
+        "command": { "default": "tooltip:dismiss" },
+        "keys": { "default": ["Escape"] },
+        "selector": { "default": "body.jp-mod-tooltip .jp-CodeConsole" }
+      },
+      "type": "object"
+    },
+    "tooltip:dismiss-notebook": {
+      "default": { },
+      "properties": {
+        "command": { "default": "tooltip:dismiss" },
+        "keys": { "default": ["Escape"] },
+        "selector": { "default": "body.jp-mod-tooltip .jp-Notebook" }
+      },
+      "type": "object"
+    },
     "tooltip:launch-console": {
       "default": { },
       "properties": {

+ 14 - 1
packages/tooltip-extension/src/index.ts

@@ -42,6 +42,9 @@ import {
  * The command IDs used by the tooltip plugin.
  */
 namespace CommandIDs {
+  export
+  const dismiss = 'tooltip:dismiss';
+
   export
   const launchConsole = 'tooltip:launch-console';
 
@@ -60,6 +63,17 @@ const service: JupyterLabPlugin<ITooltipManager> = {
   provides: ITooltipManager,
   activate: (app: JupyterLab): ITooltipManager => {
     let tooltip: Tooltip | null = null;
+
+    // Add tooltip dismiss command.
+    app.commands.addCommand(CommandIDs.dismiss, {
+      execute: () => {
+        if (tooltip) {
+          tooltip.dispose();
+          tooltip = null;
+        }
+      }
+    });
+
     return {
       invoke(options: ITooltipManager.IOptions): Promise<void> {
         const detail: 0 | 1 = 0;
@@ -141,7 +155,6 @@ const notebookPlugin: JupyterLabPlugin<void> = {
         }
       }
     });
-
   }
 };
 

+ 17 - 18
packages/tooltip/src/widget.ts

@@ -36,9 +36,9 @@ import {
 const TOOLTIP_CLASS = 'jp-Tooltip';
 
 /**
- * The class added to widgets that have spawned a tooltip and anchor it.
+ * The class added to the body when a tooltip exists on the page.
  */
-const ANCHOR_CLASS = 'jp-Tooltip-anchor';
+const BODY_CLASS = 'jp-mod-tooltip';
 
 /**
  * The minimum height of a tooltip widget.
@@ -66,21 +66,20 @@ class Tooltip extends Widget {
   constructor(options: Tooltip.IOptions) {
     super();
 
-    let layout = this.layout = new PanelLayout();
-    this.anchor = options.anchor;
+    const layout = this.layout = new PanelLayout();
+    const model = new MimeModel({ data: options.bundle });
 
+    this.anchor = options.anchor;
     this.addClass(TOOLTIP_CLASS);
-    this.anchor.addClass(ANCHOR_CLASS);
-
     this._editor = options.editor;
     this._rendermime = options.rendermime;
-    let model = new MimeModel({
-      data: options.bundle
-    });
-    let mimeType = this._rendermime.preferredMimeType(options.bundle, false);
+
+    const mimeType = this._rendermime.preferredMimeType(options.bundle, false);
+
     if (!mimeType) {
       return;
     }
+
     this._content = this._rendermime.createRenderer(mimeType);
     this._content.renderModel(model);
     layout.addWidget(this._content);
@@ -95,9 +94,6 @@ class Tooltip extends Widget {
    * Dispose of the resources held by the widget.
    */
   dispose(): void {
-    if (this.anchor && !this.anchor.isDisposed) {
-      this.anchor.removeClass(ANCHOR_CLASS);
-    }
     if (this._content) {
       this._content.dispose();
       this._content = null;
@@ -119,18 +115,19 @@ class Tooltip extends Widget {
     if (this.isHidden || this.isDisposed) {
       return;
     }
+
+    const { node } = this;
+    const target = event.target as HTMLElement;
+
     switch (event.type) {
     case 'keydown':
-      if (this.node.contains(event.target as HTMLElement)) {
-        if ((event as KeyboardEvent).keyCode === 27) { // Escape key
-          this.dispose();
-        }
+      if (node.contains(target)) {
         return;
       }
       this.dispose();
       break;
     case 'mousedown':
-      if (this.node.contains(event.target as HTMLElement)) {
+      if (node.contains(target)) {
         this.activate();
         return;
       }
@@ -156,6 +153,7 @@ class Tooltip extends Widget {
    * Handle `'after-attach'` messages.
    */
   protected onAfterAttach(msg: Message): void {
+    document.body.classList.add(BODY_CLASS);
     document.addEventListener('keydown', this, USE_CAPTURE);
     document.addEventListener('mousedown', this, USE_CAPTURE);
     this.anchor.node.addEventListener('scroll', this, USE_CAPTURE);
@@ -166,6 +164,7 @@ class Tooltip extends Widget {
    * Handle `before-detach` messages for the widget.
    */
   protected onBeforeDetach(msg: Message): void {
+    document.body.classList.remove(BODY_CLASS);
     document.removeEventListener('keydown', this, USE_CAPTURE);
     document.removeEventListener('mousedown', this, USE_CAPTURE);
     this.anchor.node.removeEventListener('scroll', this, USE_CAPTURE);