mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Add support for editing on mobile.
Summary: - Add custom handling for dblclick on mobile, to allow focusing editor. - In place of Clipboard.js, use a FocusLayer with document.body as the default focus element. - Set maximum-scale on iOS viewport to prevent auto-zoom. - Reposition the editor on window resize when editing a cell, which is a normal occurrence on Android when virtual keyboard is shown. - Add Save/Cancel icon-buttons next to cell editor on mobile. Test Plan: Tested manually on Safari / FF on iPhone, and on Chrome on Android emulator. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2721
This commit is contained in:
@@ -62,7 +62,7 @@ function Clipboard(app) {
|
||||
|
||||
FocusLayer.create(this, {
|
||||
defaultFocusElem: this.copypasteField,
|
||||
allowFocus: isCopyPasteTarget,
|
||||
allowFocus: allowFocus,
|
||||
onDefaultFocus: () => {
|
||||
this.copypasteField.value = ' ';
|
||||
this.copypasteField.select();
|
||||
@@ -184,10 +184,12 @@ var FOCUS_TARGET_TAGS = {
|
||||
* copy-paste events. Besides inputs and textareas, any element can be marked to be a valid
|
||||
* copy-paste target by adding 'clipboard_focus' class to it.
|
||||
*/
|
||||
function isCopyPasteTarget(elem) {
|
||||
function allowFocus(elem) {
|
||||
return elem && (FOCUS_TARGET_TAGS.hasOwnProperty(elem.tagName) ||
|
||||
elem.hasAttribute("tabindex") ||
|
||||
elem.classList.contains('clipboard_focus'));
|
||||
}
|
||||
|
||||
Clipboard.allowFocus = allowFocus;
|
||||
|
||||
module.exports = Clipboard;
|
||||
|
||||
@@ -23,6 +23,7 @@ var CopySelection = require('./CopySelection');
|
||||
|
||||
const {renderAllRows} = require('app/client/components/Printing');
|
||||
const {reportError} = require('app/client/models/AppModel');
|
||||
const {onDblClickMatchElem} = require('app/client/lib/dblclick');
|
||||
|
||||
// Grist UI Components
|
||||
const {Holder} = require('grainjs');
|
||||
@@ -115,12 +116,7 @@ function GridView(gristDoc, viewSectionModel, isPreview = false) {
|
||||
|
||||
//--------------------------------------------------
|
||||
// Set up DOM event handling.
|
||||
|
||||
this.onEvent(this.scrollPane, 'dblclick', '.field', function(elem, event) {
|
||||
// Assumes `click` event also occurs on a `dblclick` and has already repositioned the cursor.
|
||||
this.activateEditorAtCursor();
|
||||
});
|
||||
|
||||
onDblClickMatchElem(this.scrollPane, '.field', () => this.activateEditorAtCursor());
|
||||
this.onEvent(this.scrollPane, 'scroll', this.onScroll);
|
||||
|
||||
//--------------------------------------------------
|
||||
@@ -955,7 +951,15 @@ GridView.prototype.buildDom = function() {
|
||||
|
||||
/** @inheritdoc */
|
||||
GridView.prototype.onResize = function() {
|
||||
this.scrolly.scheduleUpdateSize();
|
||||
if (this.activeFieldBuilder().isEditorActive()) {
|
||||
// When the editor is active, the common case for a resize is if the virtual keyboard is being
|
||||
// shown on mobile device. In that case, we need to scroll active cell into view, and need to
|
||||
// do it synchronously, to allow repositioning the editor to it in response to the same event.
|
||||
this.scrolly.updateSize();
|
||||
this.scrolly.scrollRowIntoView(this.cursor.rowIndex.peek());
|
||||
} else {
|
||||
this.scrolly.scheduleUpdateSize();
|
||||
}
|
||||
};
|
||||
|
||||
/** @inheritdoc */
|
||||
|
||||
@@ -223,6 +223,9 @@ export class GristDoc extends DisposableWithEvents {
|
||||
this.autoDispose(dom.onElem(window, 'dragover', (ev) => ev.preventDefault()));
|
||||
// The default action is to open dragged files as a link, navigating out of the app.
|
||||
this.autoDispose(dom.onElem(window, 'drop', (ev) => ev.preventDefault()));
|
||||
|
||||
// On window resize, trigger the resizeEmitter to update ViewLayout and individual BaseViews.
|
||||
this.autoDispose(dom.onElem(window, 'resize', () => this.resizeEmitter.emit()));
|
||||
}
|
||||
|
||||
public addOptionsTab(label: string, iconElem: any, contentObj: TabContent[], options: TabOptions): IDisposable {
|
||||
|
||||
Reference in New Issue
Block a user