8

For the past few years I have always used a client-side hidden <input> field to store a server-side value and use it in Javascript land.

For example, let's say I need an Ajax timeout value from my app configuration.

I'd probably store it like this in my JSP:

<input type="hidden" id="ajaxTimeout" value="${serverValue}" />

and then use it like this where my AJAX call lived in an external file:

$("#ajaxTimeout").val()

I was having a discussion about this today and it was suggested that it is best practice to store values which are only going to be used by Javascript within HTML <meta> tags.
Does this matter? Is there a preferred way to obtain server-side information which is solely to be used in Javascript?
My understanding is that if the hidden input field is not part of a form then it is safe enough to use to store value as it won't be attached to any requests. Having said that, I've always thought this was indeed a bit of a hack.

Thoughts?

::EDIT::
Two fantastic answers:

wild_nothing
  • 2,845
  • 1
  • 35
  • 47

4 Answers4

4

In addition to the plain old object literal method given in other answers, if the value you want to pass to the client is about a specific DOM element (or there is a DOM element that represents the logical object that the value is about), you can put the value in a data attribute:

<div id="videoplayer" data-startplayingat="1:02">HTML Content</div>

This is accessible as an entire attribute, data-startplayingat, or in modern browsers there is the dataset attribute. jQuery syntax is $('#videoplayer').data('startplayingat').

The official W3C spec on data attributes explains all this.

Here are a few interesting highlights:

  • The name must not use upper case letters, and must be XML compatible.
  • The dataset attribute converts dashes, such that a name like start-playing will become startPlaying.

One potential drawback for the object literal method (which I like and have used myself) is that if you want the object in a .js file, then normally static javascript files have to be run through your dynamic parser--which will cause a potentially small (but still present) performance loss. Putting the object declaration into a <script> tag in an HTML file works around this, but then you can have script load order issues to deal with.

ErikE
  • 48,881
  • 23
  • 151
  • 196
  • Excellent. I'd prefer this method. Shows how long it has been since I'd written any JSP/ASP/PHP stuff.... – ZenMaster Dec 11 '13 at 03:58
  • Using the example of a AJAX timeout value (or any value which is not tied to a specific DOM), would it still be worth creating a div and using a data attribute to store this value instead of an object literal? – wild_nothing Dec 11 '13 at 04:47
  • @wild_nothing I think that using data attributes should be for things that are at least logically linked to a DOM element. I wouldn't want to use them for general in-page data. The object literal would be my preference for something like an ajax timeout. I just wanted to offer you a complete set of answers... – ErikE Dec 11 '13 at 20:31
  • Excellent. You guys have been a great help! I'll take this as a general rule then. – wild_nothing Dec 11 '13 at 22:46
3

We personally do something like this:

var options = {
    selector: '#divId',
    serverSideVariableHere: <%=AspNetProperty %>,
    anotherServerSideVariableHere: <%=AspNetPropertyTwo %>
}
var viewModel = new KnockoutViewModel(options);
ko.applyBindings(viewModel, $(options.selector)[0]);

This is simply an example using KnockOut JS, but this idea can be expanded to any JavaScript library you choose to use (or not ;))

We then pass these options to whatever use them, such as Knockout ViewModels, or whatever. That way our JavaScript remains testable and we can pass in whatever values we want to our tests.

Kyle Muir
  • 3,875
  • 2
  • 22
  • 27
  • I do the same in Backbone+Rails back-end. For instance, to some some relevant info about the currentUser, we do this in the layout: var window.AppName.currentUser = new AppName.Model.CurrentUser($.parseJSON(<%= dump current_user useful attributes in json %>)); – Enders Dec 11 '13 at 03:58
  • 2
    Just be aware that in an ASP classic or Asp.Net web site, extra action is required to run .js files through the ASP parser--so some extra setup is needed. This has a potential (though likely small) performance implication. – ErikE Dec 11 '13 at 04:02
  • On the other hand, nothing is stopping you from putting the requisite object declaration into an html file in a ` – ErikE Dec 11 '13 at 23:58
1

Using meta tag for something other than browser meta-"instructions" is no less of a hack IMO.

I would consider storing JavaScript data where it belongs - in JavaScript, using JavaScript object literals.

ZenMaster
  • 12,363
  • 5
  • 36
  • 59
1

I strongly prefer JSON snippets in data- attributes. This lets you scope them to the related HTML element, and you don't pollute your Javascript global namespace, or have to generate additional code to handle namespacing otherwise. Coupled with a JSON serialiser on the server side this minimises having to manually escape anything in your values.

(Also I have a Thing™ against <script> tags with content in general. View and logic separation and all that.)

millimoose
  • 39,073
  • 9
  • 82
  • 134
  • Not sure I'd have snippets, as you would have to `eval` them, but `data-` attribute is certainly a good way. – ZenMaster Dec 11 '13 at 03:59
  • @ZenMaster - Non-evalling JSON parsing is a standard part of JavaScript 1.7 and available on pretty much any browser you could want: http://caniuse.com/#feat=json. (For older ones you have Crockford's `json2.js`.) – millimoose Dec 11 '13 at 04:08
  • Another tiny advantage is that it will force jQuery's automatic type conversion it does in `.data()` to use JSON parsing, instead of making some other, possibly incorrect guess. – millimoose Dec 11 '13 at 04:10
  • 1
    Right. IE7 support on the latest project totally messed my approach. There is also json3, BTW. – ZenMaster Dec 11 '13 at 04:12