Is it right to put data in html5 data-*? - javascript

I have got a case like this:
There are many 'Rocks' on the screen, each one has properties like gram, score and speed. Once click the rock, we give out its properties.
Now i put all rocks' properties on the dom with data-*, like data-gram, data-score and data-speed. 'e.target' is used to get the dom and so are all properties.
<div class="rocks" data-gram="10" data-score="100" data-speed="10"></div>
I want to know is it right, and is there any disadvantage?
Also,is there any other better way?

It is right, these data- fields are made for these kind of uses.
Another way to do it is simply creating an array or object in Javascript that holds that information. As you're accessing the DOM when you click the element, it simply won't matter.
If you were trying to access the data without a DOM access, using a Javascript array/object should be faster in that case.
It's up to you really.

Yes. It's perfectly valid to store data associated with HTML attributes in this way. MDN has a whole article about it. https://developer.mozilla.org/en/docs/Web/Guide/HTML/Using_data_attributes The question I would be asking is does this fit with how your consuming / interacting with that data. Are you using a javascript framework? Have you considered loading this data in from an external source as JSON? Would that be a better fit? In my case I would tend to load this data in from an external json feed. I find that more flexable and it suits libraries like angular.

Related

Can you add properties to an existing microdata schema mark up via json - ld?

For SEO reasons I need to complete the Organization schema markup that is on a website but I only have access via javascript. I can't edit HTML, only JS and CSS overwrites. The Organization object is missing a telephone and other properties.
I rather not to create a second Organization object that is complete and have the good and the bad version up in the site. I was wondering if it is possible to reference an existing object somehow via json-ld? or do you think I should just add a second object?
I was wondering if it is possible to reference an existing object somehow via json-ld?
In practice, not really (theoretically you could give them the same identifier and when converted to RDF the data should be merged).
or do you think I should just add a second object?
I personally would do that. That way clients that (just) understand JSON-LD would get the complete information.

Server-side ruby vs client-side js api speed/organization

Say I have certain string attributes of an AR object, 'filename' and 'title' for instance, and the way I wish to dynamically fill in a select box on the front end is to ajax in the JSON representation of this object and either display the title attr as the select option's text if it exists, or use the filename attr as the select option's text if the title attr is blank. Now, should I be doing the this-else-that logic I just described on the server-side and returning it w/in my object's JSON representation as something like a 'display_name' attr, or should I be returning the vanilla as_json representation of the object w/ only the AR attrs included and let the js make the decision whether to display the title attr or the filename attr as the select option's text? From what I can tell, JS is much faster than ruby, but at the same time, it seems more maintainable to have this logic on the server-side. I'd also like to know, in general, is executing logic faster on the client side w/ js, or on the server-side w/ ruby? Thanks!
You really shouldn't have to worry about speed too much here - it's highly unlikely that you are really going to suffer from performance problems caused by if/else statements unless you're doing something wrong.
Instead, go for clarity and simplicity. In this case, that probably means rendering the pages on the server directly, unless the data is already in JSON for some reason.
My recommendation is to put logic where it belongs. If the logic is about presentation/rendering, then I would put it in your presentation layer. From your description, this seems to be your client-side JS.
I recommend you keep your APIs agnostic of how their data is rendered/presented as much as possible. This will allow you to change your views without having to also change the structure of the payload returned by the APIs.
In my experience, presentation layers tend to change more often than the underlying structure of the data they present.
I agree with the previous answer, I wouldn't worry about speed here, and go for clear separation of concerns.

Optimal way to pass system values to javascript

