问题
I am attempting to emulate Medium style comments in an html document.
This answer has gotten me nearly there: How to implement Medium-style commenting interface in VueJS
With that method, I can highlight text and make comments, but I want to display the coments on the same line as the range the commenter selected. The code as I have treats every paragraph it seems as a separate document, such that I don't know how to return to the correct paragraph to find the original range being commented on.
Here is the commenting component:
<template>
<div class="popup" :style="{top: offsetTop, left: offsetLeft}" ref="popup">
<span @click="AlertSelectedText">Comment</span>
</div>
</template>
<script>
export default {
data() {
return {
popupInitialTopOffset: 0,
popupInitialLeftOffset: 0,
offsetTop: 0,
offsetLeft: "-999em",
selectedText: undefined
};
},
methods: {
ListenToDocumentSelection() {
let sel = window.getSelection();
console.log('sel is: ', sel)
setTimeout(_ => {
if (sel && !sel.isCollapsed) {
this.selectedText = sel.toString();
if (sel.rangeCount) {
let range = sel.getRangeAt(0).cloneRange();
console.log('range is: ', range)
if (range.getBoundingClientRect) {
var rect = range.getBoundingClientRect();
console.log('boundingrect is: ', rect)
let left = rect.left + (rect.right - rect.left) / 2;
let top = rect.top;
this.offsetTop = top - this.popupInitialTopOffset - 30 + "px";
this.offsetLeft = left - this.popupInitialLeftOffset / 2 + "px";
}
}
} else {
this.offsetLeft = "-999em";
}
}, 0);
},
AlertSelectedText() {
alert(`"${this.selectedText}" posted as comment`);
}
},
mounted() {
this.popupInitialTopOffset = this.$refs.popup.offsetHeight;
this.popupInitialLeftOffset = this.$refs.popup.offsetWidth;
console.log('this is the positions of the popup', this.popupInitialTopOffset, this.popupInitialLeftOffset);
window.addEventListener("mouseup", this.ListenToDocumentSelection);
},
destroyed() {
window.removeEventListener("mouseup", this.ListenToDocumentSelection);
}
};
</script>
<style scoped>
.popup {
position: absolute;
color: #FFF;
background-color: #000;
padding: 10px;
border-radius: 5px;
transform-origin: center, center;
cursor: pointer;
}
.popup:after {
content: "";
border-bottom: 5px solid #000;
border-right: 5px solid #000;
border-top: 5px solid transparent;
border-left: 5px solid transparent;
position: absolute;
top: calc(100% - 5px);
transform: rotate(45deg);
left: calc(50% - 3px);
}
</style>
if I could know how to add coordinates for returning to the commented range, I think I could manage the rest.
回答1:
Wherever you want to enable commenting, try giving those elements a class and a unique ID.
A class would help you identify that it has commenting enabled whereas an ID would help you uniquely identify it.
In your logic, you can access the list of classes on that element as
sel.anchorNode.parentElement.classList
and ID as
sel.anchorNode.parentElement.id
With the help of this combination, you can surely associate a comment to your elements.
来源:https://stackoverflow.com/questions/61149760/trying-to-display-comments-near-appropriate-doc-range-in-vue-component