Reputation: 4306
I am trying to select a few words from the textarea and create bootstrap chips.
I am able to create the chips for selected words. I am trying to highlight the selected words with different background colors.
export class SearchComponent implements OnInit {
constructor() { }
selectedText = [];
regexFromMyArray: RegExp;
// tslint:disable-next-line:typedef
showSelectedText() {
let text = '';
if (window.getSelection) {
text = window.getSelection().toString();
if (text) {
// console.log(this.selectedText.includes(text));
if (this.selectedText.includes(text) === false)
{
this.selectedText.push(text);
this.regexFromMyArray = new RegExp(this.selectedText.join('|'), 'ig');
console.log(this.regexFromMyArray);
}
}
}
// console.log(this.selectedText);
return this.selectedText;
}
// tslint:disable-next-line:typedef
removeItem(array, item){
for (const i in array){
if (array[i] === item){
array.splice(i, 1);
break;
}
}
}
// tslint:disable-next-line:typedef
deleteChip(el) {
// el.style.display = 'none';
document.getElementById(el).style.display = 'none';
this.removeItem(this.selectedText, el);
}
ngOnInit(): void {
}
}
I am not sure how to highlight the words in the selectedText
array. I want to highlight all chip words. Like "Contrary", "Ipsum", "classical", "literature".
Help will be appreciated.
Upvotes: 2
Views: 6465
Reputation: 15083
This answer is based on the link provided by @RobinDijkhof in there comment.
We will set up the css exactly as provided
*,
*::before,
*::after {
box-sizing: border-box;
}
.container,
.backdrop,
textarea {
width: 460px;
height: 180px;
}
.highlights,
textarea {
padding: 10px;
font: 20px/28px "Open Sans", sans-serif;
letter-spacing: 1px;
}
.container {
display: block;
margin: 0 auto;
transform: translateZ(0);
-webkit-text-size-adjust: none;
}
.backdrop {
position: absolute;
z-index: 1;
border: 2px solid #685972;
background-color: #fff;
overflow: auto;
pointer-events: none;
transition: transform 1s;
}
.highlights {
white-space: pre-wrap;
word-wrap: break-word;
color: transparent;
}
textarea {
display: block;
position: absolute;
z-index: 2;
margin: 0;
border: 2px solid #74637f;
border-radius: 0;
color: #444;
background-color: transparent;
overflow: auto;
resize: none;
transition: transform 1s;
}
mark {
border-radius: 3px;
color: transparent;
background-color: #b1d5e5;
}
.perspective textarea {
transform: perspective(1500px) translateX(155px) rotateY(45deg) scale(1.1);
}
textarea:focus,
button:focus {
outline: none;
box-shadow: 0 0 0 2px #c6aada;
}
Now to the task will be to convert the JQuery code to Angular. We will build a component that can be used like
<app-textarea-highlight [(ngModel)]='txt'
[highlightTexts]='highlightTexts'
></app-textarea-highlight>
Where the values are
highlightTexts = ["text", "demo", "div"];
txt = "This demo shows how to highlight bits of text within a textarea. Alright, that's a lie. You can't actually render markup inside a textarea. However, you can fake it by carefully positioning a div behind the textarea and adding your highlight markup there.
}
To enable using property binding we will implement ControlValueAccessor
Below is the code
@Component({
selector: "app-textarea-highlight",
templateUrl: "./textarea-highlight.component.html",
styleUrls: ["./textarea-highlight.component.css"],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextareaHighlightComponent),
multi: true
}
]
})
export class TextareaHighlightComponent
implements ControlValueAccessor {
constructor() {}
@Input() highlightTexts: string[] = [];
@ViewChild("backdrop") $backdrop: ElementRef<HTMLDivElement>;
@ViewChild("textarea") $textarea: ElementRef<HTMLTextAreaElement>;
textValue: string = "";
get highlightedText () {
return this.applyHighlights(this.textValue)
}
applyHighlights(text) {
text = text ? text
.replace(/\n$/g, "\n\n") : '';
this.highlightTexts.forEach(x => {
text = text
.replace(new RegExp(x, 'g'), "<mark>$&</mark>");
})
return text;
}
handleScroll() {
var scrollTop = this.$textarea.nativeElement.scrollTop;
this.$backdrop.nativeElement.scrollTop = scrollTop;
var scrollLeft = this.$textarea.nativeElement.scrollLeft;
this.$backdrop.nativeElement.scrollLeft = scrollLeft;
}
onChanges: ($value: any) => void;
onTouched: () => void;
writeValue(value: any): void {
if (value !== undefined) {
this.textValue = value;
}
}
registerOnChange(fn: any): void {
this.onChanges = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
}
The final step is to set the html
<div class="container">
<div #backdrop class="backdrop">
<div class="highlights" [innerHTML]="highlightedText"></div>
</div>
<textarea
[(ngModel)]="textValue"
(scroll)="handleScroll()"
#textarea
></textarea>
</div>
Upvotes: 12
Reputation: 2004
You can try this.
HTML
<span class="highlightText">Your text</span>
CSS
.highlightText {
background: yellow;
}
Another Tip Any CSS text-related property will affect the whole text within the the textarea/input. You'll need an editable element or document to achieve syntax highlighting. Example (works in all recent browsers; the last major browser not to support contenteditable was Firefox 2.0):
<code contenteditable="true">
<span style="color: blue">var</span> foo = <span style="color: green">"bar"</span>;
</code>
Upvotes: -2