Sometime ago I wrote a script that allows to use CKEditor, and at the same time keep using older scripts existing on the page that relied on reading the textarea.value (or even writing it), without having to modify them to use the CKEditor API.
The initial version worked with Firefox and Internet Explorer 8, and shortly after I added some adjustments so that Opera was also supported.
Recently a comment in that second post stated that the script gave errors in Chrome, although it tries to detect if the API that I was using is supported, but of course, webkit guys decided to implement the API but not make it available for native properties. Their statement is that treating native properties as overridable would have a negative effect on performance, and as we all know it's much more important to have a fast browser than a browser that allows the developers to do new things; unless you're in their team then you can write a new API for whatever you need and everyone else should use this API because it will change the world, you'll no longer have to use Flash because now you have this API to overcome other problems that we didn't want to fix. Besides the bug tickets commented previously, here's another one: bug 36423
Ok, enough ranting.
As I said, I've worked to find out the problems and the funny fact about this new version is that it works in Chrome but it still fails in Safari 5.1. So you can use it in your site if can restrict the browser used by your users to IE8+, Firefox 3.5+ , Opera 10+, and Chrome 12+ (I don't really know the oldest version of Firefox, Opera and Chrome where this will work, but I wouldn't expect anyone to use old versions of those browsers)
// Modify the default methods in CKEDITOR.dom.element to use .nativeValue if it's available CKEDITOR.dom.element.prototype.getValue = function() { if (typeof(this.$.nativeValue) == "undefined") return this.$.value; return this.$.nativeValue; } CKEDITOR.dom.element.prototype.setValue = function( value ) { if (typeof(this.$.nativeValue) == "undefined") this.$.value = value; else this.$.nativeValue = value; return this; } // Hook each textarea with its editor CKEDITOR.on('instanceCreated', function(e) { if (e.editor.element.getName()=="textarea") { var node = e.editor.element.$; // If the .nativeValue hasn't been set for the textarea try to do it now if (typeof node.nativeValue == "undefined") { // for Opera & Firefox if (!DefineNativeValue(node)) { // IE8 & Webkit if (!DefineValueProperty(node)) { alert("Your browser is buggy. You should upgrade to something newer") return; } } } node.editor = e.editor; // House keeping. e.editor.on('destroy', function(e) { if (node.editor) delete node.editor; }); } }); // This function alters the behavior of the .value property to work with CKEditor // It also provides a new property .nativeValue that reflects the original .value // It can be used with HTMLTextAreaElement.prototype for Firefox, but Opera needs to call it on a textarea instance function DefineNativeValue(node) { if (!node.__lookupGetter__) return false; var originalGetter = node.__lookupGetter__("value"); var originalSetter = node.__lookupSetter__("value"); if (originalGetter && originalSetter) { node.__defineGetter__("value", function() { // if there's an editor, return its value if (this.editor) return this.editor.getData(); // else return the native value return originalGetter.call(this); } ); node.__defineSetter__("value", function(data) { // If there's an editor, set its value if (this.editor) this.editor.setData(data); // always set the native value originalSetter.call(this, data) } ); node.__defineGetter__("nativeValue", function() { return originalGetter.call(this); } ); node.__defineSetter__("nativeValue", function(data) { originalSetter.call(this, data) } ); return true } return false; } function DefineValueProperty(node) { var originalValuepropDesc = Object.getOwnPropertyDescriptor(node, "value"); if (!originalValuepropDesc) return false; // Safari doesn't allow to overwrite the property (but Chrome does) if (!originalValuepropDesc.configurable) return false; Object.defineProperty(node, "nativeValue", { get: function() { return ( originalValuepropDesc.get ? originalValuepropDesc.get.call(this) : originalValuepropDesc.value ); }, set: function(data) { originalValuepropDesc.set ? originalValuepropDesc.set.call(this, data) : originalValuepropDesc.value = data; } } ); Object.defineProperty(node, "value", { get: function() { // if there's an editor, return its value if (this.editor) return this.editor.getData(); // else return the native value return this.nativeValue; }, set: function(data) { // If there's an editor, set its value if (this.editor) this.editor.setData(data); // always set the native value this.nativeValue = data; } } ); return true; } // Detection, not really needed, but it can help troubleshoting. if (Object.defineProperty) { // IE 8 and updated webkits // Detect Safari if (document.head) { var test = Object.getOwnPropertyDescriptor(document.head, "innerHTML"); // IE9 if (!test) { if (!DefineValueProperty(HTMLTextAreaElement.prototype)) alert("Unable to define property override on the prototype"); } else if (!test.configurable) alert("Safari doesn't allow to overwrite native properties"); } } else if (document.__defineGetter__) { // FF 3.5 and Opera 10 // We try to get the innerHTML getter for the body, if it works then getting the value for each textarea will work // Detect old webkits if (!document.body.__lookupGetter__("innerHTML")) alert("Old webkits don't allow to read the originalGetter and Setter for the textarea value"); } else { // detect IE8 in compatibility mode... if (document.documentMode) alert("The page is running in Compatibility Mode (" + document.documentMode + "). Fix that") else alert("Your version of IE is too old"); }