132 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
			Vendored
		
	
	
	
| (function(mod) {
 | |
|   if (typeof exports == "object" && typeof module == "object") // CommonJS
 | |
|     mod(require("../../lib/codemirror"), require("./foldcode"));
 | |
|   else if (typeof define == "function" && define.amd) // AMD
 | |
|     define(["../../lib/codemirror", "./foldcode"], mod);
 | |
|   else // Plain browser env
 | |
|     mod(CodeMirror);
 | |
| })(function(CodeMirror) {
 | |
|   "use strict";
 | |
| 
 | |
|   CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
 | |
|     if (old && old != CodeMirror.Init) {
 | |
|       cm.clearGutter(cm.state.foldGutter.options.gutter);
 | |
|       cm.state.foldGutter = null;
 | |
|       cm.off("gutterClick", onGutterClick);
 | |
|       cm.off("change", onChange);
 | |
|       cm.off("viewportChange", onViewportChange);
 | |
|       cm.off("fold", onFold);
 | |
|       cm.off("unfold", onFold);
 | |
|       cm.off("swapDoc", updateInViewport);
 | |
|     }
 | |
|     if (val) {
 | |
|       cm.state.foldGutter = new State(parseOptions(val));
 | |
|       updateInViewport(cm);
 | |
|       cm.on("gutterClick", onGutterClick);
 | |
|       cm.on("change", onChange);
 | |
|       cm.on("viewportChange", onViewportChange);
 | |
|       cm.on("fold", onFold);
 | |
|       cm.on("unfold", onFold);
 | |
|       cm.on("swapDoc", updateInViewport);
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   var Pos = CodeMirror.Pos;
 | |
| 
 | |
|   function State(options) {
 | |
|     this.options = options;
 | |
|     this.from = this.to = 0;
 | |
|   }
 | |
| 
 | |
|   function parseOptions(opts) {
 | |
|     if (opts === true) opts = {};
 | |
|     if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
 | |
|     if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
 | |
|     if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
 | |
|     return opts;
 | |
|   }
 | |
| 
 | |
|   function isFolded(cm, line) {
 | |
|     var marks = cm.findMarksAt(Pos(line));
 | |
|     for (var i = 0; i < marks.length; ++i)
 | |
|       if (marks[i].__isFold && marks[i].find().from.line == line) return true;
 | |
|   }
 | |
| 
 | |
|   function marker(spec) {
 | |
|     if (typeof spec == "string") {
 | |
|       var elt = document.createElement("div");
 | |
|       elt.className = spec;
 | |
|       return elt;
 | |
|     } else {
 | |
|       return spec.cloneNode(true);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   function updateFoldInfo(cm, from, to) {
 | |
|     var opts = cm.state.foldGutter.options, cur = from;
 | |
|     cm.eachLine(from, to, function(line) {
 | |
|       var mark = null;
 | |
|       if (isFolded(cm, cur)) {
 | |
|         mark = marker(opts.indicatorFolded);
 | |
|       } else {
 | |
|         var pos = Pos(cur, 0), func = opts.rangeFinder || CodeMirror.fold.auto;
 | |
|         var range = func && func(cm, pos);
 | |
|         if (range && range.from.line + 1 < range.to.line)
 | |
|           mark = marker(opts.indicatorOpen);
 | |
|       }
 | |
|       cm.setGutterMarker(line, opts.gutter, mark);
 | |
|       ++cur;
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   function updateInViewport(cm) {
 | |
|     var vp = cm.getViewport(), state = cm.state.foldGutter;
 | |
|     if (!state) return;
 | |
|     cm.operation(function() {
 | |
|       updateFoldInfo(cm, vp.from, vp.to);
 | |
|     });
 | |
|     state.from = vp.from; state.to = vp.to;
 | |
|   }
 | |
| 
 | |
|   function onGutterClick(cm, line, gutter) {
 | |
|     var opts = cm.state.foldGutter.options;
 | |
|     if (gutter != opts.gutter) return;
 | |
|     cm.foldCode(Pos(line, 0), opts.rangeFinder);
 | |
|   }
 | |
| 
 | |
|   function onChange(cm) {
 | |
|     var state = cm.state.foldGutter, opts = cm.state.foldGutter.options;
 | |
|     state.from = state.to = 0;
 | |
|     clearTimeout(state.changeUpdate);
 | |
|     state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
 | |
|   }
 | |
| 
 | |
|   function onViewportChange(cm) {
 | |
|     var state = cm.state.foldGutter, opts = cm.state.foldGutter.options;
 | |
|     clearTimeout(state.changeUpdate);
 | |
|     state.changeUpdate = setTimeout(function() {
 | |
|       var vp = cm.getViewport();
 | |
|       if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
 | |
|         updateInViewport(cm);
 | |
|       } else {
 | |
|         cm.operation(function() {
 | |
|           if (vp.from < state.from) {
 | |
|             updateFoldInfo(cm, vp.from, state.from);
 | |
|             state.from = vp.from;
 | |
|           }
 | |
|           if (vp.to > state.to) {
 | |
|             updateFoldInfo(cm, state.to, vp.to);
 | |
|             state.to = vp.to;
 | |
|           }
 | |
|         });
 | |
|       }
 | |
|     }, opts.updateViewportTimeSpan || 400);
 | |
|   }
 | |
| 
 | |
|   function onFold(cm, from) {
 | |
|     var state = cm.state.foldGutter, line = from.line;
 | |
|     if (line >= state.from && line < state.to)
 | |
|       updateFoldInfo(cm, line, line + 1);
 | |
|   }
 | |
| });
 | 