What is the most effective way to pass object and category ids or other system variables which shouldn't be presented to the user, from server to the browser?
Let's say I have a list of items where I can do something with each of them by javascript, for example show tooltip html or add to favorites by ajax, or display on a map. Where is it best to save that tooltip html, or database id, or geoposition?
Some options I can think of are:
some dictionary within <script></script> tag for each item,
microformats,
inline xml,
rel attributes,
css class names with specific information, e.g. class="lat-12345 uid-45678",
one <script></script> with a dictionary of html ids mapping dictionaries with system values in the template,
javascript generated from the database and included via <script src="..."></script> with a dictionary of html ids mapping dictionaries with system values in the template,
ajax requests for all cases when I need more information than just id,
event handlers with parameters within html tags, e.g. onmouseover="tooltip(this, 123, 'Hello world!')".
P.S. I prefer unobtrusive solutions and also the loading/execution time is important.
Perhaps I am missing something... why not just JSON?
How you "send" it (either in the initial page load as "javascript" or via AJAX or whatnot) is really just a trivial detail determined mostly by when the data is available. (JSON is a subset of legal JavaScript syntax.)
Then it's just a matter of the correct transformation. Of course, by pushing this to JSON/JS, you may render some non-JS clients non-interoperable, if that's a consideration for you. If such is indeed the case, why not just perform the transformation server-side using well, any number of the techniques you put at top?
You can also use arbitrary attributes in HTML (the HTML5 spec may include "data-*" which is formally legalized) -- while not technically "correct", all major web-browsers will accept unknown attributes which can be accessed through the DOM API.
I'd prefer a single AJAX call to fetch whatever data you know you need at the outset, so you can have a simple JSON object available in your script. You can, of course, supplement that with additional calls should you find you need more information.
If that's impractical, then "hardcoding" a JavaScript object in a <script>...</script> tag is the next best option. Of course, "hardcoding" is from the browser's perspective. The actual content would surely be written by server-side script from your database.
One method you can use is custom attributes. I think you refer to this as micro-formats, but I am not entirely sure if they are the same thing so I have written a description below.
Having hit the same question before, I basically use something like the following:
<div data-pid="1234">
<a href="#" class="add-to-favourites">
<img src="addToFavourites.png" />
</a>
</div>
$("a.add-to-favourites").click(function() {
$.load("/Favourites/Add.php?prodID="+$(this).parent().attr("data-pid"));
});
This should do exactly what you want to do. The reason I have put the pid in the div, not the a tag, is that you can then place all the other product information within the div with other actions the user can take, for example displaying a tooltip on mouseover using data-description, or displaying on a map using data-geo-x and data-geo-y. Of course you can name these anything you want.
Support / Acceptance
This is becoming a perfectly accepted way to do what you want to do. HTML 5 supports this for precisely the kind of thing you are trying to achieve.
So it is supported by HTML 5, but what about HTML 4?
It may make HTML 4 invalid, but the world is moving on to bigger and better things. Older browsers (IE6 and before, FF1 / 2, Opera 7 / 8 / 9) are becoming less common so it shouldnt be a problem. It wont actually break older browsers - the functionality will still work.
Important validity note
Make sure you prepend the data- onto the attribute name. This will make the attribute perfectly valid in HTML 5.
A few extra hints
In jQuery 1.5, I have heard from an answer to my question that you can simply specify attr("pid") to return the value of data-pid. If this is the case then I would be careful when naming the second part of the attribute name after the name of an actual attribute (for example, instead of data-id, use data-pid - especially if the id attribute is specified. I am not sure what effect it would have if you didn't do this, but its better to avoid the problem in the first place than have issues with the site at a later date due to this.
Hope this is what you were looking for.
ASP.NET offers a very convenient way to do this. You can simply write a JavaScript object. I am sure other templating engines offer similar ways to do this.
var person = {
Name : <%= _person.Name %>,
Age : <%= _person.Age %>
};
I would implement a Javascript singleton AppCacheManager that initializes in the document.ready event. A bit JS oop and you have a fully fledged OOP datastore.
Whenever information is needed, you load it through Ajax / RESTful Webservice and cache it in the AppCache Manager. So you have 2 caches: 1. Browser Cache, possible due to RESTful webservice URL caching, and 2: the JS Cache Manager.
You access all requests to the AppCacheManager which transparently fetches the new data or returns the cached data, so that the client doesnt need to know anything of the caching.
in short:
write a JS CacheManager
don't fetch the whole data at once but in small parts when needed and cache them
define a convenient interface for the cachemanager
Example usage:
linktext
Unobtrusiveness is a very difficult thing in JS and i'd be eager to know something about that, too.
hope that helped.

Any clever ways to serialize an HTML element? - Javascript

I'm trying to store a reference of an HTML tag for later reuse.
e.g. If I click on a div and save a pointer to that div within Javascript, will there be a way I could serialize such pointer? So I could de-serialize it and use the pointer in another instance of the web application?
Only methods I can think of are the following:
Use id or name attributes
Create a CSS selector for that element
Any other ideas guys? =)
You could try generating an XPath string for the element - the more complex the string, the more accurate and portable an identifier it will be.
For example, a simple element-only XPath query string would not be very unique, and likely to re-occur:
'//html/body/div/div/p/strong'
Factoring in all attributes might be overkill
'//html/body[#onclick="somereallylongjavascript" and class="nosidebar"]/div[#id="wrapper" and #class="posts"]/div[#class="entry" and #id="firstentry"]/p[#class="first"]/strong'
But you could probably find a nice middle-ground by limiting to certain attributes, maybe just to IDs:
'//html/body/div[#id="wrapper"]/div[#id="firstentry"]/p/strong'
You can retrieve XPath natively in all browsers. There's the W3C method:
var myElement=document.evaluate(
XPathstring,
document,
function(ns){return{'html':'http://www.w3.org/1999/xhtml','':null}[ns];},
9,
null
).singleNodeValue;
(the ns function is purely if you need application/xhtml+xml support)
The IE method is more simplistic but less flexible:
var myElement=document.selectSingleNode(XPathString);
Creating the XPath string is a different issue of course - there are various options, none native unfortunately. XPather is a moz add-on that provides an interface that does this - its source is MPL-ed and relatively simple but is probably more than you need. There are various shorter scripts available that provide simpler solutions.
Edit: Justin Johnson has provided a link to an SO answer containing a VERY short XPath-generating function. It's a bit simplistic, it uses odd id notation (id(blah) instead of [#id="blah"]) and doesn't toLowerCase() its tagNames which could impair portability, but other than that it looks perfect for your needs.
What exactly are you trying to save? And where exactly are you re-using it?
A DOM element would be very specific to that particular browser rendering on that page -- Just hitting refresh will give you an whole new DOM element. So, what about it do you need to save & recreate?
How about the innerHTML of the element?
Only logical way is to use id.
It is ussually not hard to assign id to all important elements based on database values.
Based on the way you worded your question, I don't think that would be possible. What exactly do you mean by "another instance of the web application"? Since JavaScript will be running on the client side, you won't be able to share data between clients. However, you might want to do something like store/read from a database. Can you describe more of the functionality you are trying to achieve?
XPath seems to be the most appropriate; however, only if the page structure is (relatively) static up to that node. Here are some references and code:
Method for getting the xpath of an arbitrary node and example use
getPathTo($("a")[4]):
yields
"id("hlinks-custom")/A[2]"
MDC XPath documentation
It looks like JSON.stringify( yourDivReference ) and JSON.parse( serializedObjectString ) might do what you're looking for.
UPDATE: Actually, the JSON methods don't like the circular references in the DOM. See this question for more details: How to serialize DOM node to JSON even if there are circular references?
I do, however, agree with Sergey that using the ID seems like a better way to go.
Another idea - to generate own custom id's for all elements based on some rules:
element id starts from parent id. -> customid = "body/item"
If normal id is available use it. if not, use element type. Than add order in current subtree.
so, you will get something like "body-0/item-0" for example above or "body-0/div-4" if id is not known.
When you will try to use your "custom id" and page will be changed, you will have a chance to find closest element, comparing all elements custom id to stored "custom id".
I've tried something like this:
{tag:"div", style:"float:left;", "class":"fancy", inner:[
{tag:"a", href:"http://google.com", inner:"A link to google!" },
{tag:"a", href:"http://yahoo.com", inner:"A link to yahoo!" }
]}
Seems to work okay, although it's easy to get lost with all the curly brackets.
edit - maybe I completely misunderstood what you want... if you want to serialize a handle to that element, like what would be returned by getElementById, you might as well just use the id.

