DOM error: "node cannot be inserted". Why not?

D

dennis.sprengers

I am trying to write an editor object, which adds some functionality
and a toolbar to every textarea with a "form-textarea" class. Both FF
and IE generate an error in line 20
(container.appendChild(this.toolbar);) saying "Node cannot be inserted
at the specified point in the hierarchy" code: "3"

I have two questions:
- who would help me with this error
- please provide other feedback about my code, since I want to write a
solid framework

I've pasted all code (including general library functions), to provide
a complete overview.

Any help is greatly appreciated,
Dennis


/********************************** editor code
*******************************/
var Editor = {
version : "1.0 beta",

init : function() {
var textareaNodes = document.getElementsByTagName('textarea');
var thisTextarea, i = 0;
while ((thisTextarea = textareaNodes[i++])) {
if (hasClass(thisTextarea, 'form-textarea')) {
new this.textEditor(thisTextarea);
}
}
},

textEditor : function(textarea) {
this.textarea = textarea;
this.value = textarea.value.replace(/\s+$/g, "");
this.textarea.className = 'editor-textarea';
this.textarea.rows = this.value.split("\n").length;
var container = createNode('div', {
'class' : 'texteditor ' + this.textarea.id}
);
this.toolbar = Editor.textToolbar;
container.appendChild(this.toolbar);
container.appendChild(this.textarea);
this.textarea.parentNode.insertBefore(container, this.textarea);
Editor.detectKey(this.textarea);
this.textarea.focus();
},

detectKey : function(textarea) {
var theHandler = this.handleKey;
if (document.all) textarea.onkeydown = function(e) {
theHandler.call(self, e, textarea);
}
else textarea.onkeypress = function(e) {
theHandler.call(self, e, textarea);
}
},

handleKey : function(e, textarea) {
if (!e || e == null) var e = window.event;
if (e.keyCode) key = e.keyCode;
else if (e.which) key = e.which - 32;
Editor.growTextarea(textarea);
},

growTextarea : function(textarea) {
var value = textarea.value, newlines = value.split("\n"), i = 0,
rows = 1;
while (newline = newlines[i++]) {
rows += Math.ceil(newline.length / textarea.cols);
}
textarea.rows = rows;
},

textToolbar : function() {
str = createNode('input', {'type' : 'checkbox'});
return str;
}
}

addLoadEvent(function () {
Editor.init();
});

/******************************* library functions
****************************/

function addLoadEvent(func) {
var oldOnload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
}
else {
window.onload = function() {
oldOnload();
func();
}
}
}

function hasClass(el, className) {
return (
el.className &&
el.className.match(new RegExp("\\b" + className + "\\b"))
) ? true : false;
}

function createNode(type, options) {
var el = document.createElement(type);
for (var key in options) {
el.setAttribute(key, options[key]);
}
return el;
}
 
R

RobG

I am trying to write an editor object, which adds some functionality
and a toolbar to every textarea with a "form-textarea" class. Both FF
and IE generate an error in line 20
(container.appendChild(this.toolbar);) saying "Node cannot be inserted
at the specified point in the hierarchy" code: "3"

I have two questions:
- who would help me with this error
- please provide other feedback about my code, since I want to write a
solid framework

I've pasted all code (including general library functions), to provide
a complete overview.

Any help is greatly appreciated,
Dennis

/********************************** editor code
*******************************/
var Editor = {
version : "1.0 beta",

init : function() {
var textareaNodes = document.getElementsByTagName('textarea');
var thisTextarea, i = 0;
while ((thisTextarea = textareaNodes[i++])) {

I think it is better here to use:

var i = textareaNodes.length;
while (i--) {
thisTextarea = textareaNodes;
...
}


Usually I have found that puting assignments inside conditionals is
slower than doing them outside. Also, a plain for loop is probably
more readable for most and just as fast in modern browsers.

if (hasClass(thisTextarea, 'form-textarea')) {
new this.textEditor(thisTextarea);
}
}
},

textEditor : function(textarea) {
this.textarea = textarea;
this.value = textarea.value.replace(/\s+$/g, "");
this.textarea.className = 'editor-textarea';
this.textarea.rows = this.value.split("\n").length;
var container = createNode('div', {
'class' : 'texteditor ' + this.textarea.id}
);
this.toolbar = Editor.textToolbar;

Did you mean to call it?

this.toolbar = Editor.textToolbar();

container.appendChild(this.toolbar);

Presumably you want to append whatever is returned by the call to
Editor.textToolbar, which is an input element.

container.appendChild(this.textarea);
this.textarea.parentNode.insertBefore(container, this.textarea);

Here is your next problem - this.textarea.parentNode is container (the
line above makes it so), so it is effectively:

container.insertBefore(container, this.textarea)

The first argument to insertBefore should be the node to be inserted
(the new child), container can't be inserted into itself.

<URL: http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-952280727 >
 
G

Gregor Kofler

(e-mail address removed) meinte:
I am trying to write an editor object, which adds some functionality
and a toolbar to every textarea with a "form-textarea" class. Both FF
and IE generate an error in line 20
(container.appendChild(this.toolbar);) saying "Node cannot be inserted
at the specified point in the hierarchy" code: "3"

I have two questions:
- who would help me with this error
- please provide other feedback about my code, since I want to write a
solid framework

I've pasted all code (including general library functions), to provide
a complete overview.

Any help is greatly appreciated,
Dennis
detectKey : function(textarea) {
var theHandler = this.handleKey;
if (document.all) textarea.onkeydown = function(e) {
theHandler.call(self, e, textarea);
}
else textarea.onkeypress = function(e) {
theHandler.call(self, e, textarea);
}
},

What's this document.all check supposed to do? Lets see: IE knows
document.all, Opera knows it, Safari does, Firefox doesn't (IIRC it does
in quirks mode - but since I've never needed and used document.all I
might be wrong). Anyway, why are you assigning the same listener to
different handlers then?
handleKey : function(e, textarea) {
if (!e || e == null) var e = window.event;

e = e || window.event; does the same.

Gregor
 
H

Henry

(e-mail address removed) meinte:
What's this document.all check supposed to do? Lets see:
IE knows document.all, Opera knows it, Safari does,
Firefox doesn't (IIRC it does in quirks mode - but since
I've never needed and used document.all I might be wrong).
Anyway, why are you assigning the same listener to
different handlers then?


e = e || window.event; does the same.

While you are at it, all values of - e - that could result in true for
- e == null - will result in true for - !e -, so whenever the - e ==
null - expression is evaluated the result must always be false, making
the expression redundant and its evaluation a needless runtime
overhead.

Declaring - var e - is pointless as the function's formal parameter -
e - results in the Variable object having an 'e' property by the time
the variable declaration is processed (so it cannot result in the
creation of such a property), and that variable declaration is not
allowed to alter the value of any pre-existing properties of the
Variable object. Making that declaration pointless at best and a
needless runtime overhead at worst.
 
T

Thomas 'PointedEars' Lahn

Gregor said:
(e-mail address removed) meinte:

e = e || window.event; does the same.

More efficient, and recommended:

if (!e) e = window.event;
if (e)
{
// ...
}

The `=' operation performed always only adds needless runtime overhead[tm]
if e == true, and the value assigned, if necessary, should be tested for as
well.


PointedEars
 
L

Lasse Reichstein Nielsen

Thomas 'PointedEars' Lahn said:
Gregor Kofler wrote:

More efficient, and recommended:

if (!e) e = window.event;

I wouldn't recommend either over the other.

The minuscule difference in execution time is unlikely to be relevant,
since events are typically caused by user interaction, which dwarves
any such small optimizations.

/L 'Premature optimization is the root of all evil'
 
T

Thomas 'PointedEars' Lahn

Lasse said:
I wouldn't recommend either over the other.

The minuscule difference in execution time is unlikely to be relevant,

JFTR: The first optimization step, although not semantically equal as
stated, was unlikely to be relevant for the single statement as well, and
you did not object to that.
since events are typically caused by user interaction, which dwarves
any such small optimizations.

IBTD. Exactly *because* events are usually caused by user interaction they
can be caused several times in short intervals. Therefore, optimizing event
listeners is of the utmost importance in order to create a responsive user
interface. Several runtime overheads deemed "miniscule" at first do add up.

Anyway, due to the single-threaded environment, thoughtful optimization
steps should be applied to every piece of client-side script code.


PointedEars
 
R

RobG

(e-mail address removed) meinte:
What's this document.all check supposed to do? Lets see:
IE knows document.all, Opera knows it, Safari does,
Firefox doesn't (IIRC it does in quirks mode - but since
I've never needed and used document.all I might be wrong).
Anyway, why are you assigning the same listener to
different handlers then?
[...]
Declaring - var e - is pointless as the function's formal parameter -
e - results in the Variable object having an 'e' property by the time
the variable declaration is processed (so it cannot result in the
creation of such a property), and that variable declaration is not
allowed to alter the value of any pre-existing properties of the
Variable object. Making that declaration pointless at best and a
needless runtime overhead at worst.

The above explanation is correct for browsers that conform to the
ECMAScript specification, however for old versions of Safari
(somewhere around 1.0 I think) the declaration with var is required in
this particular case due to a browser bug, though I seem to remember
using:

var e = e || window.event;

The declaration is performed before any code is executed, therefore it
should have zero effect on performance after its initial parsing.
 
T

Thomas 'PointedEars' Lahn

RobG said:
(e-mail address removed) meinte:
handleKey : function(e, textarea) {
if (!e || e == null) var e = window.event;
[...]
Declaring - var e - is pointless as the function's formal parameter -
e - results in the Variable object having an 'e' property by the time
the variable declaration is processed (so it cannot result in the
creation of such a property), and that variable declaration is not
allowed to alter the value of any pre-existing properties of the
Variable object. Making that declaration pointless at best and a
needless runtime overhead at worst.

The above explanation is correct for browsers that conform to the
ECMAScript specification, however for old versions of Safari
(somewhere around 1.0 I think) the declaration with var is required in
this particular case due to a browser bug, [...]

I don't follow. Do you mean to say that Safari 1.x did not support named
arguments or did not allow to modify argument values? If so, I would simply
remove this UA from considerations because it is clearly FUBAR.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,260
Messages
2,571,039
Members
48,768
Latest member
first4landlord

Latest Threads

Top