|
| 1 | +# Edit and CellNav, Focus in the Grid |
| 2 | + |
| 3 | +Both edit and cellNav provide ways to focus particular cells in the grid. This, and the associated |
| 4 | +`editOnFocus` option have been a source of pain, but they are also (unfortunately) a very desirable |
| 5 | +feature that we'd like to have working smoothly. |
| 6 | + |
| 7 | +The current implementation is inspired by the google sheets implementation. A key feature is that |
| 8 | +the focus is held by the viewport, not by the individual cells, and focus is "faked" through use of |
| 9 | +css classes and directing keypresses to particular elements. |
| 10 | + |
| 11 | +<< @swalters: is this only true for cellNav, or is it also true for edit? It seems that edit must |
| 12 | +be receiving focus or else some of the custom editors just wouldn't work >> |
| 13 | + |
| 14 | +We continue to have difficulties with the interaction of these two modules, and with the behaviour |
| 15 | +upon events such as scrolling, scrolling that is triggered by typing (for a part-visible cell), |
| 16 | +`editOnFocus` and whether it works reliably. |
| 17 | + |
| 18 | +This overview aims to document what we think our business features are, and then describe a framework |
| 19 | +that we could move to that would make the logic cleaner and therefore easier to fix defects in. |
| 20 | + |
| 21 | +## CellNav |
| 22 | + |
| 23 | +The intention of cellNav is that a user can select a cell, and then use the keyboard to move around |
| 24 | +the grid. When the focus is given to a particular cell the grid should attempt to scroll to make that |
| 25 | +cell fully visible (if it's not already fully visible). If the cell is too tall or too wide to be |
| 26 | +fully visible, then the grid should show as much of the cell as possible whilst keeping the top left |
| 27 | +corner fully visible. |
| 28 | + |
| 29 | +Keyboard actions that should move the focused cell are: |
| 30 | + - 4 arrow keys |
| 31 | + - pg up, pg down (move a page at a time) |
| 32 | + - enter (moves down) |
| 33 | + - shift+enter (moves up) |
| 34 | + - tab (moves right) |
| 35 | + - shift+tab (moves left) |
| 36 | + |
| 37 | +Where a navigation hits the edge of the grid, the navigation should "wrap around". If we move off |
| 38 | +a row to the right, we should come back on 1 row down, in the leftmost focusable cell. If we move |
| 39 | +off a row to the left, we should come back 1 row up, in the rightmost focusable cell. Similarly for |
| 40 | +moving up and down - if we hit enter till we get to the bottom of the grid, we should re-enter at the |
| 41 | +top. |
| 42 | + |
| 43 | +There are two exceptions to this behaviour. When we exit the top left focusable cell, we should shift focus |
| 44 | +off the grid entirely, to the previous widget on the page. When we exit the bottom right focusable cell, we should |
| 45 | +shift focus to the next widget on the page. |
| 46 | + |
| 47 | +When we tab into the grid from another widget on the page, we should select the top left or bottom right |
| 48 | +focusable cell. |
| 49 | + |
| 50 | +When we scroll we should remember which cell had focus. If that cell remains visible then we should highlight |
| 51 | +it as having the focus. If that cell scrolls off the page then we should remember it, and highlight it again |
| 52 | +when it comes visible. |
| 53 | + |
| 54 | +A source of contention is that when we give a cell focus, we attempt to make it visible. When a user manually |
| 55 | +scrolls we reset the focus to the correct cell, but we don't want to automatically scroll to make it visible - this |
| 56 | +will give jankiness to our scrolling as the focused cell moves off the page. |
| 57 | + |
| 58 | +Another contention is that as we tab across a row we sometimes get scroll up and down for some reason to do with |
| 59 | +native browser behaviour. |
| 60 | + |
| 61 | + |
| 62 | +## Edit |
| 63 | + |
| 64 | +Edit works by noticing that a cell has entered edit mode, and replacing the cell contents with the specified editor. |
| 65 | +The editor will raise events for start_edit, end_edit and cancel_edit. Upon end or cancel the edit feature will |
| 66 | +remove the editor and replace it with the normal cell template. |
| 67 | + |
| 68 | +`editOnFocus` is a feature that works like a spreadsheet - when you enter a cell the editor is displayed and the |
| 69 | +cell is immediately editable. |
| 70 | + |
| 71 | +Upon a cell becoming editable we should attempt to scroll it so that it is fully visible, and as with cellNav if we |
| 72 | +cannot make it fully visible we should do as good a job as we can whilst keeping the top left corner visible. |
| 73 | + |
| 74 | +Editors often have default navigation actions. For example, in an input box if you use the arrow keys to go to the |
| 75 | +edge of the field and then off, it will shift focus to the next field. This is effectively a cellNav. |
| 76 | + |
| 77 | +Our different editors have slightly different desired default behaviours. |
| 78 | + |
| 79 | +### Input |
| 80 | + |
| 81 | +Upon an input field receiving focus all the text in that field should be automatically selected, the cell should |
| 82 | +be scrolled so far as possible to make the field fully visible. The arrow keys when pressed should remove the highlight |
| 83 | +of all text, and move around within the field. They should not exit the field when they reach the end. |
| 84 | + |
| 85 | +Enter, shift+enter, tab, shift+tab should end editing, and should trigger a cellNav. Perhaps these should still be |
| 86 | +trapped by cellNav itself, and not by edit? Is this possible with standard html5 widgets? |
| 87 | + |
| 88 | +## Date |
| 89 | + |
| 90 | +Ideally this would one day be a proper date picker. Anyway, up and down arrow keys should adjust the current |
| 91 | +date element we're on (the year, month or day), left and right arrow keys should select the next date part in that |
| 92 | +direction. They should not take us off the field to the left or right. |
| 93 | + |
| 94 | +Enter, shift+enter, tab, shift+tab should end editing, and should trigger a cellNav. Perhaps these should still be |
| 95 | +trapped by cellNav itself, and not by edit? Is this possible with standard html5 widgets? |
| 96 | + |
| 97 | +## Dropdown |
| 98 | + |
| 99 | +Starting edit should drop down the dropdown. Up and down arrows should move the selection. Left and right |
| 100 | +arrows should move the selection the same as up and down. |
| 101 | + |
| 102 | +Enter, shift+enter, tab, shift+tab should end editing, and should trigger a cellNav. Perhaps these should still be |
| 103 | +trapped by cellNav itself, and not by edit? Is this possible with standard html5 widgets? |
| 104 | + |
| 105 | +## Custom editors |
| 106 | + |
| 107 | +In general custom editors should follow the pattern of only triggering a cellNav on Enter, shift+enter, tab, shift+tab, |
| 108 | +this also means that custom editors should not use these keys for anything else. |
| 109 | + |
| 110 | +## Deep edit |
| 111 | + |
| 112 | +I can't remember why this is a good idea. It seems that the semantics of the input field work fine without a deep edit |
| 113 | +concept. I think it's more that when an editable field gets focus but hasn't yet entered edit mode, we still let the |
| 114 | +left/right work with cellNav. So maybe deep edit is sort of a halfway house of `editOnFocus` that we don't really need? |
| 115 | + |
| 116 | +## Edit On Focus |
| 117 | + |
| 118 | +Edit on focus should work that whenever a cell gets focus we should immediately enter edit mode. Otherwise the |
| 119 | +behaviour should remain the same. |
| 120 | + |
| 121 | +## Problems |
| 122 | + |
| 123 | +Edit has a number of points of contention with cellNav, and the interoperation of the two is problematic (but also |
| 124 | +essential). Areas of conflict are: |
| 125 | + |
| 126 | +- when you're typing in a cell you can trigger a scroll if the cell isn't fully visible. The scroll may change |
| 127 | + which DOM elements are what, and therefore which DOM element it is that we're editing in. The upshot is that |
| 128 | + we tend to lose focus on the editor, and then gain focus again. When we gain focus again we're sometimes not |
| 129 | + where we used to be - for example on the input field we may select all the text rather than returning our cursor |
| 130 | + to where it was. These are usability issues for a user who is typing in the field |
| 131 | + |
| 132 | +- some editors propagate events to the parent object, for example the standard input seems to propagate a right |
| 133 | + arrow key at the end of the field to the parent, which in turn causes a cellNav. This isn't our desired |
| 134 | + behaviour |
| 135 | + |
| 136 | +- if the user scrolls whilst a field is in edit mode we sometimes get unusual behaviour. Really we want it to work |
| 137 | + similarly to if a scroll happened whilst editing a field - we want our position in the editor at the end of the scroll |
| 138 | + to be the same as at the start, unless our field has gone off page, in which case we want to end edit mode |
| 139 | + |
| 140 | +- edit on focus is hard because when a cell gets focus we start edit. Starting edit then attempts to select all the |
| 141 | + text, and scroll so we're visible, which makes a mess |
| 142 | + |
| 143 | +## Design thoughts |
| 144 | + |
| 145 | +Can we agree that tab, shift+tab, enter, shift+enter are always trapped by cellNav, and that all editors must stay |
| 146 | +away from them? Can we agree that other than those 4 keys, no editor will ever propagate navigation (and work out |
| 147 | +how to make that true, as well as document how to do it for custom editors as well)? |
| 148 | + |
| 149 | +Can we define some sort of state callback for each editor (that each editor must create and respond to)? So |
| 150 | +when a scroll happens we'd call getState on the editor, then when the scroll completes we'd find the new instance |
| 151 | +of that editor and call setState? Then each editor is responsible for maintaining it's own state, or choosing not |
| 152 | +to maintain it. For some editors there may be no state at all (for a dropdown, the selected item is the state), for |
| 153 | +others it's pretty basic (for input it's the cursor location and the selected text start and end). |
| 154 | + |
| 155 | +Can we draw a distinction between getting focus through a user action (keyboard action or mouse click or touch), and |
| 156 | +re-getting focus after a scroll or other grid rendering change? Then we could choose not to select all the text |
| 157 | +and scroll to make a cell visible if we're re-getting focus as opposed to initially getting focus? |
| 158 | + |
| 159 | + |
0 commit comments