Sergey Telshevsky
Sergey Telshevsky

Reputation: 12197

Working with data in jQuery

I would like to ask for more an opinion than a question: What would the community recommend to do when you must do a webpage with lots of data, for example, a products listing, that should have some functionality like buy (adds to cart), sorting, etc. if you have to manipulate the data of the current product - price, title, image, link and other attributes? How you do it in your projects?

For example we have a page with dozens of products, each of them has attributes: price, title, description, image(URL), link(URL). How would you store the data to use it on some user interaction? Personally, I've done it by just inserting each of the attribute in tags, something like:

<div class="product" data-product_id="123">
  <div class="pr_title">Title</div>
  <div class="pr_body">Body</div>
  <div class="pr_img"><img src="http://www.www.www/img.png"></div>
  <div class="pr_link"><a href="http://www.stackoverflow.com/">Buy!</a></div>
</div>

This way I have my html structure for presentation and I worked with data in jQuery by something like:

var url = $('.product').find('.pr_link').find('a').attr('href');

But when the project got big and there were 10-15 more attributes added to each element, getting data from current product got pretty complicated and the code became mostly unreadable.

I thought of using same structure, but to keep data in some object like:

var products = {
    1: {
        title: "abc",
        description: "lorem ipsum",
        price: 25.19,
        img: "http://www.www.www/img.png",
        link: "http://www.stackoverflow.com"
    }
}

and keep markup as simple as possible, only using elements and styles needed for design with css:

<div class="product" data-product_id="123">
  <div class="title">Title</div>
  <div>Body</div>
  <img src="http://www.www.www/img.png">
  <a href="http://www.stackoverflow.com/">Buy!</a>
</div>

so onClick I would need to retrieve the id of the product and query it in our object "products":

var url = products[id].title;

While this is the most convenient way to work with it requires a new object.

Another idea was to keep all data in data- attributes of the parent div element like:

<div class="product" data-product_id="123" data-title="abc" data-body="Body">

but for much as I know jQuery doesn't work with data attributes well (natively).

So what are your suggestions? Maybe you have some even better ideas to share.

P.S. I tried to find some information on the subject, but most likely failed to find the way to formulate it well so I found nothing about it. If there are links or even similar questions on stack exchange sites, please feel free to post them. Thank you in advance!

Upvotes: 14

Views: 3571

Answers (9)

Trevor North
Trevor North

Reputation: 2296

I have to agree to Enes, you shouldnt embed your data into the jquery code or, as you already mentioned, your code will quickly become so complex as to be unsupportable. An MVC framework will help with this.

There are a couple mentioned in the answers above such as http://angularjs.com and http://backbonejs.org although i cant vouch for either of them but you should have a look to see if they help solve your problems.

I am currently rewriting a scrumwall application i originally developed in jquery and raw php into the agile toolkit. With agiletoolkit (aka atk4 on stackoverflow), you define models which map to the database tables, html templates and views which have placeholders where you want the data to go and pages where you add models, forms and grids. It provides the links between javascript and php and has features including ajax refreshes of views.

You could use html5 features but only the latest browsers will support this so you may have problems if the users are not in a controlled environment (e.g. a single company where there is a standard web browser).

Upvotes: 1

Prasenjit Kumar Nag
Prasenjit Kumar Nag

Reputation: 13461

You can use HTML5 data attribute to store products data, as you have several properties of products to associate with each product block, you can JSON encode the object and assign to the top element, and then can access that on user interaction on that element or any child element.

var product = {
    title: "abc",
    description: "lorem ipsum",
    price: 25.19,
    img: "http://www.www.www/img.png",
    link: "http://www.stackoverflow.com"
};
$(selector).data('product',JSON.stringify(product));

then to retrieve the object you can do on any event's callback

$product = $.parseJSON($(elem).data('product'));

In fact both facebook and twitter used data attributes to store associated data with tweets and stories. For example here goes some html of a FB story

<li data-ft='{"qid":"5757245005920960301","mf_story_key":"7164261693049558180"}'
 id="stream_story_4fe5d7d51bc415443080257">

You can see facebook is storing JSON encoded data into the data-ft attribute.

Similarly an example of a Twitter tweet html

<div data-tweet-id="216534496567230464" data-item-id="216534496567230464" 
data-screen-name="onimitch" data-user-id="123682011" data-is-reply-to="">

So twitter is saving associated data for a tweet into different attributes like data-tweet-id, data-user-id.

So As they both handle's a lot amount of data, I think You can also use either of the method to save your data without any performance issue.

If you store data with individual keys then be aware of the automatic data conversion that .data() does as @nnnnnn has already mentioned in comment.

