On Dynamic Elements Creation, Again

It took me a while to finally conclude my previous project (Dynamic Element Creation), or at least… have another go at it.

But, thanks to the great and insightful comments of Matthias Miller, I came up with this interesting piece of code:

The syntax is somewhat similar to the way you nest elements in XHTML or HTML. You can choose to

Konstructor: Dynamic Element Kreator
Posted by rolandog on July 18th, 2006
Constructs an element out of arrays. Using nested arrays translates into nested ChildNodes.
Update 2006-07-19: Added documentation (comments).
Update 2006-11-25: Reduced the ammount of code needed.

  1. /* Begin Type-detection functions */
  2.  
  3. //A set of helper functions for determining the type of 'a'.
  4. var Is={
  5.         nt:function(a){
  6.                 return(a===null||a===undefined);
  7.         },
  8.         Function:function(a){
  9.                 return(typeof(a)==='function')?a.constructor.toString().match(/Function/)!==null:false;
  10.         },
  11.         String:function(a){
  12.                 return(typeof(a)==='string')?true:(typeof(a)==='object')?a.constructor.toString().match(/string/i)!==null:false;
  13.         },
  14.         Array:function(a){
  15.                 return(typeof(a)==='object')?a.constructor.toString().match(/array/i)!==null||a.length!==undefined:false;
  16.         },
  17.         Boolean:function(a){
  18.                 return(typeof(a)==='boolean')?true:(typeof(a)==='object')?a.constructor.toString().match(/boolean/i)!==null:false;
  19.         },
  20.         Date:function(a){
  21.                 return(typeof(a)==='date')?true:(typeof(a)==='object')?a.constructor.toString().match(/date/i)!==null:false;
  22.         },
  23.         HTML:function(a){
  24.                 return(typeof(a)==='object')?a.constructor.toString().match(/html/i)!==null:false;
  25.         },
  26.         Number:function(a){
  27.                 return(typeof(a)==='number')?true:(typeof(a)==='object')?a.constructor.toString().match(/Number/)!==null:false;
  28.         },
  29.         Object:function(a){
  30.                 return(typeof(a)==='object')?a.constructor.toString().match(/object/i)!==null:false;
  31.         },
  32.         RegExp:function(a){
  33.                 return(typeof(a)==='function')?a.constructor.toString().match(/regexp/i)!==null:false;
  34.         }
  35. };
  36.  
  37. //An improved version of the 'typeof()' function.
  38. var type={
  39.         of:function(a){
  40.                 for(var i in Is){
  41.                         if(Is[i](a)){
  42.                                 return i.toLowerCase();
  43.                         }
  44.                 }
  45.         }
  46. };
  47.  
  48. /* End Type-detection functions */
  49.  
  50.  
  51. //Custom version of gEBC, so that it returns null if nothing is found.
  52. document.getElementsByClass=function(a){
  53.         var f=[],rE=new RegExp('(^|\\s)'+a+'(\\s|$)'),els=document.getElementsByTagName('*'),i;
  54.         for(i=0;i<els.length;i+=1){
  55.                 if(rE.test(els[i].className)){
  56.                         f.push(els[i]);
  57.                 }
  58.         }
  59.         return(f.length)?f:null;
  60. };
  61.  
  62. //Custom version of gEBTName, so that it returns null if nothing is found.
  63. document.getElementsByTag=function(a){
  64.         var r=document.getElementsByTagName(a);
  65.         return(r.length)?r:null;
  66. };
  67.  
  68. //shortcuts to the 'getters'.
  69. var by={
  70.         Id:function(a){
  71.                 return document.getElementById(a);
  72.         },
  73.         Class:function(a){
  74.                 return document.getElementsByClass(a);
  75.         },
  76.         Tag:function(a){
  77.                 return document.getElementsByTag(a);
  78.         }
  79. };
  80.  
  81. /* Custom dollar function ($()) (searches by Ids, Class Names and Tag Names). */
  82. //getElementsByClassName: $('aClassName')
  83. //getElementsByTagName: $('img')
  84. //getElementById: $('someId')
  85. function $(){
  86.         var a=arguments,r=[],e,b,i;
  87.         for(i=0;i<a.length;i+=1){
  88.                 e=a[i];
  89.                 if(Is.String(e)){
  90.                         for(var j in by){
  91.                                 b=by[j](e);
  92.                                 if(b && Is.Array(b)){
  93.                                         for(var k=0;k<b.length;k+=1){
  94.                                                 r.push(b[k]);
  95.                                         }
  96.                                 }else if(b && !Is.Array(b)){
  97.                                         r.push(b);
  98.                                 }
  99.                         }
  100.                 }else{
  101.                         r.push(e);
  102.                 }
  103.         }
  104.         return(r.length)?(r.length===1)?r[0]:r.unique():null;
  105. }
  106.  
  107. //helper function that weeds out duplicates on the custom $ (dollar) function.
  108. Array.prototype.unique=function(){
  109.         var i,e,t=[];
  110.         for(i=0;i<this.length;i+=1){
  111.                 e=this[i];
  112.                 t=this.slice(i+1,this.length);
  113.                 while(t.indexOf(e)>-1){
  114.                         this.splice(t.indexOf(e)+i+1,1);
  115.                         t.splice(t.indexOf(e),1);
  116.                 }
  117.         }
  118.         return this;
  119. };
  120.  
  121. /* the de-Konstructor function */
  122. //usage: document.getElementsByTagName("p").d();
  123. //usage: document.getElementById("anId").d();
  124. //usage: "img".d();
  125. Array.prototype.d=Object.prototype.d=String.prototype.d=function(e){
  126.         var t=type.of(this);
  127.         switch(t){
  128.                 case "array":for(var i=0;i<this.length;i+=1){try{this[i].parentNode.removeChild(this[i]);}catch(e){}}break;
  129.                 case "html":try{this.parentNode.removeChild(this);}catch(e){}break;
  130.                 case "string":try{$(this).d();}catch(e){}break;
  131.                 default:break;
  132.         }
  133. };
  134.  
  135.  
  136. /* Begin DOM custom functions (rigged with 'event monitoring')*/
  137.  
  138. //usage: someobject.before(anobject);
  139. Object.prototype.before=function(a,e){
  140.         try{a.parentNode.insertBefore(this,a);}catch(e){}queue.check();
  141. };
  142.  
  143. //usage: someobject.after(anobject);
  144. Object.prototype.after=function(a,e){
  145.         try{this.before(a.nextSibling);}catch(e){}queue.check();
  146. };
  147.  
  148. //usage: anobject.append(someobject);
  149. Object.prototype.append=function(a,e){
  150.         try{this.appendChild(a);}catch(e){}queue.check();
  151. };
  152.  
  153. //usage: anobject.prepend(someobject);
  154. Object.prototype.prepend=function(a,e){
  155.         try{this.before(a,this.firstChild);}catch(e){}queue.check();
  156. };
  157.  
  158. /* End DOM custom functions*/
  159.  
  160.  
  161. //sets an object's attribute (attributeName,attributeValue)
  162. //if the attributeName is an 'on-something' event, it sends it to the queue.
  163. Object.prototype.assign=function(aN,aV,e){
  164.         if(aN.match(/^on\w*/)){
  165.                 queue.event(this,aN,aV);
  166.         }else{
  167.                 try{this[aN]=aV;}catch(e){try{this.setAttribute(aN,aV);}catch(e){}}
  168.         }
  169. };
  170.  
  171.  
  172. /* The Events Queue */
  173. var queue={
  174. //whenever a custom DOM insertion method is called, this function checks
  175. //if the targets are in the document, if so, it sets the events properly.
  176.         check:function(){
  177.                 var t,aN,aV;
  178.                 for(var i=0;i<this.targets.length;i+=1){
  179.                         t=by.Id(this.targets[i]);
  180.                         aN=this.targetEvents[i];
  181.                         aV=this.targetFunctions[i];
  182.                         if(t){
  183.                                 try{t[aN]=aV;}catch(e){try{t.setAttribute(aN,aV);}catch(e){}}
  184.                                 this.targets.splice(i,1);this.targetEvents.splice(i,1);this.targetFunctions.splice(i,1);
  185.                         }
  186.                 }
  187.         },
  188. //pushes the object's id, eventName and function into temporary arrays.
  189.         event:function(obj,Name,Func){
  190.                 this.tag(obj);
  191.                 this.targets.push(obj.id);
  192.                 this.targetEvents.push(Name);
  193.                 this.targetFunctions.push(Func);
  194.         },
  195. //if the object doesn't have an id, it creates one for it.
  196.         tag:function(obj){
  197.                 if(Is.nt(obj.id)||obj.id===""){
  198.                         var t=obj.tagName.toLowerCase();
  199.                         obj.id=t+document.getElementsByTagName(t).length;
  200.                 }
  201.         },
  202.         targetEvents:[],
  203.         targetFunctions:[],
  204.         targets:[]
  205. };
  206.  
  207. //Creates an HTML element from a string
  208. //adapted from http://simon.incutio.com/archive/2003/06/15/javascriptWithXML
  209. String.prototype.create=function(){
  210.         return(document.createElementNS!==undefined)?document.createElementNS("http://www.w3.org/1999/xhtml",this):document.createElement(this);
  211. };
  212.  
  213.  
  214. /* The Konstructor function */
  215. //usage: var asdf=["p","This link points to ",["a",{href:"http://example.com",onclick:function(){alert("Can\'t touch this.");return false;},title:"Clicking won't take you there, as the \'onclick\' function returns \'false\'."},"example.com"],". However, the onclick function won\'t let you go there."].k();
  216. Array.prototype.k=function(){
  217.         //creates the element
  218.         var element=this[0].create();
  219.         //if there is more stuff inside the Array
  220.         if(this.length>1){
  221.                 for(var i=1;i<this.length;i+=1){
  222.                         //if it's an Object, it has attributes. Set them.
  223.                         if(Is.Object(this[i])){
  224.                                 //attributes,attributeValue
  225.                                 var a=this[i],aV;
  226.                                 //attributeName in attributes
  227.                                 for(var aN in a){
  228.                                         aV=a[aN];
  229.                                         //if you're creating a 'param' element, this is a time saver:
  230.                                         //['param',{'movie':'http://example.com/asdf.avi'},{}]
  231.                                         if(this[0]==="param"){element.assign('name',aN);element.assign('value',aV);}
  232.                                         else{element.assign(aN,aV);}
  233.                                 }
  234.                         }
  235.                         //if it's an Array, parse it and then append it.
  236.                         else if(Is.Array(this[i])){
  237.                                 var child=this[i].k();
  238.                                 element.appendChild(child);
  239.                         }
  240.                         //if it's a String,
  241.                         else if(Is.String(this[i])){
  242.                                 var txt=this[i].k();
  243.                                 element.appendChild(txt);
  244.                         }
  245.                 }
  246.         }
  247.         return element;
  248. };
  249.  
  250. //Returns a TextNode from a string.
  251. String.prototype.k=function(){
  252.         return document.createTextNode(this);
  253. };

I’ll add more info later. I’m kind of busy right now, but I didn’t wat to delay this post any longer.

Comments (3) left to “On Dynamic Elements Creation, Again”

  1. El Oso, El Moreno, and El Abogado » Blog Archive » While the world was waiting we’re overwhelmed by some sensation of something long ago and far away wrote:

    [...] It took me a while to finally conclude my previous project (Dynamic Element Creation), or at least… have another go at it.. [...]

  2. dM3 wrote:

    pfffffffffffffff.. way to difficult :)

  3. rolandog wrote:

    Hahaha
    I know… but, hey… I had fun coding it.

Post a Comment

*Required
*Required (Never published)