diff --git a/doc/manual.html b/doc/manual.html index 56fcb7b5e6..da55a1c499 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -411,8 +411,9 @@

Events

Marked range handles, as returned - by markText, emit the - following event:

+ by markText + and setBookmark, emit the + following events:

"clear" ()
@@ -929,16 +930,24 @@

Text-marking methods

the replacedWith option, if any. -
doc.setBookmark(pos, widget) → object
+
doc.setBookmark(pos, options) → object
Inserts a bookmark, a handle that follows the text around it as it is being edited, at the given position. A bookmark has two methods find() and clear(). The first returns the current position of the bookmark, if it is still in the document, and the second explicitly removes the bookmark. - The widget argument is optional, and can be used to display a - DOM node at the current location of the bookmark (analogous to - the replacedWith - option to markText).
+ The options argument is optional. If given, the following + properties are recognized: +
+
widget
Can be used to display a DOM + node at the current location of the bookmark (analogous to + the replacedWith + option to markText).
+
insertLeft
By default, text typed + when the cursor is on top of the bookmark will end up to the + right of the bookmark. Set this option to true to make it go + to the left instead.
+
doc.findMarksAt(pos) → array
Returns an array of all the bookmarks and marked ranges diff --git a/lib/codemirror.js b/lib/codemirror.js index ce58267f94..a4a35841d1 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -3431,11 +3431,11 @@ window.CodeMirror = (function() { span.marker.attachLine(line); } - function markedSpansBefore(old, startCh) { + function markedSpansBefore(old, startCh, isInsert) { if (old) for (var i = 0, nw; i < old.length; ++i) { var span = old[i], marker = span.marker; var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); - if (startsBefore || marker.type == "bookmark" && span.from == startCh) { + if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) { var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); (nw || (nw = [])).push({from: span.from, to: endsAfter ? null : span.to, @@ -3445,11 +3445,11 @@ window.CodeMirror = (function() { return nw; } - function markedSpansAfter(old, startCh, endCh) { + function markedSpansAfter(old, endCh, isInsert) { if (old) for (var i = 0, nw; i < old.length; ++i) { var span = old[i], marker = span.marker; var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); - if (endsAfter || marker.type == "bookmark" && span.from == endCh && span.from != startCh) { + if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) { var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh, to: span.to == null ? null : span.to - endCh, @@ -3464,10 +3464,10 @@ window.CodeMirror = (function() { var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; if (!oldFirst && !oldLast) return null; - var startCh = change.from.ch, endCh = change.to.ch; + var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to); // Get the spans that 'stick out' on both sides - var first = markedSpansBefore(oldFirst, startCh); - var last = markedSpansAfter(oldLast, change.from.line == change.to.line ? startCh : NaN, endCh); + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); // Next, merge those two ends var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); @@ -4267,9 +4267,11 @@ window.CodeMirror = (function() { markText: function(from, to, options) { return markText(this, clipPos(this, from), clipPos(this, to), options, "range"); }, - setBookmark: function(pos, widget) { + setBookmark: function(pos, options) { + var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft}; pos = clipPos(this, pos); - return markText(this, pos, pos, widget ? {replacedWith: widget} : {}, "bookmark"); + return markText(this, pos, pos, realOpts, "bookmark"); }, findMarksAt: function(pos) { pos = clipPos(this, pos); diff --git a/test/test.js b/test/test.js index 3b854db3e0..3398206b78 100644 --- a/test/test.js +++ b/test/test.js @@ -460,6 +460,21 @@ testCM("bookmark", function(cm) { }); }); +testCM("bookmarkInsertLeft", function(cm) { + var br = cm.setBookmark({line: 0, ch: 2}, {insertLeft: false}); + var bl = cm.setBookmark({line: 0, ch: 2}, {insertLeft: true}); + cm.setCursor({line: 0, ch: 2}); + cm.replaceSelection("hi"); + eqPos(br.find(), {line: 0, ch: 2}); + eqPos(bl.find(), {line: 0, ch: 4}); + cm.replaceRange("", {line: 0, ch: 4}, {line: 0, ch: 5}); + cm.replaceRange("", {line: 0, ch: 2}, {line: 0, ch: 4}); + cm.replaceRange("", {line: 0, ch: 1}, {line: 0, ch: 2}); + // Verify that deleting next to bookmarks doesn't kill them + eqPos(br.find(), {line: 0, ch: 1}); + eqPos(bl.find(), {line: 0, ch: 1}); +}, {value: "abcdef"}); + testCM("bug577", function(cm) { cm.setValue("a\nb"); cm.clearHistory(); @@ -726,7 +741,7 @@ testCM("badNestedFold", function(cm) { }); testCM("inlineWidget", function(cm) { - var w = cm.setBookmark({line: 0, ch: 2}, document.createTextNode("uu")); + var w = cm.setBookmark({line: 0, ch: 2}, {widget: document.createTextNode("uu")}); cm.setCursor(0, 2); CodeMirror.commands.goLineDown(cm); eqPos(cm.getCursor(), {line: 1, ch: 4});