#1
  1. 4:04 Time Not Found
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Jan 2004
    Location
    Northern Virginia
    Posts
    2,273
    Rep Power
    338

    Lightbulb 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

    • benno32 agrees : Nice One
    Last edited by jacktasia; March 14th, 2005 at 12:35 AM.
  2. #2
  3. 4:04 Time Not Found
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Jan 2004
    Location
    Northern Virginia
    Posts
    2,273
    Rep Power
    338
    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; }

    Comments on this post

    • Markisdee agrees : Wow, quite an explaination. Kudos.
    • Joseph Taylor agrees : Geez man, going at this rate you might as well save it as .pdf and right a book. ;)
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    May 2003
    Location
    Brisbane, Australia
    Posts
    1,442
    Rep Power
    29
    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.
    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
  6. #4
  7. Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Dec 2003
    Posts
    2,346
    Rep Power
    578
    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.
  8. #5
  9. 4:04 Time Not Found
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Jan 2004
    Location
    Northern Virginia
    Posts
    2,273
    Rep Power
    338
    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

    • jacktasia agrees
    • Cheesefood agrees
    I am so smart, I am so smart, S.M.R.T ... I mean S.M.A.R.T.

    Stop Using Pop-Ups
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    May 2003
    Location
    Brisbane, Australia
    Posts
    1,442
    Rep Power
    29
    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.
    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
  12. #7
  13. Contributing User
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Aug 2005
    Location
    Bucharest ROMANIA
    Posts
    2,557
    Rep Power
    604
    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'))
  14. #8
  15. c0der
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2005
    Location
    Vancouver
    Posts
    665
    Rep Power
    155
    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)!
  16. #9
  17. Application is what Divides Us
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Dec 2002
    Location
    Titusville, FL
    Posts
    2,179
    Rep Power
    58

    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

    • vbrtrmn agrees : nice mods!
    Download [ Fx | Op ] Validate [ Markup | Css ]
  18. #10
  19. c0der
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2005
    Location
    Vancouver
    Posts
    665
    Rep Power
    155
    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.
  20. #11
  21. CSS & JS/DOM Adept
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jul 2004
    Location
    USA (verifiably)
    Posts
    20,124
    Rep Power
    4304
    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

    • vbrtrmn agrees : Probably time to unsticky this, heh.
    Spreading knowledge, one newbie at a time.

    Check out my blog. | Learn CSS. | PHP includes | X/HTML Validator | CSS validator | Common CSS Mistakes | Common JS Mistakes

    Remember people spend most of their time on other people's sites (so don't violate web design conventions).
  22. #12
  23. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2009
    Posts
    80
    Rep Power
    33
    Just reading this gives me a headache.

IMN logo majestic logo threadwatch logo seochat tools logo