mirror of
https://github.com/Ionaru/easy-markdown-editor
synced 2025-07-16 14:34:28 -06:00
Merge pull request #141 from firm1/dropdown
feat : allow dropdown menu on toolbar to group secondary buttons
This commit is contained in:
commit
3096bbe291
@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
- `inputStyle` and `nativeSpellcheck` options to manage the native language of the browser (Thanks to [@firm1], [#143]).
|
- `inputStyle` and `nativeSpellcheck` options to manage the native language of the browser (Thanks to [@firm1], [#143]).
|
||||||
|
- Group buttons in drop-down lists by adding a sub-option `children` for the items in the toolbar (Thanks to [@firm1], [#141]).
|
||||||
- `sanitizerFunction` option to allow custom HTML sanitizing in the markdown preview (Thanks to [@adamb70], [#147]).
|
- `sanitizerFunction` option to allow custom HTML sanitizing in the markdown preview (Thanks to [@adamb70], [#147]).
|
||||||
### Changed
|
### Changed
|
||||||
- Delay before assuming that submit of the form as failed is `autosave.submit_delay` instead of `autosave.delay` (Thanks to [@Situphen], [#139]).
|
- Delay before assuming that submit of the form as failed is `autosave.submit_delay` instead of `autosave.delay` (Thanks to [@Situphen], [#139]).
|
||||||
|
40
README.md
40
README.md
@ -351,6 +351,46 @@ var easyMDE = new EasyMDE({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Put some buttons on dropdown menu
|
||||||
|
|
||||||
|
```Javascript
|
||||||
|
var easyMDE = new EasyMDE({
|
||||||
|
toolbar: [{
|
||||||
|
name: "heading",
|
||||||
|
action: EasyMDE.toggleHeadingSmaller,
|
||||||
|
className: "fa fa-header",
|
||||||
|
title: "Headers",
|
||||||
|
},
|
||||||
|
"|",
|
||||||
|
{
|
||||||
|
name: "others",
|
||||||
|
className: "fa fa-blind",
|
||||||
|
title: "others buttons",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: "image",
|
||||||
|
action: EasyMDE.drawImage,
|
||||||
|
className: "fa fa-picture-o",
|
||||||
|
title: "Image",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "quote",
|
||||||
|
action: EasyMDE.toggleBlockquote,
|
||||||
|
className: "fa fa-percent",
|
||||||
|
title: "Quote",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "link",
|
||||||
|
action: EasyMDE.drawLink,
|
||||||
|
className: "fa fa-link",
|
||||||
|
title: "Link",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// [, ...]
|
||||||
|
]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
### Keyboard shortcuts
|
### Keyboard shortcuts
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: auto;
|
height: auto;
|
||||||
z-index: 9;
|
z-index: 8;
|
||||||
border-right: none !important;
|
border-right: none !important;
|
||||||
border-bottom-right-radius: 0 !important;
|
border-bottom-right-radius: 0 !important;
|
||||||
}
|
}
|
||||||
@ -72,9 +72,6 @@
|
|||||||
.editor-toolbar.fullscreen {
|
.editor-toolbar.fullscreen {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -119,12 +116,11 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-toolbar button {
|
.editor-toolbar button, .editor-toolbar .easymde-dropdown {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
height: 30px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -133,6 +129,10 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editor-toolbar button {
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
.editor-toolbar button.active,
|
.editor-toolbar button.active,
|
||||||
.editor-toolbar button:hover {
|
.editor-toolbar button:hover {
|
||||||
background: #fcfcfc;
|
background: #fcfcfc;
|
||||||
@ -316,3 +316,29 @@
|
|||||||
color: #7f8c8d;
|
color: #7f8c8d;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editor-toolbar .easymde-dropdown {
|
||||||
|
position: relative;
|
||||||
|
background: linear-gradient(to bottom right, #fff 0%, #fff 84%, #333 50%, #333 100%);
|
||||||
|
border-radius: 0;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-toolbar .easymde-dropdown:hover {
|
||||||
|
background: linear-gradient(to bottom right, #fff 0%, #fff 84%, #333 50%, #333 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.easymde-dropdown-content {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
padding: 8px;
|
||||||
|
z-index: 2;
|
||||||
|
top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.easymde-dropdown:active .easymde-dropdown-content,
|
||||||
|
.easymde-dropdown:focus .easymde-dropdown-content {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
@ -110,15 +110,39 @@ function fixShortcut(name) {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create dropdown block
|
||||||
|
*/
|
||||||
|
function createToolbarDropdown(options, enableTooltips, shortcuts, parent) {
|
||||||
|
var el = createToolbarButton(options, false, enableTooltips, shortcuts, 'button', parent);
|
||||||
|
el.className += ' easymde-dropdown';
|
||||||
|
var content = document.createElement('div');
|
||||||
|
content.className = 'easymde-dropdown-content';
|
||||||
|
for (var childrenIndex = 0; childrenIndex < options.children.length; childrenIndex++) {
|
||||||
|
|
||||||
|
var child = options.children[childrenIndex];
|
||||||
|
var childElement;
|
||||||
|
|
||||||
|
if (typeof child === 'string' && child in toolbarBuiltInButtons) {
|
||||||
|
childElement = createToolbarButton(toolbarBuiltInButtons[child], true, enableTooltips, shortcuts, 'button', parent);
|
||||||
|
} else {
|
||||||
|
childElement = createToolbarButton(child, true, enableTooltips, shortcuts, 'button', parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
content.appendChild(childElement);
|
||||||
|
}
|
||||||
|
el.appendChild(content);
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create button element for toolbar.
|
* Create button element for toolbar.
|
||||||
*/
|
*/
|
||||||
function createToolbarButton(options, enableTooltips, shortcuts) {
|
function createToolbarButton(options, enableActions, enableTooltips, shortcuts, markup, parent) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var el = document.createElement('button');
|
var el = document.createElement(markup);
|
||||||
el.className = options.name;
|
el.className = options.name;
|
||||||
el.setAttribute('type', 'button');
|
el.setAttribute('type', markup);
|
||||||
enableTooltips = (enableTooltips == undefined) ? true : enableTooltips;
|
enableTooltips = (enableTooltips == undefined) ? true : enableTooltips;
|
||||||
|
|
||||||
// Properly hande custom shortcuts
|
// Properly hande custom shortcuts
|
||||||
@ -167,6 +191,20 @@ function createToolbarButton(options, enableTooltips, shortcuts) {
|
|||||||
}
|
}
|
||||||
el.appendChild(icon);
|
el.appendChild(icon);
|
||||||
|
|
||||||
|
if (options.action && enableActions) {
|
||||||
|
if (typeof options.action === 'function') {
|
||||||
|
el.onclick = function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
options.action(parent);
|
||||||
|
};
|
||||||
|
} else if (typeof options.action === 'string') {
|
||||||
|
el.onclick = function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
window.open(options.action, '_blank');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1762,7 +1800,7 @@ EasyMDE.prototype.markdown = function (text) {
|
|||||||
|
|
||||||
// Convert the markdown to HTML
|
// Convert the markdown to HTML
|
||||||
var htmlText = marked(text);
|
var htmlText = marked(text);
|
||||||
|
|
||||||
// Sanitize HTML
|
// Sanitize HTML
|
||||||
if (this.options.renderingConfig && typeof this.options.renderingConfig.sanitizerFunction === 'function') {
|
if (this.options.renderingConfig && typeof this.options.renderingConfig.sanitizerFunction === 'function') {
|
||||||
htmlText = this.options.renderingConfig.sanitizerFunction.call(this, htmlText);
|
htmlText = this.options.renderingConfig.sanitizerFunction.call(this, htmlText);
|
||||||
@ -2258,24 +2296,12 @@ EasyMDE.prototype.createToolbar = function (items) {
|
|||||||
var el;
|
var el;
|
||||||
if (item === '|') {
|
if (item === '|') {
|
||||||
el = createSep();
|
el = createSep();
|
||||||
|
} else if (item.children) {
|
||||||
|
el = createToolbarDropdown(item, self.options.toolbarTips, self.options.shortcuts, self);
|
||||||
} else {
|
} else {
|
||||||
el = createToolbarButton(item, self.options.toolbarTips, self.options.shortcuts);
|
el = createToolbarButton(item, true, self.options.toolbarTips, self.options.shortcuts, 'button', self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind events, special for info
|
|
||||||
if (item.action) {
|
|
||||||
if (typeof item.action === 'function') {
|
|
||||||
el.onclick = function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
item.action(self);
|
|
||||||
};
|
|
||||||
} else if (typeof item.action === 'string') {
|
|
||||||
el.onclick = function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
window.open(item.action, '_blank');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toolbarData[item.name || item] = el;
|
toolbarData[item.name || item] = el;
|
||||||
bar.appendChild(el);
|
bar.appendChild(el);
|
||||||
|
@ -43,18 +43,18 @@ const editor2 = new EasyMDE({
|
|||||||
{
|
{
|
||||||
name: 'bold',
|
name: 'bold',
|
||||||
action: EasyMDE.toggleBold,
|
action: EasyMDE.toggleBold,
|
||||||
className: 'fa fa-bolt',
|
className: 'fa fas fa-bolt',
|
||||||
title: 'Bold'
|
title: 'Bold'
|
||||||
},
|
},
|
||||||
'|',
|
'|',
|
||||||
|
'undo',
|
||||||
{
|
{
|
||||||
// Separator
|
|
||||||
name: 'alert',
|
name: 'alert',
|
||||||
action: (editor: EasyMDE) => {
|
action: (editor: EasyMDE) => {
|
||||||
alert('This is from a custom button action!');
|
alert('This is from a custom button action!');
|
||||||
// Custom functions have access to the `editor` instance.
|
// Custom functions have access to the `editor` instance.
|
||||||
},
|
},
|
||||||
className: 'fa fa-star',
|
className: 'fa fas fa-star',
|
||||||
title: 'A Custom Button',
|
title: 'A Custom Button',
|
||||||
noDisable: undefined,
|
noDisable: undefined,
|
||||||
noMobile: false
|
noMobile: false
|
||||||
@ -67,6 +67,29 @@ const editor2 = new EasyMDE({
|
|||||||
title: 'A Custom Link',
|
title: 'A Custom Link',
|
||||||
noDisable: true,
|
noDisable: true,
|
||||||
noMobile: true
|
noMobile: true
|
||||||
|
},
|
||||||
|
'preview',
|
||||||
|
{
|
||||||
|
name: 'links',
|
||||||
|
className: 'fa fas fa-arrow-down',
|
||||||
|
title: 'A Custom Link',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'link',
|
||||||
|
action: 'https://github.com/Ionaru/easy-markdown-editor',
|
||||||
|
className: 'fa fab fa-github',
|
||||||
|
title: 'A Custom Link',
|
||||||
|
noDisable: true,
|
||||||
|
noMobile: true
|
||||||
|
},
|
||||||
|
'preview',
|
||||||
|
{
|
||||||
|
name: 'bold',
|
||||||
|
action: EasyMDE.toggleBold,
|
||||||
|
className: 'fa fas fa-bold',
|
||||||
|
title: 'Bold'
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
34
types/easymde.d.ts
vendored
34
types/easymde.d.ts
vendored
@ -22,6 +22,29 @@
|
|||||||
/// <reference types="codemirror"/>
|
/// <reference types="codemirror"/>
|
||||||
/// <reference types="marked"/>
|
/// <reference types="marked"/>
|
||||||
|
|
||||||
|
interface ArrayOneOrMore<T> extends Array<T> {
|
||||||
|
0: T
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToolbarButton =
|
||||||
|
'strikethrough'
|
||||||
|
| 'code'
|
||||||
|
| 'table'
|
||||||
|
| 'redo'
|
||||||
|
| 'heading'
|
||||||
|
| 'undo'
|
||||||
|
| 'heading-bigger'
|
||||||
|
| 'heading-smaller'
|
||||||
|
| 'heading-1'
|
||||||
|
| 'heading-2'
|
||||||
|
| 'heading-3'
|
||||||
|
| 'clean-block'
|
||||||
|
| 'horizontal-rule'
|
||||||
|
| 'preview'
|
||||||
|
| 'side-by-side'
|
||||||
|
| 'fullscreen'
|
||||||
|
| 'guide';
|
||||||
|
|
||||||
declare namespace EasyMDE {
|
declare namespace EasyMDE {
|
||||||
interface AutoSaveOptions {
|
interface AutoSaveOptions {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
@ -87,6 +110,15 @@ declare namespace EasyMDE {
|
|||||||
onUpdate: (element: HTMLElement) => void;
|
onUpdate: (element: HTMLElement) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ToolbarDropdownIcon {
|
||||||
|
name: string;
|
||||||
|
children: ArrayOneOrMore<ToolbarIcon | ToolbarButton>;
|
||||||
|
className: string;
|
||||||
|
title: string;
|
||||||
|
noDisable?: boolean;
|
||||||
|
noMobile?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface ToolbarIcon {
|
interface ToolbarIcon {
|
||||||
name: string;
|
name: string;
|
||||||
action: string | ((editor: EasyMDE) => void);
|
action: string | ((editor: EasyMDE) => void);
|
||||||
@ -139,7 +171,7 @@ declare namespace EasyMDE {
|
|||||||
status?: boolean | ReadonlyArray<string | StatusBarItem>;
|
status?: boolean | ReadonlyArray<string | StatusBarItem>;
|
||||||
styleSelectedText?: boolean;
|
styleSelectedText?: boolean;
|
||||||
tabSize?: number;
|
tabSize?: number;
|
||||||
toolbar?: boolean | ReadonlyArray<'|' | ToolbarIcon>;
|
toolbar?: boolean | ReadonlyArray<'|' | ToolbarButton | ToolbarIcon | ToolbarDropdownIcon>;
|
||||||
toolbarTips?: boolean;
|
toolbarTips?: boolean;
|
||||||
onToggleFullScreen?: (goingIntoFullScreen: boolean) => void;
|
onToggleFullScreen?: (goingIntoFullScreen: boolean) => void;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user