Skip to content

Commit

Permalink
#1216 issue fix
Browse files Browse the repository at this point in the history
  • Loading branch information
anna-git committed Sep 19, 2016
1 parent b1b0e87 commit f5e7756
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 72 deletions.
15 changes: 14 additions & 1 deletion dist/js/medium-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,11 @@ MediumEditor.extensions = {};
}
},

/*
* this function adds one or several classes on an a element.
* if el parameter is not an a, it will look for a children of el.
* if no a children are found, it will look for the a parent.
*/
addClassToAnchors: function (el, buttonClass) {
var classes = buttonClass.split(' '),
i,
Expand All @@ -1029,7 +1034,15 @@ MediumEditor.extensions = {};
el.classList.add(classes[j]);
}
} else {
el = el.getElementsByTagName('a');
var aChildren = el.getElementsByTagName('a');
if (aChildren.length === 0) {
while (el.nodeName.toLowerCase() !== 'a') {
el = el.parentNode;
}
el = [el];
} else {
el = aChildren;
}
for (i = 0; i < el.length; i += 1) {
for (j = 0; j < classes.length; j += 1) {
el[i].classList.add(classes[j]);
Expand Down
8 changes: 4 additions & 4 deletions dist/js/medium-editor.min.js

Large diffs are not rendered by default.

178 changes: 112 additions & 66 deletions spec/anchor.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ describe('Anchor Button TestCase', function () {
describe('Anchor Form', function () {
it('should add class for visible state and remove it for invisivble', function () {
var editor = this.newMediumEditor('.editor', {
buttonLabels: 'fontawesome'
}),
buttonLabels: 'fontawesome'
}),
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar'),
activeClass = anchorExtension.activeClass;
Expand All @@ -33,8 +33,8 @@ describe('Anchor Button TestCase', function () {

it('should not hide the toolbar when mouseup fires inside the anchor form', function () {
var editor = this.newMediumEditor('.editor', {
buttonLabels: 'fontawesome'
}),
buttonLabels: 'fontawesome'
}),
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar');

Expand Down Expand Up @@ -339,10 +339,10 @@ describe('Anchor Button TestCase', function () {

it('should not change fragment identifier when link begins with hash', function () {
var editor = this.newMediumEditor('.editor', {
anchor: {
linkValidation: true
}
}),
anchor: {
linkValidation: true
}
}),
validHashLink = '#!$&\'()*+,;=123abcDEF-._~:@/?',
link,
anchorExtension = editor.getExtensionByName('anchor');
Expand Down Expand Up @@ -453,10 +453,10 @@ describe('Anchor Button TestCase', function () {
it('should create a button when user selects this option and presses enter', function () {
spyOn(MediumEditor.prototype, 'createLink').and.callThrough();
var editor = this.newMediumEditor('.editor', {
anchor: {
customClassOption: 'btn btn-default'
}
}),
anchor: {
customClassOption: 'btn btn-default'
}
}),
save,
input,
button,
Expand Down Expand Up @@ -492,77 +492,123 @@ describe('Anchor Button TestCase', function () {
expect(link.classList.contains('btn-default')).toBe(true);
});

it('should remove the target _blank from the anchor tag when the open in a new window checkbox,' +
' is unchecked and the form is saved', function () {
it('should add the specified css class to the link when user selects this option, even if selected text is styled in a complex nested way', function () {
spyOn(MediumEditor.prototype, 'createLink').and.callThrough();
this.el.innerHTML = '<b>this is a</b><i><b> complicated</b> <strike><b>markup</b></strike></i>';

var editor = this.newMediumEditor('.editor', {
anchor: {
targetCheckbox: true
customClassOption: 'btn btn-default'
}
}),
b = this.el.firstChild,
endb = this.el.querySelector('strike b'),
save,
input,
button,
link,
opts,
anchorExtension = editor.getExtensionByName('anchor'),
targetCheckbox,
link;
toolbar = editor.getExtensionByName('toolbar');

selectElementContentsAndFire(editor.elements[0]);
anchorExtension.showForm('http://test.com');
expect(anchorExtension.isDisplayed()).toBe(true);
targetCheckbox = anchorExtension.getForm().querySelector('input.medium-editor-toolbar-anchor-target');
targetCheckbox.checked = true;
fireEvent(anchorExtension.getForm().querySelector('a.medium-editor-toolbar-save'), 'click');
link = editor.elements[0].querySelector('a');
expect(link.target).toBe('_blank');
MediumEditor.selection.select(document, b.firstChild, 'this'.length, endb.firstChild, 'mar'.length);
save = toolbar.getToolbarElement().querySelector('[data-action="createLink"]');
fireEvent(save, 'click');

input = anchorExtension.getInput();
input.value = 'http://test.com';

button = anchorExtension.getForm().querySelector('input.medium-editor-toolbar-anchor-button');
button.setAttribute('type', 'checkbox');
button.checked = true;

fireEvent(input, 'keyup', {
keyCode: MediumEditor.util.keyCode.ENTER
});
opts = {
value: 'http://test.com',
target: '_self',
buttonClass: 'btn btn-default'
};
expect(editor.createLink).toHaveBeenCalledWith(opts);

selectElementContentsAndFire(editor.elements[0]);
anchorExtension.showForm('http://test.com');
targetCheckbox = anchorExtension.getForm().querySelector('input.medium-editor-toolbar-anchor-target');
targetCheckbox.checked = false;
fireEvent(anchorExtension.getForm().querySelector('a.medium-editor-toolbar-save'), 'click');
link = editor.elements[0].querySelector('a');
expect(link.target).toBe('');
expect(link).not.toBeNull();
expect(link.classList.contains('btn')).toBe(true);
expect(link.classList.contains('btn-default')).toBe(true);
});

it('should fire editableInput only once when the user creates a link open to a new window,' +
' and it should fire at the end of the DOM and selection modifications', function () {
spyOn(MediumEditor.prototype, 'createLink').and.callThrough();
this.el.innerHTML = '<p>Lorem ipsum et dolitur sunt.</p>';
var editor = this.newMediumEditor('.editor', {
it('should remove the target _blank from the anchor tag when the open in a new window checkbox,' +
' is unchecked and the form is saved', function () {
var editor = this.newMediumEditor('.editor', {
anchor: {
targetCheckbox: true
}
}),
p = this.el.lastChild,
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar'),
selectionWhenEventsFired = [],
listener = function () {
selectionWhenEventsFired.push(window.getSelection().toString());
};

MediumEditor.selection.select(document, p.firstChild, 'Lorem '.length, p.firstChild, 'Lorem ipsum'.length);
fireEvent(editor.elements[0], 'focus');
jasmine.clock().tick(1);

// Click the 'anchor' button in the toolbar
fireEvent(toolbar.getToolbarElement().querySelector('[data-action="createLink"]'), 'click');

// Input a url and save
var input = anchorExtension.getInput(),
checkbox = anchorExtension.getAnchorTargetCheckbox();
input.value = 'http://www.example.com';
checkbox.checked = true;
editor.subscribe('editableInput', listener);
fireEvent(input, 'keyup', {
keyCode: MediumEditor.util.keyCode.ENTER
anchorExtension = editor.getExtensionByName('anchor'),
targetCheckbox,
link;

selectElementContentsAndFire(editor.elements[0]);
anchorExtension.showForm('http://test.com');
expect(anchorExtension.isDisplayed()).toBe(true);
targetCheckbox = anchorExtension.getForm().querySelector('input.medium-editor-toolbar-anchor-target');
targetCheckbox.checked = true;
fireEvent(anchorExtension.getForm().querySelector('a.medium-editor-toolbar-save'), 'click');
link = editor.elements[0].querySelector('a');
expect(link.target).toBe('_blank');

selectElementContentsAndFire(editor.elements[0]);
anchorExtension.showForm('http://test.com');
targetCheckbox = anchorExtension.getForm().querySelector('input.medium-editor-toolbar-anchor-target');
targetCheckbox.checked = false;
fireEvent(anchorExtension.getForm().querySelector('a.medium-editor-toolbar-save'), 'click');
link = editor.elements[0].querySelector('a');
expect(link.target).toBe('');
});

expect(editor.createLink).toHaveBeenCalledWith({
value: 'http://www.example.com',
target: '_blank'
it('should fire editableInput only once when the user creates a link open to a new window,' +
' and it should fire at the end of the DOM and selection modifications', function () {
spyOn(MediumEditor.prototype, 'createLink').and.callThrough();
this.el.innerHTML = '<p>Lorem ipsum et dolitur sunt.</p>';
var editor = this.newMediumEditor('.editor', {
anchor: {
targetCheckbox: true
}
}),
p = this.el.lastChild,
anchorExtension = editor.getExtensionByName('anchor'),
toolbar = editor.getExtensionByName('toolbar'),
selectionWhenEventsFired = [],
listener = function () {
selectionWhenEventsFired.push(window.getSelection().toString());
};

MediumEditor.selection.select(document, p.firstChild, 'Lorem '.length, p.firstChild, 'Lorem ipsum'.length);
fireEvent(editor.elements[0], 'focus');
jasmine.clock().tick(1);

// Click the 'anchor' button in the toolbar
fireEvent(toolbar.getToolbarElement().querySelector('[data-action="createLink"]'), 'click');

// Input a url and save
var input = anchorExtension.getInput(),
checkbox = anchorExtension.getAnchorTargetCheckbox();
input.value = 'http://www.example.com';
checkbox.checked = true;
editor.subscribe('editableInput', listener);
fireEvent(input, 'keyup', {
keyCode: MediumEditor.util.keyCode.ENTER
});

expect(editor.createLink).toHaveBeenCalledWith({
value: 'http://www.example.com',
target: '_blank'
});
expect(window.getSelection().toString()).toBe('ipsum', 'selected text should remain selected');
expect(selectionWhenEventsFired.length).toBe(1, 'only one editableInput event should have been registered');
expect(selectionWhenEventsFired[0]).toBe('ipsum', 'selected text should have been the same when event fired');
});
expect(window.getSelection().toString()).toBe('ipsum', 'selected text should remain selected');
expect(selectionWhenEventsFired.length).toBe(1, 'only one editableInput event should have been registered');
expect(selectionWhenEventsFired[0]).toBe('ipsum', 'selected text should have been the same when event fired');
});

// https://github.com/yabwe/medium-editor/issues/757
it('should not select empty paragraphs when link is created at beginning of paragraph after empty paragraphs', function () {
Expand Down
15 changes: 14 additions & 1 deletion src/js/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,11 @@
}
},

/*
* this function adds one or several classes on an a element.
* if el parameter is not an a, it will look for a children of el.
* if no a children are found, it will look for the a parent.
*/
addClassToAnchors: function (el, buttonClass) {
var classes = buttonClass.split(' '),
i,
Expand All @@ -623,7 +628,15 @@
el.classList.add(classes[j]);
}
} else {
el = el.getElementsByTagName('a');
var aChildren = el.getElementsByTagName('a');
if (aChildren.length === 0) {
while (el.nodeName.toLowerCase() !== 'a') {
el = el.parentNode;
}
el = [el];
} else {
el = aChildren;
}
for (i = 0; i < el.length; i += 1) {
for (j = 0; j < classes.length; j += 1) {
el[i].classList.add(classes[j]);
Expand Down

0 comments on commit f5e7756

Please sign in to comment.