Our application uses a lot of configuration options. Those options need to be reflected on the client side in the form of User preferences, site wide preferences, etc.
Currently, we pass server side settings down to the client side in the form of JSON that is stored in custom attributes in the markup for a specific element (and no, our application currently doesn't worry about W3C validation). We then retrieve the data from the custom attribute, and parse it into a JSON object for us开发者_JS百科e in script using jQuery.
One drawback to this is referencing attributes on elements from within event handlers. I know this is frowned upon, as it can create circular references, and subsequently memory leaks. I would much prefer to use jQuery's data function, but you can't invoke this from the server side at page render time.
What does everyone else do in this type of scenario?
Return the server data in JSON format. You could do this through AJAX by returning a JSON header, or simple page outup and JSON.parse()
.
You can assign the JSON data directly to an element's data.
$('#elementid').data('serverdata', data);
Update
After better understanding your situation I would suggest you use the data-
attributes for three reasons.
- You will have standards compliant markup.
- The recent version of jQuery relies on these for the
.data
function. - The change will require little modification to your current application (changing the way custom attributes are output from
customAtt="value"
todata-customAtt="value"
Here is some more information on the data attributes.
You can render in the page an inline script that defines a JS object with all the preferences. This way, your scripts have access to the data the moment the browser is done with the page load. The drawbacks:
- you have inline script in the page, which some people frown upon;
- caching the page might result in oder preferences being used for particular page instance;
- each page size is increased with the prefs size.
Or you can render in the page a link to an external script that declares the preferences. This way, the preferences don't block the page rendering, and can be cached separately by the browser. Drawbacks:
- the page might render with older preferences and then get update to the new preferences, which on slower networks might be visible;
Or you could directly add the data to an element using the HTML5 data attributes (thus being HTML5 conformant and jQuery.Data compatible, as it uses those as well). Drawback:
- you lose IE support;
At my projects I usually render such data as global JavaScript variables at the top of master page:
<script language="javascript">
var g_someOption=<%= Options.SomeOption.SerializeToJsonLiteral() %>;
var g_someOtherOption=<%= Options.SomeOtherOption.SerializeToJsonLiteral() %>;
// or
var g_globalOptions = {
thirdOption:<%= Options.ThirdOption.SerializeToJsonLiteral() %>,
foursOption:<%= Options.FourthOption.SerializeToJsonLiteral() %>
};
// or even via special helper that renders object above
<%= Html.RenderGlobalScriptVars() %>
</script>
If project is full of AJAX and user can stay on some page for a long time, it is possible to refresh settings periodically using AJAX requests to the server.
P.S. I've used aspx syntax, but I believe that you got an idea even if you're using some other language.
Just to add another option, you can always do a
<script type="text/javascript" src="settings.php"></script>
to output stuff from PHP. You can use this to invoke the necessary data calls, for example. Just send the correct header.
I usually use MVC, so I'm in the habit of making AJAX calls when the page loads to get objects I might need. I'm not sure what technology you're using, but it shouldn't be too hard to set up an endpoint that returns this JSON and call it when the DOM is ready. Then you can store it as a JavaScript variable and not worry about stuffing it into some element's attributes.
A good compromise is to render a single configuration object that is keyed by the ids you use for the nodes (or any other scheme that will let your handlers find the data). Instead of using inline handlers, set the handlers after the page is loaded. Then it should be easy to reference the json your server side created.
This example uses semi-globals
<script>
$(function() {
// The following line would be generated in php using something like:
// var cfg = <?= json_encode($cfg) ?>;
var cfg = {
orders: [{total: 25, itemCount: 10}],
waiting: [{total: 20, reason: "Out of strock"}]
};
$('orders').click(function(){
alert('You have a total of ' + cfg.orders[0].itemCount + 'orders');
});
})
</script>
<body>
<div id='orders'> Here are your orders</div>
</body>
Alternatively if you really want to scope your variables, you can do the following:
<script>
$(function() {
$('orders').click(function(){
var orders = <?= json_encode($orders) ?>;
alert('You have a total of ' + orders[0].itemCount + 'orders');
});
})
</script>
<body>
<div id='orders'> Here are your orders</div>
</body>
The above example is less flexible since you couldn't reuse the orders variable from other handlers if you needed to.
精彩评论