我是javascript的新手。我正在尝试做一个简单的切换div用户选择方向生病放置切换div。经过一些谷歌搜索我发现一个工作小提琴但不如预期请参阅下面的截图,看看差异< / p>
当我选择段落前面的一些文字时,它可以正常使用
其实我在React版本中工作Fiddle是在Jquery
这是我的代码
import React from 'react'
import {render} from 'react-dom';
export default class App extends React.Component{
constructor(props){
super(props);
this.state = {
display:'none' ,
top:'',
bottom:'',
left:'',
right:'',
diplayForDown:'none'
};
this.handleOnMouseDown = this.handleOnMouseDown.bind(this)
this.onMounseUp = this.onMounseUp.bind(this)
this.onMouseDwn = this.onMouseDwn.bind(this)
this.triggerAlltime = this.triggerAlltime.bind(this)
}
handleOnMouseDown(){
let sel = window.getSelection && window.getSelection();
let r = sel.getRangeAt(0).getBoundingClientRect();
let relative=document.body.parentNode.getBoundingClientRect();
console.log('Relative ',relative);
if(!sel.isCollapsed){
console.log(sel,r);
let display = 'block';
let top = (r.bottom - relative.top - 80)+'px';
let bottom = r.bottom+'px';
let left =( r.left)+'px';
let right = (r.right)+'px';
console.log('This is Height',r.bottom-r.top);
let selectionHeight = r.bottom - r.top;
if(selectionHeight => 22.22){
this.setState({
display,
top:top,
bottom,
left,
right
})
}else{
this.setState({
display,
top,
bottom,
left,
right
})
}
}else{
this.setState({
display:'none'
})
}
console.log('Slected')
}
onMounseUp(e){
e.preventDefault()
let sel = window.getSelection && window.getSelection();
if(!sel.isCollapsed){
console.log('Moved Up')
}
}
onMouseDwn(e){
let sel = window.getSelection && window.getSelection();
if(!sel.isCollapsed){
console.log('Moved Down')
}
}
getSelectionHtml() {
let html = "";
if (typeof window.getSelection != "undefined") {
let sel = window.getSelection();
if (sel.rangeCount) {
let container = document.createElement("div");
for (let i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
console.log('html',html)
return html;
}
lastCharRTL(txt) {
return /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]$/.test(txt);
}
triggerAlltime(e){
// console.log('Some Thinms')
if(!window.getSelection().isCollapsed){
//find the Direction Of Slelection
let sel = window.getSelection();
console.log(sel)
let range = document.createRange();
range.setStart(sel.anchorNode, sel.anchorOffset);
range.setEnd(sel.focusNode, sel.focusOffset);
let backwards = range.collapsed;
range.detach();
// get selection rects
let rects = sel.getRangeAt(0).getClientRects();
let n = rects.length - 1;
let display = 'block';
console.log(this.lastCharRTL(this.getSelectionHtml()))
if (this.lastCharRTL(this.getSelectionHtml()))
this.setState({
display:'none',
diplayForDown:'none',
top: rects[n].top + 10,
left: rects[n].left - 10
})
else if (backwards)
this.setState({
display,
diplayForDown:'none',
top: rects[0].top + -68,
left: rects[0].left
})
else
this.setState({
display:'none',
diplayForDown:'block',
top: rects[n].top + 40,
left: rects[n].right+-160
})
}else{
this.setState({
display:'none',
diplayForDown:'none',
})
}
}
render(){
return(
<div className="container">
<div className="CenterCon">
<div contentEditable="true" onMouseUp={this.triggerAlltime} onMouseDown={this.triggerAlltime} onKeyUp={this.triggerAlltime} onKeyDown={this.triggerAlltime} className="Edithis" >
<p>Test</p>
</div>
</div>
<div style={{top: this.state.top, bottom: this.state.bottom, left:this.state.left, right:this.state.right, display: this.state.display}} className="Toggle">
<ul>
<li>B</li>
<li>U</li>
<li>H</li>
<li>"</li>
</ul>
<div className="triangle">
</div>
</div>
{/*DownWard Toggle*/}
<div style={{top: this.state.top, bottom: this.state.bottom, left: this.state.left, right: this.state.right, display: this.state.diplayForDown}} className="ToggleForDownWardSelection">
<div className="triangle-bottom" />
<ul>
<li>B</li>
<li>U</li>
<li>H</li>
<li>li</li>
</ul>
</div>
</div>
)
}
}
render(<App/>,document.getElementById('app'));
答案 0 :(得分:2)
最后我找到了答案,我修复了它将简单样式应用于contentEditable div 它就像一个魅力一样工作。我不知道它为什么有效但我怀疑 窗口API
<div contentEditable="true" style={{height:'100vh',overflow:'auto'}} onMouseUp={this.triggerAlltime} onMouseDown={this.triggerAlltime} onKeyUp={this.triggerAlltime} onKeyDown={this.triggerAlltime} className="Edithis" >
<p>Test</p>
</div>
答案 1 :(得分:1)
问题是#pointer
设置为绝对位置,但是当内容长且可滚动时,最高距离是从窗口顶部而不是内容顶部计算的。
添加height: 100vh
可以解决此问题,但在某些情况下您可能会看到两个滚动条。
另一种方法是在计算指针div的window.pageYOffset
时添加top
。
if (backwards) {
$('#pointer').css({top: rects[0].top + window.pageYOffset + 10, left: rects[0].left - 10}).show();
} else {
$('#pointer').css({top: rects[n].top + window.pageYOffset + 10, left: rects[n].right}).show();
}
这是DEMO
答案 2 :(得分:0)
没有办法做到这一点。您可以检查鼠标按下并取消按下事件位置并确定初始/结束位置,以确定它是向前还是向后选择。
答案 3 :(得分:0)
const isBackwards = () => {
const selection = window.getSelection();
let range = document.createRange();
range.setStart(selection.anchorNode, selection.anchorOffset);
range.setEnd(selection.focusNode, selection.focusOffset);
let backwards = range.collapsed;
range.detach();
return backwards;
}