Skip to content

Instantly share code, notes, and snippets.

@jperl
Last active August 29, 2015 14:02
Show Gist options
  • Save jperl/547d12613c1fd964de50 to your computer and use it in GitHub Desktop.
Save jperl/547d12613c1fd964de50 to your computer and use it in GitHub Desktop.
Meteor Rider with Offline Support / Caching
var CordovaApp = {
/**
* Load the meteor app with meteor-rider.
* @param {Boolean} [force] Overwrite the cache.
*/
loadMeteor: function (force) {
if (force) {
CordovaApp.loaded = false;
MeteorRider.clearCache();
}
if (CordovaApp.loaded) return;
MeteorRider.init(METEOR_URL, function (error) {
if (error) return;
CordovaApp.loaded = true;
});
},
/**
* Callback for the meteor app to call when it is started.
*/
started: function () {
// Hide the splashscreen.
navigator.splashscreen && navigator.splashscreen.hide();
}
};
// Need to wait until the device is ready
// so cordova can load plugins.
document.addEventListener('deviceReady', function () {
CordovaApp.loadMeteor();
});
/**
* (Modified) Meteor Rider
* ===================
*
* This script is to facilitate an easy means of "taking over" or "hijacking"
* a HTML page, with a Meteor app.
*
* Use Case
* ----------------
* The Use Case for this, is for a PhoneGap application. On the device, you
* load a basic HTML file, and it initializes the phone and device specific JS.
* Then you use Meteor Rider to connect to your Meteor backend and "take over"
* the HTML.
*
* Requirements
* ----------------
* jQuery or Zepto are required, because I'm lazy and want to use their API for
* AJAX+DOM
*
* Gotchas
* ----------------
* Cross Origin Request Security doesn't allow this in a browser,
* but PhoneGap does, and if we can inject CORS headers into Meteor it might
* work in a browser sometime
* Meteor Rider can not remove CSS... so anything loaded on the root page, remains.
*
*/
var cachedHtmlKey = 'MeteorRider.html',
cachedUrlKey = 'MeteorRider.url';
var MeteorRider = {
clearCache: function () {
localStorage.removeItem(cachedHtmlKey);
localStorage.removeItem(cachedUrlKey);
},
replaceDocument: function (url, html) {
// set the window.location object correctly so iron-router
// and other packages that depend on window.location work correctly
window.history.replaceState({}, '', url);
// replace the document with the new document/data
document.open();
document.write(html);
document.close();
// trigger the "loaded" events (it'd be nice to do this AFTER JS has loaded
$(document).trigger('DOMContentLoaded');
$(document).trigger('load');
$(document).trigger('complete');
},
init: function (url, callback) {
if (MeteorRider.loading) return;
var cachedHtml = localStorage.getItem(cachedHtmlKey);
var cachedUrl = localStorage.getItem(cachedUrlKey);
// Make sure the cached html is for the right url.
// The url should not change often (except in development)
// but we need to check just in case.
if (cachedUrl !== url) {
localStorage.removeItem(cachedHtmlKey);
localStorage.setItem(cachedUrl, url);
} else if (cachedHtml) {
MeteorRider.replaceDocument(url, cachedHtml);
if (callback) callback();
return;
}
MeteorRider.loading = true;
// request html document
$.ajax({
url: url,
cache: false,
error: function (jqXHR, textStatus, errorThrown) {
if (callback) callback(errorThrown + ' ' + textStatus);
MeteorRider.loading = false;
},
success: function (data) {
// update URLs
var html = data.replace(/(href|src|manifest)\=\"\//gm, '$1="' + url + '/');
// add app cache manifest
html = html.replace(/<html/, '<html manifest="' + url + '/app.manifest"');
MeteorRider.replaceDocument(url, html);
// cache the html
localStorage.setItem(cachedHtmlKey, html);
if (callback) callback();
MeteorRider.loading = false;
}
});
}
};
Meteor.startup(function () {
if (window.CordovaApp) {
// Manually reload the app with the hijack method
// to maintain references to cordova and the plugins.
Reload._onMigrate('CordovaApp', function () {
CordovaApp.loadMeteor(true);
// XXX cleanup memory.
return [false];
});
// Let the cordova app know the meteor app has started.
CordovaApp.started();
}
});
@jperl
Copy link
Author

jperl commented Jun 17, 2014

Need the reload package in the meteor app to access Reload._onMigrate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment