I''ve been trying to use both the xinha html editor (the successor to
htmlarea) and the prototype library in my Rails project.
Unfortunately they conflict. I''ve written to Sam Stephenson, but
didn''t get a response, so I''m hoping someone on the list can
give
insight.
The problem is that prototype.js extends the Object prototype. Since
all objects are descendants of Object, this will affect all objects.
Xinha often iterates over objects, and gets all counfused when it
encounters the ''extend'' function - how could it know it would
be there?
The ''extend'' approach seems to be elegant - but it
isn''t so elegant
if it later unexpectedly breaks other apps. After reading the code a
few times, I still can''t 100% understand what this function is
actually used for. Can anyone explain? Does anyone have an idea of
how to work around this?
Here''s a more detailed analysis of the problem:
When I had both prototype.js and htmlare.js enabled, the editor
didn''t show. I was getting strange messages like:
"btn[1] has no properties" in Firefox, or
"''1'' is null or not an object" in Internet Explorer
Somehow I found that if I remove the Prototype library, the editor
shows. I''ve tracked it down to this bit of code - when I commented it
out, the editor would show:
Object.prototype.extend = function(object) {
for (property in object) {
this[property] = object[property];
}
return this;
}
I searched the htmlarea.js for ''extend'', thinking that this
was
somehow overriding something there, but it doesn''t contain the
string. So I''ve had a session with Venkman. The problem occurs in
many places in htmlarea.js, one of them for example:
// initialize tooltips from the I18N module and generate correct
image path
for (var i in this.btnList) {
var btn = this.btnList[i];
if(typeof btn[1] != ''string'')
{
btn[1][0] = _editor_url + this.imgURL + btn[1][0];
}
else
{
btn[1] = _editor_url + this.imgURL + btn[1];
}
btn[0] = HTMLArea._lc(btn[0]); //initialize tooltip
}
btnList is an array of arrays, indexed by strings. so you have btnList
[''bold''], btnList[''italic'']... but because
you add the ''extend''
property to all of the objects, the for loop iterates over btnList
[''extend''] too, which is not an array, and it dies there.
The Xinha folks couldn''t have expected that you will extend the
Object prototype of course. I did a stupid workaround:
// initialize tooltips from the I18N module and generate correct
image path
for (var i in this.btnList) {
if (i != "extend") {
var btn = this.btnList[i];
if(typeof btn[1] != ''string'')
{
btn[1][0] = _editor_url + this.imgURL + btn[1][0];
}
else
{
btn[1] = _editor_url + this.imgURL + btn[1];
}
btn[0] = HTMLArea._lc(btn[0]); //initialize tooltip
}
}
This works, but it isn''t the ideal solution, and I would have to do
it in a dozen places, and after that I still wouldn''t be sure that
everything works. I don''t know what would be the best solution, maybe
if Prototype would only extend its own classes, and not Object? Or
should the Xinha guys rewrite their code?
Here''s how ''extend'' is being used in effects.js for
example - it
seems to be adding bits of code somewhere, but I don''t really
understand the approach or the purpose...
Effect.Opacity = Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype,
Effect.Base.prototype), {
initialize: function(element) {
this.element = $(element);
options = Object.extend({
from: 0.0,
to: 1.0
}, arguments[1] || {});
this.start(options);
},
update: function(position) {
this.setOpacity(position);
},
setOpacity: function(opacity) {
opacity = (opacity == 1) ? 0.99999 : opacity;
this.element.style.opacity = opacity;
this.element.style.filter =
"alpha(opacity:"+opacity*100+")";
}
});
regards,
Zoltan Varady
p.s. Xinha can be found at: http://xinha.python-hosting.com/