瀏覽代碼

Finish dir listing refactor

Steven Silvester 8 年之前
父節點
當前提交
6972f0c7c1
共有 2 個文件被更改,包括 86 次插入21 次删除
  1. 83 18
      src/filebrowser/listing.ts
  2. 3 3
      src/filebrowser/theme.css

+ 83 - 18
src/filebrowser/listing.ts

@@ -291,7 +291,8 @@ class DirListing extends Widget {
    * Sort the items using a sort condition.
    */
   sort(state: DirListing.ISortState): void {
-
+    this._sortedModels = Private.sort(this.model.items, state);
+    this.update();
   }
 
   /**
@@ -654,8 +655,9 @@ class DirListing extends Widget {
     let header = this.headerNode;
     if (header.contains(target)) {
       let state = this.renderer.handleHeaderClick(header, event);
-      this.sort(state);
-      this.update();
+      if (state) {
+        this.sort(state);
+      }
       return;
     }
 
@@ -1127,7 +1129,7 @@ class DirListing extends Widget {
     let original = item.name;
     this._editNode.value = original;
 
-    return Private.doRename(row, nameNode, this._editNode).then(newName => {
+    return Private.doRename(nameNode, this._editNode).then(newName => {
       if (newName === original) {
         return;
       }
@@ -1193,7 +1195,6 @@ class DirListing extends Widget {
     }
     // Update the sorted items.
     this.sort(this.sortState);
-    this.update();
   }
 
   /**
@@ -1365,6 +1366,43 @@ namespace DirListing {
      * @returns The sort state of the header after the click event.
      */
     handleHeaderClick(node: HTMLElement, event: MouseEvent): ISortState {
+      let name = utils.findElement(node, NAME_ID_CLASS);
+      let modified = utils.findElement(node, MODIFIED_ID_CLASS);
+      let state: ISortState = { direction: 'ascending', key: 'name' };
+      let target = event.target as HTMLElement;
+      if (name.contains(target)) {
+        if (name.classList.contains(SELECTED_CLASS)) {
+          if (!name.classList.contains(DESCENDING_CLASS)) {
+            state.direction = 'descending';
+            name.classList.add(DESCENDING_CLASS);
+          } else {
+            name.classList.remove(DESCENDING_CLASS);
+          }
+        } else {
+          name.classList.remove(DESCENDING_CLASS);
+        }
+        name.classList.add(SELECTED_CLASS);
+        modified.classList.remove(SELECTED_CLASS);
+        modified.classList.remove(DESCENDING_CLASS);
+        return state;
+      }
+      if (modified.contains(target)) {
+        state.key = 'last_modified';
+        if (modified.classList.contains(SELECTED_CLASS)) {
+          if (!modified.classList.contains(DESCENDING_CLASS)) {
+            state.direction = 'descending';
+            modified.classList.add(DESCENDING_CLASS);
+          } else {
+            modified.classList.remove(DESCENDING_CLASS);
+          }
+        } else {
+          modified.classList.remove(DESCENDING_CLASS);
+        }
+        modified.classList.add(SELECTED_CLASS);
+        name.classList.remove(SELECTED_CLASS);
+        name.classList.remove(DESCENDING_CLASS);
+        return state;
+      }
       return void 0;
     }
 
@@ -1395,20 +1433,20 @@ namespace DirListing {
      * @param model - The model object to use for the item state.
      */
     updateItemNode(node: HTMLElement, model: IContentsModel): void {
-      let icon = node.firstChild as HTMLElement;
-      let text = icon.nextSibling as HTMLElement;
-      let modified = text.nextSibling as HTMLElement;
+      let icon = utils.findElement(node, ITEM_ICON_CLASS);
+      let text = utils.findElement(node, ITEM_TEXT_CLASS);
+      let modified = utils.findElement(node, ITEM_MODIFIED_CLASS);
 
-      let type: string;
+      icon.className = ITEM_ICON_CLASS;
       switch (model.type) {
       case 'directory':
-        type = FOLDER_TYPE_CLASS;
+        icon.classList.add(FOLDER_TYPE_CLASS);
         break;
       case 'notebook':
-        type = NOTEBOOK_TYPE_CLASS;
+        icon.classList.add(NOTEBOOK_TYPE_CLASS);
         break;
       default:
-        type = FILE_TYPE_CLASS;
+        icon.classList.add(FILE_TYPE_CLASS);
         break;
       }
 
@@ -1420,7 +1458,6 @@ namespace DirListing {
         modTitle = moment(model.last_modified).format('YYYY-MM-DD HH:mm');
       }
 
-      node.className = `${ITEM_CLASS} ${type}`;
       text.textContent = model.name;
       modified.textContent = modText;
       modified.title = modTitle;
@@ -1434,11 +1471,11 @@ namespace DirListing {
      * @returns The node containing the file name.
      */
     getNameNode(node: HTMLElement): HTMLElement {
-      return void 0;
+      return utils.findElement(node, ITEM_TEXT_CLASS);
     }
 
     /**
-     * Create an appropriate drag image for an item.
+     * Create a drag image for an item.
      *
      * @param node - A node created by [[createItemNode]].
      *
@@ -1447,7 +1484,14 @@ namespace DirListing {
      * @returns An element to use as the drag image.
      */
     createDragImage(node: HTMLElement, count: number): HTMLElement {
-      return void 0;
+      let dragImage = node.cloneNode(true) as HTMLElement;
+      let modified = utils.findElement(node, ITEM_MODIFIED_CLASS);
+      dragImage.removeChild(modified as HTMLElement);
+      if (count > 1) {
+        let nameNode = utils.findElement(node, ITEM_TEXT_CLASS);
+        nameNode.textContent = '(' + count + ')';
+      }
+      return dragImage;
     }
 
     /**
@@ -1475,7 +1519,6 @@ namespace DirListing {
 }
 
 
-
 /**
  * The namespace for the listing private data.
  */
@@ -1486,8 +1529,9 @@ namespace Private {
    * @returns Boolean indicating whether the name changed.
    */
   export
-  function doRename(parent: HTMLElement, text: HTMLElement, edit: HTMLInputElement): Promise<string> {
+  function doRename(text: HTMLElement, edit: HTMLInputElement): Promise<string> {
     let changed = true;
+    let parent = text.parentElement as HTMLElement;
     parent.replaceChild(edit, text);
     edit.focus();
     let index = edit.value.lastIndexOf('.');
@@ -1520,6 +1564,27 @@ namespace Private {
     });
   }
 
+  /**
+   * Sort a list of items by sort state as a new array.
+   */
+  export
+  function sort(items: IContentsModel[], state: DirListing.ISortState) : IContentsModel[] {
+    let output = items.slice();
+    if (state.key === 'last_modified') {
+      output.sort((a, b) => {
+        let valA = new Date(a.last_modified).getTime();
+        let valB = new Date(b.last_modified).getTime();
+        return valB - valA;
+      });
+    }
+
+    // Reverse the order if descending.
+    if (state.direction === 'descending') {
+      output.reverse();
+    }
+    return output;
+  }
+
   /**
    * Scroll an element into view if needed.
    *

+ 3 - 3
src/filebrowser/theme.css

@@ -201,17 +201,17 @@
 **/
 
 
-.jp-DirListing-item.jp-type-folder .jp-DirListing-itemIcon:before {
+.jp-type-folder.jp-DirListing-itemIcon:before {
   content: "\f114";
 }
 
 
-.jp-DirListing-item.jp-type-file .jp-DirListing-itemIcon:before {
+.jp-type-file.jp-DirListing-itemIcon:before {
   content: "\f016";
 }
 
 
-.jp-DirListing-item.jp-type-notebook .jp-DirListing-itemIcon:before {
+.jp-type-notebook.jp-DirListing-itemIcon:before {
   content: "\f02d";
 }