Skip to content

Commit bf426a3

Browse files
committed
Modified replace feature, bug fixes needed
1 parent e600f5d commit bf426a3

File tree

1 file changed

+196
-104
lines changed

1 file changed

+196
-104
lines changed

client/utils/codemirror-search.js

Lines changed: 196 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)