I am building a rich text editor and want to autosave the text in the iframe. I have multiple code parts and snippets which – taken by itself – are working perfectly but I am failing to assemble them correctly. LIVEDEMO
Here is a graphic of what I want to achieve:
I have an editable iFrame which is my text editor. The innerHTML of this iFrame should be loaded into a textarea hidden under the iframe and the content of the textarea should be saved in the localStorage regularly.
The iFrame code works.
<script>
function iFrameOn() {
richTextField.document.designMode = 'On';
}
function iBold() {
richTextField.document.execCommand('bold', false, null);
}
function iUnderline() {
richTextField.document.execCommand('underline', false, null);
}
function iItalic() {
richTextField.document.execCommand('italic', false, null);
}
function iFontSize() {
var size = prompt('Enter a size 1-7', '')
richTextField.document.execCommand('FontSize', false, size);
}
function iForeColor() {
var color = prompt('Define a basic color or apply a hexadecimal color code for advanced colors:', '')
richTextField.document.execCommand('ForeColor', false, color);
}
function iHorizontalRule() {
richTextField.document.execCommand('InsertHorizontalRule', false, null);
}
function iUnorderedList() {
richTextField.document.execCommand('InsertUnorderedList', false, "newUL");
}
function iOrderedList() {
richTextField.document.execCommand('InsertOrderedList', false, "newOL");
}
function iLink() {
var linkURL = prompt('Enter the URL for this link:', 'http://')
richTextField.document.execCommand('CreateLink', false, linkURL);
}
function iUnLink() {
richTextField.document.execCommand('UnLink', false, null);
}
function iImage() {
var imgSrc = prompt('Enter image location:', '');
if(imgSrc != null){
richTextField.document.execCommand('insertimage', false, imgSrc);
}
}
</script>
<body onLoad="iFrameOn();">
<h2>Text Editor</h2>
<form action="my_parse_file.php" name="myform" id="myform" method="post" onLoad="autosave_form();">
<fieldset>
<p>Entry Title: <input name="title" id="title" type="text" size="80" maxlength="80" /></p>
<p>Entry Body:<br />
<div id="wysiwyg_cp" style="padding: 8px; width: 700px;">
<input type="button" onClick="iBold()" value="B" />
<input type="button" onClick="iUnderline()" value="U" />
<input type="button" onClick="iItalic()" value="I" />
<input type="button" onClick="iFontSize()" value="Text Size" />
<input type="button" onClick="iForeColor()" value="Text Color" />
<input type="button" onClick="iHorizontalRule()" value="HR" />
<input type="button" onClick="iUnorderedList()" value="UL" />
<input type="button" onClick="iOrderedList()" value="OL" />
<input type="button" onClick="iLink()" value="Link" />
<input type="button" onClick="iUnLink()" value="UnLink" />
<input type="button" onClick="iImage()" value="Image" />
</div>
<textarea style="display: none;" name="myTextArea" id="myTextArea" cols="100" rows="14"></textarea>
<iframe name="richTextField" id="richTextField" style="border: #000000 1px solid; width: 700px; height: 300px"></iframe>
</p><br />
<input name="myBtn" type="button" value="Submit Data" onClick="javascript:submit_form();"/>
</fieldset>
</form>
</body>
The autosaver also works – but only with the textarea and not the iFrame.
// get the state of the form
function getFormState() {
var fields = document.getElementsByTagName('form')[0].elements;
if (fields.length == 0){return};
for (var i = 1; i <= fields.length-1; i++) {
var name = fields[i].getAttribute('name');
if (name in localStorage && localStorage[name] !== null) {
fields[i].value = localStorage[name];
}
}
}
// save the state of the form
function saveFormState() {
var fields = document.getElementsByTagName('form')[0].elements;
if (fields.length == 0){return};
var populated = false;
for (var i = 1; i <= fields.length-1; i++) {
var name = fields[i].getAttribute('name');
if (fields[i].value != '' && fields[i].getAttribute('type') != 'submit') {
localStorage[name] = fields[i].value;
populated = true;
}
}
// display the time form data was saved (optional)
if (populated) {
var date = new Date();
var hours = date.getHours();
var mins = date.getMinutes();
var secs = date.getSeconds();
hours = (hours < 10) ? '0' + hours : hours;
mins = (mins < 10) ? '0' + mins : mins;
secs = (secs < 10) ? '0' + secs : secs;
var msg = '[Form data was saved at ' + hours + ':' + mins + ':' + secs + ']';
var timecont = document.getElementById('time_container');
if (timecont !== null) {
timecont.innerHTML = msg;
}
else {
timecont = document.createElement('span');
timecont.setAttribute('id', 'time_container');
timecont.appendChild(document.createTextNode(msg));
document.getElementsByTagName('fieldset')[0].appendChild(timecont);
}
}
}
// run the above functions when the web page is loaded
window.onload = function () {
// check if HTML5 localStorage is supported by the browser
if ('localStorage' in window && window['localStorage'] !== null) {
// get the form state
getFormState();
// save the state of the form each 15 seconds (customizable)
setInterval('saveFormState()', 15 * 1000);
}
}
And now I need some binding code which loads the innerHTML of the iFrame routinely into the textarea.
function autosave_form() {
var theForm = document.getElementbyID('myform');
theForm.elements["myTextArea"].value = window.frames['richTextField'].document.body.innerHTML;
setTimeout(yourFunction, 5000);
}
So where are my fellacies? Or what did I overlook? Please help. LIVEDEMO
You're not using the interface on the iframe object correctly. To get the content of an iframe on the same domain, you need to go through the contentWindow field. For example:
function read_iframe() {
return window.frames['richTextField'].contentWindow.document.body.innerHTML;
}
Remember that you cannot read the content of an iframe on another domain.
You can find complete docs on the HTMLIFrameElement's methods and fields at https://developer.mozilla.org/en/docs/Web/API/HTMLIFrameElement