Wiring of search-replace popup; moved some services up one level
This commit is contained in:
parent
5aa6c7ca10
commit
e64a18b18b
BIN
public/imgs/only-in-selection.png
Normal file
BIN
public/imgs/only-in-selection.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
BIN
public/imgs/whole-word.png
Normal file
BIN
public/imgs/whole-word.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
@ -2,6 +2,7 @@
|
|||||||
<info-bar></info-bar>
|
<info-bar></info-bar>
|
||||||
<tabs></tabs>
|
<tabs></tabs>
|
||||||
<editors></editors>
|
<editors></editors>
|
||||||
|
<search-replace></search-replace>
|
||||||
|
|
||||||
<files-modal></files-modal>
|
<files-modal></files-modal>
|
||||||
</div>
|
</div>
|
@ -3,6 +3,7 @@ import { Component } from '@angular/core';
|
|||||||
import { InfoBarComponent } from './editor/info-bar/info-bar.component';
|
import { InfoBarComponent } from './editor/info-bar/info-bar.component';
|
||||||
import { TabsComponent } from './editor/tabs/tabs.component';
|
import { TabsComponent } from './editor/tabs/tabs.component';
|
||||||
import { EditorsComponent } from './editor/editors.component';
|
import { EditorsComponent } from './editor/editors.component';
|
||||||
|
import { SearchReplaceComponent } from "./editor/search-replace/search-replace.component";
|
||||||
import { FilesModalComponent } from "./common/components/modals/files/files-modal.component";
|
import { FilesModalComponent } from "./common/components/modals/files/files-modal.component";
|
||||||
|
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ import { FilesModalComponent } from "./common/components/modals/files/files-moda
|
|||||||
InfoBarComponent,
|
InfoBarComponent,
|
||||||
TabsComponent,
|
TabsComponent,
|
||||||
EditorsComponent,
|
EditorsComponent,
|
||||||
|
SearchReplaceComponent,
|
||||||
FilesModalComponent
|
FilesModalComponent
|
||||||
],
|
],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
import { Injectable, inject } from '@angular/core';
|
||||||
|
import { ReplaySubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { ServiceMessage } from '../../../types/service-message.type';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SearchReplaceService {
|
||||||
|
private messageSubject: ReplaySubject<ServiceMessage> = new ReplaySubject<ServiceMessage>(1);
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public sendMessage(data: ServiceMessage): void {
|
||||||
|
this.messageSubject.next(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMessage$(): Observable<ServiceMessage> {
|
||||||
|
return this.messageSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,10 +4,10 @@ import { ReplaySubject, Observable } from 'rxjs';
|
|||||||
import { EditSession, UndoManager } from 'ace-builds';
|
import { EditSession, UndoManager } from 'ace-builds';
|
||||||
import { getModeForPath } from 'ace-builds/src-noconflict/ext-modelist';
|
import { getModeForPath } from 'ace-builds/src-noconflict/ext-modelist';
|
||||||
|
|
||||||
import { TabsService } from './tabs/tabs.service';
|
import { TabsService } from './editor/tabs/tabs.service';
|
||||||
|
|
||||||
import { NewtonFile } from '../../types/file.type';
|
import { NewtonFile } from '../types/file.type';
|
||||||
import { ServiceMessage } from '../../types/service-message.type';
|
import { ServiceMessage } from '../types/service-message.type';
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,7 +5,8 @@ import { InfoBarService } from '../../common/services/editor/info-bar/info-bar.s
|
|||||||
import { FilesModalService } from '../../common/services/editor/modals/files-modal.service';
|
import { FilesModalService } from '../../common/services/editor/modals/files-modal.service';
|
||||||
import { TabsService } from '../../common/services/editor/tabs/tabs.service';
|
import { TabsService } from '../../common/services/editor/tabs/tabs.service';
|
||||||
import { EditorsService } from '../../common/services/editor/editors.service';
|
import { EditorsService } from '../../common/services/editor/editors.service';
|
||||||
import { FilesService } from '../../common/services/editor/files.service';
|
import { FilesService } from '../../common/services/files.service';
|
||||||
|
import { SearchReplaceService } from '../../common/services/editor/search-replace/search-replace.service';
|
||||||
|
|
||||||
import { EditorSettings } from "../../common/configs/editor.config";
|
import { EditorSettings } from "../../common/configs/editor.config";
|
||||||
import { NewtonFile } from '../../common/types/file.type';
|
import { NewtonFile } from '../../common/types/file.type';
|
||||||
@ -16,17 +17,18 @@ import { ServiceMessage } from '../../common/types/service-message.type';
|
|||||||
|
|
||||||
@Directive()
|
@Directive()
|
||||||
export class CodeViewBase {
|
export class CodeViewBase {
|
||||||
public uuid: string = uuid.v4();
|
public uuid: string = uuid.v4();
|
||||||
@Input() public isDefault: boolean = false;
|
@Input() public isDefault: boolean = false;
|
||||||
@Input() public isMiniMap: boolean = false;
|
@Input() public isMiniMap: boolean = false;
|
||||||
public leftSiblingUUID!: string;
|
public leftSiblingUUID!: string;
|
||||||
public rightSiblingUUID!: string;
|
public rightSiblingUUID!: string;
|
||||||
|
|
||||||
protected infoBarService: InfoBarService = inject(InfoBarService);
|
protected infoBarService: InfoBarService = inject(InfoBarService);
|
||||||
protected filesModalService: FilesModalService = inject(FilesModalService);
|
protected filesModalService: FilesModalService = inject(FilesModalService);
|
||||||
protected tabsService: TabsService = inject(TabsService);
|
protected tabsService: TabsService = inject(TabsService);
|
||||||
protected editorsService: EditorsService = inject(EditorsService);
|
protected editorsService: EditorsService = inject(EditorsService);
|
||||||
protected filesService: FilesService = inject(FilesService);
|
protected filesService: FilesService = inject(FilesService);
|
||||||
|
protected searchReplaceService: SearchReplaceService = inject(SearchReplaceService);
|
||||||
|
|
||||||
@ViewChild('editor') editorElm!: ElementRef;
|
@ViewChild('editor') editorElm!: ElementRef;
|
||||||
@Input() editorSettings!: typeof EditorSettings;
|
@Input() editorSettings!: typeof EditorSettings;
|
||||||
@ -94,11 +96,19 @@ export class CodeViewBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public searchPopup() {
|
public searchPopup() {
|
||||||
this.editor.execCommand("find");
|
let message = new ServiceMessage();
|
||||||
|
message.action = "toggle-search-replace";
|
||||||
|
this.searchReplaceService.sendMessage(message);
|
||||||
|
|
||||||
|
// this.editor.execCommand("find");
|
||||||
}
|
}
|
||||||
|
|
||||||
public replacePopup() {
|
public replacePopup() {
|
||||||
this.editor.execCommand("replace");
|
let message = new ServiceMessage();
|
||||||
|
message.action = "toggle-search-replace";
|
||||||
|
this.searchReplaceService.sendMessage(message);
|
||||||
|
|
||||||
|
// this.editor.execCommand("replace");
|
||||||
}
|
}
|
||||||
|
|
||||||
public showFilesList() {
|
public showFilesList() {
|
||||||
|
@ -7,10 +7,10 @@ import "ace-builds/src-noconflict/ext-keybinding_menu";
|
|||||||
import "ace-builds/src-noconflict/ext-command_bar";
|
import "ace-builds/src-noconflict/ext-command_bar";
|
||||||
import "ace-builds/src-noconflict/ext-prompt";
|
import "ace-builds/src-noconflict/ext-prompt";
|
||||||
import "ace-builds/src-noconflict/ext-code_lens";
|
import "ace-builds/src-noconflict/ext-code_lens";
|
||||||
import "ace-builds/src-noconflict/ext-searchbox";
|
// import "ace-builds/src-noconflict/ext-searchbox";
|
||||||
import "ace-builds/src-noconflict/ext-language_tools";
|
import "ace-builds/src-noconflict/ext-language_tools";
|
||||||
//import "ace-builds/src-noconflict/theme-one_dark";
|
// import "ace-builds/src-noconflict/theme-one_dark";
|
||||||
//import "ace-builds/src-noconflict/theme-penguins_in_space";
|
// import "ace-builds/src-noconflict/theme-penguins_in_space";
|
||||||
import "ace-builds/src-noconflict/theme-gruvbox";
|
import "ace-builds/src-noconflict/theme-gruvbox";
|
||||||
|
|
||||||
import { CodeViewBase } from './view.base';
|
import { CodeViewBase } from './view.base';
|
||||||
@ -51,6 +51,7 @@ export class CodeViewComponent extends CodeViewBase {
|
|||||||
if (this.isDefault) {
|
if (this.isDefault) {
|
||||||
this.editorsService.setActiveEditor(this.uuid);
|
this.editorsService.setActiveEditor(this.uuid);
|
||||||
this.addActiveStyling();
|
this.addActiveStyling();
|
||||||
|
this.editor.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isMiniMap) {
|
if (this.isMiniMap) {
|
||||||
@ -111,8 +112,10 @@ export class CodeViewComponent extends CodeViewBase {
|
|||||||
let message = new ServiceMessage();
|
let message = new ServiceMessage();
|
||||||
message.action = "set-active-editor";
|
message.action = "set-active-editor";
|
||||||
message.editorUUID = this.uuid;
|
message.editorUUID = this.uuid;
|
||||||
|
message.rawData = this.editor;
|
||||||
|
|
||||||
this.editorsService.sendMessage(message);
|
this.editorsService.sendMessage(message);
|
||||||
|
this.searchReplaceService.sendMessage(message);
|
||||||
|
|
||||||
this.updateInfoBar();
|
this.updateInfoBar();
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,7 @@ import { Subject, takeUntil } from 'rxjs';
|
|||||||
|
|
||||||
import { EditorsService } from '../common/services/editor/editors.service';
|
import { EditorsService } from '../common/services/editor/editors.service';
|
||||||
import { TabsService } from '../common/services/editor/tabs/tabs.service';
|
import { TabsService } from '../common/services/editor/tabs/tabs.service';
|
||||||
import { FilesService } from '../common/services/editor/files.service';
|
import { FilesService } from '../common/services/files.service';
|
||||||
|
|
||||||
import { CodeViewComponent } from "./code-view/view.component";
|
import { CodeViewComponent } from "./code-view/view.component";
|
||||||
|
|
||||||
|
34
src/app/editor/search-replace/search-replace.component.css
Normal file
34
src/app/editor/search-replace/search-replace.component.css
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
.width-8em {
|
||||||
|
width: 8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-tb-1em {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
background-color: rgba(125, 125, 125, 1);
|
||||||
|
color: rgba(0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.searching,
|
||||||
|
.search-success,
|
||||||
|
.search-fail {
|
||||||
|
border-style: solid;
|
||||||
|
color: rgba(125, 125, 125, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searching {
|
||||||
|
border-color: rgba(0, 225, 225, 0.64) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-success {
|
||||||
|
background: rgba(136, 204, 39, 0.12) !important;
|
||||||
|
border-color: rgba(136, 204, 39, 1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-fail {
|
||||||
|
background: rgba(170, 18, 18, 0.12) !important;
|
||||||
|
border-color: rgba(200, 18, 18, 1) !important;
|
||||||
|
}
|
84
src/app/editor/search-replace/search-replace.component.html
Normal file
84
src/app/editor/search-replace/search-replace.component.html
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-3">
|
||||||
|
<label id="find-status-lbl">Find in Current File</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col col-4">
|
||||||
|
<label id="find-options-lbl">Finding with Options: {{findOptions || "Case Insensitive"}}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col col-5 line-height-32px">
|
||||||
|
<button title="Close Panel"
|
||||||
|
class="float-end btn btn-sm btn-dark"
|
||||||
|
(click)="hideSearchReplace()">X
|
||||||
|
</button>
|
||||||
|
<button id="whole-word-btn" title="Whole Word"
|
||||||
|
class="float-end btn btn-sm btn-dark"
|
||||||
|
(click)="toggleWholeWordSearch($event)">
|
||||||
|
<img src="resources/imgs/whole-word.png" />
|
||||||
|
</button>
|
||||||
|
<button id="only-in-selection-btn" title="Only In Selection"
|
||||||
|
class="float-end btn btn-sm btn-dark"
|
||||||
|
(click)="toggleSelectionOnlyScan($event)">
|
||||||
|
<img src="resources/imgs/only-in-selection.png" />
|
||||||
|
</button>
|
||||||
|
<button id="match-case-btn" title="Match Case"
|
||||||
|
class="float-end btn btn-sm btn-dark"
|
||||||
|
(click)="toggleCaseSensitive($event)">Aa
|
||||||
|
</button>
|
||||||
|
<button id="use-regex-btn" title="Use Regex"
|
||||||
|
class="float-end btn btn-sm btn-dark"
|
||||||
|
(click)="toggleRegex($event)">.*
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="margin-tb-1em"></div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="input-group-sm mb-3">
|
||||||
|
<input #findEntryElm
|
||||||
|
id="find-entry"
|
||||||
|
class="form-control"
|
||||||
|
type="search"
|
||||||
|
(keyup)="searchForString()"
|
||||||
|
placeholder="Find in current file..."
|
||||||
|
aria-label="Find in current file..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col col-auto">
|
||||||
|
<button id="find-btn" class="width-8em btn btn-sm btn-dark" (click)="findNextEntry()">Find</button>
|
||||||
|
<button id="find-all-btn" class="width-8em btn btn-sm btn-dark" (click)="findAllEntries()">Find All</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="input-group-sm mb-3">
|
||||||
|
<input #replaceEntryElm
|
||||||
|
id="replace-entry"
|
||||||
|
class="form-control"
|
||||||
|
type="search"
|
||||||
|
(keyup)="replaceEntry($event)"
|
||||||
|
title="Replace in current file..."
|
||||||
|
placeholder="Replace in current file..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col col-auto">
|
||||||
|
<button id="replace-btn" class="width-8em btn btn-sm btn-dark" (click)="replaceEntry($event)">Replace</button>
|
||||||
|
<button id="replace-all-btn" class="width-8em btn btn-sm btn-dark" (click)="replaceAll()">Replace All</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
268
src/app/editor/search-replace/search-replace.component.ts
Normal file
268
src/app/editor/search-replace/search-replace.component.ts
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
import { Component, ElementRef, HostBinding, Input, ViewChild, inject } from '@angular/core';
|
||||||
|
import { Subject, takeUntil } from 'rxjs';
|
||||||
|
|
||||||
|
import { SearchReplaceService } from '../../common/services/editor/search-replace/search-replace.service';
|
||||||
|
|
||||||
|
import { ServiceMessage } from '../../common/types/service-message.type';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'search-replace',
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
],
|
||||||
|
templateUrl: './search-replace.component.html',
|
||||||
|
styleUrl: './search-replace.component.css',
|
||||||
|
host: {
|
||||||
|
'class': 'row search-replace',
|
||||||
|
"(keyup)": "globalSearchReplaceKeyHandler($event)"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class SearchReplaceComponent {
|
||||||
|
private unsubscribe: Subject<void> = new Subject();
|
||||||
|
|
||||||
|
private searchReplaceService: SearchReplaceService = inject(SearchReplaceService);
|
||||||
|
|
||||||
|
@HostBinding("class.hidden") isHidden: boolean = true;
|
||||||
|
@ViewChild('findEntryElm') findEntryElm!: ElementRef;
|
||||||
|
@ViewChild('replaceEntryElm') replaceEntryElm!: ElementRef;
|
||||||
|
|
||||||
|
private editor!: any;
|
||||||
|
|
||||||
|
@Input() findOptions: string = "";
|
||||||
|
private useWholeWordSearch: boolean = false;
|
||||||
|
private searchOnlyInSelection: boolean = false;
|
||||||
|
private useCaseSensitive: boolean = false;
|
||||||
|
private useRegex: boolean = false;
|
||||||
|
private selection: string = "";
|
||||||
|
private query: string = "";
|
||||||
|
private toStr: string = "";
|
||||||
|
private isBackwards: boolean = false;
|
||||||
|
private isWrap: boolean = true;
|
||||||
|
private searchTimeoutId: number = -1;
|
||||||
|
private searchTimeout: number = 400;
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ngAfterViewInit(): void {
|
||||||
|
this.loadSubscribers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ngOnDestroy() {
|
||||||
|
this.unsubscribe.next();
|
||||||
|
this.unsubscribe.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadSubscribers() {
|
||||||
|
this.searchReplaceService.getMessage$().pipe(
|
||||||
|
takeUntil(this.unsubscribe)
|
||||||
|
).subscribe((message: ServiceMessage) => {
|
||||||
|
if (message.action === "toggle-search-replace") {
|
||||||
|
this.toggleSearchReplace(message);
|
||||||
|
} else if (message.action === "set-active-editor") {
|
||||||
|
this.setActiveEditor(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private toggleSearchReplace(message: ServiceMessage) {
|
||||||
|
this.selection = this.editor.getSelectedText();
|
||||||
|
this.findEntryElm.nativeElement.value = this.selection;
|
||||||
|
|
||||||
|
if (this.selection && !this.isHidden) {
|
||||||
|
this.findEntryElm.nativeElement.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isHidden = !this.isHidden;
|
||||||
|
|
||||||
|
if (this.isHidden) {
|
||||||
|
this.editor.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.findEntryElm.nativeElement.focus();
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private setActiveEditor(message: ServiceMessage) {
|
||||||
|
if (!this.isHidden && this.editor == message.rawData) return;
|
||||||
|
|
||||||
|
this.editor = message.rawData;
|
||||||
|
|
||||||
|
if (this.isHidden) return;
|
||||||
|
|
||||||
|
|
||||||
|
this.searchForString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public hideSearchReplace() {
|
||||||
|
if (this.selection) {
|
||||||
|
this.selection = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isHidden = true;
|
||||||
|
this.editor.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public globalSearchReplaceKeyHandler(event: any) {
|
||||||
|
if (event.ctrlKey && event.key === "f") {
|
||||||
|
this.hideSearchReplace();
|
||||||
|
} else if (event.ctrlKey && event.key === "l") {
|
||||||
|
this.findEntryElm.nativeElement.focus();
|
||||||
|
} else if (event.ctrlKey && event.key === "r") {
|
||||||
|
this.replaceEntryElm.nativeElement.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleWholeWordSearch(event: any) {
|
||||||
|
let target = event.target;
|
||||||
|
if (target.nodeName === "IMG")
|
||||||
|
target = target.parentElement;
|
||||||
|
|
||||||
|
this.useWholeWordSearch = !this.useWholeWordSearch;
|
||||||
|
target.classList.toggle("selected");
|
||||||
|
this.setFindOptionsLbl();
|
||||||
|
this.findAllEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleSelectionOnlyScan(event: any) {
|
||||||
|
let target = event.target;
|
||||||
|
if (target.nodeName === "IMG")
|
||||||
|
target = target.parentElement;
|
||||||
|
|
||||||
|
this.searchOnlyInSelection = !this.searchOnlyInSelection;
|
||||||
|
target.classList.toggle("selected");
|
||||||
|
this.setFindOptionsLbl();
|
||||||
|
this.findAllEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleCaseSensitive(event: any) {
|
||||||
|
this.useCaseSensitive = !this.useCaseSensitive;
|
||||||
|
event.target.classList.toggle("selected");
|
||||||
|
this.setFindOptionsLbl();
|
||||||
|
this.findAllEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleRegex(event: any) {
|
||||||
|
this.useRegex = !this.useRegex;
|
||||||
|
event.target.classList.toggle("selected");
|
||||||
|
this.setFindOptionsLbl();
|
||||||
|
this.findAllEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setFindOptionsLbl() {
|
||||||
|
let findOptionsStr = "";
|
||||||
|
|
||||||
|
if (this.useRegex)
|
||||||
|
findOptionsStr += "Regex"
|
||||||
|
|
||||||
|
findOptionsStr += (findOptionsStr) ? ", " : "";
|
||||||
|
findOptionsStr += (this.useCaseSensitive) ? "Case Sensitive" : "Case InSensitive";
|
||||||
|
|
||||||
|
if (this.searchOnlyInSelection)
|
||||||
|
findOptionsStr += ", Within Current Selection"
|
||||||
|
|
||||||
|
if (this.useWholeWordSearch)
|
||||||
|
findOptionsStr += ", Whole Word"
|
||||||
|
|
||||||
|
this.findOptions = findOptionsStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public findNextEntry() {
|
||||||
|
this.editor.findNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public findAllEntries() {
|
||||||
|
this.query = this.findEntryElm.nativeElement.value;
|
||||||
|
|
||||||
|
if (!this.query) return;
|
||||||
|
|
||||||
|
let totalCount = this.editor.findAll(this.query, {
|
||||||
|
backwards: this.isBackwards,
|
||||||
|
wrap: this.isWrap,
|
||||||
|
caseSensitive: this.useCaseSensitive,
|
||||||
|
wholeWord: this.useWholeWordSearch,
|
||||||
|
regExp: this.useRegex,
|
||||||
|
range: this.searchOnlyInSelection
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public findPreviousEntry() {
|
||||||
|
this.editor.findPrevious();
|
||||||
|
}
|
||||||
|
|
||||||
|
public replaceEntry(event: any) {
|
||||||
|
if (event instanceof KeyboardEvent) {
|
||||||
|
if (event.key !== "Enter") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fromStr = this.findEntryElm.nativeElement.value;
|
||||||
|
let toStr = this.replaceEntryElm.nativeElement.value;
|
||||||
|
|
||||||
|
if (!fromStr || !toStr) return;
|
||||||
|
|
||||||
|
let totalCount = this.editor.replace(toStr, fromStr, {
|
||||||
|
backwards: this.isBackwards,
|
||||||
|
wrap: this.isWrap,
|
||||||
|
caseSensitive: this.useCaseSensitive,
|
||||||
|
wholeWord: this.useWholeWordSearch,
|
||||||
|
regExp: this.useRegex,
|
||||||
|
range: this.searchOnlyInSelection
|
||||||
|
});
|
||||||
|
|
||||||
|
this.editor.clearSelection();
|
||||||
|
this.editor.findNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public replaceAll() {
|
||||||
|
let fromStr = this.findEntryElm.nativeElement.value;
|
||||||
|
let toStr = this.replaceEntryElm.nativeElement.value;
|
||||||
|
|
||||||
|
if (!fromStr || !toStr) return;
|
||||||
|
|
||||||
|
let totalCount = this.editor.replaceAll(toStr, fromStr, {
|
||||||
|
backwards: this.isBackwards,
|
||||||
|
wrap: this.isWrap,
|
||||||
|
caseSensitive: this.useCaseSensitive,
|
||||||
|
wholeWord: this.useWholeWordSearch,
|
||||||
|
regExp: this.useRegex,
|
||||||
|
range: this.searchOnlyInSelection
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public searchForString() {
|
||||||
|
if (event instanceof KeyboardEvent) {
|
||||||
|
if (event.key !== "Enter") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.query = this.findEntryElm.nativeElement.value;
|
||||||
|
|
||||||
|
if (!this.query) return;
|
||||||
|
|
||||||
|
if (this.searchTimeoutId) { clearTimeout(this.searchTimeoutId); }
|
||||||
|
|
||||||
|
this.searchTimeoutId = setTimeout(() => {
|
||||||
|
let totalCount = this.editor.find(this.query, {
|
||||||
|
backwards: this.isBackwards,
|
||||||
|
wrap: this.isWrap,
|
||||||
|
caseSensitive: this.useCaseSensitive,
|
||||||
|
wholeWord: this.useWholeWordSearch,
|
||||||
|
regExp: this.useRegex,
|
||||||
|
range: this.searchOnlyInSelection
|
||||||
|
});
|
||||||
|
}, this.searchTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -26,6 +26,16 @@ body {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-replace {
|
||||||
|
bottom: 2em;
|
||||||
|
z-index: 999;
|
||||||
|
display: inline-block;
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
background-color: rgba(64, 64, 64, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
Loading…
Reference in New Issue
Block a user