should I ALSO keep my data in a Javascript data structure? or just in the DOM?

I am very new to Javascript and Jquery, so my apologies for this beginner's question.
In a simple ajax web app, I am creating an HTML page which is mainly a big table. Each row in this table describes an event (party, show, etc). My page not only displays this information but is meant to let the user do a bunch of things with it, in particular to dynamically search and filter the table according to a variety of criteria.
First an abstract beginner's question: in this broad kind of situation (by which I mean that you want your javascript code to run a bunch of operations on the information you retrieve from the webserver) would you use the DOM as a data structure? The ease with which one can search and manipulate it (using Jquery) makes that a possibility. (E.g., "find me table rows describing an event with date column = 2010-01-01 and event type column = 'private party'.) Or would you keep the same information in a traditional Javascript data structure, search/filter/operate on that using plain javascript code and then update the DOM accordingly to display the results to the user?
(As a newbie, I imagine the first, DOM-only approach to be slower while the latter to be take up a good deal of memory. Right? Wrong?)
Assuming the second strategy is reasonable (is it?), then a practical question: can I simply store in my Javascript objects a pointer to the corresponding Jquery object? Eg, can I do
var events = new Array();
// ....
var event3094 = new Event('party','2010-01-01' /*, ... */);
event3094.domElement = $("#correctIdOfTheEventRowInMyTable");
events.push(event3094)
Does this store just a reference (pointer?) to the Jquery object in each Event object or is it creating a new copy of the Jquery object?
I am just wondering "how the pros" do it. : )
Thank you for any advice and insight.
cheers
lara
There are so many ways to do this, but DOM manipulation will almost always be slower than JS manipulation.
To answer your question, anytime you use $(selector) a new jQuery object is created and a match to find the element is performed.
I would recommend two approaches:
FIRST OPTION
Load data in a normal HTML table
Read through the rows, and store just the data (each cell's contents) in an array similar to your code example.
Store a reference to the tr in that object.
Then you can process filter, etc, and only apply changes and searches to the DOM as needed.
SECOND OPTION
Load the page without the table
Load the data as JSON from the server, and generate a table from the data
Store reference to the tr element
Basically, you don't want to perform a $(selector) a 1000 times. The concept is something like this:
var $rows = $("table tr");
// ...
event.domElement = $rows[0]; // Stores reference to existing DOM node, not a new jQuery object.
Then when you need to use jQuery methods on the object, you could use $(yourEvent.domElement) to wrap it in a jQuery wrapper.
Depending on the number of rows you might expect to be shown for most of your users (let's assume it's no more than a few hundred), I myself would probably aim to just keep everything in the DOM table that you're already building. (If you are expecting to be dealing with thousands of rows on one page, you might want to explore a different solution rather than sending it all to the browser.)
There are a few things that you did not mention in your original post. First, how are you creating this table? I imagine using a server-side solution. How easy is that to modify? How much extra work would it be to go through and generate all of your data a second time in a different format, as XML or JSON? Does this add a bunch of complexity on the server-side, only so that you can add more complexity client-side to match? Certain platforms may make this trivial, but is something to consider.
Now, in regards to your alternatives to the DOM:
I agreed and mentioned in a comment above that I don't think JSON would be very optimal "out of the box" for what you want to do. A javascript array is no better. XML is nice in that you can use jquery to easily traverse/filter, but then you still have to deal with your DOM. Sure, you can store references to your DOM elements, but that just seems like a bunch of work up front and then some more work later when matching them up. And without necessarily guaranteeing any major performance boost.
So, to answer your question directly as it is phrased, should you ALSO keep your data in a JavaScript data structure, or just in the DOM: You did mention this was a "simple" ajax web app. My recommendation is to try and keep this simple, then! Your example of how you can so easily use jquery to find rows and cells based on search criteria should be enough to convince you to give this a try!
Best of luck!-Mike
I think you'l find that the DOM method is close to the same speed if I follow your logic right. The second method will require you to manipulate the data, and then apply the changes to the DOM, where the first method allows both operations at the same time.
If youve got alot of data i would for go making objects and just supply it as XML. that way you get most of the same features as operating on the HTML DOM but you dont have a crazy markup structure like a table to navigate through.
I think it's largely a personal preference, but I like to store the objects in JavaScript and then render them to HTML as needed. From my understanding
event3094.domElement = $("#correctIdOfTheEventRowInMyTable");
will store a reference to the jQuery wrapper of your row element (not a copy).
One benefit of storing is JS is that if you have lost of objects (eg 10,000 ) and only render a small fraction of them, the browser will perform a lot better if you're not creating 10,000 * (number of DOM elements per object) elements.
Edit: Oh, and if you can, you might want to send the data from the server to the client as JSON. It's very compact (compared to XML) and in the new browsers it can be parsed quickly and safely using JSON.parse(). For older browsers, just use this library http://www.json.org/js.html . The library will only create a global JSON namespace if the browser doesn't supply it.
One thing to consider is how you need to access your data. If all the data for an element's event is contained in the element (an event operating solely on a table cell for example), then storing in the DOM makes sense.
However, if the calculation of one element depends on data form other elements (a summation of all table cells in a particular column, for example), you may find it difficult to gather up all the data if it's scattered about in DOM elements compared to a single data structure.

Categories