From a67e99923b0f00a6a436cc9ad5ab555ef9f8de68 Mon Sep 17 00:00:00 2001 From: Samuel Vasko Date: Mon, 9 Jun 2014 12:31:47 +0200 Subject: [PATCH 1/8] Failing test for firefox link bug --- test/commands.spec.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/commands.spec.js b/test/commands.spec.js index 7e7f817d..051039b2 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -400,4 +400,21 @@ describe('commands', function () { }); }); }); + + describe('createlink', function () { + given('an empty editor', function () { + when('the command is executed', function () { + beforeEach(function () { + scribeNode.click(); + executeCommand('createlink', 'http://example.com'); + }); + + it('should insert A with specified URL and content followed by BR', function () { + return scribeNode.getInnerHTML().then(function (innerHTML) { + expect(innerHTML).to.have.html('

http://example.com

'); + }); + }); + }); + }); + }); }); From ed1d7b07811e7c39582cbbe1db1f526cab6eea31 Mon Sep 17 00:00:00 2001 From: Samuel Vasko Date: Mon, 9 Jun 2014 12:47:52 +0200 Subject: [PATCH 2/8] Fixed case, description and BR --- test/commands.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/commands.spec.js b/test/commands.spec.js index 051039b2..1d215543 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -401,17 +401,17 @@ describe('commands', function () { }); }); - describe('createlink', function () { + describe.only('createLink', function () { given('an empty editor', function () { when('the command is executed', function () { beforeEach(function () { scribeNode.click(); - executeCommand('createlink', 'http://example.com'); + executeCommand('createLink', 'http://example.com'); }); - it('should insert A with specified URL and content followed by BR', function () { + it('should insert A with specified URL and content', function () { return scribeNode.getInnerHTML().then(function (innerHTML) { - expect(innerHTML).to.have.html('

http://example.com

'); + expect(innerHTML).to.have.html('

http://example.com

'); }); }); }); From 4c8b536b3f029e51f54de43a6df9ce07bcf63f3e Mon Sep 17 00:00:00 2001 From: Samuel Vasko Date: Mon, 9 Jun 2014 17:25:11 +0200 Subject: [PATCH 3/8] Added createLink inconsistency for Firefox --- BROWSERINCONSISTENCIES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BROWSERINCONSISTENCIES.md b/BROWSERINCONSISTENCIES.md index 7c18331a..68b2b9c8 100644 --- a/BROWSERINCONSISTENCIES.md +++ b/BROWSERINCONSISTENCIES.md @@ -54,6 +54,9 @@ Playground: http://jsbin.com/iwEWUXo/2/edit?js,console,output - Chrome converts BRs to Ps: http://jsbin.com/zeti/2/edit?js,output - Firefox does not perform transformation upon Ps containing BRs: http://jsbin.com/yiyaq/1/edit?js,output +* "`createLink`" + - Firefox does not create A if selection is empty: + http://jsbin.com/tutufi/2/edit?js,output * "`delete`": - Given a selection across multiple P elements, Firefox will place the caret outside of any P element: http://jsbin.com/xopivama/3/edit?js,output From b922bcc0d81dfe249ac4e42408cfe1b9cc22b9c8 Mon Sep 17 00:00:00 2001 From: Samuel Vasko Date: Wed, 11 Jun 2014 20:20:31 +0200 Subject: [PATCH 4/8] Removed only statement and shortened link --- test/commands.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/commands.spec.js b/test/commands.spec.js index 1d215543..90086937 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -401,17 +401,17 @@ describe('commands', function () { }); }); - describe.only('createLink', function () { + describe('createLink', function () { given('an empty editor', function () { when('the command is executed', function () { beforeEach(function () { scribeNode.click(); - executeCommand('createLink', 'http://example.com'); + executeCommand('createLink', '#'); }); it('should insert A with specified URL and content', function () { return scribeNode.getInnerHTML().then(function (innerHTML) { - expect(innerHTML).to.have.html('

http://example.com

'); + expect(innerHTML).to.have.html('

#

'); }); }); }); From 9d421975f70bfe2932e2c144b1663fad5d134418 Mon Sep 17 00:00:00 2001 From: Samuel Vasko Date: Thu, 12 Jun 2014 16:24:43 +0200 Subject: [PATCH 5/8] Patch for creating links without selection --- src/plugins/core/patches.js | 5 ++- .../core/patches/commands/create-link.js | 40 +++++++++++++++++++ src/scribe.js | 1 + test/commands.spec.js | 14 +++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/plugins/core/patches/commands/create-link.js diff --git a/src/plugins/core/patches.js b/src/plugins/core/patches.js index c196f760..438cbe10 100644 --- a/src/plugins/core/patches.js +++ b/src/plugins/core/patches.js @@ -4,6 +4,7 @@ define([ './patches/commands/insert-html', './patches/commands/insert-list', './patches/commands/outdent', + './patches/commands/create-link', './patches/events' ], function ( boldCommand, @@ -11,6 +12,7 @@ define([ insertHTMLCommand, insertListCommands, outdentCommand, + createLinkCommand, events ) { @@ -28,7 +30,8 @@ define([ indent: indentCommand, insertHTML: insertHTMLCommand, insertList: insertListCommands, - outdent: outdentCommand + outdent: outdentCommand, + createLink: createLinkCommand, }, events: events }; diff --git a/src/plugins/core/patches/commands/create-link.js b/src/plugins/core/patches/commands/create-link.js new file mode 100644 index 00000000..41f37154 --- /dev/null +++ b/src/plugins/core/patches/commands/create-link.js @@ -0,0 +1,40 @@ +define(function () { + + 'use strict'; + + return function () { + return function (scribe) { + var createLinkCommand = new scribe.api.CommandPatch('createLink'); + scribe.commandPatches.createLink = createLinkCommand; + + createLinkCommand.execute = function (value) { + var selection = new scribe.api.Selection(); + + /** + * Firefox does not create a link when selection is collapsed + * so we create is manually. http://jsbin.com/tutufi/2/edit?js,output + */ + if (selection.selection.isCollapsed) { + var aElement = document.createElement('a'); + aElement.setAttribute('href', value); + aElement.textContent = value; + + var range = selection.range.cloneRange(); + range.insertNode(aElement); + + // Place caret at the end of link + var newRange = document.createRange(); + newRange.setStartAfter(aElement); + newRange.setEndAfter(aElement); + selection.selection.removeAllRanges(); + selection.selection.addRange(newRange); + + return null; + }; + + return scribe.api.CommandPatch.prototype.execute.call(this, value); + }; + }; + }; + +}); diff --git a/src/scribe.js b/src/scribe.js index a763aa4a..e52823e9 100644 --- a/src/scribe.js +++ b/src/scribe.js @@ -95,6 +95,7 @@ define([ this.use(patches.commands.insertHTML()); this.use(patches.commands.insertList()); this.use(patches.commands.outdent()); + this.use(patches.commands.createLink()); this.use(patches.events()); this.use(commands.indent()); diff --git a/test/commands.spec.js b/test/commands.spec.js index 90086937..e42948dd 100644 --- a/test/commands.spec.js +++ b/test/commands.spec.js @@ -416,5 +416,19 @@ describe('commands', function () { }); }); }); + + givenContentOf('

|1|

', function () { + when('the command is executed', function () { + beforeEach(function () { + executeCommand('createLink', '#'); + }); + + it('should wrap selection with A', function () { + return scribeNode.getInnerHTML().then(function (innerHTML) { + expect(innerHTML).to.have.html('

1

'); + }); + }); + }); + }); }); }); From 26df696f4925d9e92606cf521b894ba7f88f21dd Mon Sep 17 00:00:00 2001 From: Samuel Vasko Date: Thu, 12 Jun 2014 16:51:39 +0200 Subject: [PATCH 6/8] Collapse on end of the link for default case --- src/plugins/core/patches/commands/create-link.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/core/patches/commands/create-link.js b/src/plugins/core/patches/commands/create-link.js index 41f37154..86675224 100644 --- a/src/plugins/core/patches/commands/create-link.js +++ b/src/plugins/core/patches/commands/create-link.js @@ -32,7 +32,10 @@ define(function () { return null; }; - return scribe.api.CommandPatch.prototype.execute.call(this, value); + scribe.api.CommandPatch.prototype.execute.call(this, value); + + // Place caret at the end of link + selection.selection.collapseToEnd(); }; }; }; From a09a182738458f69b6410199dea8c16dba88e9fd Mon Sep 17 00:00:00 2001 From: Samuel Vasko Date: Thu, 12 Jun 2014 17:17:14 +0200 Subject: [PATCH 7/8] Changed return statements and insertNode call --- src/plugins/core/patches/commands/create-link.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/plugins/core/patches/commands/create-link.js b/src/plugins/core/patches/commands/create-link.js index 86675224..33797605 100644 --- a/src/plugins/core/patches/commands/create-link.js +++ b/src/plugins/core/patches/commands/create-link.js @@ -19,23 +19,21 @@ define(function () { aElement.setAttribute('href', value); aElement.textContent = value; - var range = selection.range.cloneRange(); - range.insertNode(aElement); + selection.range.insertNode(aElement); // Place caret at the end of link var newRange = document.createRange(); newRange.setStartAfter(aElement); newRange.setEndAfter(aElement); + selection.selection.removeAllRanges(); selection.selection.addRange(newRange); + } else { + scribe.api.CommandPatch.prototype.execute.call(this, value); - return null; - }; - - scribe.api.CommandPatch.prototype.execute.call(this, value); - - // Place caret at the end of link - selection.selection.collapseToEnd(); + // Place caret at the end of link + selection.selection.collapseToEnd(); + } }; }; }; From 47d2b1464ef94cbcdcfce7732dba5c21ec1cf336 Mon Sep 17 00:00:00 2001 From: Samuel Vasko Date: Thu, 12 Jun 2014 17:59:19 +0200 Subject: [PATCH 8/8] Removed range modifications --- src/plugins/core/patches/commands/create-link.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/plugins/core/patches/commands/create-link.js b/src/plugins/core/patches/commands/create-link.js index 33797605..298763b5 100644 --- a/src/plugins/core/patches/commands/create-link.js +++ b/src/plugins/core/patches/commands/create-link.js @@ -21,18 +21,15 @@ define(function () { selection.range.insertNode(aElement); - // Place caret at the end of link + // Select the created link var newRange = document.createRange(); - newRange.setStartAfter(aElement); + newRange.setStartBefore(aElement); newRange.setEndAfter(aElement); selection.selection.removeAllRanges(); selection.selection.addRange(newRange); } else { scribe.api.CommandPatch.prototype.execute.call(this, value); - - // Place caret at the end of link - selection.selection.collapseToEnd(); } }; };