I'm writing a framework which uses javascript/html as the client and it-doesn't-matter as the back end.
From time to time I have a need to store data in the HTML DOM. Ideally I'd like to store the data against a DOM element, but I want this element to have no UI impact.
At the moment I'm thinking I'll use a <span> with no text content and decorate it with attribution so that my framework can pick up that it is a data container and behave appropriately.
Is there a better choice? (For the avoidance of doubt, I know there are other ways I could do things - I'm not interested in these, purely in what the best HTML element to use to contain data without having a UI impact).
Edit (explanation of architecture):
I've created a server-side technology which is based on top of a generic reporting engine I've previously created. This server-side thing essentially works as a web-server - this might seem like an unusual choice to make but, given organisational constraints, it's the best choice - for the sake of argument, assume this is true. One of the things I need this system to do is to generate dynamic forms to capture data which is in a tree-like form. This has been fine and has worked well - my question is because when a sub-form is hidden (for example, the user has made all required decisions in a given sub-section of the data), I destroy the data capture elements - if the form is embedded within a parent form which needs access to the data captured in a destroyed sub-form, I need a way of embedding the data into the DOM so it can be collected to be passed back to the server. The requirements are a lot more complicated that this, but it'll take far too long to detail them all.
Well (and for the avoidance of doubt), the HTML elements are not supposed to store data. If you really want to, use the <input type="hidden"> element.
For your purpose, I recommend (in that order) using localstorage or cookie or web database.
here are some resources :
localstorage : http://diveintohtml5.info/storage.html
cookie : http://www.the-art-of-web.com/javascript/setcookie/
web database : http://www.tutorialspoint.com/html5/html5_web_sql.htm
As JLRishe pointed out, if you need, for whatever reason, a text node storage, then span is a good choice as div is (and as lot of elements are as long as you display: none them).
You could just create javascript objects...
var myData ={
property1:"aaaaa",
property2:500,
property3:{morestuff1:"AAA", ... },
property3:["list1", "list2", ... ],
....
}
Easy to access and easy to manipulte within the DOM if you need.
No UI impact.... (no render)
The obvious choice here is to use HTML data attribute. If you have a table and want to store info about the table that is not shown to the user - you could just:
<table id="mytable" data-id="2000" data-rows="20" data-whatever="whatever">
You could then get it with jQuery easely with:
$("#mytable").data('rows');
Which would give you 20.
It's not good practice to store data in the DOM, if you're not actually using it for the purpose of layout. Yikes!
To better suit your needs, HTML5 provides a JavaScript API for handling client side storage. Depending on your circumstances, you have 2 options to choose from. The APIs are exactly the same, the only difference is the lifetime of the storage.
They are:
localStorage: Local storage is persistent; data stored in local storage is even available to the webpage after the user closes the browser completely and reopens it.
sessionStorage: As the name says, this data is only available for the current session.
Here's a link that will help you better understand these APIs so you can solve your particular problem: http://www.w3schools.com/html/html5_webstorage.asp
Related
I have a list of id's stored in my ASP.NET application's session. For contextual purposes:
This is a facebook-like chat module. Id's are relevant to individual chat tabs.
jQuery is handling many things and requires the specific id of each box.
When a new chat session is created, it is given an id on the serverside used for client-side interaction like jQuery event binding
The program works fine I just need a way to access the list on the front-end. I would assume converting the object to a json object makes the most sense but I'm not quite sure where to start.
You can always render server-side content to the client by doing something like:
var ids = '<%= Session["Keys"].ToString() %>';
And then split the results and convert them however you want them. It really depends on what the ID's look like (just numbers, or is more info involved), and how you use them, so it's hard to provide additional advice without more information about the structures.
Add this to your project http://www.nuget.org/packages/Newtonsoft.Json then review this resource http://james.newtonking.com/projects/json/help/index.html?topic=html/SerializingJSON.htm to work out how to do the serialize/deserialize operations ;o)
I'm new to web applications and am trying to understand the best way to work with data in HTML. I'm using Appengine (Python) and have managed to load a bunch of data to the view. In the simplest form, it's a set of movie names and each name has associated details with it (e.g. year, rating etc). Now how do I pass data between the movie link and then a div where all the details will be displayed? I'll be using jQuery for some controls in my application so I'm wondering if there's a way to do data binding to controls with that?
Additionally, can anyone tell me what're the standards around this i.e. if I load all this data to the UI in one call (assuming it's not a lot of movie titles), wouldn't it make it easy for people to screen scrape this information? Or is there some obfuscation that's typically used here?
Sorry if I'm not very clear but I really am an absolute beginner with web development!
Update1:
I found the jQuery data() api. It seems like this'll work. Comments?
Update2:
Some testing later and it turns out that data() actually attaches the data to the elements rather than showing it in a div itself.
There's a few ways to do it but the basic idea is to put the data in the HTML in a way that is not visibly rendered, then use Javascript to parse the HTML and pull the data out when you need it.
The easiest way on modern browsers is to use data- attributes. These are any attribute that start with data-, and you can name the rest yourself. For example:
Czar Wars
In this case, the user will only see a link called "Tsar Wars" but your javascript can easily access the data- attributes to get the data it needs. The other benefit of this approach is that jQuery will automatically make data- attributes accessible by the data() api.
Another way to do it is to have a hidden HTML list element with all your data elements in the list, but you'll have to parse this all yourself.
There's no standard obfuscation. You'll need to obfuscate yourself on the server side, and unobfuscate in your JS. It's not too difficult to figure out any obfuscation algorighm in js, so this is not worth your while.
If the data really is private, then you would have to architect it as to do all the processing on the server. For example, only show tokens (like 1234), and use AJAX calls to pass the token to the server so the server can do the data processing and spit back publicly safe results to the script.
I'm integrating an external application to SharePoint 2010 by developing custom ribbon tabs, groups, controls and commands that are made available to editors of a SharePoint 2010 site. The ribbon commands use the dialog framework to open dialogs with custom application pages.
In order to pass a number of query string parameters to the custom applications pages, I'm therefore looking for the equivalent of SPContext.Current.ListItem in the Client Object Model (ECMAScript).
Regarding available tokens (i.e. {ListItemId} or {SelectedItemId}) that can be used in the declarative XML, I already emitting all tokens, but unfortunately the desired tokens are not either not parsed or simply null, while in the context of a Publishing Page (i.e. http://domain/pages/page.aspx). Thus, none of the tokes that do render, are of use to establishing the context of the calling SPListItem in the application page.
Looking at the SP.ClientContext.get_current() provides a lot of information about the current SPSite, SPWeb etc. but nothing about the current SPListItem I'm currently positioned at (again, having the page rendered in the context of a Publishing Page).
What I've come up with so far is the idea of passing in the url of the current page (i.e. document.location.href) and parse that in the application page - however, it feels like I'm going in the wrong direction, and SharePoint surely should be able to provide this information.
I'm not sure this is a great answer, or even fully on-topic, but is basically something I originally intended to blog about - anyway:
It is indeed a pain that the Client OM does not seem to provide a method/property with details of the current SPListItem. However, I'd venture to say that this is a simple concept, but actually has quite wide-ranging implications in SharePoint which aren't apparent until you stop to think about it.
Consider:
Although a redirect exists, a discussion post can be surfaced on 2 or 3 different URLs (e.g. Threaded.aspx/Flat.aspx)
Similarly, a blog post can exist on a couple (Post.aspx/EditPost.aspx, maybe one other)
A list item obviously has DispForm.aspx/EditForm.aspx and (sort of) NewForm.aspx
Also for even for items with an associated SPFile (e.g. document, publishing page), consider that these URLs represent the same item:
http://mydomain/sites/someSite/someLib/Forms/DispForm.aspx?ID=x, http://mydomain/sites/someSite/someLib/Filename.aspx
Also, there could be other content types outside of this set which have a similar deal
In our case, we wanted to 'hang' data off internal and external items (e.g. likes, comments). We thought "well everything in SharePoint has a URL, so that could be a sensible way to identify an item". Big mistake, and I'm still kicking myself for falling into it. It's almost like we need some kind of 'normalizeUrl' method in the API if we wanted to use URLs in this way.
Did you ever notice the PageUrlNormalization class in Microsoft.SharePoint.Utilities? Sounds promising doesn't it? Unfortunately that appears to do something which isn't what I describe above - it doesn't work across the variations of content types etc (but does deal with extended web apps, HTTP/HTTPS etc).
To cut a long story short, we decided the best approach was to make the server emit details which allowed us to identify the current SPListItem when passed back to the server (e.g. in an AJAX request). We hide the 'canonical' list item ID in a JavaScript variable or hidden input field (whatever really), and these are evaluated when back at the server to re-obtain the list item. Not as efficient as obtaining everything from context, but for us it's OK because we only need to resolve when the user clicks something, not on every page load. By canonical, I mean:
SiteID|WebID|ListID|ListItemID
IIRC, one of the key objects has a CanonicalId property (or maybe it's internal), which may help you build such a string.
So in terms of using the window.location.href, I'd avoid that if you're in vaguely the same situation as us. Suggest considering an approach similar to the one we used, but do remember that there are some locations (e.g. certain forms) where even on the server SPContext.Current.ListItem is null, despite the fact that SPContext.Current.Web (and possibly SPContext.Current.List) are populated.
In summary - IDs are your friend, URLs are not.
I'm building what I am hoping to be a fairly simple, quick and dirty demo app.
So far, I've managed to build a bunch of components using only html and javascript. I know that eventually I'll hook-up a db, but at this point I'm just trying to show off some functionality.
In the page, a user can select a bunch of other users (like friends). Then they go to a separate html page and there is some sorting info based on the selected users.
So my first attempt was to put the selected users object into a cookie, and retrieve the cookie on the second page. Unfortunately, if the user changed their selection, the cookie wasn't getting updated, and my searches on StackOverflow seemed to say that deleting and updating cookies is unreliable.
I tried
function updateCookie(updatedUserList){
jQuery.cookie('userList',null);
jQuery.cookie('userList',updatedUserList);
}
but though it set the cookie to null, it wouldn't update it on the second value.
So I decided to put the selected users object into a form. Unfortunately, it looks like I can't retrieve the contents from the form on the client-side, only on the server-side.
Is there another way to do this? I've worked in PHP and Rails, but I'm trying to do this quickly and simply before building it out into something larger and am trying to avoid any server-side processing for now, which I have managed to do up to this point.
Since this is a demo, can you use HTML5? If so, you can use local storage: link text.
Another option is to use AJAX to load the other HTML page (replace whole body of the current document). Your storage variables would be stored in the <head>. This is a tightly coupled design, but again you're making a quick and dirty demo.
Is updatedUserList a string? If it's an array you might have to stringify it first:
jQuery.cookie('userList', JSON.stringify(updatedUserList))
(and of course parse it when you're retrieving it.)
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.