JSFiddle - React, Tailwind, and code Playground
Dual TinyMCE communication
by tonytlwu
HTML
<script src="https://tinymce.cachefly.net/4.3/tinymce.min.js"></script>
<p>This demo uses 2 TinyMCEs to sync configurations and commands.</p>
<hr />
<textarea id="phantom"></textarea>
<p>Zoom: <input type="range" id="zoom" name="zoom" min="10" max="100" value="100" /></p>
<div id="device">
<div id="preview">
<h3>Here's a bunch of content</h3>
<p>
Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Vestibulum id ligula porta felis euismod semper.
</p>
<ul>
<li>Risus Egestas</li>
<li>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</li>
<li>Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</li>
<li>Adipiscing Magna Parturient Justo</li>
</ul>
</div>
</div>
CSS
#preview {
background: #fff;
width: 100%;
height: 100%;
border: 1px solid #afafaf;
box-sizing: border-box;
padding: 10px;
font-size: 14px;
font-family: 'Open Sans';
overflow: hidden;
}
#preview h1,
#preview h2,
#preview h3 {
font-family: Dosis;
font-weight: 200;
font-size: 1.65em;
color: #00abd1;
}
#device {
width: 320px;
height: 568px;
box-sizing: content-box;
padding: 60px 15px 80px;
background-color: #d0d2d2;
border-radius: 32px;
margin: 20px auto;
transform-origin: center top;
transition: all 0.2s ease-out;
}
#device > iframe {
width: 100%;
height: 100%;
}
#phantom_ifr {
/* Hides Phantom Editor */
display: none !important;
}
.mce-container.disabled {
opacity: 0.5;
pointer-events: none;
}
.mce-tinymce-inline {
display: none !important;
}
JavaScript
function syncPreviewToPhantom() {
tinymce.get('phantom').setContent(document.querySelector('#preview').innerHTML);
}
function savePreviewEditor() {
tinymce.get('preview').save();
}
// Phantom TinyMCE setup
tinymce.init({
selector: '#phantom',
menubar: false,
statusbar: false,
setup: function(ed) {
ed.on('BeforeExecCommand', function(e) {
var cmd = e.command;
var ui = e.ui;
var value = e.value;
tinymce.get('preview').execCommand(cmd, ui, value);
// return false; // Prevents the command from executing in the Phantom Editor so the button state doesn't change
});
}
});
// Preview TinyMCE setup
tinymce.init({
selector: '#preview',
menubar: false,
inline: true,
setup: function(ed) {
setTimeout(syncPreviewToPhantom, 0);
ed.on('change paste keyup mouseup focus blur', function(e) {
// savePreviewEditor();
// syncPreviewToPhantom();
var activeButtons = document.querySelectorAll('.mce-tinymce-inline .mce-toolbar-grp .mce-btn');
var label = null;
for (var i = 0, l = activeButtons.length; i < l; i++) {
label = activeButtons[i].getAttribute('aria-label');
if ( label !== null ) {
if ( activeButtons[i].classList.contains('mce-active') ) {
tinymce.get('phantom').editorContainer.querySelector('.mce-toolbar-grp .mce-btn[aria-label="'+label+'"]').classList.add('mce-active');
} else {
tinymce.get('phantom').editorContainer.querySelector('.mce-toolbar-grp .mce-btn[aria-label="'+label+'"]').classList.remove('mce-active');
}
}
}
});
}
});
// Adds zoom functionality
function zoomDevice() {
var zoom = document.querySelector('#zoom').value;
var device = document.querySelector('#device');
device.style.webkitTransform = 'scale(' + (zoom/100) + ')';
device.style.transform = 'scale(' + (zoom/100) + ')';
}
document.querySelector('#zoom').addEventListener( 'change', zoomDevice, false );