diff --git a/examples/summernote-sm.html b/examples/summernote-sm.html index 0561f4ca6..e7924caf3 100644 --- a/examples/summernote-sm.html +++ b/examples/summernote-sm.html @@ -79,7 +79,10 @@ -
+ +diff --git a/src/js/editing/Selection.js b/src/js/editing/Selection.js index 72b5072d8..98d22bc8f 100644 --- a/src/js/editing/Selection.js +++ b/src/js/editing/Selection.js @@ -297,7 +297,7 @@ export default class Selection { let endContainer = rng.endContainer; let node = rng.commonAncestorContainer; - // Handle selection a image or other control like element such as anchors + // Handle selection an image or other control like element such as anchors if (!rng.collapsed) { if (startContainer === endContainer) { if (endOffset - startOffset < 2) { diff --git a/src/js/fmt/MatchFormat2.js b/src/js/fmt/MatchFormat2.js index 1761a1534..fb91c56a5 100644 --- a/src/js/fmt/MatchFormat2.js +++ b/src/js/fmt/MatchFormat2.js @@ -10,7 +10,7 @@ const matchesUnInheritedFormatSelector = (editor, node, name) => { for (let i = 0; i < formatList.length; i++) { const format = formatList[i]; if (FormatUtils.isSelectorFormat(format) && format.inherit === false && dom.matches(node, format.selector)) { - return true; + return { node, format }; } } } @@ -20,15 +20,24 @@ const matchesUnInheritedFormatSelector = (editor, node, name) => { const matchParents = (editor, node, name, vars = null) => { // Find first node with similar format settings - const matchedNode = dom.closest(node, (elm) => { - if (matchesUnInheritedFormatSelector(editor, elm, name)) { + let matchedFormat; + let matchedNode = dom.closest(node, (elm) => { + let match = matchesUnInheritedFormatSelector(editor, elm, name); + if (match) { + matchedFormat = match.format; return true; } - return !!matchNode(editor, elm, name, vars); + match = matchNode(editor, elm, name, vars); + if (match) { + matchedFormat = match.format; + return true; + } + + return false; }); - return matchedNode; + return !!matchedNode ? { node: matchedNode, format: matchedFormat } : undefined; }; const matchName = (node, format) => { @@ -104,6 +113,8 @@ const matchNode = (editor, node, name, vars = null) => { }; if (formatList && dom.isElement(node)) { + let isMatch; + // Check each format in list for (let i = 0; i < formatList.length; i++) { const format = formatList[i]; @@ -111,16 +122,17 @@ const matchNode = (editor, node, name, vars = null) => { // Custom match if (Type.isFunction(format.onmatch)) { // onmatch is generic in a way that we can't really express without casting - return format.onmatch(node, format); + isMatch = format.onmatch(node, format); + return isMatch ? { node, format } : undefined; } // Match name, attributes, styles and classes if (matchName(node, format) && matchItems(node, format, 'attributes', vars)) { const stylesMatch = matchItems(node, format, 'styles', vars); - const isMatch = format.compound ? stylesMatch && classesMatch(format) : stylesMatch || classesMatch(format); + isMatch = format.compound ? stylesMatch && classesMatch(format) : stylesMatch || classesMatch(format); if (isMatch) { - return format; + return { node, format }; } } } @@ -135,11 +147,14 @@ const match = (editor, node, name, vars = null) => { return matchParents(editor, node, name, vars); } - // // Check selected node - // node = editor.selection.getNode(); - // if (matchParents(editor, node, name, vars)) { - // return true; - // } + // Check selected start node + //node = editor.selection.getNode(); + node = editor.selection.getRange().startContainer; + + let match = matchParents(editor, node, name, vars); + if (match) { + return match; + } // // Check start node if it's different // const startNode = editor.selection.getStart(); diff --git a/src/js/module/Toolbar.js b/src/js/module/Toolbar.js index 8eb3c1271..b296aa393 100644 --- a/src/js/module/Toolbar.js +++ b/src/js/module/Toolbar.js @@ -68,8 +68,8 @@ export default class Toolbar { const editorHeight = this.$editor.outerHeight(); const editorWidth = this.$editor.width(); - const toolbarHeight = this.$toolbar.height(); - const statusbarHeight = this.$statusbar.height(); + // const toolbarHeight = this.$toolbar.outerHeight(); + // const statusbarHeight = this.$statusbar.outerHeight(); // check if the web app is currently using another static bar let otherBarHeight = 0; @@ -77,37 +77,27 @@ export default class Toolbar { otherBarHeight = $(this.options.otherStaticBar).outerHeight(); } + let stickyOffset = parseInt(window.getComputedStyle(document.body).getPropertyValue('--content-offset') || 0); + const currentOffset = this.$document.scrollTop(); const editorOffsetTop = this.$editor.offset().top; const editorOffsetBottom = editorOffsetTop + editorHeight; - const activateOffset = editorOffsetTop - otherBarHeight; - const deactivateOffsetBottom = editorOffsetBottom - otherBarHeight - toolbarHeight - statusbarHeight; + const activateOffset = editorOffsetTop - otherBarHeight - stickyOffset; + const deactivateOffsetBottom = editorOffsetBottom - otherBarHeight - stickyOffset; + + if (!this.isFollowing && + (currentOffset > activateOffset && currentOffset < deactivateOffsetBottom)) { - if (!this.isFollowing && - (currentOffset > activateOffset) && (currentOffset < deactivateOffsetBottom - toolbarHeight)) { this.isFollowing = true; - this.$editable.css({ - marginTop: this.$toolbar.outerHeight(), - }); - this.$toolbar.css({ - //position: 'fixed', - position: 'sticky', - top: otherBarHeight, - //width: editorWidth, - zIndex: 1000, + this.$toolbar.addClass('note-toolbar-sticky').css({ + top: stickyOffset, + width: editorWidth }); - } else if (this.isFollowing && + } + else if (this.isFollowing && ((currentOffset < activateOffset) || (currentOffset > deactivateOffsetBottom))) { this.isFollowing = false; - this.$toolbar.css({ - position: 'relative', - top: 0, - //width: '100%', - zIndex: 'auto', - }); - this.$editable.css({ - marginTop: '', - }); + this.$toolbar.removeClass('note-toolbar-sticky').css({ top: '', bottom: '', width: '' }); } } diff --git a/src/styles/sm/summernote-sm.scss b/src/styles/sm/summernote-sm.scss index 5ba837402..b4f97dd27 100644 --- a/src/styles/sm/summernote-sm.scss +++ b/src/styles/sm/summernote-sm.scss @@ -67,6 +67,8 @@ $img-margin-right: 10px; @include border-top-radius($input-border-radius); @include border-bottom-radius($input-border-radius); + --note-sticky-toolbar-zindex: #{$zindex-sticky - 1}; + &:focus-within, &:focus, &.focus { @@ -200,6 +202,13 @@ $img-margin-right: 10px; border-color: $note-border-color !important; z-index: $zindex-tooltip !important; + > .note-toolbar { + position: relative !important; + z-index: auto !important; + top: 0 !important; + width: 100% !important; + } + .note-resizebar { display: none; } @@ -586,6 +595,12 @@ $img-margin-right: 10px; } } + &.note-toolbar-sticky { + // Main toolbar + position: sticky; + z-index: var(--note-sticky-toolbar-zindex); + } + &:not(.dropdown-menu) { display: flex; }