diff --git a/lib/codemirror.js b/lib/codemirror.js index 06b10ac3905ced93669b6eef0fcf872a210ebf0d..c297fe5d36535afd4843e4783fbb61b992fd48a6 100644 --- a/lib/codemirror.js +++ b/lib/codemirror.js @@ -4924,12 +4924,6 @@ }); }), - addLineWidget: methodOp(function(handle, node, options) { - return addLineWidget(this, handle, node, options); - }), - - removeLineWidget: function(widget) { widget.clear(); }, - lineInfo: function(line) { if (typeof line == "number") { if (!isLine(this.doc, line)) return null; @@ -6449,10 +6443,10 @@ // Line widgets are block elements displayed above or below a line. - var LineWidget = CodeMirror.LineWidget = function(cm, node, options) { + var LineWidget = CodeMirror.LineWidget = function(doc, node, options) { if (options) for (var opt in options) if (options.hasOwnProperty(opt)) this[opt] = options[opt]; - this.cm = cm; + this.doc = doc; this.node = node; }; eventMixin(LineWidget); @@ -6463,52 +6457,55 @@ } LineWidget.prototype.clear = function() { - var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); + var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); if (no == null || !ws) return; for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); if (!ws.length) line.widgets = null; var height = widgetHeight(this); - runInOp(cm, function() { + updateLineHeight(line, Math.max(0, line.height - height)); + if (cm) runInOp(cm, function() { adjustScrollWhenAboveVisible(cm, line, -height); regLineChange(cm, no, "widget"); - updateLineHeight(line, Math.max(0, line.height - height)); }); }; LineWidget.prototype.changed = function() { - var oldH = this.height, cm = this.cm, line = this.line; + var oldH = this.height, cm = this.doc.cm, line = this.line; this.height = null; var diff = widgetHeight(this) - oldH; if (!diff) return; - runInOp(cm, function() { + updateLineHeight(line, line.height + diff); + if (cm) runInOp(cm, function() { cm.curOp.forceUpdate = true; adjustScrollWhenAboveVisible(cm, line, diff); - updateLineHeight(line, line.height + diff); }); }; function widgetHeight(widget) { if (widget.height != null) return widget.height; + var cm = widget.doc.cm; + if (!cm) return 0; if (!contains(document.body, widget.node)) { var parentStyle = "position: relative;"; if (widget.coverGutter) - parentStyle += "margin-left: -" + widget.cm.display.gutters.offsetWidth + "px;"; + parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; if (widget.noHScroll) - parentStyle += "width: " + widget.cm.display.wrapper.clientWidth + "px;"; - removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle)); + parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; + removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); } return widget.height = widget.node.offsetHeight; } - function addLineWidget(cm, handle, node, options) { - var widget = new LineWidget(cm, node, options); - if (widget.noHScroll) cm.display.alignWidgets = true; - changeLine(cm.doc, handle, "widget", function(line) { + function addLineWidget(doc, handle, node, options) { + var widget = new LineWidget(doc, node, options); + var cm = doc.cm; + if (cm && widget.noHScroll) cm.display.alignWidgets = true; + changeLine(doc, handle, "widget", function(line) { var widgets = line.widgets || (line.widgets = []); if (widget.insertAt == null) widgets.push(widget); else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); widget.line = line; - if (!lineIsHidden(cm.doc, line)) { - var aboveVisible = heightAtLine(line) < cm.doc.scrollTop; + if (cm && !lineIsHidden(doc, line)) { + var aboveVisible = heightAtLine(line) < doc.scrollTop; updateLineHeight(line, line.height + widgetHeight(widget)); if (aboveVisible) addToScrollPos(cm, null, widget.height); cm.curOp.forceUpdate = true; @@ -7382,6 +7379,11 @@ }); }), + addLineWidget: docMethodOp(function(handle, node, options) { + return addLineWidget(this, handle, node, options); + }), + removeLineWidget: function(widget) { widget.clear(); }, + markText: function(from, to, options) { return markText(this, clipPos(this, from), clipPos(this, to), options, "range"); },