Demo With .data() : http://jsfiddle.net/joycse06/vcFYj/

Demo With .attr() : http://jsfiddle.net/joycse06/vcFYj/1/

Upvotes: 5

aaaidan
aaaidan

Reputation: 7316

Although there are many excellent clientside mvc frameworks, check out Backbone.js, which is a powerful-but-easy-to-use framework for managing the interface between your data source (usually an http server), and your DOM. In short, it keeps "your truth out of the DOM"

As a contrived example, if you are creating a simple address book app, you would probably have a clientside Contact Backbone model, which would roughly (or exactly) mirror the model you have on your server.

Backbone manages requesting and parsing the contact data (json, xml, etc) from the server (or localstorage, etc) into these Contact model objects, and you provide a js callback to update your DOM when changes occur. This also works in reverse: Backbone updates the server when the model objects change, either instantly, after some delay, or when you explicitly call the save function.

Backbone might not be the correct framework for you. But check them all out before you decide to roll your own solution. Even so, you could create your own clientside MVC layer, if you feel you:

  • Can do a better job than one of the many excellent existing javascript MVC frameworks,
  • Have such a unique problem that only a bespoke solution will work for you, or
  • Find clientside MVC, or javascript frameworks somehow scary or distasteful.

Upvotes: 1

Tallmaris
Tallmaris

Reputation: 7590

You can use (as you already are) the data- attributes in HTML through jQuery. When you create the DIV from the server data, you can do something like this:

$('.product').data(yourProduct); // yourProduct would be the JSON representation of the data

To retrieve:

var url = $('product').data('product-link'); // if the JSON object has a product-link property that is.

The caveat someone mentioned above that your data is exposed to the browser is of course still valid, so take care.

Upvotes: 0

Christopher Ram&#237;rez
Christopher Ram&#237;rez

Reputation: 1720

The combination of DOM and jQuery is one of the most powerful things the Web has. You are not taking all of them.

Make the DOM help you and work for you. Organize better the DOM. Take all of it. Your example can be optimized this way:

<div class="product" data-product_id="123">
  <div class="pr_title">Title</div>
  <div class="pr_body">Body</div>
  <img class="prodcut-image" src="http://www.www.www/img.png">
  <a class="product-link" href="http://www.stackoverflow.com/">Buy!</a>
</div>

To select with jQuery, simple write:

var url = $('.product .product-link').attr('href');

I believe that your problem is that your are forgetting the way CSS selectors work. It's not necessary to transverse into every level of the DOM.

You can take off some DIV's in your example. A link not necessary have to be in-line. A CSS rule can make them work like a DIV.

Upvotes: 0

totten
totten

Reputation: 2817

I don't recommend you to keep your data in an object and fill HTML with it,

There are reasons for this:

  • Your data is open to all hackers to steal.
  • When your data is too big to fetch, your page can be initially loaded without data - and it's what any web developer do not want.
  • Again, when your data is too big, old computers -computers which has approx. 512M Ram- may come to a deadlock
  • Again and again, when your data is too big, traversing or sorting it may costs too much time.

I understand that your data is static for minimum about 5 min.. What I recommend is,

  • Place your data with Server-side languages(PHP,ASP(.NET),Python,etc.)
  • Fetch data with queries seperately when your script needs it.
  • Anything you do not need is cost for your user, user may have lots of page in his/her browser and it will be cause of deadlock too.

p.s. Any detail will help me to help you more.

Upvotes: 2

0xCC
0xCC

Reputation: 1514

You should try AngularJS. It works great with jQuery and it is easy to learn. AngularJS contains two way data binding and extends HTML by new attributes and elements. Last but not least it is MVC framework by Google. See more at http://www.angularjs.com

Upvotes: 1

DanyZift
DanyZift

Reputation: 687

No need to use ids or references within the DOM. Keep it clean.

Just use the data() function in jquery and bind it to the html elements. That way when you click on each element you will be able to get the object by calling this from within your click event.

//loop through your elements in the dom or build them dynamically. 
$.each('div.products', function(){
 $(this).data('product', <your data>);
};

//assign a handler to each element and grab the data object by using this. :)
$(container).delegate('.products', 'click' function(){
  console.log($(this).data('product'))
});

Upvotes: 3

Cranio
Cranio

Reputation: 9847

You don't need to traverse the whole object tree. How about putting IDs:

<div class="pr_link" id='id_link_123'><a href="http://www.stackoverflow.com/">Buy!</a></div>

and retrive them as:

// ....
var id = 123;
// ....
var url = $("#id_title_" + id + " a").attr('href');

Upvotes: 1

Related Questions