TwelvestoneProjects and Theory

Simple jQuery template plugin


Sign in

  • Waiting for Godot ( 730 k posts )
    Just conversation.
  • Thunder Dome ( 23 k posts )
    Photoshop Tennis and Collabs.
  • Photography ( 5.1 k posts )
    For all you shutterbugs, sh...
  • Flash ( 18 k posts )
    ActionScripting to tweens, ...
  • Front End ( 5.9 k posts )
    general front end design an...
  • Back End ( 9.7 k posts )
    serverside scripting, progr...
  • Projects and Theory ( 12 k posts )
    This forum is for discussio...
  • FAQ ( 269 posts )
    All those nagging questions...
  • Design ( 17 k posts )
    graphics & all aspects of g...
  • Purgatory ( 3.6 k posts )
    12stone Jail, feel free to ...
Stinky
 
2011-02-04

This is how it works, dig it:

$("#person") .template("initialize", "#person_template") .template("replace", { ".name": "Hortense Bartleswigmot", "li": [ function(i, li, object) { li.find(".date").html(object.date); li.find(".description").html(object.description); }, objects ] });

The plugin so far:

(function($){ var methods = { initialize: function(selector) { return this.each(function(){ $(this).html($(selector)); }); }, replace: function(replacements){ return this.each(function(){ var $this = $(this); $.each(replacements, function(key, value) { var matches = $this.find(key);

                if(value.charAt) {        // string
                    matches.html(value);
                } else if (value.slice) { // array

                    // in the case of an Array [Function, Array] we
                    // take the match as a template and duplicate
                    // it for each element in the array, using the
                    // function to format the template.
                    if($.isFunction(value[0])) {
                        var parent = matches.parent(),
                        newElement = matches.clone();

                        for(var l = value[1].length, i = 0; i<l; i++) {
                            value[0](i, newElement, value[1][i]);
                            parent.append(newElement);
                            newElement = matches.clone();
                        }
                        // clean up template
                        matches.remove();

                    // apply array values to matches                            
                    } else { 
                        throw "template#replace(Array) not implemented";
                    }
                }
            });
        });
    }
};

$.fn.template = function(method){
    return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
};

})(jQuery);

I'll pop it up on github when I implement the plain array replacements.

Stinky
 
2011-02-04

Also, I know that DOM manipulation is slow but this was just so straight forward that I couldn't justify doing it any other way. If I need to optimize in the future I can, but for the most part template updates aren't crazy performance critical.

persist
 
2011-02-04

Very nice idea.

:notworthy

persist
 
2011-02-04

was thinking the graphic designer can participate by using a naming convention on css class and selectors to mark editable regions for the developers.

Stinky
 
2011-02-06

Thanks k

And good call. Yeah, all of the current JS templating libraries that I've seen are purely string replace/interpolation, which is fine, but it's a pain to integrate in a clean way with a back end templating system without making everything look wonky. This way feels a lot cleaner and works better with how I work.

persist
 
2011-02-06

I particularly like it because it has the potential to standardize dom manipulation. And you're right, you want to avoid dom manipulation, but it's often clearly logical in many cases.

Currently I have 4 devs and myself, and we all work slightly differently. Some of us are awesome at html and css, and one or two need some help. It's a difficult balance of trying to encourage them to learn and discover what's best, while resisting the desire to demand some arbitrary pattern. I don't ever want to create an environment on a team where they can't invent, discover or suggest something awesome.

A plugin gives everyone a path of least resistance. A template pattern for jquery dom manipulation allows the html/css dev to make sure the java devs turned jquery devs don't wring the dom to pieces, while utilizing html that looks like it should. Dev's don't have to be referencing the freaking photoshop file after the designer is no longer involved with the project and can trust the css and html. It's one less thing to worry about. It also discourages one of jquery's largest weaknesses, and temptations, which is to add inline styles via $.css() to solve ui issues.

I said it already, but it's a great idea.

Stinky
 
2011-02-06

Well, I added the simple Array support and the code is on github k https://github.com/weeksie/jquery-dom-template

MIT license. If you do use it, let me know (unless you're working on something super-sekrit, of course).

baron ruhstoff
 
2011-02-08

Originally posted by: persist It also discourages one of jquery's largest weaknesses, and temptations, which is to add inline styles via $.css() to solve ui issues. k

:loves:

persist
 
2011-02-08

i had you in mind when i typed that.

high fives.

Stickman
 
2011-03-24

Hey Stinky,

Just gave this a go -- might well use it in a thing I'm working on -- and tried the example in the readme but it doesn't quite work. There's a closing quote missing on the class="description" in the HTML template.

Otherwise -- 'tis sweet. :thumbsup:

Stickman
 
2011-03-25

Oh, and...you have a trailing comma in the example objects array that makes IE choke (it assumes that there are three elements in the array and then barfs because the third 'element' has no properties).

Stinky
 
2011-03-25

Thanks for the heads up on those, definitely let me know how it goes k

Stickman
 
2011-03-26

Interested to hear how you'd deal with more deeply-nested object structures. For example, I have a list of items that have sub-items, that I'd like to render as ULs with nested ULs. I have working code but it seems a little verbose, did you have a particular approach in mind?

Stinky
 
2011-03-26

How are you doing it now?

I think the way to go about it would be to call template again inside a closure on the replace method.

.template("replace", { ".name": "Hortense Bartleswigmot", "li": [ function(i, li, object) { $(li).template("replace", { . . . }, object.children); }, objects ] });

But I do see how that could get complex, I'd probably not use inline functions and just pass variables at that point.

    "li": [ replace, objects ]
  . . . 

});

function replace(i, li, object) { $(li).template({ "ul > li": [ innerReplace, object.children ]}); }

function innerReplace(i, li, object) { . . . }

Sort of off the top of my head, anyway.

Stickman
 
2011-03-27

My code is pretty much like your first example. Breaking it out into separate functions would make it more legible, I think.

Stinky
 
2011-03-27

I run into the same legibility issues with node js because it's so callback heavy. Named functions are the only way to fly in that case.

Stickman
 
2011-03-28

OK I've (reluctantly) had to stop using this for now.

The problem being, it's currently set up such that the original template element is deleted once the output is rendered --meaning, you can't use the same template twice. I have a page that updates a certain part of the layout dynamically when a particular form element's value is changed, so I need to be able to re-use a template.

Stinky
 
2011-03-28

Curses. I'll see about fixing that and hopefully you can use it next time around k

Stickman
 
2011-03-28

Yeah, it was looking good up to that point. Took a while for me to work out why everything just went blank when updating...k

Sorry, you must be a member to post to a conversation. Either log in or sign up to get involved.
TwelvestoneProjects and Theory

Simple jQuery template plugin