diff --git a/public/javascripts/publisher.js b/public/javascripts/publisher.js index 1d4c5f927..1c8262c8b 100644 --- a/public/javascripts/publisher.js +++ b/public/javascripts/publisher.js @@ -101,35 +101,47 @@ var Publisher = { return resultString; }, - insertionAt : function(insertionStartIndex, keyCode){ - this.incrementMentionLocations(insertionStartIndex, 1); - var mentionIndex = this.mentionAt(insertionStartIndex + 1); - - var mention = this.mentions[mentionIndex]; - if(mention){ - this.mentions.splice(mentionIndex, 1); - } - + insertionAt : function(insertionStartIndex, selectionEnd, keyCode){ + this.selectionDeleted(insertionStartIndex, selectionEnd); + this.updateMentionLocations(insertionStartIndex, 1); + this.destroyMentionAt(insertionStartIndex); }, - deletionAt : function(visibleCursorIndex, keyCode){ + deletionAt : function(selectionStart, selectionEnd, keyCode){ + if(selectionStart != selectionEnd){ + this.selectionDeleted(selectionStart, selectionEnd); + return; + } var effectiveCursorIndex; if(keyCode == KEYCODES.DEL){ - effectiveCursorIndex = visibleCursorIndex; + effectiveCursorIndex = selectionStart; }else{ - effectiveCursorIndex = visibleCursorIndex - 1; + effectiveCursorIndex = selectionStart - 1; } - this.decrementMentionLocations(effectiveCursorIndex, keyCode); + this.updateMentionLocations(effectiveCursorIndex, -1); + this.destroyMentionAt(effectiveCursorIndex); + }, + selectionDeleted : function(selectionStart, selectionEnd){ + Publisher.autocompletion.mentionList.destroyMentionsWithin(selectionStart, selectionEnd); + Publisher.autocompletion.mentionList.updateMentionLocations(selectionStart, selectionStart - selectionEnd); + }, + destroyMentionsWithin : function(start, end){ + for (var i = this.mentions.length - 1; i >= 0; i--){ + var mention = this.mentions[i]; + if(start < mention.visibleEnd && end >= mention.visibleStart){ + this.mentions.splice(i, 1); + } + } + }, + destroyMentionAt : function(effectiveCursorIndex){ var mentionIndex = this.mentionAt(effectiveCursorIndex); - var mention = this.mentions[mentionIndex]; if(mention){ this.mentions.splice(mentionIndex, 1); } - }, - incrementMentionLocations : function(effectiveCursorIndex, offset){ + updateMentionLocations : function(effectiveCursorIndex, offset){ var changedMentions = this.mentionsAfter(effectiveCursorIndex); for(i in changedMentions){ var mention = changedMentions[i]; @@ -137,15 +149,6 @@ var Publisher = { mention.visibleEnd += offset; } }, - decrementMentionLocations : function(effectiveCursorIndex){ - var visibleOffset = -1; - var changedMentions = this.mentionsAfter(effectiveCursorIndex); - for(i in changedMentions){ - var mention = changedMentions[i]; - mention.visibleStart += visibleOffset; - mention.visibleEnd += visibleOffset; - } - }, mentionAt : function(visibleCursorIndex){ for(i in this.mentions){ var mention = this.mentions[i]; @@ -179,15 +182,14 @@ var Publisher = { keyDownHandler : function(event){ var input = Publisher.input(); - var visibleCursorIndex = input[0].selectionStart; - //if(Publisher.cursorIndexAtKeydown == -1){ - // Publisher.cursorIndexAtKeydown = visibleCursorIndex; - //} + var selectionStart = input[0].selectionStart; + var isDeletion = (event.keyCode == KEYCODES.DEL && selectionStart < input.val().length) || (event.keyCode == KEYCODES.BACKSPACE && selectionStart > 0) + var isInsertion = (KEYCODES.isInsertion(event.keyCode) && event.keyCode != KEYCODES.RETURN ) - if((event.keyCode == KEYCODES.DEL && visibleCursorIndex < input.val().length) || (event.keyCode == KEYCODES.BACKSPACE && visibleCursorIndex > 0)){ - Publisher.autocompletion.mentionList.deletionAt(visibleCursorIndex, event.keyCode); - }else if(KEYCODES.isInsertion(event.keyCode) && event.keyCode != KEYCODES.RETURN ){ - Publisher.autocompletion.mentionList.insertionAt(visibleCursorIndex, event.keyCode); + if(isDeletion){ + Publisher.autocompletion.mentionList.deletionAt(selectionStart, input[0].selectionEnd, event.keyCode); + }else if(isInsertion){ + Publisher.autocompletion.mentionList.insertionAt(selectionStart, input[0].selectionEnd, event.keyCode); } }, @@ -201,7 +203,7 @@ var Publisher = { input.val(stringStart + formatted + stringEnd); var offset = formatted.length - stringLoc[1] - stringLoc[0] - Publisher.autocompletion.mentionList.incrementMentionLocations(stringStart.length, offset); + Publisher.autocompletion.mentionList.updateMentionLocations(stringStart.length, offset); return [stringStart.length, stringStart.length + formatted.length] }, diff --git a/spec/javascripts/publisher-spec.js b/spec/javascripts/publisher-spec.js index 5001ac9ea..e3f5e9ea0 100644 --- a/spec/javascripts/publisher-spec.js +++ b/spec/javascripts/publisher-spec.js @@ -120,6 +120,49 @@ describe("Publisher", function() { hiddenVal = "@{Danny; dan@pod.org} loves testing javascript"; hiddenInput.val(hiddenVal); }); + describe("selectionDeleted", function(){ + var func, danny, daniel, david, darren; + beforeEach(function(){ + func = list.selectionDeleted; + visibleVal = "Danny Daniel David Darren"; + visibleInput.val(visibleVal); + list.mentions = []; + danny = { + visibleStart : 0, + visibleEnd : 5, + mentionString : "@{Danny; danny@pod.org}" + }; + daniel = { + visibleStart : 6, + visibleEnd : 12, + mentionString : "@{Daniel; daniel@pod.org}" + }; + david = { + visibleStart : 13, + visibleEnd : 18, + mentionString : "@{David; david@pod.org}" + }; + darren = { + visibleStart : 19, + visibleEnd : 25, + mentionString : "@{Darren; darren@pod.org}" + }; + list.push(danny) + list.push(daniel) + list.push(david) + list.push(darren) + }); + it("destroys mentions within the selection", function(){ + func(4,11); + expect(list.sortedMentions()).toEqual([darren, david]) + }); + it("moves remaining mentions back", function(){ + func(7,14); + var length = 11 - 4 + expect(danny.visibleStart).toBe(0); + expect(darren.visibleStart).toBe(19-length); + }); + }); describe("generateHiddenInput", function(){ it("replaces mentions in a string", function(){ expect(list.generateHiddenInput(visibleVal)).toBe(hiddenVal); @@ -160,19 +203,19 @@ describe("Publisher", function() { mentionString : "@{SomeoneElse; other@pod.org}" }; list.push(mentionTwo); - spyOn(list, 'incrementMentionLocations'); + spyOn(list, 'updateMentionLocations'); list.insertionAt(3,4, 60); - expect(list.incrementMentionLocations).toHaveBeenCalled(); + expect(list.updateMentionLocations).toHaveBeenCalled(); }); }); - describe("incrementMentionLocations", function(){ - it("increments the offsets of the remaining mentions in the list", function(){ + describe("updateMentionLocations", function(){ + it("updates the offsets of the remaining mentions in the list", function(){ mentionTwo = { visibleStart : 8, visibleEnd : 15, mentionString : "@{SomeoneElse; other@pod.org}" }; list.push(mentionTwo); - list.incrementMentionLocations(7, 1); + list.updateMentionLocations(7, 1); expect(mentionTwo.visibleStart).toBe(9); expect(mentionTwo.visibleEnd).toBe(16); });