|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
||||
|
||||
|
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>
Please post if you need further help with this code or you want to know what kind of crack I have been smoking. Last edited by jacktasia : March 14th, 2005 at 12:35 AM. |
|
#2
|
||||
|
||||
|
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 Code:
if(exit!=1) {
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. Code:
p.appendChild(EL); Now, I'm going to assign the specified ID. Code:
EL.id=i; Now, I'm inputting any innerHTML. Code:
EL.innerHTML=h; 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 Code:
} 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 Code:
} return the object Code:
return(EL); close the function Code:
} The error function, called many times, above. Code:
function eO(message) { exit=1; (debug==1)?alert(message):null; }
|
|
#3
|
|||
|
|||
|
Ok, maybe I'm going to come across as a nay-sayer here but I don't see what the big deal is.
Quote:
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.
__________________
Like the answers I give? Why not ask me directly at my forum. I'm always glad to help. Javascript scripts and tips can be found at Dynamic Tools. Check out DynamicTable, the best javascript table sorter around. Get reliable and affordable hosting at www.thinksmarthosting.com |
|
#4
|
||||
|
||||
|
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. ![]()
__________________
Free Willy and the Whalers Quote:
|
|
#5
|
||||
|
||||
|
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!
__________________
------------- vbrtrmn -------------- i think i'm missing some vowels here ------------------------------------ ---------- js.antinoc.net ---------- ------------------------------------ --- The Two Types of Programmers --- |
|
#6
|
|||
|
|||
|
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. |
|
#7
|
||||
|
||||
|
There might be a middle way. When coding, I use 3 "subroutine" functions:
PHP Code:
and along with a removing all the childs and finding abolute position subroutines, if neded: PHP Code:
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')) |
|
#8
|
||||
|
||||
|
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)! ![]() |
|
#9
|
||||
|
||||
|
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');
__________________
Download [ Fx | Op ] Validate [ Markup | Css ] Code:
javascript per the (do ... while loop) Almost sounds like an introduction... haha great ! |