ratchet
ratchet copied to clipboard
What is the best practice for dynamic data?
I am populating a slide-in page using the results of an Ajax call. I ended up hacking ratchet to include a callback on PUSH() so I could use jQuery to inject the data. Is there a best practice for this sort of thing that doesn't involve modifying PUSH() to suit my needs?
+1 i am looking for solution too, maybe implement callback in push.js by default?
I have the following scheme working pretty well. This is all in one central JS file (which is loaded for all pages in the layout template).
var initializers = {
'Home': function() {
// Do stuff for home page
},
'Settings': function() {
// Do stuff for settings page
}
};
function initializePage(title) {
var func = initializers[title];
// Only call the initializer if it exists
if(func) { func(); }
}
jQuery(document).ready(function($) {
// Initialize the page on push
window.addEventListener('push', function(e) {
initializePage(e.detail.state.title);
});
// Initialize the page on load, using the server-side
// generated page title
initializePage('{{ page.title }}');
});
This version is a bit better and needs no server-side stuff, which means it can be loaded as an independent script on all pages.
var initializers = {
'/index.html': function() {
// Do stuff for home page
},
'/settings.html': function() {
// Do stuff for settings page
}
};
function initializePage(title) {
var func = initializers[title];
// Only call the initializer if it exists
if(func) { func(); }
}
jQuery(document).ready(function($) {
// Initialize the page on push
window.addEventListener('push', function(e) {
// Remove the host from the URL to get the pathname
var pathname = e.detail.state.url.replace(window.location.origin, '');
initializePage(pathname);
});
// Initialize the page on load, using the current pathname
initializePage(window.location.pathname);
});
But the above push event only seems to fire once per page. Sigh.
I've just resolved the problem, using a simple XHR hook. Requirements : Underscore.js
(function(exports) {
var _proto = XMLHttpRequest.prototype;
var _open = _proto.open;
var _send = _proto.send;
var _hooks = [];
_proto.open = function() {
this.addEventListener('readystatechange', function() {
_.each(_hooks, function(hook, index) {
var matchURL = !hook.url || this.responseURL.indexOf(hook.url) !== -1;
if (this.readyState === 4 && this.status === 200 && matchURL) {
var attr = 'responseText';
var template = _.template(this[attr]);
var data = hook.data;
if (hook.attr) data = data[hook.attr];
delete this[attr];
this[attr] = template(data);
}
}, this);
});
_open.apply(this, arguments);
};
exports.afterPUSH = function(_url, _data, _attr) {
_hooks.push({url: _url, data: _data, attr: _attr});
};
})(window.RATCHET);
Usage :
window.RATCHET.afterPUSH('index.html', _app); // static data
window.RATCHET.afterPUSH('service.html', _app, 'category'); // dynamic object attribute data
You can even use this for templating your entry point (ie: index.html), only by wrapping your index template in a hidden container on DOM ready, and calling PUSH({url: location.href});
when you get your dynamic data.