jump-to-line.js
8 years ago
jump-to-line.min.js
8 years ago
match-highlighter.js
8 years ago
match-highlighter.min.js
8 years ago
matchesonscrollbar.css
8 years ago
matchesonscrollbar.js
8 years ago
matchesonscrollbar.min.js
8 years ago
search.js
8 years ago
search.min.js
8 years ago
searchcursor.js
8 years ago
searchcursor.min.js
8 years ago
matchesonscrollbar.js
98 lines
| 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others |
| 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE |
| 3 | |
| 4 | (function(mod) { |
| 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS |
| 6 | mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar")); |
| 7 | else if (typeof define == "function" && define.amd) // AMD |
| 8 | define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod); |
| 9 | else // Plain browser env |
| 10 | mod(CodeMirror); |
| 11 | })(function(CodeMirror) { |
| 12 | "use strict"; |
| 13 | |
| 14 | CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) { |
| 15 | if (typeof options == "string") options = {className: options}; |
| 16 | if (!options) options = {}; |
| 17 | return new SearchAnnotation(this, query, caseFold, options); |
| 18 | }); |
| 19 | |
| 20 | function SearchAnnotation(cm, query, caseFold, options) { |
| 21 | this.cm = cm; |
| 22 | this.options = options; |
| 23 | var annotateOptions = {listenForChanges: false}; |
| 24 | for (var prop in options) annotateOptions[prop] = options[prop]; |
| 25 | if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match"; |
| 26 | this.annotation = cm.annotateScrollbar(annotateOptions); |
| 27 | this.query = query; |
| 28 | this.caseFold = caseFold; |
| 29 | this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1}; |
| 30 | this.matches = []; |
| 31 | this.update = null; |
| 32 | |
| 33 | this.findMatches(); |
| 34 | this.annotation.update(this.matches); |
| 35 | |
| 36 | var self = this; |
| 37 | cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); }); |
| 38 | } |
| 39 | |
| 40 | var MAX_MATCHES = 1000; |
| 41 | |
| 42 | SearchAnnotation.prototype.findMatches = function() { |
| 43 | if (!this.gap) return; |
| 44 | for (var i = 0; i < this.matches.length; i++) { |
| 45 | var match = this.matches[i]; |
| 46 | if (match.from.line >= this.gap.to) break; |
| 47 | if (match.to.line >= this.gap.from) this.matches.splice(i--, 1); |
| 48 | } |
| 49 | var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold); |
| 50 | var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES; |
| 51 | while (cursor.findNext()) { |
| 52 | var match = {from: cursor.from(), to: cursor.to()}; |
| 53 | if (match.from.line >= this.gap.to) break; |
| 54 | this.matches.splice(i++, 0, match); |
| 55 | if (this.matches.length > maxMatches) break; |
| 56 | } |
| 57 | this.gap = null; |
| 58 | }; |
| 59 | |
| 60 | function offsetLine(line, changeStart, sizeChange) { |
| 61 | if (line <= changeStart) return line; |
| 62 | return Math.max(changeStart, line + sizeChange); |
| 63 | } |
| 64 | |
| 65 | SearchAnnotation.prototype.onChange = function(change) { |
| 66 | var startLine = change.from.line; |
| 67 | var endLine = CodeMirror.changeEnd(change).line; |
| 68 | var sizeChange = endLine - change.to.line; |
| 69 | if (this.gap) { |
| 70 | this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line); |
| 71 | this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line); |
| 72 | } else { |
| 73 | this.gap = {from: change.from.line, to: endLine + 1}; |
| 74 | } |
| 75 | |
| 76 | if (sizeChange) for (var i = 0; i < this.matches.length; i++) { |
| 77 | var match = this.matches[i]; |
| 78 | var newFrom = offsetLine(match.from.line, startLine, sizeChange); |
| 79 | if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch); |
| 80 | var newTo = offsetLine(match.to.line, startLine, sizeChange); |
| 81 | if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch); |
| 82 | } |
| 83 | clearTimeout(this.update); |
| 84 | var self = this; |
| 85 | this.update = setTimeout(function() { self.updateAfterChange(); }, 250); |
| 86 | }; |
| 87 | |
| 88 | SearchAnnotation.prototype.updateAfterChange = function() { |
| 89 | this.findMatches(); |
| 90 | this.annotation.update(this.matches); |
| 91 | }; |
| 92 | |
| 93 | SearchAnnotation.prototype.clear = function() { |
| 94 | this.cm.off("change", this.changeHandler); |
| 95 | this.annotation.clear(); |
| 96 | }; |
| 97 | }); |
| 98 |