diff --git a/CHANGELOG.md b/CHANGELOG.md index ff1248b..aa754fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - Support for Node.js 14. +- Preview without fullscreen (Thanks to [@nick-denry], [#196]). ### Fixed - Fix cursor displayed position on activity ([#183]). @@ -168,6 +169,7 @@ Project forked from [SimpleMDE](https://github.com/sparksuite/simplemde-markdown [#9]: https://github.com/Ionaru/easy-markdown-editor/issues/9 +[#196]: https://github.com/Ionaru/easy-markdown-editor/pull/196 [#175]: https://github.com/Ionaru/easy-markdown-editor/pull/175 [#173]: https://github.com/Ionaru/easy-markdown-editor/pull/173 [#170]: https://github.com/Ionaru/easy-markdown-editor/pull/170 @@ -192,6 +194,7 @@ Project forked from [SimpleMDE](https://github.com/sparksuite/simplemde-markdown [#19]: https://github.com/Ionaru/easy-markdown-editor/pull/19 +[@nick-denry]: https://github.com/nick-denry [@StefKors]: https://github.com/StefKors [@felipefdl]: https://github.com/felipefdl [@A-312]: https://github.com/A-312 diff --git a/README.md b/README.md index ba8a756..3f2bdb8 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ easyMDE.value('New input for **EasyMDE**'); - **spellChecker**: If set to `false`, disable the spell checker. Defaults to `true`. - **inputStyle**: `textarea` or `contenteditable`. Defaults to `textarea` for desktop and `contenteditable` for mobile. `contenteditable` option is necessary to enable nativeSpellcheck. - **nativeSpellcheck**: If set to `false`, disable native spell checker. Defaults to `true`. +- **sideBySideFullscreen**: If set to `false`, allows side-by-side editing without going into fullscreen. Defaults to `true`. - **status**: If set to `false`, hide the status bar. Defaults to the array of built-in status bar items. - Optionally, you can set an array of status bar items to include, and in what order. You can even define your own custom status bar items. - **styleSelectedText**: If set to `false`, remove the `CodeMirror-selectedtext` class from selected lines. Defaults to `true`. @@ -288,6 +289,7 @@ var editor = new EasyMDE({ }, }], // Another optional usage, with a custom status bar item that counts keystrokes styleSelectedText: false, + sideBySideFullscreen: false, syncSideBySidePreviewScroll: false, tabSize: 4, toolbar: false, diff --git a/src/css/easymde.css b/src/css/easymde.css index 1a0881a..c1ec62c 100644 --- a/src/css/easymde.css +++ b/src/css/easymde.css @@ -1,3 +1,13 @@ +.EasyMDEContainer { + display: block; +} + +.EasyMDEContainer.sided--no-fullscreen { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + .CodeMirror { box-sizing: border-box; height: auto; @@ -31,6 +41,13 @@ width: 50% !important; } +.CodeMirror-sided.sided--no-fullscreen { + border-right: none!important; + border-bottom-right-radius: 0px; + position: relative; + flex: 1 1 auto; +} + .CodeMirror-placeholder { opacity: .5; } @@ -116,6 +133,10 @@ padding: 0; } +.editor-toolbar.sided--no-fullscreen { + width: 100%; +} + .editor-toolbar button, .editor-toolbar .easymde-dropdown { background: transparent; display: inline-block; @@ -195,6 +216,10 @@ text-align: right; } +.editor-statusbar.sided--no-fullscreen { + width: 100%; +} + .editor-statusbar span { display: inline-block; min-width: 4em; @@ -243,6 +268,12 @@ display: block } +.editor-preview-active-side.sided--no-fullscreen { + flex: 1 1 auto; + height: auto; + position: static; +} + .editor-preview-active { display: block } diff --git a/src/js/easymde.js b/src/js/easymde.js index b6c7a1e..62aaa69 100644 --- a/src/js/easymde.js +++ b/src/js/easymde.js @@ -332,6 +332,29 @@ function toggleFullScreen(editor) { } + // Hide side by side if needed + var sidebyside = cm.getWrapperElement().nextSibling; + if (/editor-preview-active-side/.test(sidebyside.className)) + toggleSideBySide(editor); + + if (editor.options.onToggleFullScreen) { + editor.options.onToggleFullScreen(cm.getOption('fullScreen') || false); + } + + // Remove or set maxHeight + if (cm.getOption('fullScreen')) { + if (editor.options.maxHeight !== false) { + cm.getScrollerElement().style.removeProperty('height'); + sidebyside.style.removeProperty('height'); + } + } else { + if (editor.options.maxHeight !== false) { + cm.getScrollerElement().style.height = editor.options.maxHeight; + editor.setPreviewMaxHeight(); + } + } + + // Update toolbar class if (!/fullscreen/.test(editor.toolbar_div.className)) { editor.toolbar_div.className += ' fullscreen'; @@ -350,16 +373,6 @@ function toggleFullScreen(editor) { toolbarButton.className = toolbarButton.className.replace(/\s*active\s*/g, ''); } } - - - // Hide side by side if needed - var sidebyside = cm.getWrapperElement().nextSibling; - if (/editor-preview-active-side/.test(sidebyside.className)) - toggleSideBySide(editor); - - if (editor.options.onToggleFullScreen) { - editor.options.onToggleFullScreen(cm.getOption('fullScreen') || false); - } } @@ -857,7 +870,32 @@ function toggleSideBySide(editor) { var preview = wrapper.nextSibling; var toolbarButton = editor.toolbarElements && editor.toolbarElements['side-by-side']; var useSideBySideListener = false; + + var noFullscreenItems = [ + wrapper.parentNode, // easyMDEContainer + editor.gui.toolbar, + wrapper, + preview, + editor.gui.statusbar, + ]; + + function addNoFullscreenClass(el) { + el.className += ' sided--no-fullscreen'; + } + + function removeNoFullscreenClass(el) { + el.className = el.className.replace( + /\s*sided--no-fullscreen\s*/g, '' + ); + } + if (/editor-preview-active-side/.test(preview.className)) { + if (cm.getOption('sideBySideNoFullscreen')) { + cm.setOption('sideBySideNoFullscreen', false); + noFullscreenItems.forEach(function (el) { + removeNoFullscreenClass(el); + }); + } preview.className = preview.className.replace( /\s*editor-preview-active-side\s*/g, '' ); @@ -868,8 +906,16 @@ function toggleSideBySide(editor) { // give some time for the transition from editor.css to fire and the view to slide from right to left, // instead of just appearing. setTimeout(function () { - if (!cm.getOption('fullScreen')) - toggleFullScreen(editor); + if (!cm.getOption('fullScreen')) { + if (editor.options.sideBySideFullscreen === false) { + cm.setOption('sideBySideNoFullscreen', true); + noFullscreenItems.forEach(function(el) { + addNoFullscreenClass(el); + }); + } else { + toggleFullScreen(editor); + } + } preview.className += ' editor-preview-active-side'; }, 1); if (toolbarButton) toolbarButton.className += ' active'; @@ -924,6 +970,12 @@ function togglePreview(editor) { var toolbar_div = editor.toolbar_div; var toolbar = editor.options.toolbar ? editor.toolbarElements.preview : false; var preview = wrapper.lastChild; + + // Turn off side by side if needed + var sidebyside = cm.getWrapperElement().nextSibling; + if (/editor-preview-active-side/.test(sidebyside.className)) + toggleSideBySide(editor); + if (!preview || !/editor-preview-full/.test(preview.className)) { preview = document.createElement('div'); @@ -943,6 +995,7 @@ function togglePreview(editor) { wrapper.appendChild(preview); } + if (/editor-preview-active/.test(preview.className)) { preview.className = preview.className.replace( /\s*editor-preview-active\s*/g, '' @@ -965,10 +1018,6 @@ function togglePreview(editor) { } preview.innerHTML = editor.options.previewRender(editor.value(), preview); - // Turn off side by side if needed - var sidebyside = cm.getWrapperElement().nextSibling; - if (/editor-preview-active-side/.test(sidebyside.className)) - toggleSideBySide(editor); } function _replaceSelection(cm, active, startEnd, url) { @@ -1672,6 +1721,7 @@ function EasyMDE(options) { options.shortcuts = extend({}, shortcuts, options.shortcuts || {}); options.minHeight = options.minHeight || '300px'; + options.maxHeight = options.maxHeight || false; options.errorCallback = options.errorCallback || function (errorMessage) { alert(errorMessage); @@ -1959,6 +2009,10 @@ EasyMDE.prototype.render = function (el) { this.codemirror.getScrollerElement().style.minHeight = options.minHeight; + if (options.maxHeight !== false) { + this.codemirror.getScrollerElement().style.height = options.maxHeight; + } + if (options.forceSync === true) { var cm = this.codemirror; cm.on('change', function () { @@ -1968,6 +2022,14 @@ EasyMDE.prototype.render = function (el) { this.gui = {}; + // Wrap Codemirror with container before create toolbar, etc, + // to use with sideBySideFullscreen option. + var easyMDEContainer = document.createElement('div'); + easyMDEContainer.classList.add('EasyMDEContainer'); + var cmWrapper = this.codemirror.getWrapperElement(); + cmWrapper.parentNode.insertBefore(easyMDEContainer, cmWrapper); + easyMDEContainer.appendChild(cmWrapper); + if (options.toolbar !== false) { this.gui.toolbar = this.createToolbar(); } @@ -2229,6 +2291,21 @@ EasyMDE.prototype.uploadImageUsingCustomFunction = function(imageUploadFunction, imageUploadFunction(file, onSuccess, onError); }; +EasyMDE.prototype.setPreviewMaxHeight = function () { + var cm = this.codemirror; + var wrapper = cm.getWrapperElement(); + var preview = wrapper.nextSibling; + + // Calc preview max height + var paddingTop = parseInt(window.getComputedStyle(wrapper).paddingTop); + var borderTopWidth = parseInt(window.getComputedStyle(wrapper).borderTopWidth); + var optionsMaxHeight = parseInt(this.options.maxHeight); + var wrapperMaxHeight = optionsMaxHeight + paddingTop * 2 + borderTopWidth * 2; + var previewMaxHeight = wrapperMaxHeight.toString() + 'px'; + + preview.style.height = previewMaxHeight; +}; + EasyMDE.prototype.createSideBySide = function () { var cm = this.codemirror; var wrapper = cm.getWrapperElement(); @@ -2253,6 +2330,10 @@ EasyMDE.prototype.createSideBySide = function () { wrapper.parentNode.insertBefore(preview, wrapper.nextSibling); } + if (this.options.maxHeight !== false) { + this.setPreviewMaxHeight(); + } + if (this.options.syncSideBySidePreviewScroll === false) return preview; // Syncs scroll editor -> preview var cScroll = false; diff --git a/types/easymde-test.ts b/types/easymde-test.ts index 9ba9898..fdf6077 100644 --- a/types/easymde-test.ts +++ b/types/easymde-test.ts @@ -164,6 +164,7 @@ const editorImagesCustom = new EasyMDE({ }); new EasyMDE({ + sideBySideFullscreen: true, autosave: { enabled: true, delay: 2000, @@ -180,6 +181,7 @@ new EasyMDE({ }); new EasyMDE({ + sideBySideFullscreen: false, toolbar: [ 'bold', 'italic', diff --git a/types/easymde.d.ts b/types/easymde.d.ts index 55f26ae..1e04120 100644 --- a/types/easymde.d.ts +++ b/types/easymde.d.ts @@ -183,6 +183,7 @@ declare namespace EasyMDE { spellChecker?: boolean; inputStyle?: 'textarea' | 'contenteditable'; nativeSpellcheck?: boolean; + sideBySideFullscreen?: boolean; status?: boolean | ReadonlyArray; styleSelectedText?: boolean; tabSize?: number;