Skip to content

Instantly share code, notes, and snippets.

@ashleycoker
Created July 17, 2014 16:10
Show Gist options
  • Save ashleycoker/0adc0e2db836ef2d6183 to your computer and use it in GitHub Desktop.
Save ashleycoker/0adc0e2db836ef2d6183 to your computer and use it in GitHub Desktop.
/**
* Offline Proxy
* @extend Ext.data.proxy.Ajax
*/
Ext.define('proxy.OfflineProxy', {
extend: 'Ext.data.proxy.Ajax',
alias: 'proxy.offline',
config: {
storageKey: null,
storageFacility: null,
online: true
},
originalCallback: null,
/**
* Override doRequest so that we can intercept the request and
* catch a failed request to fall back to offline
* @param operation
* @param callback
* @param scope
* @returns {*}
*/
doRequest: function(operation, callback, scope) {
},
/**
* Override processResponse so that if we are online we can store the response
* into the offline storage method provided and if a response fails,
* we can fall back.
* @param success
* @param operation
* @param request
* @param response
* @param callback
* @param scope
*/
processResponse: function(success, operation, request, response, callback, scope) {
}
});
/**
* A class that gives access into WebSQL storage
*/
Ext.define('storage.WebSQL', {
singleton: true,
config:{
/**
* The database capacity in bytes (can't be changed after construction). 50MB by default.
*/
capacity:50 * 1024 * 1024
},
/**
* @private
* The websql database object.
*/
storage:null,
connected: false,
constructor: function (config) {
this.callParent(config);
this.storage = openDatabase('storage', '1.0', 'Offline resource storage', this.getCapacity());
this.storage.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS items (key, value)');
}, function (error) {
console.error('WebSQL: Connection Error');
}, function () {
console.log('WebSQL: Connected');
});
},
/**
* Get an item from the store.
* @param key The key to get.
* @param callbacks object of success and failure callbacks
*/
getItem:function (key, callbacks) {
this.storage.transaction(function (tx) {
tx.executeSql('SELECT * FROM items WHERE key = ?', [key], function (tx, results) {
var len = results.rows.length;
if (len > 0) {
callbacks.success(results.rows.item(0).value)
} else {
callbacks.failure(); // no result
}
});
}, function (error) {
console.log('WebSQL: Error in getItem');
callbacks.failure(error);
});
},
/**
* Set an item in the store.
* @param key The key to set.
* @param value The string to store.
* @param callbacks object of success and failure callbacks
*/
setItem:function (key, value, callbacks) {
this.storage.transaction(function (tx) {
//remove old version first
tx.executeSql('DELETE FROM items WHERE key = ?', [key]);
tx.executeSql('INSERT INTO items (key, value) VALUES (?, ?)', [key, value]);
}, function (error) {
console.log('WebSQL: Error in setItem:' + error.message);
callbacks.failure(error.message);
}, function () {
callbacks.success(); // no value.
});
}
});
setItem:function (key, value, callbacks) {
this.storage.transaction(function (tx) {
//remove old version first
tx.executeSql('DELETE FROM items WHERE key = ?', [key]);
tx.executeSql('INSERT INTO items (key, value) VALUES (?, ?)', [key, value]);
}, function (error) {
console.log('WebSQL: Error in setItem:' + error.message);
callbacks.failure(error.message);
}, function () {
callbacks.success(); // no value.
});
}
});
tx.executeSql('DELETE FROM items WHERE key = ?', [key]);
tx.executeSql('INSERT INTO items (key, value) VALUES (?, ?)', [key, value]);
localstorage.removeItem(key);
localstorage.setItem(key, value);
getItem:function (key, callbacks) {
this.storage.transaction(function (tx) {
tx.executeSql('SELECT * FROM items WHERE key = ?', [key], function (tx, results) {
var len = results.rows.length;
if (len > 0) {
callbacks.success(results.rows.item(0).value)
} else {
callbacks.failure(); // no result
}
});
}, function (error) {
console.log('WebSQL: Error in getItem');
callbacks.failure(error);
});
}
doRequest: function(operation, callback, scope) {
var that = this,
passCallback,
request,
fakedResponse = {};
this.originalCallback = callback;
function failedRequest() {
fakedResponse.status = 500;
fakedResponse.responseText = 'Error';
fakedResponse.statusText = 'ERROR';
that.processResponse(false, operation, request, fakedResponse, passCallback, scope);
}
if(this.getOnline()) {
console.log('PROXY: Loading from online resource');
return this.callParent(arguments);
}else{
console.log('PROXY: Loading from offline resource');
request = this.buildRequest(operation);
passCallback = this.createRequestCallback(request, operation, callback, scope);
if(this.getStorageKey() && this.getStorageFacility()) {
this.getStorageFacility().getItem(this.getStorageKey(), {
success: function(dataString) {
fakedResponse.status = 200;
fakedResponse.responseText = dataString;
fakedResponse.statusText = 'OK';
that.processResponse(true, operation, request, fakedResponse, passCallback, scope);
},
failure: failedRequest
});
}else{
console.error('No storage key or facility for proxy');
setTimeout(function() {
failedRequest();
}, 1);
}
}
},
processResponse: function(success, operation, request, response, callback, scope) {
var that = this;
if(success) {
console.log('PROXY: Request succeeded');
this.callParent(arguments);
if(this.getOnline()) {
if(this.getStorageKey() && this.getStorageFacility()) {
this.getStorageFacility().setItem(this.getStorageKey(), response.responseText, {
success: function() {
console.log('PROXY: Data stored to offline storage: ' + that.getStorageKey());
},
failure: function(error) {
console.log('PROXY: Error in storing data: ' + that.getStorageKey());
}
});
}else{
console.error('PROXY: No storage key or facility for proxy');
}
}
}else{
if(this.getOnline()) {
//If the request failed and we were online, we need to try and fall back to offline
console.log('PROXY: Request failed, will try to fallback to offline');
this.setOnline(false);
this.doRequest(operation, this.originalCallback, scope);
}else{
this.callParent(arguments);
}
}
}
proxy: {
type : 'offline',
url : '/test-api/test-resource.json',
storageKey : 'buttons',
storageFacility : storage.WebSQL,
reader : {
type : 'json',
rootProperty : 'data'
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment