Why browserfreeze when appending childnode?

  • Thread starter dennis.sprengers
  • Start date
D

dennis.sprengers

Hi all,

I'm writing my first javascript prototyped application (many thanks to
Thomas 'PointedEars' Lahn for explaining "this" stuff to me :) but am
experiencing a problem.

I'm writing a function that transformes an ordinary textarea in a
textarea with a UBB type toolbar. Left of the original textarea, I
want to attach textarea which I will transform into a gutter with
linecount (as any programming editor has).

I'm attaching all my code. I commented out one line (//
container.appendChild(this.gutter);). If uncommented, the code runs
smoothly, uncommented, my browser freezes and I don't understand why.
I'm doing nothing more than appending a childnode (gutter) to the
container div. Could somebody please me explain why this happend and
how I can resolve it? Any help would be greatly appreciated!

Keep in mind that the editor depends on a css file that is not
included, so the layout of the editor may not be all that :)


/*********************** FUNCTIONS FROM OTHER LIBRARIES
***********************/

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

document.getElementsByClassName = function(className) {
var elements = new Array ();
var children = document.getElementsByTagName("*");
for (var a = 0; a < children.length; a++) {
if (children[a].hasClass(className)) elements.push (children[a]);
}
return elements;
}

Element.prototype.hasClass = function(className) {
return (
this.className &&
this.className.match(new RegExp("\\b" + className + "\\b"))
) ? true : false;
}

String.prototype.ucfirst = function() {
return this.charAt(0).toUpperCase() + this.substr(1);
}

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

Object.extend = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
};

function setCookie(sName, sValue){
document.cookie = sName + '=' + escape(sValue) + '; expires=Fri, 31
Dec 2030 23:59:59 GMT; path=/';
}

function getCookie(sName) {
var aCookie = document.cookie.split('; '), i = aCookie.length,
aCrumb;
while (i--) {
aCrumb = aCookie.split('=');
if (sName == aCrumb[0]) {
return typeof aCrumb[1] != 'undefined' ? unescape(aCrumb[1]) :
null;
}
}
return null;
}

/*********************** FUNCTIONS FROM OTHER LIBRARIES
***********************/

addLoadEvent(editorInit);

function editorInit() {
var theTextareas = document.getElementsByTagName('textarea');
var thisTextarea, i = 0;

while ((thisTextarea = theTextareas[i++])) {
if (thisTextarea.hasClass('form-text')) {
if (thisTextarea.id == '') {
thisTextarea.id = thisTextarea.name;
}
new textEditor(thisTextarea);
}
}
}

function textEditor(textarea) {
var parent = textarea.parentNode;
var nextsibling = textarea.nextSibling;

var container = createNode('div', {'id' : textarea.name + '-
txtContainer',
'className' : 'txtContainer'}
);

this.txtToolbarItems = ['bold', 'underline', 'italic', 'strike',
'link',
'image', 'wrap', 'tabs'
];
this.txtOpenTags = {'b' : false, 'u' : false, 'i' : false, 's' :
false}

this.textarea = parent.removeChild(textarea);
this.textarea.setAttribute('wrap', 'off');
this.toolbar = this.createToolbar();
this.gutter = this.createGutter();

container.appendChild(this.toolbar);
//container.appendChild(this.gutter);
container.appendChild(this.textarea);

if (nextsibling) {
parent.insertBefore(container, nextsibling);
}
else {
parent.appendChild(container);
}

this.detectKey();

var target = this.textarea;
if (typeof target.createTextRange != 'undefined') {
target.onkeyup = storeCursor;
target.onclick = storeCursor;
target.onselect = storeCursor;
}

target.focus();
}

