2 if (typeof exports
== "object" && typeof module
== "object") // CommonJS
3 mod(require("../../lib/codemirror"), require("./foldcode"));
4 else if (typeof define
== "function" && define
.amd
) // AMD
5 define(["../../lib/codemirror", "./foldcode"], mod
);
6 else // Plain browser env
8 })(function(CodeMirror
) {
11 CodeMirror
.defineOption("foldGutter", false, function(cm
, val
, old
) {
12 if (old
&& old
!= CodeMirror
.Init
) {
13 cm
.clearGutter(cm
.state
.foldGutter
.options
.gutter
);
14 cm
.state
.foldGutter
= null;
15 cm
.off("gutterClick", onGutterClick
);
16 cm
.off("change", onChange
);
17 cm
.off("viewportChange", onViewportChange
);
18 cm
.off("fold", onFold
);
19 cm
.off("unfold", onFold
);
20 cm
.off("swapDoc", updateInViewport
);
23 cm
.state
.foldGutter
= new State(parseOptions(val
));
25 cm
.on("gutterClick", onGutterClick
);
26 cm
.on("change", onChange
);
27 cm
.on("viewportChange", onViewportChange
);
28 cm
.on("fold", onFold
);
29 cm
.on("unfold", onFold
);
30 cm
.on("swapDoc", updateInViewport
);
34 var Pos
= CodeMirror
.Pos
;
36 function State(options
) {
37 this.options
= options
;
38 this.from = this.to
= 0;
41 function parseOptions(opts
) {
42 if (opts
=== true) opts
= {};
43 if (opts
.gutter
== null) opts
.gutter
= "CodeMirror-foldgutter";
44 if (opts
.indicatorOpen
== null) opts
.indicatorOpen
= "CodeMirror-foldgutter-open";
45 if (opts
.indicatorFolded
== null) opts
.indicatorFolded
= "CodeMirror-foldgutter-folded";
49 function isFolded(cm
, line
) {
50 var marks
= cm
.findMarksAt(Pos(line
));
51 for (var i
= 0; i
< marks
.length
; ++i
)
52 if (marks
[i
].__isFold
&& marks
[i
].find().from.line
== line
) return true;
55 function marker(spec
) {
56 if (typeof spec
== "string") {
57 var elt
= document
.createElement("div");
61 return spec
.cloneNode(true);
65 function updateFoldInfo(cm
, from, to
) {
66 var opts
= cm
.state
.foldGutter
.options
, cur
= from;
67 cm
.eachLine(from, to
, function(line
) {
69 if (isFolded(cm
, cur
)) {
70 mark
= marker(opts
.indicatorFolded
);
72 var pos
= Pos(cur
, 0), func
= opts
.rangeFinder
|| CodeMirror
.fold
.auto
;
73 var range
= func
&& func(cm
, pos
);
74 if (range
&& range
.from.line
+ 1 < range
.to
.line
)
75 mark
= marker(opts
.indicatorOpen
);
77 cm
.setGutterMarker(line
, opts
.gutter
, mark
);
82 function updateInViewport(cm
) {
83 var vp
= cm
.getViewport(), state
= cm
.state
.foldGutter
;
85 cm
.operation(function() {
86 updateFoldInfo(cm
, vp
.from, vp
.to
);
88 state
.from = vp
.from; state
.to
= vp
.to
;
91 function onGutterClick(cm
, line
, gutter
) {
92 var opts
= cm
.state
.foldGutter
.options
;
93 if (gutter
!= opts
.gutter
) return;
94 cm
.foldCode(Pos(line
, 0), opts
.rangeFinder
);
97 function onChange(cm
) {
98 var state
= cm
.state
.foldGutter
, opts
= cm
.state
.foldGutter
.options
;
99 state
.from = state
.to
= 0;
100 clearTimeout(state
.changeUpdate
);
101 state
.changeUpdate
= setTimeout(function() { updateInViewport(cm
); }, opts
.foldOnChangeTimeSpan
|| 600);
104 function onViewportChange(cm
) {
105 var state
= cm
.state
.foldGutter
, opts
= cm
.state
.foldGutter
.options
;
106 clearTimeout(state
.changeUpdate
);
107 state
.changeUpdate
= setTimeout(function() {
108 var vp
= cm
.getViewport();
109 if (state
.from == state
.to
|| vp
.from - state
.to
> 20 || state
.from - vp
.to
> 20) {
110 updateInViewport(cm
);
112 cm
.operation(function() {
113 if (vp
.from < state
.from) {
114 updateFoldInfo(cm
, vp
.from, state
.from);
115 state
.from = vp
.from;
117 if (vp
.to
> state
.to
) {
118 updateFoldInfo(cm
, state
.to
, vp
.to
);
123 }, opts
.updateViewportTimeSpan
|| 400);
126 function onFold(cm
, from) {
127 var state
= cm
.state
.foldGutter
, line
= from.line
;
128 if (line
>= state
.from && line
< state
.to
)
129 updateFoldInfo(cm
, line
, line
+ 1);