From 14bdf87d126c3ff1635d0b851533fbcc74363d1a Mon Sep 17 00:00:00 2001 From: Axel Haustant Date: Sun, 13 Nov 2016 21:34:14 +0100 Subject: [PATCH] Allow toolbar to be multiline --- OPTIONS.md | 7 +++++ demo/multiline-toolbar.html | 53 ++++++++++++++++++++++++++++++++++ spec/anchor.spec.js | 8 +++-- spec/fontname.spec.js | 4 ++- spec/fontsize.spec.js | 4 ++- src/js/extensions/toolbar.js | 48 ++++++++++++++++++++++++------ src/sass/themes/beagle.scss | 1 - src/sass/themes/bootstrap.scss | 1 - src/sass/themes/default.scss | 1 - src/sass/themes/flat.scss | 1 - src/sass/themes/tim.scss | 1 - 11 files changed, 111 insertions(+), 18 deletions(-) create mode 100644 demo/multiline-toolbar.html diff --git a/OPTIONS.md b/OPTIONS.md index 9739e1b52..4cfb0627e 100644 --- a/OPTIONS.md +++ b/OPTIONS.md @@ -232,6 +232,13 @@ enables/disables whether the toolbar should be displayed when selecting multiple The set of buttons to display on the toolbar. +Can also be nested for multiline toolbar: +`[['bold', 'italic', 'underline', 'pre'], ['anchor', 'h2', 'h3', 'quote']]` + +**NOTE:** +Depending on the theme you are using, you may need to make some visual adjustments for proper rendering +(ie. when buttons don't have fixed width). + *** #### `diffLeft` **Default:** `0` diff --git a/demo/multiline-toolbar.html b/demo/multiline-toolbar.html new file mode 100644 index 000000000..df4b5ffba --- /dev/null +++ b/demo/multiline-toolbar.html @@ -0,0 +1,53 @@ + + + + + medium editor | demo + + + + + + + Fork me on GitHub +
+ Theme: + +
+
+

Medium Editor

+
+

Font Awesome

+

My father’s family name being Pirrip, and my Christian name Philip, my infant tongue could make of both names nothing longer or more explicit than Pip. So, I called myself Pip, and came to be called Pip.

+

I give Pirrip as my father’s family name, on the authority of his tombstone and my sister,—Mrs. Joe Gargery, who married the blacksmith. As I never saw my father or my mother, and never saw any likeness of either of them (for their days were long before the days of photographs), my first fancies regarding what they were like were unreasonably derived from their tombstones...

+
+
+

Source

+ + + + diff --git a/spec/anchor.spec.js b/spec/anchor.spec.js index 41e15dc3a..052942223 100644 --- a/spec/anchor.spec.js +++ b/spec/anchor.spec.js @@ -838,7 +838,9 @@ describe('Anchor Button TestCase', function () { selectElementContentsAndFire(editor.elements[0]); button = toolbar.getToolbarElement().querySelector('[data-action="createLink"]'); fireEvent(button, 'click'); - expect(toolbar.getToolbarActionsElement().style.display).toBe('none'); + toolbar.getToolbarActionsElements().forEach(function (el) { + expect(el.style.display).toBe('none'); + }); expect(anchorExtension.isDisplayed()).toBe(true); expect(anchorExtension.showForm).toHaveBeenCalled(); }); @@ -874,7 +876,9 @@ describe('Anchor Button TestCase', function () { // Click the 'anchor' button in the toolbar fireEvent(toolbar.getToolbarElement().querySelector('[data-action="createLink"]'), 'click'); - expect(toolbar.getToolbarActionsElement().style.display).toBe('none'); + toolbar.getToolbarActionsElements().forEach(function (el) { + expect(el.style.display).toBe('none'); + }); expect(anchorExtension.isDisplayed()).toBe(true); expect(anchorExtension.showForm).toHaveBeenCalled(); expect(anchorExtension.getInput().value).toBe(''); diff --git a/spec/fontname.spec.js b/spec/fontname.spec.js index 718d1010b..7a1c97e3b 100644 --- a/spec/fontname.spec.js +++ b/spec/fontname.spec.js @@ -38,7 +38,9 @@ describe('Font Name Button TestCase', function () { selectElementContentsAndFire(editor.elements[0]); button = toolbar.getToolbarElement().querySelector('[data-action="fontName"]'); fireEvent(button, 'click'); - expect(toolbar.getToolbarActionsElement().style.display).toBe('none'); + toolbar.getToolbarActionsElements().forEach(function (el) { + expect(el.style.display).toBe('none'); + }); expect(fontNameExtension.isDisplayed()).toBe(true); expect(fontNameExtension.showForm).toHaveBeenCalled(); }); diff --git a/spec/fontsize.spec.js b/spec/fontsize.spec.js index 6d948d1a0..8f9824ba4 100644 --- a/spec/fontsize.spec.js +++ b/spec/fontsize.spec.js @@ -38,7 +38,9 @@ describe('Font Size Button TestCase', function () { selectElementContentsAndFire(editor.elements[0]); button = toolbar.getToolbarElement().querySelector('[data-action="fontSize"]'); fireEvent(button, 'click'); - expect(toolbar.getToolbarActionsElement().style.display).toBe('none'); + toolbar.getToolbarActionsElements().forEach(function (el) { + expect(el.style.display).toBe('none'); + }); expect(fontSizeExtension.isDisplayed()).toBe(true); expect(fontSizeExtension.showForm).toHaveBeenCalled(); }); diff --git a/src/js/extensions/toolbar.js b/src/js/extensions/toolbar.js index ab94bab43..e48dde577 100644 --- a/src/js/extensions/toolbar.js +++ b/src/js/extensions/toolbar.js @@ -117,7 +117,9 @@ toolbar.className += ' medium-editor-stalker-toolbar'; } - toolbar.appendChild(this.createToolbarButtons()); + this.createToolbarButtons().forEach(function (row) { + toolbar.appendChild(row); + }); // Add any forms that extensions may have this.forEachExtension(function (extension) { @@ -132,19 +134,37 @@ }, createToolbarButtons: function () { + var rows = []; + + if (Array.isArray(this.buttons[0])) { + this.buttons.forEach(function (row, index) { + rows.push(this.createToolbarButtonsRow(row, index)); + }, this); + } else { + rows.push(this.createToolbarButtonsRow(this.buttons, 0)); + } + + return rows; + }, + + createToolbarButtonsRow: function (buttons, index) { var ul = this.document.createElement('ul'), li, btn, - buttons, + buttonEls, extension, buttonName, buttonOpts; ul.id = 'medium-editor-toolbar-actions' + this.getEditorId(); + if (index > 0) { + // Preserve backward compatibility and add index only for extra rows + ul.id += '-' + index; + } ul.className = 'medium-editor-toolbar-actions'; ul.style.display = 'block'; - this.buttons.forEach(function (button) { + buttons.forEach(function (button) { if (typeof button === 'string') { buttonName = button; buttonOpts = null; @@ -169,10 +189,10 @@ } }, this); - buttons = ul.querySelectorAll('button'); + buttonEls = ul.querySelectorAll('button'); if (buttons.length > 0) { - buttons[0].classList.add(this.firstButtonClass); - buttons[buttons.length - 1].classList.add(this.lastButtonClass); + buttonEls[0].classList.add(this.firstButtonClass); + buttonEls[buttonEls.length - 1].classList.add(this.lastButtonClass); } return ul; @@ -202,7 +222,13 @@ }, getToolbarActionsElement: function () { - return this.getToolbarElement().querySelector('.medium-editor-toolbar-actions'); + // For backward compatibility + return this.getToolbarActionsElements()[0]; + }, + + getToolbarActionsElements: function () { + var els = this.getToolbarElement().querySelectorAll('.medium-editor-toolbar-actions'); + return Array.prototype.slice.call(els); }, // Toolbar event handlers @@ -315,7 +341,9 @@ hideToolbarDefaultActions: function () { if (this.isToolbarDefaultActionsDisplayed()) { - this.getToolbarActionsElement().style.display = 'none'; + this.getToolbarActionsElements().forEach(function (el) { + el.style.display = 'none'; + }); } }, @@ -323,7 +351,9 @@ this.hideExtensionForms(); if (!this.isToolbarDefaultActionsDisplayed()) { - this.getToolbarActionsElement().style.display = 'block'; + this.getToolbarActionsElements().forEach(function (el) { + el.style.display = 'block'; + }); } // Using setTimeout + options.delay because: diff --git a/src/sass/themes/beagle.scss b/src/sass/themes/beagle.scss index 040a926c5..3102f3440 100644 --- a/src/sass/themes/beagle.scss +++ b/src/sass/themes/beagle.scss @@ -10,7 +10,6 @@ $medium-editor-placeholder-color: #f8f5f3; // theme rules .medium-toolbar-arrow-under:after { border-color: $medium-editor-bgcolor transparent transparent transparent; - top: $medium-editor-button-size; } .medium-toolbar-arrow-over:before { diff --git a/src/sass/themes/bootstrap.scss b/src/sass/themes/bootstrap.scss index d1fcc1d13..6da211526 100644 --- a/src/sass/themes/bootstrap.scss +++ b/src/sass/themes/bootstrap.scss @@ -11,7 +11,6 @@ $medium-editor-placeholder-color: #fff; // theme rules .medium-toolbar-arrow-under:after { border-color: $medium-editor-bgcolor transparent transparent transparent; - top: $medium-editor-button-size; } .medium-toolbar-arrow-over:before { diff --git a/src/sass/themes/default.scss b/src/sass/themes/default.scss index 5b2d746e2..46ae6cb86 100644 --- a/src/sass/themes/default.scss +++ b/src/sass/themes/default.scss @@ -6,7 +6,6 @@ $medium-editor-border-radius: 5px; // theme rules .medium-toolbar-arrow-under:after { border-color: $medium-editor-bgcolor transparent transparent transparent; - top: $medium-editor-button-size; } .medium-toolbar-arrow-over:before { diff --git a/src/sass/themes/flat.scss b/src/sass/themes/flat.scss index 8e75a3c76..f70ec8ba4 100644 --- a/src/sass/themes/flat.scss +++ b/src/sass/themes/flat.scss @@ -8,7 +8,6 @@ $medium-editor-placeholder-color: #fff; // theme rules .medium-toolbar-arrow-under:after { - top: $medium-editor-button-size; border-color: $medium-editor-bgcolor transparent transparent transparent; } diff --git a/src/sass/themes/tim.scss b/src/sass/themes/tim.scss index d11af752c..9e21b7ec5 100644 --- a/src/sass/themes/tim.scss +++ b/src/sass/themes/tim.scss @@ -11,7 +11,6 @@ $medium-editor-placeholder-color: #ffedd5; // theme rules .medium-toolbar-arrow-under:after { border-color: $medium-editor-bgcolor transparent transparent transparent; - top: $medium-editor-button-size; } .medium-toolbar-arrow-over:before {