ratchet icon indicating copy to clipboard operation
ratchet copied to clipboard

What is the best practice for dynamic data?

Open chriswhong opened this issue 9 years ago • 5 comments

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?

chriswhong avatar Mar 02 '15 15:03 chriswhong

+1 i am looking for solution too, maybe implement callback in push.js by default?

kamil7x avatar Apr 21 '15 21:04 kamil7x

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 }}');
});

datashaman avatar Apr 26 '15 04:04 datashaman

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);
});

datashaman avatar Apr 26 '15 05:04 datashaman

But the above push event only seems to fire once per page. Sigh.

datashaman avatar Apr 26 '15 06:04 datashaman

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.

qkdreyer avatar Jun 30 '15 12:06 qkdreyer