Selaa lähdekoodia

More refactoring of CSVWidget, work in progress.

Afshin Darian 8 vuotta sitten
vanhempi
commit
e2d4b1b377
2 muutettua tiedostoa jossa 116 lisäystä ja 198 poistoa
  1. 1 1
      src/csvwidget/index.css
  2. 115 197
      src/csvwidget/widget.ts

+ 1 - 1
src/csvwidget/index.css

@@ -35,7 +35,7 @@
     background: transparent;
 }
 
-.jp-CSVWidget-toolbar .jp-CSVWidget-toolbarDropdown {
+.jp-CSVToolbar .jp-CSVToolbar-dropdown {
     flex: 0 0 auto;
     padding-left: 8px;
     padding-right: 8px;

+ 115 - 197
src/csvwidget/widget.ts

@@ -1,227 +1,145 @@
-// Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
+  // Copyright (c) Jupyter Development Team.
+  // Distributed under the terms of the Modified BSD License.
 
-import * as d3Dsv from 'd3-dsv';
+  import {
+    Message
+  } from 'phosphor/lib/core/messaging';
 
-import {
-  Message
-} from 'phosphor/lib/core/messaging';
+  import {
+    PanelLayout
+  } from 'phosphor/lib/ui/panel';
 
-import {
-  PanelLayout
-} from 'phosphor/lib/ui/panel';
+  import {
+    Widget
+  } from 'phosphor/lib/ui/widget';
 
-import {
-  Widget
-} from 'phosphor/lib/ui/widget';
+  import {
+    ABCWidgetFactory, DocumentRegistry
+  } from '../docregistry';
 
-import {
-  ABCWidgetFactory, DocumentRegistry
-} from '../docregistry';
+  import {
+    CSVModel, CSVTable
+  } from './table';
 
-import {
-  CSVTable
-} from './table';
+  import {
+    CSVToolbar
+  } from './toolbar';
 
 
-/**
- * The class name added to a csv widget.
- */
-const CSV_CLASS = 'jp-CSVWidget';
-
-/**
- * The class name added to a csv toolbar widget.
- */
-const CSV_TOOLBAR_CLASS = 'jp-CSVWidget-toolbar';
-
-/**
- * The class name added to a csv toolbar's dropdown element.
- */
-const CSV_TOOLBAR_DROPDOWN_CLASS = 'jp-CSVWidget-toolbarDropdown';
-
-/**
- * The class name added to a csv warning widget.
- */
-const CSV_WARNING_CLASS = 'jp-CSVWidget-warning';
-
-/**
- * The hard limit on the number of rows to display.
- */
-const DISPLAY_LIMIT = 1000;
-
-
-/**
- * A widget for csv tables.
- */
-export
-class CSVWidget extends Widget {
   /**
-   * Construct a new csv table widget.
+   * The class name added to a csv widget.
    */
-  constructor(context: DocumentRegistry.IContext<DocumentRegistry.IModel>) {
-    super();
-    this._context = context;
-    this.addClass(CSV_CLASS);
-
-    this.layout = new PanelLayout();
-    this._toolbar = new Widget({ node: createDelimiterSwitcherNode() });
-    this._toolbar.addClass(CSV_TOOLBAR_CLASS);
-    this._table = new CSVTable();
-    this._warning = new Widget();
-    this._warning.addClass(CSV_WARNING_CLASS);
-
-    let layout = this.layout as PanelLayout;
-    layout.addWidget(this._toolbar);
-    layout.addWidget(this._table);
-    layout.addWidget(this._warning);
-
-    let select = this._toolbar.node.getElementsByClassName(
-      CSV_TOOLBAR_DROPDOWN_CLASS)[0] as HTMLSelectElement;
-
-    if (context.model.toString()) {
-      this.update();
-    }
-    context.pathChanged.connect(this.update, this);
-    context.model.contentChanged.connect(this.update, this);
-    context.fileChanged.connect(this.update, this);
-
-    // Change delimiter on a change in the dropdown.
-    select.addEventListener('change', event => {
-      this.delimiter = select.value;
-      this.update();
-    });
-  }
+  const CSV_CLASS = 'jp-CSVWidget';
 
   /**
-   * Dispose of the resources used by the widget.
+   * The class name added to a csv warning widget.
    */
-  dispose(): void {
-    if (this.isDisposed) {
-      return;
-    }
-    this._context = null;
-    super.dispose();
-  }
+  const CSV_WARNING_CLASS = 'jp-CSVWidget-warning';
 
-  /**
-   * Handle `update-request` messages for the widget.
-   */
-  protected onUpdateRequest(msg: Message): void {
-    this.title.label = this._context.path.split('/').pop();
-    let cm = this._context.contentsModel;
-    if (cm === null) {
-      return;
-    }
-    let content = this._context.model.toString();
-    let delimiter = this.delimiter as string;
-    this.renderTable(content, delimiter);
-  }
 
   /**
-   * Render an html table from a csv string.
+   * A widget for csv tables.
    */
-  renderTable(content: string, delimiter: string) {
-    let parsed = d3Dsv.dsvFormat(delimiter).parse(content);
-    let table = document.createElement('table');
-    let header = document.createElement('thead');
-    let body = document.createElement('tbody');
-    for (let name of parsed.columns) {
-      let th = document.createElement('th');
-      th.textContent = name;
-      header.appendChild(th);
+  export
+  class CSVWidget extends Widget {
+    /**
+     * Construct a new csv table widget.
+     */
+    constructor(context: DocumentRegistry.IContext<DocumentRegistry.IModel>) {
+      super();
+      this._context = context;
+      this.addClass(CSV_CLASS);
+
+      this.layout = new PanelLayout();
+
+      this._table = new CSVTable();
+      this._table.model = new CSVModel({ content: context.model.toString() });
+
+      this._toolbar = new CSVToolbar();
+      this._toolbar.delimiterChanged.connect((sender, delimiter) => {
+        this._table.model.delimiter = delimiter;
+      });
+
+      this._warning = new Widget();
+      this._warning.addClass(CSV_WARNING_CLASS);
+
+      let layout = this.layout as PanelLayout;
+      layout.addWidget(this._toolbar);
+      layout.addWidget(this._table);
+      layout.addWidget(this._warning);
+
+      context.pathChanged.connect(this.update, this);
+      context.model.contentChanged.connect(() => {
+        this._table.model.content = context.model.toString();
+      });
     }
-    for (let row of parsed.slice(0, DISPLAY_LIMIT)) {
-      let tr = document.createElement('tr');
-      for (let col of parsed.columns) {
-        let td = document.createElement('td');
-        td.textContent = row[col];
-        tr.appendChild(td);
+
+    /**
+     * Dispose of the resources used by the widget.
+     */
+    dispose(): void {
+      if (this.isDisposed) {
+        return;
       }
-      body.appendChild(tr);
+      super.dispose();
+      this._table.model.dispose();
+      this._table.dispose();
+      this._toolbar.dispose();
+      this._warning.dispose();
+      this._context = null;
     }
-    let msg =  `Table is too long to render, rendering ${DISPLAY_LIMIT} of ` +
-               `${parsed.length} rows`;
-    if (parsed.length > DISPLAY_LIMIT) {
-      this._warning.node.textContent = msg;
-    } else {
-      this._warning.node.textContent = '';
-    }
-    table.appendChild(header);
-    table.appendChild(body);
-    this._table.node.textContent = '';
-    this._table.node.appendChild(table);
-  }
 
-  /**
-   * Handle `'activate-request'` messages.
-   */
-  protected onActivateRequest(msg: Message): void {
-    this.node.focus();
-  }
+    /**
+     * Handle `update-request` messages for the widget.
+     */
+    protected onUpdateRequest(msg: Message): void {
+      this.title.label = this._context.path.split('/').pop();
+    }
 
-  private _context: DocumentRegistry.IContext<DocumentRegistry.IModel>;
-  private delimiter: string = ',';
-  private _toolbar: Widget = null;
-  private _table: Widget = null;
-  private _warning: Widget = null;
-}
-
-
-/**
- * Create the node for the delimiter switcher.
- */
-function createDelimiterSwitcherNode(): HTMLElement {
-  let div = document.createElement('div');
-  let label = document.createElement('span');
-  label.textContent = 'Delimiter:';
-  let select = document.createElement('select');
-  for (let delim of [',', ';', '\t']) {
-    let option = document.createElement('option');
-    option.value = delim;
-    if (delim === '\t') {
-      option.textContent = '\\t';
-    } else {
-      option.textContent = delim;
+    /**
+     * Handle `'activate-request'` messages.
+     */
+    protected onActivateRequest(msg: Message): void {
+      this.node.focus();
     }
-    select.appendChild(option);
-  }
-  select.className = CSV_TOOLBAR_DROPDOWN_CLASS;
-  div.appendChild(label);
-  div.appendChild(select);
-  return div;
-}
-
-
-/**
- * A widget factory for csv tables.
- */
-export
-class CSVWidgetFactory extends ABCWidgetFactory<CSVWidget, DocumentRegistry.IModel> {
-  /**
-   * The name of the widget to display in dialogs.
-   */
-  get name(): string {
-    return 'Table';
-  }
 
-  /**
-   * The file extensions the widget can view.
-   */
-  get fileExtensions(): string[] {
-    return ['.csv'];
+    private _context: DocumentRegistry.IContext<DocumentRegistry.IModel>;
+    private _toolbar: CSVToolbar = null;
+    private _table: CSVTable = null;
+    private _warning: Widget = null;
   }
 
-  /**
-   * The file extensions for which the factory should be the default.
-   */
-  get defaultFor(): string[] {
-    return ['.csv'];
-  }
 
   /**
-   * Create a new widget given a context.
+   * A widget factory for csv tables.
    */
-  protected createNewWidget(context: DocumentRegistry.IContext<DocumentRegistry.IModel>): CSVWidget {
-    return new CSVWidget(context);
+  export
+  class CSVWidgetFactory extends ABCWidgetFactory<CSVWidget, DocumentRegistry.IModel> {
+    /**
+     * The name of the widget to display in dialogs.
+     */
+    get name(): string {
+      return 'Table';
+    }
+
+    /**
+     * The file extensions the widget can view.
+     */
+    get fileExtensions(): string[] {
+      return ['.csv'];
+    }
+
+    /**
+     * The file extensions for which the factory should be the default.
+     */
+    get defaultFor(): string[] {
+      return ['.csv'];
+    }
+
+    /**
+     * Create a new widget given a context.
+     */
+    protected createNewWidget(context: DocumentRegistry.IContext<DocumentRegistry.IModel>): CSVWidget {
+      return new CSVWidget(context);
+    }
   }
-}