2525 * @author Patrick Oladimeji
2626 * @date 10/24/13 9:35:26 AM
2727 */
28-
2928define ( function ( require , exports , module ) {
3029 "use strict" ;
3130
@@ -53,7 +52,12 @@ define(function (require, exports, module) {
5352 collapseAllKey = "Alt-1" ,
5453 expandAllKey = "Shift-Alt-1" ,
5554 collapseAllKeyMac = "Cmd-1" ,
56- expandAllKeyMac = "Cmd-Shift-1" ;
55+ expandAllKeyMac = "Cmd-Shift-1" ,
56+ SAVE_FOLD_STATES = "saveFoldStates" ,
57+ HIDE_UNTIL_MOUSE_OVER = "hideUntilMouseover" ,
58+ MAKE_SELECTION_FOLDABLE = "makeSelectionFoldable" ,
59+ ALWAYS_USE_INDENT_FOLD = "alwaysUseIndentFold" ,
60+ LINE_NUMBER_GUTTER = "CodeMirror-linenumbers" ;
5761
5862 ExtensionUtils . loadStyleSheet ( module , "main.less" ) ;
5963
@@ -70,10 +74,10 @@ define(function (require, exports, module) {
7074 indentFold = require ( "foldhelpers/indentFold" ) ,
7175 selectionFold = require ( "foldhelpers/foldSelected" ) ;
7276
73-
7477 /** Set to true when init() has run; set back to false after deinit() has run */
75- var _isInitialized = false ;
76-
78+ var _isInitialized = false ,
79+ gutterObservers = { } ;
80+
7781 /**
7882 * Restores the linefolds in the editor using values fetched from the preference store
7983 * Checks the document to ensure that changes have not been made (e.g., in a different editor)
@@ -112,7 +116,7 @@ define(function (require, exports, module) {
112116 } ) ;
113117 }
114118
115- var saveFolds = prefs . getSetting ( "saveFoldStates" ) ;
119+ var saveFolds = prefs . getSetting ( SAVE_FOLD_STATES ) ;
116120 if ( ! editor || ! saveFolds ) {
117121 return ;
118122 }
@@ -147,7 +151,7 @@ define(function (require, exports, module) {
147151 * @param {Editor } editor the editor whose line folds should be saved
148152 */
149153 function saveLineFolds ( editor ) {
150- var saveFolds = prefs . getSetting ( "saveFoldStates" ) ;
154+ var saveFolds = prefs . getSetting ( SAVE_FOLD_STATES ) ;
151155 if ( ! editor || ! saveFolds ) {
152156 return ;
153157 }
@@ -263,34 +267,38 @@ define(function (require, exports, module) {
263267 */
264268 function createGutter ( editor ) {
265269 var cm = editor . _codeMirror ;
270+ var rootElement = editor . getRootElement ( ) ;
266271 var path = editor . document . file . fullPath , _lineFolds = prefs . getFolds ( path ) ;
267272 _lineFolds = _lineFolds || { } ;
268273 cm . _lineFolds = _lineFolds ;
269274 var gutters = cm . getOption ( "gutters" ) . slice ( 0 ) ;
270275
271276 // Reuse any existing fold gutter
272277 if ( gutters . indexOf ( GUTTER_NAME ) < 0 ) {
273- var lnIndex = gutters . indexOf ( "CodeMirror-linenumbers" ) ;
274- $ ( editor . getRootElement ( ) ) . addClass ( "folding-enabled" ) ;
275- gutters . splice ( lnIndex + 1 , 0 , GUTTER_NAME ) ;
278+ var lineNumberIndex = gutters . indexOf ( LINE_NUMBER_GUTTER ) ;
279+ if ( lineNumberIndex < 0 ) {
280+ $ ( rootElement ) . addClass ( "linenumber-disabled" ) ;
281+ }
282+ $ ( rootElement ) . addClass ( "folding-enabled" ) ;
283+ gutters . splice ( lineNumberIndex + 1 , 0 , GUTTER_NAME ) ;
276284 cm . setOption ( "gutters" , gutters ) ;
277285 cm . refresh ( ) ; // force recomputing gutter width - .folding-enabled class affects linenumbers gutter which has existing cached width
278286 }
279287 cm . setOption ( "foldGutter" , { onGutterClick : onGutterClick } ) ;
280288
281289 $ ( cm . getGutterElement ( ) ) . on ( {
282290 mouseenter : function ( ) {
283- if ( prefs . getSetting ( "hideUntilMouseover" ) ) {
291+ if ( prefs . getSetting ( HIDE_UNTIL_MOUSE_OVER ) ) {
284292 foldGutter . updateInViewport ( cm ) ;
285293 } else {
286- $ ( editor . getRootElement ( ) ) . addClass ( "over-gutter" ) ;
294+ $ ( rootElement ) . addClass ( "over-gutter" ) ;
287295 }
288296 } ,
289297 mouseleave : function ( ) {
290- if ( prefs . getSetting ( "hideUntilMouseover" ) ) {
298+ if ( prefs . getSetting ( HIDE_UNTIL_MOUSE_OVER ) ) {
291299 foldGutter . clearGutter ( cm ) ;
292300 } else {
293- $ ( editor . getRootElement ( ) ) . removeClass ( "over-gutter" ) ;
301+ $ ( rootElement ) . removeClass ( "over-gutter" ) ;
294302 }
295303 }
296304 } ) ;
@@ -304,10 +312,12 @@ define(function (require, exports, module) {
304312 var cm = editor . _codeMirror ;
305313 var gutters = cm . getOption ( "gutters" ) . slice ( 0 ) ;
306314 var index = gutters . indexOf ( GUTTER_NAME ) ;
307- $ ( editor . getRootElement ( ) ) . removeClass ( "folding-enabled" ) ;
315+ var rootElement = editor . getRootElement ( ) ;
316+ $ ( rootElement ) . removeClass ( "folding-enabled" ) ;
308317 gutters . splice ( index , 1 ) ;
309318 cm . setOption ( "gutters" , gutters ) ;
310- cm . refresh ( ) ; // force recomputing gutter width - .folding-enabled class affected linenumbers gutter
319+ // Force recomputing gutter width - .folding-enabled class affected linenumbers gutter
320+ cm . refresh ( ) ;
311321 CodeMirror . defineOption ( "foldGutter" , false , null ) ;
312322 }
313323
@@ -316,6 +326,39 @@ define(function (require, exports, module) {
316326 if ( editor . _codeMirror . getOption ( "gutters" ) . indexOf ( GUTTER_NAME ) === - 1 ) {
317327 createGutter ( editor ) ;
318328 restoreLineFolds ( editor ) ;
329+ // Watch mutations on code mirror gutters and ensure line numbers are added before fold gutter.
330+ var config = { childList : true } ;
331+ var gutters ,
332+ lineNumberIndex ,
333+ foldGutterIndex ,
334+ cm = editor . _codeMirror ,
335+ rootElement = editor . getRootElement ( ) ,
336+ guttersContainer = $ ( ".CodeMirror-gutters" , rootElement ) ,
337+ observer = new MutationObserver ( function ( mutations ) {
338+ observer . disconnect ( ) ;
339+ // Ensure fold-gutter appears after line numbers.
340+ gutters = cm . getOption ( "gutters" ) . slice ( 0 ) ;
341+ lineNumberIndex = gutters . indexOf ( LINE_NUMBER_GUTTER ) ;
342+ foldGutterIndex = gutters . indexOf ( GUTTER_NAME ) ;
343+ if ( lineNumberIndex > - 1 && foldGutterIndex < lineNumberIndex ) {
344+ gutters . splice ( foldGutterIndex , 1 ) ;
345+ lineNumberIndex = gutters . indexOf ( LINE_NUMBER_GUTTER ) ;
346+ gutters . splice ( lineNumberIndex + 1 , 0 , GUTTER_NAME ) ;
347+ }
348+ if ( lineNumberIndex < 0 ) {
349+ $ ( rootElement ) . addClass ( "linenumber-disabled" ) ;
350+ } else {
351+ $ ( rootElement ) . removeClass ( "linenumber-disabled" ) ;
352+ }
353+ $ ( rootElement ) . addClass ( "folding-enabled" ) ;
354+ cm . setOption ( "gutters" , gutters ) ;
355+ cm . refresh ( ) ;
356+ createGutter ( editor ) ;
357+ // Reconnect the observer.
358+ observer . observe ( guttersContainer [ 0 ] , config ) ;
359+ } ) ;
360+ observer . observe ( guttersContainer [ 0 ] , config ) ;
361+ gutterObservers [ editor . document . file . fullPath ] = observer ;
319362 }
320363 }
321364
@@ -371,6 +414,12 @@ define(function (require, exports, module) {
371414 Editor . forEveryEditor ( function ( editor ) {
372415 CodeMirror . commands . unfoldAll ( editor . _codeMirror ) ;
373416 removeGutter ( editor ) ;
417+ //disconnect any mutation observers on the gutter
418+ var gutterObserver = gutterObservers [ editor . document . file . fullPath ] ;
419+ if ( gutterObserver ) {
420+ gutterObserver . disconnect ( ) ;
421+ delete gutterObservers [ editor . document . file . fullPath ] ;
422+ }
374423 } ) ;
375424 }
376425
@@ -387,10 +436,10 @@ define(function (require, exports, module) {
387436 // don't, we register helpers explicitly here. We also register a global helper for generic indent-based
388437 // folding, which cuts across all languages if enabled via preference.
389438 CodeMirror . registerGlobalHelper ( "fold" , "selectionFold" , function ( mode , cm ) {
390- return prefs . getSetting ( "makeSelectionsFoldable" ) ;
439+ return prefs . getSetting ( MAKE_SELECTION_FOLDABLE ) ;
391440 } , selectionFold ) ;
392441 CodeMirror . registerGlobalHelper ( "fold" , "indent" , function ( mode , cm ) {
393- return prefs . getSetting ( "alwaysUseIndentFold" ) ;
442+ return prefs . getSetting ( ALWAYS_USE_INDENT_FOLD ) ;
394443 } , indentFold ) ;
395444
396445 CodeMirror . registerHelper ( "fold" , "django" , CodeMirror . helpers . fold . brace ) ;
0 commit comments