Object.extend(textEditor.prototype, {
createToolbar : function() {
theList = document.createElement('ul');
theList.className = 'txtToolbar';
for (var i = 0; i < this.txtToolbarItems.length; i++) {
button = this.createButton(this.txtToolbarItems);
if (button) {
theList.appendChild(button);
}
}
return theList;
},

createButton : function(name) {
var menuItem = document.createElement('li');
menuItem.className = 'txtButton' + name.ucfirst();
menuItem.action = name;
var self = this;
var onclickHandler = this.toolbarAction;
menuItem.onclick = function() {
onclickHandler.call(self, name);
return false;
}
return menuItem;
},

createGutter : function() {
var target = this.textarea;
gutter = createNode('textarea', {'id' : target.name + '-gutter',
'className' : 'gutter'}
);
return gutter;
},

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

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

if (key == 9 && (getCookie('tabs') == 1)) {
this.toolbarAction('plain', ' ');
return cancelEvent(e);
}

if (e.ctrlKey && !e.shiftKey) {
switch (key) {
case 66:
this.toolbarAction('bold');
return cancelEvent(e);
break;
case 73:
this.toolbarAction('italic');
return cancelEvent(e);
break;
case 83:
this.toolbarAction('strike');
return cancelEvent(e);
break;
case 85:
this.toolbarAction('underline');
return cancelEvent(e);
break;
}
}
return true;
},

toolbarAction : function(theAction, text) {
var target = this.textarea;
if (typeof target.cursorPos != 'undefined') {
this.IEWrap(theAction, text);
}
else {
this.mozWrap(theAction, text);
}
target.focus();
},

mozWrap : function(type, text) {
var target = this.textarea;
var scrollTop = target.scrollTop;
var sStart = target.selectionStart;
var sEnd = target.selectionEnd;

if (type != 'plain') {
text = target.value.substring(sStart, sEnd);
}
text = this.replaceText(type, text);
var nStart = (sStart == sEnd) ? sStart + text.length : sStart;
var nEnd = sStart + text.length;
target.value = target.value.substr(0, sStart) + text +
target.value.substr(sEnd);
target.setSelectionRange(nEnd, nEnd);
target.scrollTop = scrollTop;
},

IEWrap : function(type, text) {
var target = this.textarea;
var cursorPos = target.cursorPos;

if (type != 'plain') {
text = cursorPos.text;
}
cursorPos.text = replaceText(type, text);
},

replaceText : function(type, text) {
var tags = this.txtOpenTags;
var target = this.textarea;
switch (type) {
case 'plain':
break;
case 'bold':
if (text) {
var re = new RegExp('^<b[^>]*>(.*?)</b>$');
text = (!re.test(text)) ? '<b>'+ text +'</b>' :
text.replace(re, '$1');
}
else {
text = (tags['b'] == false) ? '<b>' : '</b>';
tags['b'] = (tags['b'] == false) ? true : false;
}
break;
case 'underline':
if (text) {
var re = new RegExp('^<u[^>]*>(.*?)</u>$');
text = (!re.test(text)) ? '<u>'+ text +'</u>' :
text.replace(re, '$1');
}
else {
text = (tags['u'] == false) ? '<u>' : '</u>';
tags['u'] = (tags['u'] == false) ? true : false;
}
break;
case 'italic':
if (text) {
var re = new RegExp('^<i[^>]*>(.*?)</i>$');
text = (!re.test(text)) ? '<i>'+ text +'</i>' :
text.replace(re, '$1');
}
else {
text = (tags['i'] == false) ? '<i>' : '</i>';
tags['i'] = (tags['i'] == false) ? true : false;
}
break;
case 'strike':
if (text) {
var re = new RegExp('^<s[^>]*>(.*?)</s>$');
text = (!re.test(text)) ? '<s>'+ text +'</s>' :
text.replace(re, '$1');
}
else {
text = (tags['s'] == false) ? '<s>' : '</s>';
tags['s'] = (tags['s'] == false) ? true : false;
}
break;
case 'link':
createPopup('link');
break;
case 'image':
createPopup('image');
break;
case 'wrap':
wrap = target.getAttribute('wrap');
if (wrap.toLowerCase() == 'off') {
target.setAttribute('wrap', 'soft');
var parNod = target.parentNode, nxtSib = target.nextSibling;
parNod.removeChild(target);
parNod.insertBefore(target, nxtSib);
}
else {
target.setAttribute('wrap', 'off');
var parNod = target.parentNode, nxtSib = target.nextSibling;
parNod.removeChild(target); parNod.insertBefore(target,
nxtSib);
}
break;
case 'tabs':
var value = (getCookie('tabs') && getCookie('tabs') == 1) ?
0 : 1;
setCookie('tabs', value)
break;
}
return text;
}
});

function cancelEvent(e) {
var e = e || window.event;

e.cancelBubble = true;
if (typeof e.stopPropagation == 'function') {
e.stopPropagation();
}
e.returnValue = false;
if (typeof e.preventDefault == 'function') {
e.preventDefault();
}
}

function storeCursor() {
this.cursorPos = document.selection.createRange().duplicate();
}
 
E

Ed

