(function() { CodeMirror.defineOption("collapseRange", false, function(cm, val, old) { var wasOn = old && old != CodeMirror.Init; if (val && !wasOn) enableRangeCollapsing(cm); else if (!val && wasOn) disableRangeCollapsing(cm); }); var gutterClass = "CodeMirror-collapserange"; function enableRangeCollapsing(cm) { cm.on("gutterClick", gutterClick); cm.setOption("gutters", (cm.getOption("gutters") || []).concat([gutterClass])); } function disableRangeCollapsing(cm) { cm.rangeCollapseStart = null; cm.off("gutterClick", gutterClick); var gutters = cm.getOption("gutters"); for (var i = 0; i < gutters.length && gutters[i] != gutterClass; ++i) {} cm.setOption("gutters", gutters.slice(0, i).concat(gutters.slice(i + 1))); } function gutterClick(cm, line, gutter) { if (gutter != gutterClass) return; var start = cm.rangeCollapseStart; if (start) { var old = cm.getLineNumber(start); cm.setGutterMarker(start, gutterClass, null); cm.rangeCollapseStart = null; var from = Math.min(old, line), to = Math.max(old, line); if (from != to) { // Finish this fold var fold = cm.markText(CodeMirror.Pos(from + 1, 0), {line: to - 1}, { collapsed: true, inclusiveLeft: true, inclusiveRight: true, clearOnEnter: true }); var clear = function() { cm.setGutterMarker(topLine, gutterClass, null); cm.setGutterMarker(botLine, gutterClass, null); fold.clear(); }; var topLine = cm.setGutterMarker(from, gutterClass, makeMarker(true, true, clear)); var botLine = cm.setGutterMarker(to, gutterClass, makeMarker(false, true, clear)); CodeMirror.on(fold, "clear", clear); return; } } // Start a new fold cm.rangeCollapseStart = cm.setGutterMarker(line, gutterClass, makeMarker(true, false)); } function makeMarker(isTop, isFinished, handler) { var node = document.createElement("div"); node.innerHTML = isTop ? "\u25bc" : "\u25b2"; if (!isFinished) node.style.color = "red"; node.style.fontSize = "85%"; node.style.cursor = "pointer"; if (handler) CodeMirror.on(node, "mousedown", handler); return node; } })();