Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1047 - Add 'positionedToolbar' custom event #1050

Merged
merged 6 commits into from
Apr 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CUSTOM-EVENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ If you need to override the editor's bult-in behavior, try overriding the built-
- [Toolbar Custom Events](#toolbar-custom-events)
- [`hideToolbar`](#hidetoolbar)
- [`positionToolbar`](#positiontoolbar)
- [`positionedToolbar`](#positionedtoolbar)
- [`showToolbar`](#showtoolbar)
- [Proxied Custom Events](#proxied-custom-events)
- [`editableClick`](#editableclick)
Expand Down Expand Up @@ -152,6 +153,9 @@ These events are triggered by the toolbar when the toolbar extension has not bee
### `positionToolbar`
`positionToolbar` is triggered each time the current selection is checked and the toolbar's position is about to be updated. This event is triggered after all of the buttons have had their state updated, but before the toolbar is moved to the correct location. This event will be triggered even if nothing will be changed about the toolbar's appearance.

### `positionedToolbar`
`positionedToolbar` is triggered each time the current selection is checked, the toolbar is displayed, and the toolbar's position was updated. This differs from the `positionToolbar` event in that the visibility and location of the toolbar has already been changed (as opposed to the event triggering before those changes occur). This event will be triggered even if nothing was changed about the toolbar's appearance.

### `showToolbar`
`showToolbar` is triggered whenever the toolbar was hidden and has just been displayed.

Expand Down
96 changes: 72 additions & 24 deletions spec/anchor-preview.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,16 +237,16 @@ describe('Anchor Preview TestCase', function () {

it('should be displayed when the option showWhenToolbarIsVisible is set to true and toolbar is visible', function () {
var editor = this.newMediumEditor('.editor', {
delay: 200,
anchorPreview: {
showWhenToolbarIsVisible: true
},
toolbar: {
static: true
}
}),
anchorPreview = editor.getExtensionByName('anchor-preview'),
toolbar = editor.getExtensionByName('toolbar');
delay: 200,
anchorPreview: {
showWhenToolbarIsVisible: true
},
toolbar: {
static: true
}
}),
anchorPreview = editor.getExtensionByName('anchor-preview'),
toolbar = editor.getExtensionByName('toolbar');

selectElementContentsAndFire(editor.elements[0].firstChild);

Expand All @@ -258,21 +258,21 @@ describe('Anchor Preview TestCase', function () {
jasmine.clock().tick(250);
expect(anchorPreview.showPreview).toHaveBeenCalled();
expect(toolbar.isDisplayed()).toBe(true);
expect(anchorPreview.getPreviewElement().classList.contains('medium-toolbar-arrow-over')).toBe(true);
expect(anchorPreview.getPreviewElement().classList.contains('medium-editor-anchor-preview-active')).toBe(true);
});

it('should be displayed when the option showWhenToolbarIsVisible is set to true and toolbar is visible', function () {
it('should NOT be displayed when the option showWhenToolbarIsVisible is set to false and toolbar is visible', function () {
var editor = this.newMediumEditor('.editor', {
delay: 200,
anchorPreview: {
showWhenToolbarIsVisible: false
},
toolbar: {
static: true
}
}),
anchorPreview = editor.getExtensionByName('anchor-preview'),
toolbar = editor.getExtensionByName('toolbar');
delay: 200,
anchorPreview: {
showWhenToolbarIsVisible: false
},
toolbar: {
static: true
}
}),
anchorPreview = editor.getExtensionByName('anchor-preview'),
toolbar = editor.getExtensionByName('toolbar');

selectElementContentsAndFire(editor.elements[0].firstChild);

Expand All @@ -282,10 +282,58 @@ describe('Anchor Preview TestCase', function () {

// preview shows only after delay
jasmine.clock().tick(250);

expect(anchorPreview.showPreview).not.toHaveBeenCalled();
expect(toolbar.isDisplayed()).toBe(true);
expect(anchorPreview.getPreviewElement().classList.contains('medium-toolbar-arrow-over')).toBe(false);
expect(anchorPreview.getPreviewElement().classList.contains('medium-editor-anchor-preview-active')).toBe(false);
});

// https://github.com/yabwe/medium-editor/issues/1047
it('should display the anchor form in the toolbar when clicked when showWhenToolbarIsVisible is set to true adn toolbar is visible', function () {
var editor = this.newMediumEditor('.editor', {
anchorPreview: {
showWhenToolbarIsVisible: true
},
toolbar: {
static: true
}
}),
anchorPreview = editor.getExtensionByName('anchor-preview'),
anchor = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar');

// show toolbar
selectElementContentsAndFire(editor.elements[0].firstChild);
jasmine.clock().tick(1);
expect(toolbar.isDisplayed()).toBe(true);

// show preview
fireEvent(document.getElementById('test-link'), 'mouseover');

// load into editor
jasmine.clock().tick(1);
expect(anchorPreview.getPreviewElement().classList.contains('medium-editor-anchor-preview-active')).toBe(true);

var clickEvent = {
defaultPrevented: false,
preventDefault: function () {
this.defaultPrevented = true;
}
};

// trigger all events toolbar is listening to on clicks
fireEvent(anchorPreview.getPreviewElement(), 'mousedown');
fireEvent(anchorPreview.getPreviewElement(), 'mouseup');
anchorPreview.handleClick(clickEvent);
jasmine.clock().tick(1);

// click on the link should have called `preventDefault` to stop from navigating away
expect(clickEvent.defaultPrevented).toBe(true, 'link navigation was not prevented on click of the anchor-preview');

// anchor form should be visible in toolbar
expect(toolbar.isDisplayed()).toBe(true);
expect(anchor.isDisplayed()).toBe(true, 'anchor form to edit link is not visible');
expect(anchorPreview.getPreviewElement().classList.contains('medium-editor-anchor-preview-active')).toBe(false,
'anchor-preview is still visible after being clicked');
});

it('should NOT be present when anchorPreview option is set to false', function () {
Expand Down
34 changes: 34 additions & 0 deletions spec/toolbar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,18 @@ describe('MediumEditor.extensions.toolbar TestCase', function () {
selectElementContentsAndFire(this.el);

expect(callback).toHaveBeenCalledWith({}, this.el);
});

it('should trigger positionedToolbar custom event when toolbar is moved', function () {
var editor = this.newMediumEditor('.editor'),
callback = jasmine.createSpy();

this.el.innerHTML = 'specOnUpdateToolbarTest';
editor.subscribe('positionedToolbar', callback);

selectElementContentsAndFire(this.el);

expect(callback).toHaveBeenCalledWith({}, this.el);
});

it('should trigger positionToolbar before setToolbarPosition is called', function () {
Expand Down Expand Up @@ -131,6 +142,29 @@ describe('MediumEditor.extensions.toolbar TestCase', function () {
expect(toolbar.setToolbarPosition).toHaveBeenCalled();
});

it('should trigger positionedToolbar after setToolbarPosition and showToolbar is called', function () {
this.el.innerHTML = 'position sanity check';
var editor = this.newMediumEditor('.editor'),
toolbar = editor.getExtensionByName('toolbar'),
temp = {
update: function () {
expect(toolbar.setToolbarPosition).toHaveBeenCalled();
expect(toolbar.showToolbar).toHaveBeenCalled();
}
};

selectElementContents(this.el);
jasmine.clock().tick(1);

spyOn(toolbar, 'setToolbarPosition').and.callThrough();
spyOn(toolbar, 'showToolbar').and.callThrough();
spyOn(temp, 'update').and.callThrough();
editor.subscribe('positionedToolbar', temp.update);
selectElementContentsAndFire(this.el);
expect(temp.update).toHaveBeenCalled();
expect(toolbar.setToolbarPosition).toHaveBeenCalled();
});

it('should trigger the hideToolbar custom event when toolbar is hidden', function () {
var editor = this.newMediumEditor('.editor'),
callback = jasmine.createSpy();
Expand Down
9 changes: 9 additions & 0 deletions src/js/extensions/anchor-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@

attachToEditables: function () {
this.subscribe('editableMouseover', this.handleEditableMouseover.bind(this));
this.subscribe('positionedToolbar', this.handlePositionedToolbar.bind(this));
},

handlePositionedToolbar: function () {
// If the toolbar is visible and positioned, we don't need to hide the preview
// when showWhenToolbarIsVisible is true
if (!this.showWhenToolbarIsVisible) {
this.hidePreview();
}
},

handleClick: function (event) {
Expand Down
20 changes: 8 additions & 12 deletions src/js/extensions/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,30 +514,26 @@

setToolbarPosition: function () {
var container = this.base.getFocusedElement(),
selection = this.window.getSelection(),
anchorPreview;
selection = this.window.getSelection();

// If there isn't a valid selection, bail
if (!container) {
return this;
}

if (this.static && !this.relativeContainer) {
this.showToolbar();
this.positionStaticToolbar(container);
} else if (!selection.isCollapsed) {
if (this.static || !selection.isCollapsed) {
this.showToolbar();

// we don't need any absolute positioning if relativeContainer is set
if (!this.relativeContainer) {
this.positionToolbar(selection);
if (this.static) {
this.positionStaticToolbar(container);
} else {
this.positionToolbar(selection);
}
}
}

anchorPreview = this.base.getExtensionByName('anchor-preview');

if (anchorPreview && typeof anchorPreview.hidePreview === 'function') {
anchorPreview.hidePreview();
this.trigger('positionedToolbar', {}, this.base.getFocusedElement());
}
},

Expand Down