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});