View Full Version : wysiwyg editor cursor control

04-28-2004, 09:15 PM
Folks, I know it's been done over and over and better than I've done so far, but all I need is very minor functionality, and I don't feel like learning a new piece of software's API. Now: I'm using simple buttons at the moment to enable my bold, italic, and underline functionality. The problem exists in both IE and Firefox, but manifests itself differently.

When I click a formatting button (such as bold), the focus stays on the button. IE will continue typing, which is odd as no control has been granted back to the editable document's iframe. The space bar presses the button again. This leads to the strange situation of allowing the user to type with every other word appearing in bold and the rest in normal text. Firefox doesn't have the typing problem, as it never moves focus off the button.

Okay, so Firefox is doing exactly what I've programmed it to. IE has the quirk of directing non-canceled keystrokes to the input buffer, so that they appear in the editable document.

The big question: Is there a way to return focus to the last place focus existed in an editable-document iframe? If pointers for either browser can be shared, I'd love to write the code forking.

And here, for you all to enjoy and ridicule me by, is my code as it exists so far. I'm using Chris Nott's (dithered.com) DOM2Events class to bring IE up to snuff, and pointed this demo version at the file published at dithered. I highly recommend grabbing it, as it's usually a lifesaver for event handling!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<script type="text/javascript" src="http://www.dithered.com/javascript/dom2_events/dom2_events.js"></script>
<script type="text/javascript">
window.onload = loadHandler;
function loadHandler () {
function getIframeDocument (iframeName) {
var d;
if (document.getElementById(iframeName).contentWindow.document) {
d = document.getElementById(iframeName).contentWindow.document;
} else if (document.frames[iframeName].document != document) {
d = document.frames[iframeName].document;
return d;
function launchDocument () {
var d = window.open('about:blank').document,
newDoc = getIframeDocument('editableDocument').documentElement.innerHTML;
function doCmd (e) {
if (typeof(DOM2Event) != 'undefined' || typeof(e.target) == 'undefined') {
e = new DOM2Event(e, window.event);
var d = getIframeDocument('editableDocument');
if (!d.execCommand) {
d = d.document;
d.execCommand(e.target.id.toLowerCase(), false, null);
function loadDocument () {
var d = getIframeDocument('editableDocument'),
btns = ['Bold','Italic','Underline','Undo','Redo','JustifyLeft','JustifyCenter','JustifyRight'],
i = btns.length,
try {
pageContent = document.getElementById('originalContent').innerHTML;
if (typeof(d.designMode) != 'undefined') {
d.designMode = "on";
} else {
d.setAttribute("contentEditable", true);
do {
document.getElementById(btns[--i]).addEventListener('click', doCmd, false);
} while (i > 0);
} catch (E) {
var err = 'There is a problem with the document, and it is not editable. Please try again later.\n\nIf this error has occurred before, please contact the Solutions Center.\n';
for (var r in E) {
err += '\n' + r + ': ' + E[r];
<style type="text/css">
.originalDocument {
display: none;
#documentControls {
margin: 0;
border: 0;
padding: 0;
#documentControls button {
width: 2.5em;
#editableDocument {
width: 90%;
height: 30em;
overflow: auto;
background: #fff;
color: #000;
<legend>Edit Document</legend>
<fieldset id="documentControls">
<button type="button" id="Bold" title="Bold"><strong>B</strong></button>
<button type="button" id="Italic" title="Italics"><em>I</em></button>
<button type="button" id="Underline" title="Underline"><u>U</u></button>

<button type="button" id="Undo" title="Undo">&lt;-</button>
<button type="button" id="Redo" title="Redo">-&gt;</button>
<button type="button" id="JustifyLeft" title="Align left">&lt;&lt;</button>
<button type="button" id="JustifyCenter" title="Center">&gt;&lt;</button>
<button type="button" id="JustifyRight" title="Align right">&gt;&gt;</button>

<iframe id="editableDocument" src="about:blank"></iframe>

<button type="button" onclick="launchDocument();" class="submit">Print</button>

<div id="originalContent" class="originalDocument">
<p style="float:right;">
Safety Office<br />
Department of Transportation<br />
State of Georgia<br />

Wednesday, April 28, 2004
<p style="clear:both;">
Department of Administrative Services<br />
State of Georgia<br />
<p style="text-indent: 2em;">This is a Sworn Proof of Loss of one GDOT <strong>(type of property)</strong>. It's lost. We swear.</p>

<p style="text-indent: 2em;">We've got proof.</p>
<p>Thank you,</p>
<p>Robert Maguire</p>
<p>State Safety Coordinator</p>

05-01-2004, 11:12 AM
The big question: Is there a way to return focus to the last place focus existed...

For IE, one can use the createRange method, along with the onbeforedeactivate event, to store the caret location (in a global var)... then, when a command button is clicked, use the select method of the created textRange to return focus at the stored position, and finally execute the execCommand from the caret pos.