【发布时间】:2022-01-23 10:05:17
【问题描述】:
【问题讨论】:
标签: javascript html angular
【问题讨论】:
标签: javascript html angular
您应该能够轻松地将其转换为角度代码。 这是您需要做的基本工作,它没有经过全面测试,但它几乎可以工作。
const textarea = document.getElementById('text')
const result = document.getElementById('selected')
const tooltip = document.getElementById('tooltip')
const cols = document.getElementById('text').cols;
const width = document.getElementById('text').clientWidth;
const height = window.getComputedStyle(textarea).lineHeight;
textarea.onclick = function getSelection() {
const pos = {
top: textarea.offsetTop,
left: textarea.offsetLeft,
};
result.textContent = `${textarea.selectionStart}, ${textarea.selectionEnd}`;
let selection
if (textarea.selectionStart) {
selection = textarea.selectionStart;
} else if (document.selection) {
textarea.focus();
const r = document.selection.createRange();
if (r == null) {
selection = 0;
}
let re = textarea.createTextRange();
let rc = re.duplicate();
re.moveToBookmark(r.getBookmark());
rc.setEndPoint('EndToStart', re);
selection = rc.text.length;
} else {
selection = 0
}
const row = Math.floor((selection - 1) / cols);
const col = (selection - (row * cols));
const x = Math.floor((col * (width / cols)));
const y = (parseInt(height) * row);
tooltip.innerHTML = "<b>row: " + row + "<br>columns" + col + "<br>width: " + width + "</b>";
tooltip.style.top = `${pos.top+y}px`;
tooltip.style.left = `${pos.left+x+10}px`;
}
textarea {
height: 80px;
line-height: 12px;
overflow-y: scroll;
display: block;
}
#tooltip {
position: absolute;
background:red;
color: white;
}
<textarea id="text">Lopsum</textarea>
<span id="tooltip"></span>
<span id="selected"></span>
【讨论】:
tooltip.style.left, tooltip.style.top
我想的唯一方法是创建文本区域的副本(非常类似于 SO,(欧文开尔文的回应)关于文本区域中的高亮词
由于我们只需要位置,我们可以拆分“texarea”和“background”。此外,使用 another SO 中的 Yurzui 响应,我们可以控制何时调整文本区域的大小
我们可以想象一个 .html 之类的
<div class="container">
<div
#backdrop
class="backdrop"
[style.width.px]="textWidth"
[style.height.px]="textHeight"
>
<div
class="highlights"
[innerHTML]="sanitizer.bypassSecurityTrustHtml(highlightedText)"
></div>
</div>
</div>
<textarea
#textarea
spellcheck="false"
(resize)="rect = null;"
(select)="applyHighlights(textarea.value)"
(mousedown)="mouseDown()"
(blur)="rect = null"
[ngModel]="textValue"
(ngModelChange)="textValue = $event; applyHighlights(textarea.value)"
(scroll)="handleScroll(); applyHighlights(textarea.value)"
></textarea>
<div
class="tooltip"
*ngIf="rect"
[style.top.px]="rect.y"
[style.left.px]="rect.x"
></div>
看到“文本”被隐藏了,因为我们有一个像这样的 div 容器
.container {
overflow:hidden;
width:0;
height:0;
}
我们使“text”的尺寸由两个变量“textWidth”和“textHeight”决定
代码是
ngOnInit() {
this.resize();
}
resize() {
const event = {
width: this.$textarea.nativeElement.getBoundingClientRect().width,
height: this.$textarea.nativeElement.getBoundingClientRect().height,
};
this.textWidth = event.width;
this.textHeight = event.height;
}
mouseDown() {
setTimeout(() => {
const start = this.$textarea.nativeElement.selectionStart;
const end = this.$textarea.nativeElement.selectionEnd;
if (start == end) this.rect = null;
});
}
applyHighlights(text: string) {
if (text) {
let start = this.$textarea.nativeElement.selectionStart;
let end = this.$textarea.nativeElement.selectionEnd;
if (start == end) this.highlightedText = text;
else {
const selected = text.substr(start, end - start);
this.toolTipText=this.getTooltipText(selected)
this.highlightedText =
text.substr(0, start) +
"<span id='mark'>" +
selected +
'</span>' +
text.substr(end);
this.resize();
setTimeout(() => {
const recArea = this.$textarea.nativeElement.getBoundingClientRect();
const recText = this.$backdrop.nativeElement.getBoundingClientRect();
const rect = document.getElementById('mark').getBoundingClientRect();
rect.y += window.scrollY;
rect.x+=rect.width/2
this.rect = rect.y - window.scrollY < recArea.y ? null : rect;
});
}
}
}
handleScroll() {
var scrollTop = this.$textarea.nativeElement.scrollTop;
this.$backdrop.nativeElement.scrollTop = scrollTop;
var scrollLeft = this.$textarea.nativeElement.scrollLeft;
this.$backdrop.nativeElement.scrollLeft = scrollLeft;
}
我在stackblitz 中放入了一个自定义表单组件(原因是欧文为我做了这个工作
【讨论】: