Avoid using tinymce in polymer as it heavily relies on the document root, which can be broken by shadow dom.
However, there is a solution...
Utilize an object in your polymer template to load tinymce and resolve the document root issue. Once loaded, you can access tinymce from the object in the following manner.
Create an HTML file to load tinymce
<!DOCTYPE html>
<html>
<head>
<script src="https://cloud.tinymce.com/stable/tinymce.min.js"></script>
<style>
html { height: 96%; }
body { height: 96%; }
</style>
</head>
<body>
<textarea>Loading...</textarea>
<script>
var ta = document.querySelector('textarea');
ta.tinymce = tinymce;
var editorChangeHandler;
tinymce.init({ selector: 'textarea', height: document.body.scrollHeight - 100, setup: function (editor) {
editor.on('Paste Change input Undo Redo', function () {
if (editorChangeHandler) { clearTimeout(editorChangeHandler); }
editorChangeHandler = setTimeout(function () {
ta.dispatchEvent(new CustomEvent('save'));
}, 2000);
});
} });
</script>
</body>
</html>
Add an object to your component template and use the data attribute of the object to load the HTML content.
Once loaded, access the object, query the DOM, retrieve the textarea, add event listeners for custom save events, pre-set content, adjust height, etc. Be cautious about cross-domain issues, although serving alongside other components should work fine.
Include the object in your component template
<object id="editor" type="text/html" data="/src/lib/tinymce/tinymce.html"></object>
Pre-load, retrieve content, set height, and handle save events
ready() {
super.ready();
// wait five seconds before capturing input
var interval = setInterval(() => {
if (!this.$.editor.contentDocument.body) return;
let ta = this.$.editor.contentDocument.body.querySelector('textarea');
if (!ta || !ta.tinymce || !ta.tinymce.activeEditor) return;
// clear interval once loaded
window.clearInterval(interval);
setTimeout(() => {
// resize on window change
window.addEventListener('resize', this._updateEditorSize.bind(this));
// pre-load content
ta.tinymce.activeEditor.setContent(this.element.value);
// listen for save events every few seconds, with a 4-second debounce on save naturally
ta.addEventListener('save', (ev) => {
this.set('element.value', ta.tinymce.activeEditor.getContent({ format: 'raw' }));
});
}, 250);
}, 250);
}
This approach works smoothly for polymer 3 and tinymce, providing fast loading, auto-resizing, and efficient handling of save events without altering tinymce's default setup. You can apply a similar method to circumvent shadow dom limitations in other embedded applications.