Monday, August 5, 2013

building custom tags in html5 and javascript, part 2

Several months ago, I toyed around with the idea of building custom, JavaScript powered tags. My motivation for this was simple: It makes building the client-side portion of web application easy. But, it only handles one side of the equation elegantly: binding existing markup to JavaScript objects.

Ideally, I'd like to work the other way around too. I'd like to be able to create a new object and have the corresponding markup generated for me. And I'd like to drop the object right into the DOM without performing any object-to-node conversion.

We can start with a markup template. And we can plan on consuming the data-id attribute to identify nodes within the object [to avoid conflict with any existing id's in the DOM]. So, let's consider a simple "Blurb" ... like so:

<div class='blurb'>
  <h3 data-id="blurbTitle" style='text-decoration: italic;'>Title will go here</h3>
  <p data-id="blurbBody" style='color: silver;'></p>
</div>


And we want a JavaScript "class" definition that shows and hides the body when on click:

var Blurb = function(title, body) {

  this.init = function(title, body) {
    this.setTitle(title);
    this.setBody(body);
  }

  this.setTitle = function(t) {
    this.blurbTitle.innerHTML = t;
  }

  this.setBody = function(b) {
    this.blurbBody.innerHTML = b;
  }

  this.onclick = function() {
    if (this.blurbBody.style.display == 'none') {
      this.blurbBody.style.display = 'block';
    } else {
      this.blurbBody.style.display = 'none';
    }
  }


  this.init(title, body);

}


Using that template and class, we want to be able to throw a Blurb on the page by doing this:

var b = New(Blurb);
b.blurbTitle.innerHTML = "Some Title";
b.body.innerHTML = "Some body text";
document.body.appendChild(b);


Or this:

var b = New(Blurb);
b.setTitle("Some Title");
b.setBody("Some body text");
document.body.appendChild(b);


Or this:

var b = New(Blurb, "Some Title", "Some body text.");
document.body.appendChild(b);


All we're missing is a simple, easy-to-understand link between the template and the class definition. We need a call to something to make the Blurb constructor operate on a node based on the markup from the template, with the title and body nodes imported into the object as properties. (The outer div will be this.)

Sounds easy enough. But, it's a two-step process. Firstly, you'll notice I used a New() function instead of the new keyword, and that's for good reason. The new keyword will create a new this, which won't be our DOM node. And it's pretty tricky, if not impossible, to "consecrate" an existing object as a DOM node. So, by making a simple concession to use a New() function instead we make our job a lot easier.

So, let's write the fundamentals. Let's write a method that applies our Blurb constructor to a DOM node based on our template. (For now, let's assume we're attaching our template markup as text to class definitions themselves. I.e., Blurb.templateMarkup = "<div ... ")

function New(DomClass) {
  // create a container for the template markup
  var rv = document.createElement('div');

  // drop the markup in and grab the first child, which is what we're really after
  rv.innerHTML = DomClass.templateMarkup;
  rv = rv.firstChild;

  // and "bless" the return value with the class constructor, supplying any ~additional~
  // arguments that were supplied to this New() call
  DomClass.apply(rv, Array.prototype.slice.call(arguments, 1));

  return rv;
}


Simple enough. That gets us a DOM node that's "blessed" as an instance of the supplied object. The missing link: import data-id's from the template as object properties. And for now, we'll assume this must be done "pre-blessing" in simple, recursive manner. So, let's create a little helper function to do that work, which we can define and call in the context of New().

function New(DomClass) {
  // create and bless the object as before
  var rv = document.createElement('div');
  rv.innerHTML = DomClass.templateMarkup;
  rv = rv.firstChild;

  // before blessing it, import the properties
  importProperties(rv, rv.childNodes);

  DomClass.apply(rv, Array.prototype.slice.call(arguments, 1));
  return rv;


  // hoisted functions:

  // given a list of nodes, recursively attaches any with data-id's as properties of obj
  function importProperties(obj, nodes) {
    for (var i = 0; i < nodes.length; i++) {
      if (!nodes[i].getAttribute) continue;
      var id = nodes[i].getAttribute('data-id');
      if (id) {
        obj[id] = nodes[i];
        importProperties(obj, nodes[i].childNodes);
      }
    }
  }

}


And we're done. Our desired calls ...

var b = New(Blurb, "Some Title", "Some body text.");
document.body.appendChild(b);


... (etc.) will work as expected now. Give it a try.

Next time, we'll use what we've done here to improve our work from part 1 and bridge any gaps between the two. Hopefully, we'll end up with a robust system for more seamless, elegant, and straightforward interactions between our script and the DOM.

28 comments:

  1. Replies
    1. The effectiveness of IEEE Project Domains depends very much on the situation in which they are applied. In order to further improve IEEE Final Year Project Domains practices we need to explicitly describe and utilise our knowledge about software domains of software engineering Final Year Project Domains for CSE technologies. This paper suggests a modelling formalism for supporting systematic reuse of software engineering technologies during planning of software projects and improvement programmes in Final Year Projects for CSE.

      Software management seeks for decision support to identify technologies like JavaScript that meet best the goals and characteristics of a software project or improvement programme. JavaScript Training in Chennai Accessible experiences and repositories that effectively guide that technology selection are still lacking.

      Aim of technology domain analysis is to describe the class of context situations (e.g., kinds of JavaScript software projects) in which a software engineering technology JavaScript Training in Chennai can be applied successfully

      The Angular Training covers a wide range of topics including Components, Angular Directives, Angular Services, Pipes, security fundamentals, Routing, and Angular programmability. The new Angular TRaining will lay the foundation you need to specialise in Single Page Application developer. Angular Training

      Delete
  2. Very Nice Blog I like the way you explained these things. I’ve been looking for ways to improve my website and overall rankings.I hope your future article will help me further.Take SEO Training in Chennai to mould yourself.

    ReplyDelete
  3. I found your blog while searching for the updates, I am happy to be here. Very useful content and also easily understandable providing.. Believe me I did wrote an post about tutorials for beginners with reference of your blog.
    Sql server dba online training

    ReplyDelete
  4. Good Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.
    Selenium training in Chennai || Devops online training

    ReplyDelete
  5. Thank you for allowing me to read it, welcome to the next in a recent article. And thanks for sharing the nice article, keep posting or updating news article.
    I think you have a long story to share and i am glad after long time finally you cam and shared your experience.
    Docker online training
    Docker certification training
    Docker online course
    Docker training course

    ReplyDelete
  6. Exactly! This is a great information on custom tags in html5.
    Twin Cities Website Design

    ReplyDelete
  7. Very excellent post!!! Thank you so much for your great content. Keep posting.....

    Spark and Scala Training
    Apache Spark Online Course

    ReplyDelete
  8. I am really happy with your blog because your article is very unique and powerful for new.
    Data Science Course in Pune

    ReplyDelete
  9. This article will outline all the different strategies you should be aware of when it comes to soccer.

    Best IAS Coaching in India

    ReplyDelete
  10. It's really a cool and useful piece of information. I satisfied that you shared this useful information with us. ufabet1688

    ReplyDelete
  11. The article was absolutely fantastic! Lot of great information which can be helpful in some or the other way. Keep updating the blog, looking forward for more contents.
    by cognex is the AWS Training in chennai

    ReplyDelete
  12. Escort Service In Gurgaon - Our call girls agency is ready to meet your all needs. They are enjoying most seductive female call Girls from different parts of the World. Have you ever date any female in your life? If no then you do not know the real taste of dating fun with a call girl. Then our Gurgaon Escorts service will help you to tackle your dreams with one of the independent female escort agencies.

    Escort Service In Gurgaon
    https://www.kajalvermas.com/escort-service-in-gurgaon/

    ReplyDelete
  13. great post ! This was actually what i was looking for and i am glad to came here!
    SAP Ariba Training
    MuleSoft Training

    ReplyDelete
  14. Sharma Academy is Central Indias largest provider of Mppsc Notes and Mppsc Study Material. You will get updated MPPSC Notes as per the latest syllabus of state level psc exam in Hindi and English medium both.

    ReplyDelete