Answer the question
In order to leave comments, you need to log in
How to get the coordinates of an element in an iframe?
In general, the task is to render a reactive table of contents for the contents of the WYSIWYG editor.
I am working with React and I am integrating ckeditor as an editor. The task is to make it so that when filling the editor with content, all headings are parsed and reactively displayed as a table of contents next to the editor window. At the same time, the items in this table of contents should be clickable - on click, the editor window should scroll to the corresponding anchor (title). Available plugins only allow you to display a table with a table of contents, but do not make its elements clickable.
I decided to "manually" extract the titles from the content of the editor, display them, and link them to anchors inside the editor. But that didn't work, navigating through anchors inside an iframe is either not possible or I couldn't find a way to do it. Then I decided to hang handlers on these displayed headers and use the scrollTo method to simulate the transition through anchors.
There was a problem here with getting the coordinates of the headings in the editor text (inside the iframe). headerObj.offsetTop always returns equal to 0.
I would be glad for help in solving the problem in any way)
import React, { useState } from 'react';
import CKEditor from 'ckeditor4-react';
const App = () => {
const [headers, setHeaders] = useState([]);
const handleChange = e => {
const content = e.editor.getData();
const contentObject = document.createElement('div');
contentObject.innerHTML = content;
const headersArray = [...contentObject.getElementsByTagName('h2')];
setHeaders(headersArray);
};
const goToAnchor = headerObj => {
const frame = document.getElementsByTagName('iframe')[0];
const top = headerObj.offsetTop + frame.contentWindow.scrollY;
frame.contentWindow.scrollTo({
top: top,
behavior: "smooth"
})
};
return (
<div className="App">
<h2>Using CKEditor 4 in React</h2>
<CKEditor
data="<h2>1. Заголовок 1</h2><h2>2. Заголовок 2</h2><h2>3. Заголовок 3</h2>"
onChange={e => handleChange(e)}
/>
<div>
<h2>Содержание</h2>
{headers.map((header, index) => {
return (
<h2
key={index}
dangerouslySetInnerHTML={{__html: header.innerHTML}}
onClick={() => goToAnchor(header)}
/>
);
})}
</div>
</div>
);
};
export default App;
Answer the question
In order to leave comments, you need to log in
headerObj.offsetTop
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question