@@ -6,7 +6,6 @@ let currentRowData = null;
66
77( function  ( )  { 
88
9-     var  table  =   /** @type  {HTMLElement } */  ( document . getElementById ( "resource-table" ) ) ; 
109    var  addNewButton  =  document . getElementById ( "add-resource-button" ) ; 
1110
1211    addNewButton . onclick  =  ( )  =>  { 
@@ -15,58 +14,95 @@ let currentRowData = null;
1514        } ) ; 
1615    } ; 
1716
17+     const  grid  =  document . getElementById ( "resource-table" ) ; 
18+     initEditableDataGrid ( ) ; 
1819
19-     table . onclick  =  cellClick ; 
20-     table . oncontextmenu  =  cellRightClick ; 
21- 
22-     function  cellRightClick ( cell )  { 
23-         const  sourceElement  =  cell . target ; 
24-         currentRowData  =  sourceElement . _rowData ; 
25-     } 
26- 
27-     function  cellClick ( cell )  { 
28-         const  sourceElement  =  cell . target ; 
29-         currentRowData  =  sourceElement . _rowData ; 
30- 
31-         if  ( sourceElement  &&  sourceElement . className  !==  "column-header" )  { 
20+     function  initEditableDataGrid ( )  { 
21+         grid . oncontextmenu  =  cellRightClick ; 
22+         grid ?. addEventListener ( "cell-focused" ,  ( e )  =>  { 
23+             const  cell  =  e . target ; 
24+             // Do not continue if `cell` is undefined/null or is not a grid cell 
25+             if  ( ! cell  ||  cell . role  !==  "gridcell" )  { 
26+                 return ; 
27+             } 
28+             // Do not allow data grid header cells to be editable 
29+             if  ( cell . className  ===  "column-header" )  { 
30+                 return ; 
31+             } 
3232
33-             const  handleChange  =  ( target )  =>  { 
34-                 const  column  =  target . _columnDefinition ; 
35-                 const  originalRow  =  target . _rowData ; 
36-                 const  originalValue  =  originalRow [ column . columnDataKey ] ; 
37-                 const  newValue  =  target . innerText ; 
33+             // Note: Need named closures in order to later use removeEventListener 
34+             // in the handleBlurClosure function 
35+             const  handleKeydownClosure  =  ( e )  =>  { 
36+                 handleKeydown ( e ,  cell ) ; 
37+             } ; 
38+             const  handleClickClosure  =  ( )  =>  { 
39+                 setCellEditable ( cell ) ; 
40+             } ; 
41+             const  handleBlurClosure  =  ( )  =>  { 
42+                 syncCellChanges ( cell ) ; 
43+                 unsetCellEditable ( cell ) ; 
44+                 // Remove the blur, keydown, and click event listener _only after_ 
45+                 // the cell is no longer focused 
46+                 cell . removeEventListener ( "blur" ,  handleBlurClosure ) ; 
47+                 cell . removeEventListener ( "keydown" ,  handleKeydownClosure ) ; 
48+                 cell . removeEventListener ( "click" ,  handleClickClosure ) ; 
49+             } ; 
3850
51+             cell . addEventListener ( "keydown" ,  handleKeydownClosure ) ; 
52+             cell . addEventListener ( "click" ,  handleClickClosure ) ; 
53+             cell . addEventListener ( "blur" ,  handleBlurClosure ) ; 
54+         } ) ; 
55+     } 
3956
40-                 if  ( originalValue  !==  newValue )  { 
41-                     sendLog ( "Value changed...Original value: "  +  originalValue  +  "; "  +  "New value: "  +  newValue ) ; 
42-                     target . _rowData [ column . columnDataKey ]  =  newValue ; 
43-                     refreshResxData ( ) ; 
44-                 } 
57+     // Handle keyboard events on a given cell 
58+     function  handleKeydown ( e ,  cell )  { 
59+         if  ( ! cell . hasAttribute ( "contenteditable" )  ||  cell . getAttribute ( "contenteditable" )  ===  "false" )  { 
60+             if  ( e . key  ===  "Enter" )  { 
61+                 e . preventDefault ( ) ; 
62+                 setCellEditable ( cell ) ; 
63+             } 
64+         }  else  { 
65+             if  ( e . key  ===  "Enter"  ||  e . key  ===  "Escape" )  { 
66+                 e . preventDefault ( ) ; 
67+                 syncCellChanges ( cell ) ; 
68+                 unsetCellEditable ( cell ) ; 
69+             } 
70+         } 
71+     } 
4572
46-                 sourceElement . setAttribute ( "contenteditable" ,  false ) ; 
73+     // Make a given cell editable 
74+     function  setCellEditable ( cell )  { 
75+         cell . setAttribute ( "contenteditable" ,  "true" ) ; 
76+     } 
4777
48-                 sourceElement . onkeydown  =  undefined ; 
49-                 sourceElement . onblur  =  undefined ; 
50-             } ; 
78+     // Make a given cell non-editable 
79+     function  unsetCellEditable ( cell )  { 
80+         cell . setAttribute ( "contenteditable" ,  "false" ) ; 
81+     } 
5182
52-             sourceElement . onkeydown  =  ( event )  =>  { 
53-                 if  ( event . code  ===  "Enter" )  { 
54-                     event . preventDefault ( ) ; 
55-                     handleChange ( event . target ) ; 
56-                     return  false ; 
57-                 } 
58-             } ; 
83+     // Syncs changes made in an editable cell with the 
84+     // underlying data structure of a vscode-data-grid 
85+     function  syncCellChanges ( cell )  { 
86+         const  column  =  cell . columnDefinition ; 
87+         const  row  =  cell . rowData ; 
5988
60-             sourceElement . onblur  =  ( event )  =>  { 
61-                 event . preventDefault ( ) ; 
62-                 handleChange ( event . target ) ; 
63-                 return  false ; 
64-             } ; 
89+         if  ( column  &&  row )  { 
90+             const  originalValue  =  row [ column . columnDataKey ] ; 
91+             const  newValue  =  cell . innerText ; 
6592
66-             sourceElement . setAttribute ( "contenteditable" ,  true ) ; 
93+             if  ( originalValue  !==  newValue )  { 
94+                 row [ column . columnDataKey ]  =  newValue ; 
95+                 sendLog ( "Value changed...Original value: "  +  originalValue  +  "; "  +  "New value: "  +  newValue ) ; 
96+                 refreshResxData ( ) ; 
97+             } 
6798        } 
6899    } 
69100
101+     function  cellRightClick ( cell )  { 
102+         const  sourceElement  =  cell . target ; 
103+         currentRowData  =  sourceElement . _rowData ; 
104+     } 
105+ 
70106    window . addEventListener ( 'message' ,  event  =>  { 
71107        const  message  =  event . data ; 
72108        switch  ( message . type )  { 
@@ -82,9 +118,9 @@ let currentRowData = null;
82118            case  'delete' :
83119                sendLog ( "Deleting row: "  +  JSON . stringify ( currentRowData ) ) ; 
84120                if  ( currentRowData )  { 
85-                     const  index  =  table . rowsData . indexOf ( currentRowData ) ; 
121+                     const  index  =  grid . rowsData . indexOf ( currentRowData ) ; 
86122                    if  ( index  >  - 1 )  { 
87-                         table . rowsData . splice ( index ,  1 ) ; 
123+                         grid . rowsData . splice ( index ,  1 ) ; 
88124                        refreshResxData ( ) ; 
89125                    } 
90126                } 
@@ -98,10 +134,10 @@ let currentRowData = null;
98134            case  'add' :
99135                sendLog ( `Adding new resource: Key: ${ message . key }  , Value: ${ message . value }  , Comment: ${ message . comment }  ` ) ; 
100136                if  ( message . key )  { 
101-                     const  index  =  table . rowsData . findIndex ( x  =>  x . Key  ===  message . key ) ; 
137+                     const  index  =  grid . rowsData . findIndex ( x  =>  x . Key  ===  message . key ) ; 
102138                    if  ( index  ===  - 1 )  { 
103139                        // eslint-disable-next-line @typescript-eslint/naming-convention 
104-                         table . rowsData . push ( {  Key : message . key ,  Value : message . value ,  Comment : message . comment  } ) ; 
140+                         grid . rowsData . push ( {  Key : message . key ,  Value : message . value ,  Comment : message . comment  } ) ; 
105141                        refreshResxData ( ) ; 
106142                    } 
107143                    else  { 
@@ -118,10 +154,10 @@ let currentRowData = null;
118154
119155    function  refreshResxData ( )  { 
120156        var  obj  =  { } ; 
121-         for  ( var  i  =  0 ;  i  <  table . rowsData . length ;  i ++ )  { 
122-             var  key  =  table . rowsData [ i ] . Key ; 
123-             var  value  =  table . rowsData [ i ] . Value ; 
124-             var  comment  =  table . rowsData [ i ] . Comment ; 
157+         for  ( var  i  =  0 ;  i  <  grid . rowsData . length ;  i ++ )  { 
158+             var  key  =  grid . rowsData [ i ] . Key ; 
159+             var  value  =  grid . rowsData [ i ] . Value ; 
160+             var  comment  =  grid . rowsData [ i ] . Comment ; 
125161            obj [ key ]  =  {  value : value ,  comment : comment  } ; 
126162        } 
127163
@@ -166,7 +202,7 @@ let currentRowData = null;
166202                } 
167203            } 
168204
169-             table . rowsData  =  resxValues ; 
205+             grid . rowsData  =  resxValues ; 
170206        } 
171207        else  { 
172208            console . log ( "text is null" ) ; 
0 commit comments