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();
}
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();
}