mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Show default context menu on link
Summary: also: - closes opened menu if any when click on a custom widget - closes opened menu if any when F2 Test Plan: Include test case Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3269
This commit is contained in:
parent
f224afcc62
commit
afa90cc365
@ -22,6 +22,7 @@ const {copyToClipboard} = require('app/client/lib/copyToClipboard');
|
||||
const {setTestState} = require('app/client/lib/testState');
|
||||
const {ExtraRows} = require('app/client/models/DataTableModelWithDiff');
|
||||
const {createFilterMenu} = require('app/client/ui/ColumnFilterMenu');
|
||||
const {closeRegisteredMenu} = require('app/client/ui2018/menus');
|
||||
|
||||
/**
|
||||
* BaseView forms the basis for ViewSection classes.
|
||||
@ -219,7 +220,7 @@ BaseView.commonCommands = {
|
||||
this.scrollToCursor(true).catch(reportError);
|
||||
this.activateEditorAtCursor({init});
|
||||
},
|
||||
editField: function() { this.scrollToCursor(true); this.activateEditorAtCursor(); },
|
||||
editField: function() { closeRegisteredMenu(); this.scrollToCursor(true); this.activateEditorAtCursor(); },
|
||||
|
||||
insertRecordBefore: function() { this.insertRow(this.cursor.rowIndex()); },
|
||||
insertRecordAfter: function() { this.insertRow(this.cursor.rowIndex() + 1); },
|
||||
|
@ -20,6 +20,7 @@ import {dom as grains} from 'grainjs';
|
||||
import * as ko from 'knockout';
|
||||
import defaults = require('lodash/defaults');
|
||||
import {AccessLevel} from 'app/common/CustomWidget';
|
||||
import {closeRegisteredMenu} from 'app/client/ui2018/menus';
|
||||
|
||||
/**
|
||||
* CustomView components displays arbitrary html. There are two modes available, in the "url" mode
|
||||
@ -218,6 +219,8 @@ export class CustomView extends Disposable {
|
||||
if (!this.viewSection.isDisposed() && !this.viewSection.hasFocus()) {
|
||||
this.viewSection.hasFocus(true);
|
||||
}
|
||||
// allow menus to close if any
|
||||
closeRegisteredMenu();
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -29,7 +29,7 @@ const {onDblClickMatchElem} = require('app/client/lib/dblclick');
|
||||
|
||||
// Grist UI Components
|
||||
const {dom: grainjsDom, Holder, Computed} = require('grainjs');
|
||||
const {menu} = require('../ui2018/menus');
|
||||
const {closeRegisteredMenu, menu} = require('../ui2018/menus');
|
||||
const {calcFieldsCondition} = require('../ui/GridViewMenus');
|
||||
const {ColumnAddMenu, ColumnContextMenu, MultiColumnMenu, freezeAction} = require('../ui/GridViewMenus');
|
||||
const {RowContextMenu} = require('../ui/RowContextMenu');
|
||||
@ -273,7 +273,7 @@ GridView.gridCommands = {
|
||||
|
||||
fieldEditSave: function() { this.cursor.rowIndex(this.cursor.rowIndex() + 1); },
|
||||
// Re-define editField after fieldEditSave to make it take precedence for the Enter key.
|
||||
editField: function() { this.scrollToCursor(true); this.activateEditorAtCursor(); },
|
||||
editField: function() { closeRegisteredMenu(); this.scrollToCursor(true); this.activateEditorAtCursor(); },
|
||||
|
||||
deleteRecords: function() {
|
||||
const saved = this.cursor.getCursorPos();
|
||||
|
@ -8,7 +8,7 @@
|
||||
* `dom.on('contextmenu', ev => ev.preventDefault())`
|
||||
*/
|
||||
import { Disposable, dom, DomArg, DomContents, Holder } from "grainjs";
|
||||
import { cssMenuElem } from 'app/client/ui2018/menus';
|
||||
import { cssMenuElem, registerMenuOpen } from 'app/client/ui2018/menus';
|
||||
import { IOpenController, Menu } from 'popweasel';
|
||||
|
||||
export type IContextMenuContentFunc = (ctx: ContextMenuController) => DomContents;
|
||||
@ -50,6 +50,8 @@ class ContextMenuController extends Disposable implements IOpenController {
|
||||
dom.domDispose(content);
|
||||
content.remove();
|
||||
});
|
||||
|
||||
registerMenuOpen(this);
|
||||
}
|
||||
|
||||
public close() {
|
||||
|
@ -24,6 +24,9 @@ export function gristLink(href: string|Observable<string>, ...args: IDomArgs<HTM
|
||||
dom.attr("href", href),
|
||||
dom.attr("target", "_blank"),
|
||||
dom.on("click", ev => onClickHyperLink(ev, typeof href === 'string' ? href : href.get())),
|
||||
// stop propagation to prevent the grist custom context menu to show up and let the default one
|
||||
// to show up instead.
|
||||
dom.on("contextmenu", ev => ev.stopPropagation()),
|
||||
// As per Google and Mozilla recommendations to prevent opened links
|
||||
// from running on the same process as Grist:
|
||||
// https://developers.google.com/web/tools/lighthouse/audits/noopener
|
||||
|
@ -17,11 +17,28 @@ export interface IOptionFull<T> {
|
||||
icon?: IconName;
|
||||
}
|
||||
|
||||
let _lastOpenedController: weasel.IOpenController|null = null;
|
||||
|
||||
// Close opened menu if any, otherwise do nothing.
|
||||
export function closeRegisteredMenu() {
|
||||
if (_lastOpenedController) { _lastOpenedController.close(); }
|
||||
}
|
||||
|
||||
// Register `ctl` to make sure it is closed when `closeMenu()` is called.
|
||||
export function registerMenuOpen(ctl: weasel.IOpenController) {
|
||||
_lastOpenedController = ctl;
|
||||
ctl.onDispose(() => _lastOpenedController = null);
|
||||
}
|
||||
|
||||
// For string options, we can use a string for label and value without wrapping into an object.
|
||||
export type IOption<T> = (T & string) | IOptionFull<T>;
|
||||
|
||||
export function menu(createFunc: weasel.MenuCreateFunc, options?: weasel.IMenuOptions): DomElementMethod {
|
||||
return weasel.menu(createFunc, {...defaults, ...options});
|
||||
const wrappedCreateFunc = (ctl: weasel.IOpenController) => {
|
||||
registerMenuOpen(ctl);
|
||||
return createFunc(ctl);
|
||||
};
|
||||
return weasel.menu(wrappedCreateFunc, {...defaults, ...options});
|
||||
}
|
||||
|
||||
// TODO Weasel doesn't allow other options for submenus, but probably should.
|
||||
|
Loading…
Reference in New Issue
Block a user