I'm attaching all my code. I commented out one line (//
container.appendChild(this.gutter);). If uncommented, the code runs
smoothly, uncommented, my browser freezes and I don't understand why.
I'm doing nothing more than appending a childnode (gutter) to the
container div. Could somebody please me explain why this happend and
how I can resolve it? Any help would be greatly appreciated!
function editorInit() {
  var theTextareas = document.getElementsByTagName('textarea');

Here, theTextareas is a NodeList, which is "live": if a textarea is
subsequently added to the document, that textarea is automatically
added to theTextareas.

http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#td-live
  var thisTextarea, i = 0;

  while ((thisTextarea = theTextareas[i++])) {
    if (thisTextarea.hasClass('form-text')) {
      if (thisTextarea.id == '') {
        thisTextarea.id = thisTextarea.name;
      }
      new textEditor(thisTextarea);

This constructor calls container.appendChild(this.gutter), adding a
new textarea to the document and hence to theTextareas. This will
cause the loop to execute again, adding another textarea, and so on ...
 
D

dennis.sprengers

I'm attaching all my code. I commented out one line (//
container.appendChild(this.gutter);). If uncommented, the code runs
smoothly, uncommented, my browser freezes and I don't understand why.
I'm doing nothing more than appending a childnode (gutter) to the
container div. Could somebody please me explain why this happend and
how I can resolve it? Any help would be greatly appreciated!
function editorInit() {
var theTextareas = document.getElementsByTagName('textarea');

Here, theTextareas is a NodeList, which is "live": if a textarea is
subsequently added to the document, that textarea is automatically
added to theTextareas.

http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#td-...
var thisTextarea, i = 0;
while ((thisTextarea = theTextareas[i++])) {
if (thisTextarea.hasClass('form-text')) {
if (thisTextarea.id == '') {
thisTextarea.id = thisTextarea.name;
}
new textEditor(thisTextarea);

This constructor calls container.appendChild(this.gutter), adding a
new textarea to the document and hence to theTextareas. This will
cause the loop to execute again, adding another textarea, and so on ...

Thanks! Now I see... but how do I work around this? I really need the
extra textarea to be added...
 
D

Dr J R Stockton

In comp.lang.javascript message <e092c78c-c697-4321-bf3a-73ce95a8c491@w1
1g2000hsh.googlegroups.com>, Fri, 4 Jan 2008 12:22:46,
(e-mail address removed) posted:
function setCookie(sName, sValue){
document.cookie = sName + '=' + escape(sValue) + '; expires=Fri, 31
Dec 2030 23:59:59 GMT; path=/';
}

If that is taken literally, expiry will never occur. 2030-12-31 will be
a Tuesday. Remember New Year's Eve 2002 ?
 
S

Steve Swift

Dr said:
If that is taken literally, expiry will never occur. 2030-12-31 will be
a Tuesday. Remember New Year's Eve 2002 ?

Is that so? It's always worried me that there is scope for ambiguity in
data that is primarily intended to be used by computers (so no need for
easy legibility in humans). I always set such dates using a subroutine
that more or less guaranteed consistency (I'm not excluding bugs/human
error in my code), but have assumed that the computers ignore the day of
the week data.
 
E

Evertjan.

Steve Swift wrote on 06 jan 2008 in comp.lang.javascript:
Is that so? It's always worried me that there is scope for ambiguity
in data that is primarily intended to be used by computers (so no need
for easy legibility in humans). I always set such dates using a
subroutine that more or less guaranteed consistency (I'm not excluding
bugs/human error in my code), but
have assumed that the computers ignore the day of the week data.

Your final concept is wrong, Steve.

Computers do what you tell them to do,
unless you trip over the mains plug.

So if thy react unexpectedly, you have given the wrong command.

Programme languages on the other hand
while they also only do what they are told to do,
they do what they are told to do by another programmer,
so confusing the issue,
if you don't exactly understand their aim, implementation and bugs.

So wether you tell the computer to ignore the weekday data or not,
is up to you, you being the programmer.

So if the browser programme, not the computer, ignores the expire string,
if there is an error in it, because it is programmed tht way, don't blame
the computer.
 
D

David Mark

Is that so? It's always worried me that there is scope for ambiguity in
data that is primarily intended to be used by computers (so no need for
easy legibility in humans). I always set such dates using a subroutine
that more or less guaranteed consistency (I'm not excluding bugs/human
error in my code), but have assumed that the computers ignore the day of
the week data.

Your best bet is to use a relative expiration (e.g. 30 days from now.)

Anything more than thirty days in the future is considered Spam.
Expiration dates decades in the future are pretty silly as surely the
computer will be in a landfill by then.
 
S

Steve Swift

David said:
Anything more than thirty days in the future is considered Spam.
Expiration dates decades in the future are pretty silly as surely the
computer will be in a landfill by then.

I have a good reason to set the expiry dates on most of my
business-related cookies to Mon 16 Sep 2013 because that is my 63rd
birthday. According to my original contract that is also the day I
retire. I want all hell to break out the moment I'm gone :)

Don't all rush to send me birthday presents on 16 Sep!

On the other hand, anti age-discrimination laws might mean that I'm
still at work on Tue 17 Sep 2013, busy fixing all the cookie-related
problems, and wondering what prat hardcoded the expiry date.

It never ceases to amaze me the reasonable words that I have to add to
my dictionary… "prat" in this case.
 
D

Dr J R Stockton

Sun said:
Is that so? It's always worried me that there is scope for ambiguity in
data that is primarily intended to be used by computers (so no need for
easy legibility in humans). I always set such dates using a subroutine
that more or less guaranteed consistency (I'm not excluding bugs/human
error in my code), but have assumed that the computers ignore the day
of the week data.


I wrote "If that is taken literally"; ISTM unlikely that the day-of-week
is checked. IIRC, the formats that new Date().toString() or new
Date().toUTCString() give don't all (or any?) comply exactly with the
cookies RFCs anyway,
 

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
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top