@@ -49,7 +49,7 @@ export default function(CodeMirror) {
4949 else return false ;
5050 }
5151
52- function persistentDialog ( cm , text , deflt , onEnter , onKeyDown ) {
52+ function persistentDialog ( cm , text , deflt , onEnter , replaceOpened , onKeyDown ) {
5353 var searchField = document . getElementsByClassName ( "CodeMirror-search-field" ) [ 0 ] ;
5454 if ( ! searchField ) {
5555 cm . openDialog ( text , onEnter , {
@@ -63,7 +63,7 @@ export default function(CodeMirror) {
6363 closeOnBlur : false
6464 } ) ;
6565
66- searchField = document . getElementsByClassName ( "CodeMirror-search -field") [ 0 ] ;
66+ searchField = document . getElementById ( "Find-input -field") ;
6767
6868 var dialog = document . getElementsByClassName ( "CodeMirror-dialog" ) [ 0 ] ;
6969 var closeButton = dialog . getElementsByClassName ( "close" ) [ 0 ] ;
@@ -141,6 +141,35 @@ export default function(CodeMirror) {
141141 el . setAttribute ( 'aria-checked' , nextState ) ;
142142 return nextState ;
143143 }
144+
145+ var showReplaceButton = dialog . getElementsByClassName ( "CodeMirror-replace-button" ) [ 0 ] ;
146+ var replaceDiv = dialog . getElementsByClassName ( "Replace-div" ) [ 0 ] ;
147+ if ( replaceOpened ) {
148+ replaceDiv . style . height = "138px" ;
149+ }
150+ CodeMirror . on ( showReplaceButton , "click" , function ( ) {
151+ if ( replaceDiv . style . height === "0px" ) {
152+ replaceDiv . style . height = "138px" ;
153+ } else {
154+ replaceDiv . style . height = "0px" ;
155+ }
156+ } ) ;
157+
158+ var replaceField = document . getElementById ( 'Replace-input-field' ) ;
159+ CodeMirror . on ( replaceField , "keyup" , function ( e ) {
160+ if ( e . keyCode == 13 ) // if enter
161+ {
162+ startSearch ( cm , getSearchState ( cm ) , searchField . value ) ;
163+ replace ( cm , parseString ( searchField . value ) , parseString ( replaceField . value ) ) ;
164+ }
165+ } )
166+
167+ var doReplaceButton = document . getElementById ( 'Btn-replace' ) ;
168+ CodeMirror . on ( doReplaceButton , "click" , function ( e ) {
169+ startSearch ( cm , getSearchState ( cm ) , searchField . value ) ;
170+ replace ( cm , parseString ( searchField . value ) , parseString ( replaceField . value ) ) ;
171+ } )
172+
144173 } else {
145174 searchField . focus ( ) ;
146175 searchField . select ( ) ;
@@ -232,59 +261,6 @@ export default function(CodeMirror) {
232261 return regexp ;
233262 }
234263
235- var queryDialog = `
236- <h3 class="CodeMirror-search-title">Find</h3>
237- <input type="text" class="search-input CodeMirror-search-field" placeholder="Find in files" />
238- <div class="CodeMirror-search-actions">
239- <div class="CodeMirror-search-modifiers button-wrap">
240- <button
241- title="Regular expression"
242- aria-label="Regular expression"
243- role="checkbox"
244- class="CodeMirror-search-modifier-button CodeMirror-regexp-button"
245- >
246- <span aria-hidden="true" class="button">.*</span>
247- </button>
248- <button
249- title="Case sensitive"
250- aria-label="Case sensitive"
251- role="checkbox"
252- class="CodeMirror-search-modifier-button CodeMirror-case-button"
253- >
254- <span aria-hidden="true" class="button">Aa</span>
255- </button>
256- <button
257- title="Whole words"
258- aria-label="Whole words"
259- role="checkbox"
260- class="CodeMirror-search-modifier-button CodeMirror-word-button"
261- >
262- <span aria-hidden="true" class="button">" "</span>
263- </button>
264- </div>
265- <div class="CodeMirror-search-nav">
266- <button class="CodeMirror-search-results"></button>
267- <button
268- title="Previous"
269- aria-label="Previous"
270- class="CodeMirror-search-button icon up-arrow prev"
271- >
272- </button>
273- <button
274- title="Next"
275- aria-label="Next"
276- class="CodeMirror-search-button icon down-arrow next"
277- >
278- </button>
279- </div>
280- </div>
281- <button
282- title="Close"
283- aria-label="Close"
284- class="CodeMirror-close-button close icon">
285- </button>
286- ` ;
287-
288264 function startSearch ( cm , state , originalQuery ) {
289265 state . queryText = originalQuery ;
290266 state . query = parseQuery ( originalQuery , state ) ;
@@ -301,6 +277,60 @@ export default function(CodeMirror) {
301277 }
302278 }
303279
280+ function doFindAndReplace ( cm , rev , persistent , immediate , ignoreQuery , replaceOpened ) {
281+ var state = getSearchState ( cm ) ;
282+ if ( ! ignoreQuery && state . query ) {
283+ console . log ( 'Here' ) ;
284+ return findNext ( cm , rev ) ;
285+ }
286+ var q = cm . getSelection ( ) || state . lastQuery ;
287+ if ( persistent && cm . openDialog ) {
288+ var hiding = null ;
289+ var searchNext = function ( query , event ) {
290+ CodeMirror . e_stop ( event ) ;
291+ if ( ! query ) return ;
292+ if ( query != state . queryText ) {
293+ startSearch ( cm , state , query ) ;
294+ state . posFrom = state . posTo = cm . getCursor ( ) ;
295+ }
296+ if ( hiding ) hiding . style . opacity = 1
297+ findNext ( cm , event . shiftKey , function ( _ , to ) {
298+ var dialog
299+ if ( to . line < 3 && document . querySelector &&
300+ ( dialog = cm . display . wrapper . querySelector ( ".CodeMirror-dialog" ) ) &&
301+ dialog . getBoundingClientRect ( ) . bottom - 4 > cm . cursorCoords ( to , "window" ) . top )
302+ ( hiding = dialog ) . style . opacity = 1
303+ } )
304+ } ;
305+ persistentDialog ( cm , queryDialog , q , searchNext , replaceOpened , function ( event , query ) {
306+ var keyName = CodeMirror . keyName ( event )
307+ var cmd = CodeMirror . keyMap [ cm . getOption ( "keyMap" ) ] [ keyName ]
308+ if ( ! cmd ) cmd = cm . getOption ( 'extraKeys' ) [ keyName ]
309+ if ( cmd == "findNext" || cmd == "findPrev" ||
310+ cmd == "findPersistentNext" || cmd == "findPersistentPrev" ) {
311+ CodeMirror . e_stop ( event ) ;
312+ startSearch ( cm , getSearchState ( cm ) , query ) ;
313+ cm . execCommand ( cmd ) ;
314+ } else if ( cmd == "find" || cmd == "findPersistent" ) {
315+ CodeMirror . e_stop ( event ) ;
316+ searchNext ( query , event ) ;
317+ }
318+ } ) ;
319+ if ( immediate && q ) {
320+ startSearch ( cm , state , q ) ;
321+ findNext ( cm , rev ) ;
322+ }
323+ } else {
324+ dialog ( cm , queryDialog , "Search for:" , q , function ( query ) {
325+ if ( query && ! state . query ) cm . operation ( function ( ) {
326+ startSearch ( cm , state , query ) ;
327+ state . posFrom = state . posTo = cm . getCursor ( ) ;
328+ findNext ( cm , rev ) ;
329+ } ) ;
330+ } ) ;
331+ }
332+ }
333+
304334 function doSearch ( cm , rev , persistent , immediate , ignoreQuery ) {
305335 var state = getSearchState ( cm ) ;
306336 if ( ! ignoreQuery && state . query ) return findNext ( cm , rev ) ;
@@ -382,12 +412,6 @@ export default function(CodeMirror) {
382412 if ( state . annotate ) { state . annotate . clear ( ) ; state . annotate = null ; }
383413 } ) ; }
384414
385- var replaceQueryDialog =
386- '<input type="text" class="search-input CodeMirror-search-field"/><div class="close icon"></div>' ;
387-
388- var replacementQueryDialog = 'With: <input type="text" class="replace-input CodeMirror-search-field"/>' ;
389- var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>" ;
390-
391415 function replaceAll ( cm , query , text ) {
392416 cm . operation ( function ( ) {
393417 for ( var cursor = getSearchCursor ( cm , query ) ; cursor . findNext ( ) ; ) {
@@ -399,60 +423,128 @@ export default function(CodeMirror) {
399423 } ) ;
400424 }
401425
402- // TODO: This will need updating if replace is implemented
403- function replace ( cm , all ) {
426+ function replace ( cm , queryText , withText , all ) {
427+ if ( ! queryText ) return ;
404428 const state = getSearchState ( cm ) ;
405429 var prevDialog = document . getElementsByClassName ( "CodeMirror-dialog" ) [ 0 ] ;
406430 if ( prevDialog ) {
407431 clearSearch ( cm ) ;
408- prevDialog . parentNode . removeChild ( prevDialog ) ;
409- cm . focus ( ) ;
410432 }
433+ prevDialog . parentNode . removeChild ( prevDialog ) ;
434+ cm . focus ( ) ;
411435 if ( cm . getOption ( "readOnly" ) ) return ;
412436 var query = cm . getSelection ( ) || state . lastQuery ;
413- var dialogText = all ? "Replace all:" : "Replace:"
414- dialog ( cm , dialogText + replaceQueryDialog , dialogText , query , function ( query ) {
415- if ( ! query ) return ;
416- query = parseQuery ( query , state ) ;
417-
418- dialog ( cm , replacementQueryDialog , "Replace with:" , "" , function ( text ) {
419- text = parseString ( text )
420- if ( all ) {
421- replaceAll ( cm , query , text )
422- } else {
423- clearSearch ( cm ) ;
424- var cursor = getSearchCursor ( cm , query , cm . getCursor ( "from" ) ) ;
425- var advance = function ( ) {
426- var start = cursor . from ( ) , match ;
427- if ( ! ( match = cursor . findNext ( ) ) ) {
428- cursor = getSearchCursor ( cm , query ) ;
429- if ( ! ( match = cursor . findNext ( ) ) ||
430- ( start && cursor . from ( ) . line == start . line && cursor . from ( ) . ch == start . ch ) ) return ;
431- }
432- cm . setSelection ( cursor . from ( ) , cursor . to ( ) ) ;
433- cm . scrollIntoView ( { from : cursor . from ( ) , to : cursor . to ( ) } , 60 ) ;
434- confirmDialog ( cm , doReplaceConfirm , "Replace?" ,
435- [ function ( ) { doReplace ( match ) ; } , advance ,
436- function ( ) { replaceAll ( cm , query , text ) } ] ) ;
437- } ;
438- var doReplace = function ( match ) {
439- cursor . replace ( typeof query == "string" ? text :
440- text . replace ( / \$ ( \d ) / g, function ( _ , i ) { return match [ i ] ; } ) ) ;
441- advance ( ) ;
442- } ;
443- advance ( ) ;
437+
438+ if ( all ) {
439+ replaceAll ( cm , query , withText )
440+ } else {
441+ clearSearch ( cm ) ;
442+ var cursor = getSearchCursor ( cm , query , cm . getCursor ( "from" ) ) ;
443+ var advance = function ( ) {
444+ var start = cursor . from ( ) , match ;
445+ if ( ! ( match = cursor . findNext ( ) ) ) {
446+ cursor = getSearchCursor ( cm , query ) ;
447+ if ( ! ( match = cursor . findNext ( ) ) ||
448+ ( start && cursor . from ( ) . line == start . line && cursor . from ( ) . ch == start . ch ) ) return ;
444449 }
445- } ) ;
446- } ) ;
450+ cm . setSelection ( cursor . from ( ) , cursor . to ( ) ) ;
451+ cm . scrollIntoView ( { from : cursor . from ( ) , to : cursor . to ( ) } , 60 ) ;
452+ confirmDialog ( cm , doReplaceConfirm , "Replace?" ,
453+ [ function ( ) { doReplace ( match ) ; } , advance ,
454+ function ( ) { replaceAll ( cm , query , withText ) } ] ) ;
455+ } ;
456+ var doReplace = function ( match ) {
457+ cursor . replace ( typeof query == "string" ? withText :
458+ withText . replace ( / \$ ( \d ) / g, function ( _ , i ) { return match [ i ] ; } ) ) ;
459+ advance ( ) ;
460+ } ;
461+ advance ( ) ;
462+ }
447463 }
448464
449- CodeMirror . commands . find = function ( cm ) { doSearch ( cm ) ; } ;
450- CodeMirror . commands . findPersistent = function ( cm ) { doSearch ( cm , false , true , false , true ) ; } ;
451- CodeMirror . commands . findPersistentNext = function ( cm ) { doSearch ( cm , false , true , true ) ; } ;
452- CodeMirror . commands . findPersistentPrev = function ( cm ) { doSearch ( cm , true , true , true ) ; } ;
465+ var doReplaceConfirm = "<button>Replace</button> <button>Skip</button> <button>Replace All</button> <button>Stop</button>" ;
466+
467+ var queryDialog = `
468+ <h3 class="CodeMirror-search-title">Find</h3>
469+ <input id="Find-input-field" type="text" class="search-input CodeMirror-search-field" placeholder="Find in files" />
470+ <div class="CodeMirror-search-actions">
471+ <div class="CodeMirror-search-modifiers button-wrap">
472+ <button
473+ title="Regular expression"
474+ aria-label="Regular expression"
475+ role="checkbox"
476+ class="CodeMirror-search-modifier-button CodeMirror-regexp-button"
477+ >
478+ <span aria-hidden="true" class="button">.*</span>
479+ </button>
480+ <button
481+ title="Case sensitive"
482+ aria-label="Case sensitive"
483+ role="checkbox"
484+ class="CodeMirror-search-modifier-button CodeMirror-case-button"
485+ >
486+ <span aria-hidden="true" class="button">Aa</span>
487+ </button>
488+ <button
489+ title="Whole words"
490+ aria-label="Whole words"
491+ role="checkbox"
492+ class="CodeMirror-search-modifier-button CodeMirror-word-button"
493+ >
494+ <span aria-hidden="true" class="button">" "</span>
495+ </button>
496+ <button
497+ title="Replace"
498+ aria-label="Replace"
499+ role="button"
500+ class="CodeMirror-search-modifier-button CodeMirror-replace-button"
501+ >
502+ <span aria-hidden="true" class="button">Replace</span>
503+ </button>
504+ </div>
505+ <div class="CodeMirror-search-nav">
506+ <button class="CodeMirror-search-results"></button>
507+ <button
508+ title="Previous"
509+ aria-label="Previous"
510+ class="CodeMirror-search-button icon up-arrow prev"
511+ >
512+ </button>
513+ <button
514+ title="Next"
515+ aria-label="Next"
516+ class="CodeMirror-search-button icon down-arrow next"
517+ >
518+ </button>
519+ </div>
520+ </div>
521+ <button
522+ title="Close"
523+ aria-label="Close"
524+ class="CodeMirror-close-button close icon">
525+ </button>
526+ <div style="height: 0px; transition: 0.4s; overflow: hidden;" class="Replace-div">
527+ <hr/>
528+ <h3 class="CodeMirror-search-title">Replace</h3>
529+ <input id="Replace-input-field" type="text" placeholder="Text to replace" class="search-input CodeMirror-search-field"/><div class="close icon"></div>
530+ <button
531+ title="Replace"
532+ aria-label="Replace"
533+ role="button"
534+ id="Btn-replace"
535+ class="CodeMirror-search-modifier-button CodeMirror-replace-button"
536+ >
537+ <span aria-hidden="true" class="button">Replace</span>
538+ </button>
539+ </div>
540+ ` ;
541+
542+ CodeMirror . commands . findPersistent = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , false ) ; } ;
543+ CodeMirror . commands . findPersistentNext = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , false ) ; } ;
544+ CodeMirror . commands . findPersistentPrev = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , false ) ; } ;
453545 CodeMirror . commands . findNext = doSearch ;
454546 CodeMirror . commands . findPrev = function ( cm ) { doSearch ( cm , true ) ; } ;
455547 CodeMirror . commands . clearSearch = clearSearch ;
456- CodeMirror . commands . replace = replace ;
457- CodeMirror . commands . replaceAll = function ( cm ) { replace ( cm , true ) ; } ;
548+ CodeMirror . commands . replace = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , true ) ; } ;
549+ CodeMirror . commands . replaceAll = function ( cm ) { doFindAndReplace ( cm , false , true , false , true , true ) ; } ;
458550} ;
0 commit comments