views:

95

answers:

3

Hi !

I have a div that basically represents a book (so a nice div layout with an image of the book, title, price, red background if on sale etc.). So what i do is to get the properties of a book from the database, insert the values in kind of an html template and display it.

Now, once it is displayed i hate how i have to handle the data. I have to either parse css properties to figure out if a book is on sale for an example or i have to keep the data in another place as well (some javascript array or use the jquery data feature). The first option is ugly the second one would require me to update two things when one property changes - which is ugly as well.

So what i would like is to handle that block of html (that represents a single book) as an object. Where i can call obj.setPrice(30); and things like that and finally call obj.update(); so it would update its appearance.

Is there anyway to accomplish this ? Or something like this ? I just feel that once i render the data as html i loose control over it :(

+2  A: 

I guess your best shot is write your own object / methods for that.

var Book = function(){
    var price    =   args.price  || 0,
        color    =   args.color  || 'red',
        height   =   args.height || '200px',
        width    =   args.width  || '600px',
        template =   "<div style='background-color: COLOR; width=WIDTH; height: HEIGHT;'><span>$PRICE</span><br/></div>";

    return {
        setPrice:  function(np){
             price = np;
             return this;
        },
        setColor:  function(nc){
             color = nc;
             return this;
        },
        setHeight: function(nh){
             height = nh;
             return this;
        },
        render:    function(){
             template = template.replace(/COLOR/, color);
             template = template.replace(/PRICE/, price);
             // etc
             // use jQuery or native javascript to form and append your html
             $(template).appendTo(document.body);
        }
    };
};

This is just a pretty basic example which can be optimized like a lot. You may even think about using John Resigs microtemplate (http://ejohn.org/blog/javascript-micro-templating/)

Usage from the above example would look like:

var book = Book({
    price:  30,
    color:  'blue'
});

book.render();

To change values:

book.setPrice(140).setColor('yellow').setHeight('500').render();
jAndy
+3  A: 

Suppose your html div is like this

<div id="book1">
<div id="price">$30</div>    
...
</div>

You can define a Book object as follows:

var Book = function(name) {
   this.name = name;
}

Book.prototype = {
   setPrice : function(price) {
      this.price = price;
   },
   update : function() {
      pricediv = document.getElementById(this.name)
      pricediv.innerHTML = '$'+price;
   }
}

var book = new Book('book1')
book.setPrice(50);
book.update();
Jayesh
pricediv.innerHTML = '$'+price; => pricediv.innerHTML = '$'+this.price;
MeanShift
+1  A: 

I have been playing around with Microsoft's proposal for jQuery Templates and Data Linking and so far it's going awesome.

TLDR, checkout this demo.

It's extremely easy to just link up a piece of HTML with a JavaScript object and from thereon, only update the JavaScript object and the HTML updates automatically.

Here's a simple example. Create the HTML that will represent your widget.

<div class="book">
    <img width="100" height="100" src="" />
    <div class="title"></div>
    <div class="price"></div>
</div>

Then create a JavaScript object and dynamically link it to the HTML above. Here is a sample object:

var book = {
    title: "Alice in Wonderland",
    price: 24.99,
    onSale: true,
    image: "http://bit.ly/cavCXS"
};

Now onto the actual linking part. The items we are going to link up are:

  • A data-onsale attribute in the outer div which will be either "true" or "false"
  • The image src attribute to the image property of our book
  • title div to the title property
  • price div to the price property

The following sets up the linking. Note that we are only doing a one way linking here, but it's possible to setup a two way linking also using the linkBoth function.

$(book)
    .linkTo('title', '.title', 'html')
    .linkTo('price', '.price', 'html')
    .linkTo('image', '.book img', 'src')
    .linkTo('onSale', '.book', 'data-onsale')

That's it. From now onwards, just update the book object and the HTML will automatically update. Update the properties of the book like you would update html attributes using the attr function.

$(book).attr({
    price: 14.75
});

or

$(book).attr('price', 14.75);

The code above is only using Data Linking, but the proposal also mentions combining data linking with templates which would make this even more easier. From what I reckon, you would be able to do this and get the above functionality:

<script id="bookTemplate" type="text/html">
    <div class="book" data-onsale="{{link onSale }}">
        <img width="100" height="100" src="{{link image }}" />
        <div class="title">{{link title }}</div>
        <div class="price">{{link price }}</div>
    </div>
</script>

Link the above template with the book object in one step and add it to the page:

$('#bookTemplate').render(book).appendTo('body')

Update the properties of the book object, and changes will reflect.

Anurag
Another example using only templates - http://jsfiddle.net/tRkwG/4/
Anurag