January 11th, 2005, 02:03 PM
-
Object Builder of Doom
I just finished an in-depth break-out of this code, found a few posts down.
Okay, we've been getting many many many many many questions here about createElement appendChild and all that, which is a big hassle to work with, especially if you need to add a bunch of different elements. So, I wrote this monster to help everyone out.
Code:
// p = parent id or full object - required
// i = new id - required
// t = element type (p,h1) - required
// h = innerHTML - pass '' for nothing
// a = attributes - should be passed as: attribute=value:attribute=value:attribute=value
// z = styles - should be passed as: style=value:style=value:style=value
// be sure to use the javascript style names, instead of the CSS ones ie: background-color == backgroundColor
// debug - this turns on alerts
function objBuilder(p,i,t,h,a,z,debug) {
debug = (debug==1)?1:0;
var d = document;
var s = 'string'
var exit=0;
p = (typeof p==s) ? d.getElementById(p) : p;
(typeof i!=s)?eO('New id must be a string value.'):null;
(d.getElementById(i))?eO('An element with that id already exists.'):null;
(typeof t!=s)?eO('Element type must be a string value.'):null;
(typeof h!=s)?eO('innerHTML must be a string.'):null;
(typeof a!=s)?eO('Attributes must be a string.'):null;
(typeof z!=s)?eO('Styles must be a string.'):null;
if(exit!=1) {
var EL=d.createElement(t);
p.appendChild(EL);
EL.id=i;
EL.innerHTML=h;
for(var n=0;n<a.split(':').length;n++) {
if (a.split(':')[n]=='') break;
(!a.split(':')[n].match(/=/))?
eO('Error in attributes missing equal (=) sign in '+ a.split(':')[n] +'.'):
(a.split(':')[n].split('=')[0]=='class')?
EL.className=a.split(':')[n].split('=')[1]:
EL.setAttribute(a.split(':')[n].split('=')[0],a.split(':')[n].split('=')[1]);
}
for(var n=0;n<z.split(':').length;n++) {
if (z.split(':')[n]=='') break;
(!z.split(':')[n].match(/=/))?
eO('Error in styles missing equal (=) sign in: '+ z.split(':')[n] +'.'):
EL.style[z.split(':')[n].split('=')[0]] = (z.split(':')[n].split('=')[1].match(/^\d+$/))?
z.split(':')[n].split('=')[1] +'px':
z.split(':')[n].split('=')[1];
}
return(EL);
}
function eO(message) { exit=1; (debug==1)?alert(message):null; }
}
So, let's say you wanted to add a dozen TD elements to a TR...
Code:
<table>
<tr id="tr1"></tr>
</table>
<script type="text/javascript">
// objBuilder(p,i,t,h,a,z,debug)
for (var n=0;n<12;n++) {
objBuilder('tr1','td'+n,'td','col'+n,'','',0);
}
</script>
That's freaking it!
Please post if you need further help with this code or you want to know what kind of crack I have been smoking.
Comments on this post
Last edited by jacktasia; March 14th, 2005 at 01:35 AM.
March 2nd, 2005, 03:08 PM
-
So, I realized that a lot of new coders will look at this mess and think WTF is vbrtrmn thinking, this code is insane!
So, here's what I'm doing..
First the basic function creation, it requires:
p = The parent id or full object of where you want to stick the new object.
i = The new id of the object you're creating
t = element type (p,h1) - required
h = innerHTML - pass '' for nothing
a = attributes - should be passed as: attribute=value:attribute=value:attribute=value
z = styles - should be passed as: style=value:style=value:style=value
be sure to use the javascript style names, instead of the CSS ones ie: background-color == backgroundColor
debug - this turns on alerts
Code:
function objBuilder(p,i,t,h,a,z,debug) {
This turns on debugging alerts, if you mess up, it will alert you 
Code:
debug = (debug==1)?1:0;
These are some function variables. I like to use these, so I don't have to type as much junk.
d is basically a "shortcut to" document so I can call d.getElementById.
s just means 'string' and exit is 0.
Code:
var d = document;
var s = 'string';
var exit=0;
Here I'm checking to see if the Parent ID (p) passed in is an object or a string (s='string'; see above).
Now, you may be wondering where the heck the if statement is, using ?: is a quick way of doing if statements.
This can also be written as:
Code:
if (typeof p=='string') {
p = document.getElementById(p);
} else {
p = p;
}
As you can see, this is much smaller than that mess.
Code:
p = (typeof p==s) ? d.getElementById(p) : p;
This checks to see if the new id is a string.
Also can be written as
Code:
if (typeof i!='string') {
// call eO (error out) function (see below)
eO('New id must be a string value.');
} else {
null;
}
Again this is much nicer.
Code:
(typeof i!=s)?eO('New id must be a string value.'):null;
Checks to see if the i, aka new id exists, if so, error out.
Code:
(d.getElementById(i))?eO('An element with that id already exists.'):null;
These check to see if the rest of the data passed in are strings, otherwise they error out; again they can be written in long format too, but I'm lazy and having 30 lines of if/else is crap 
Code:
(typeof t!=s)?eO('Element type must be a string value.'):null;
(typeof h!=s)?eO('innerHTML must be a string.'):null;
(typeof a!=s)?eO('Attributes must be a string.'):null;
(typeof z!=s)?eO('Styles must be a string.'):null;
Now the eO function, below, will set exit to 0, if anything above calls eO
Here I'm createing a new element, t is the type, specified, when the objBuilder function was called. I'm assigning that Element to EL
Code:
var EL=d.createElement(t);
Here I'm appending the created Element to the parent.
Now, I'm going to assign the specified ID.
Now, I'm inputting any innerHTML.
Here's the tricky part, the attributes, I ask for the attributes to be sent in key/value pairs, seperated with colons, let's say you were doing a table:
border=1:cellpadding=0:cellspacing=0:width=100%
In this for loop, I am splitting the attributes at the :, this creates an array of key/value pairs... something like this:
Code:
a.split(':')[0] = 'border=1';
a.split(':')[1] = 'cellpadding=0';
a.split(':')[2] = 'cellspacing=0';
a.split(':')[3] = 'width=100%';
So, I'm getting the length, in that case it would be 4.
Code:
for(var n=0;n<a.split(':').length;n++) {
If the current key/value pair is empty, stop the for loop.
Code:
if (a.split(':')[n]=='') break;
If this key/value pair does not have an equal sign, then...
Code:
(!a.split(':')[n].match(/=/))?
...then call the eO function, and alert an error... else ...
Code:
eO('Error in attributes missing equal (=) sign in '+ a.split(':')[n] +'.'):
... else ... if ... the key (attribute name) is 'class'
This is a bit confusing too, I'm taking the current key/value pair, say border=1, and splitting it again on the =.
So, border is essentially a.split(':')[0].split('=')[0] and 1 is a.split(':')[0].split('=')[1].
Code:
(a.split(':')[n].split('=')[0]=='class')?
Set the className to the value
Code:
EL.className=a.split(':')[n].split('=')[1]:
... else ... if the key is not 'class', do a setAttribute(key,value), again splitting the current key/value pair at the =
Code:
EL.setAttribute(a.split(':')[n].split('=')[0],a.split(':')[n].split('=')[1]);
end of the attribute for loop
Now, I'm going to do basically the same thing with the style sheets..
Code:
for(var n=0;n<z.split(':').length;n++) {
Stop the for loop if the key/value pair is empty.
Code:
if (z.split(':')[n]=='') break;
If the key/value pair is empty ... then ...
Code:
(!z.split(':')[n].match(/=/))?
... then ... error out .. else ...
Code:
eO('Error in styles missing equal (=) sign in: '+ z.split(':')[n] +'.'):
... else ... the style name is in the left side of the equal sign, the first element.
if the value is ONLY digits .. then ..
Code:
EL.style[z.split(':')[n].split('=')[0]] = (z.split(':')[n].split('=')[1].match(/^\d*$/))?
.. then .. it is most likely a number of pixels .. else ..
Code:
z.split(':')[n].split('=')[1] +'px':
.. else .. just use the value, the second element.
Code:
z.split(':')[n].split('=')[1];
End the loop here
return the object
close the function
The error function, called many times, above.
Code:
function eO(message) { exit=1; (debug==1)?alert(message):null; }
Comments on this post
April 4th, 2005, 07:33 PM
-
Ok, maybe I'm going to come across as a nay-sayer here but I don't see what the big deal is.
<script type="text/javascript">
// objBuilder(p,i,t,h,a,z,debug)
for (var n=0;n<12;n++) {
objBuilder('tr1','td'+n,'td','col'+n,'','',0);
}
</script>
Vs
Code:
<script type="text/javascript">
insertPoint = document.getElementById('tr1');
for (var n=0;n<12;n++) {
var newCell = document.createElement('td');
newCell.id = 'td' + n;
newCell.innerHTML = 'col' + n;
insertPoint.appendChild(newCell);
}
</script>
Doesn't seem like a huge improvement to me. I think the standard method is easier to read & understand and I'd prefer not having to remember what each of the parameters for the objBuilder function are.
April 4th, 2005, 10:36 PM
-
Well, the objbuilder function is more flexable and easier for beginners of javascript. It can be used multiple times to add different content, where your method would have to have a separate function for each instance.
That said, I always prefer writing my own code as well.
April 5th, 2005, 02:34 AM
-
Pete, imagine that you had to create 500 objects/elements on the fly, your way would take a bloody long time. Now imagine, adding attributes, styles, and what not to each of those elements, damn, that would be a lot of code!
Comments on this post
April 5th, 2005, 09:18 PM
-
If you want 500 near identical elements either way will work fine. If you want 500 wildly different elements I'd use your script, it's still going be a lot of code and take a long time though. In that sort of situation most of the time will be spent typing in id's, attributes etc anyway.
I still take my hat off to you for helping out the javascript noobies and I suspect this thread will stop a lot of the 'how do i add an object' posts.
August 10th, 2005, 07:06 AM
-
There might be a middle way. When coding, I use 3 "subroutine" functions:
PHP Code:
function cE(el){
this.obj=document.createElement(el);
return this.obj;
}
function cT(txt){
this.obj=document.createTextNode(txt);
return this.obj;
}
function cA(obj,att,val){
obj.setAttribute(att,val);
return
}
and along with a removing all the childs and finding abolute position subroutines, if neded:
PHP Code:
function rC(obj){
while(obj.hasChildNodes()){
obj.removeChild(obj.childNodes[0])
}
function fP(obj,x,y){
while(obj.offsetParent){
if(obj==document.getElementsByTagName('body')[0]){break;}
else{
x=x+obj.offsetParent.offsetLeft;
y=y+obj.offsetParent.offsetTop;
obj=obj.offsetParent;
}
}
this.x=x;this.y=y;
return this.x;
return this.y;
}
}
would help me to shorten the codes and make them easily to handle.
-------
by the way, vbrtrmn... innerHTML is not a standard DOM method. You may use
object.firstChild.nodeValue='some text'
or better (nodeValue is in fact a read-only property but, surprisingly, sometimes can be used as a writing method)
object.firstChild.data='some text'
or
object.appendChild(document.createTextNode('some text'))
September 23rd, 2005, 12:16 PM
-
Certainly makes it simpler, and it doesn't interfere with anything so rock on. 
Anything that makes my life as a coder easier is welcome. Hail object oriented programming (or prototype based)!
September 27th, 2005, 06:41 PM
-
ObjBuilder v2
ObjBuilder_v2 ... not really... just a few new things. A breakdown below...
Code:
function getObj(ref){
if (document.getElementById){ return document.getElementById(ref); }
if (document.all){ return document.all[ref]; }
if (document.layers){ return document.layers[ref]; }
}
function objBuilder_v2(d,pRef,obj,ref,val,att,sty){
// d debug
// pRef parent reference
// obj element to be created dynamically
// ref object reference
// val the dynamic element's node value
// attr the dynamic element's attributes
// s the dynamic element's styles
var msgError = 'The following errors have occured:\n\n';
var debug = (d==1) ? 1 : 0;
var s = 'string';
var _parent = (typeof(pRef)==s) ? getObj(pRef) : pRef;
(typeof(ref) !== s) ? msgError += 'Element reference must be a string.\n' : null;
(getObj(ref)) ? msgError += 'An element with that reference already exists.\n' : null;
(typeof(obj) !== s) ? msgError += 'Element must be a string.\n' : null;
(typeof(val) !== s) ? msgError += 'Element node value must be a string.\n' : null;
(typeof(att) !== s) ? msgError += 'Element attributes must be a string.\n' : null;
(typeof(sty) !== s) ? msgError += 'Element styles must be a string.\n' : null;
var el;
var tmp= (obj.match(/=/)) ? obj.split('=') : null;
if (obj.match(/=/)){
el = document.createElement(tmp[0]);
(obj.match(/textarea/)) ? (el.rows=tmp[1].split('|')[0],el.cols=tmp[1].split('|')[1]) : el.type= tmp[1];
el.value = val;
}else{
el = document.createElement(obj);
el.appendChild(document.createTextNode(val));
}
_parent.appendChild(el);
el.name= ref;
el.id= ref;
var attS= att.split(':');
for (var i=0; i < attS.length; i++){
if (attS[i] == ''){ break; }
(!attS[i].match(/=/))
? msgError += 'Missing equal sign in ' + attS[i] +'.\n'
: (attS[i].split('=')[0]=='class')
? el.className= attS[i].split('=')[1]
: el.setAttribute(attS[i].split('=')[0], attS[i].split('=')[1]);
}
var styS=sty.split(':');
for (var i=0; i < styS.length; i++){
if (styS[i]==''){ break; }
(!styS[i].match(/=/))
? msgError += 'Style missing equal sign in: '+ styS[i] +'.\n'
: el.style[styS[i].split('=')[0]]= ((styS[i].split('=')[1].match(/^\d+$/)) ? styS[i].split('=')[1] +'px' : styS[i].split('=')[1]);
}
_parent.appendChild(el);
(debug==1 && msgError !== 'The following errors have occured:\n\n') ? window.alert(msgError) : null;
}
Specify input types, and value
Code:
objBuilder_v2(1,'parentObj','input=text','inpText1','Text Input Value 1','','fontFamily=Arial:fontSize=11px');
Specify textarea's rows and columns
Code:
objBuilder_v2(1,'parentObj','textarea=5|15','tarea1','Textarea Value 1','','fontFamily=Arial:fontSize=16px');
Comments on this post
-
Originally Posted by Joseph Taylor
Geez man, going at this rate you might as well save it as .pdf and right a book.
I wonder how old that comment is? I can't believe I rote that.
-
Originally Posted by Joseph Taylor
Originally Posted by Joseph Taylor
Geez man, going at this rate you might as well save it as .pdf and right a book.
I wonder how old that comment is? I can't believe I rote that.
2 years, probably. Must we go off-topic in a stickied thread?
Comments on this post
October 30th, 2009, 07:05 AM
-
Just reading this gives me a headache.