From 7d418f5efb09f9dc04226a334cbe8af3a13bf5d7 Mon Sep 17 00:00:00 2001 From: Park Hyunwoo Date: Tue, 7 Jan 2020 23:04:49 +0900 Subject: [PATCH] Allow airpopover on contextmenu --- src/js/base/module/AirPopover.js | 54 +++++++++++++++++++++++--------- src/js/base/module/Editor.js | 9 +++++- src/js/base/settings.js | 1 + 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/js/base/module/AirPopover.js b/src/js/base/module/AirPopover.js index 6cd11f5c8..9aaa48887 100644 --- a/src/js/base/module/AirPopover.js +++ b/src/js/base/module/AirPopover.js @@ -2,7 +2,8 @@ import $ from 'jquery'; import func from '../core/func'; import lists from '../core/lists'; -const AIR_MODE_POPOVER_X_OFFSET = 20; +const AIRMODE_POPOVER_X_OFFSET = -5; +const AIRMODE_POPOVER_Y_OFFSET = 5; export default class AirPopover { constructor(context) { @@ -11,17 +12,35 @@ export default class AirPopover { this.options = context.options; this.hidable = true; + this.onContextmenu = false; + this.pageX = null; + this.pageY = null; this.events = { - 'summernote.keyup summernote.mouseup summernote.scroll': () => { + 'summernote.contextmenu': (e) => { if (this.options.editing) { + e.preventDefault(); + e.stopPropagation(); + this.onContextmenu = true; + this.update(true); + } + }, + 'summernote.mousedown': (we, e) => { + this.pageX = e.pageX; + this.pageY = e.pageY; + }, + 'summernote.keyup summernote.mouseup summernote.scroll': (we, e) => { + if (this.options.editing && !this.onContextmenu) { + this.pageX = e.pageX; + this.pageY = e.pageY; this.update(); } + this.onContextmenu = false; }, 'summernote.disable summernote.change summernote.dialog.shown summernote.blur': () => { this.hide(); }, - 'summernote.focusout': (we, e) => { + 'summernote.focusout': () => { if (!this.$popover.is(':active,:focus')) { this.hide(); } @@ -51,20 +70,25 @@ export default class AirPopover { this.$popover.remove(); } - update() { + update(forcelyOpen) { const styleInfo = this.context.invoke('editor.currentStyle'); - if (styleInfo.range && !styleInfo.range.isCollapsed()) { - const rect = lists.last(styleInfo.range.getClientRects()); - if (rect) { - const bnd = func.rect2bnd(rect); + if (styleInfo.range && (!styleInfo.range.isCollapsed() || forcelyOpen)) { + let rect = { + left: this.pageX, + top: this.pageY, + }; + + const bnd = func.rect2bnd(rect); + const containerOffset = $(this.options.container).offset(); + bnd.top -= containerOffset.top; + bnd.left -= containerOffset.left; - this.$popover.css({ - display: 'block', - left: Math.max(bnd.left + bnd.width / 2, 0) - AIR_MODE_POPOVER_X_OFFSET, - top: bnd.top + bnd.height, - }); - this.context.invoke('buttons.updateCurrentStyle', this.$popover); - } + this.$popover.css({ + display: 'block', + left: Math.max(bnd.left, 0) + AIRMODE_POPOVER_X_OFFSET, + top: bnd.top + AIRMODE_POPOVER_Y_OFFSET, + }); + this.context.invoke('buttons.updateCurrentStyle', this.$popover); } else { this.hide(); } diff --git a/src/js/base/module/Editor.js b/src/js/base/module/Editor.js index aeb844454..947482e89 100644 --- a/src/js/base/module/Editor.js +++ b/src/js/base/module/Editor.js @@ -404,7 +404,14 @@ export default class Editor { this.context.triggerEvent('focusout', event); }); - if (!this.options.airMode) { + if (this.options.airMode) { + if (this.options.overrideContextMenu) { + this.$editor.on('contextmenu', (event) => { + this.context.triggerEvent('contextmenu', event); + return false; + }); + } + } else { if (this.options.width) { this.$editor.outerWidth(this.options.width); } diff --git a/src/js/base/settings.js b/src/js/base/settings.js index 21b61d324..597e405ec 100644 --- a/src/js/base/settings.js +++ b/src/js/base/settings.js @@ -112,6 +112,7 @@ $.summernote = $.extend($.summernote, { // air mode: inline editor airMode: false, + overrideContextMenu: true, // TBD width: null, height: null,