/* REQUIRED PLUGINS indexeddb: https://www.npmjs.com/package/cordova-plugin-indexeddb-async file: http://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/index.html - Which is for what: 1. IndexedDB: It's like MongoDB. Stores objects, no sequel. 2. FileSystem: Keep file like images, music file, video file, document file and etc. 3. Web Storage: For simple temporary data storage. iOS will empty this to give space to their RAM. 4. Web Session: Sessions. Data destroyed when App is exited. - Future Developments: 1. Full support IndexedDB 2. Full support Filesystem 3. Full support Web Session 4. Upgrade the push function */ var leStorage = { init: function(){ // init -- check if there is any local storage support if(typeof(Storage) !== "undefined") { // Code for localStorage/sessionStorage. // console.log('local storage defined'); } else { // Sorry! No Web Storage support.. alert('There is no local storage! The app will not function properly.'); } // check if indexed DB is available leStorage.idb.init(); }, set: function(storageName, object){ if(!storageName){ console.error('Please provide storage name'); return false; } if(object !== null && typeof object === 'object'){ object = JSON.stringify(object); } if(object === null || object === 'null'){ return delete localStorage[storageName]; } return localStorage.setItem(storageName,object); }, get: function(storageName){ var retrievedObject = localStorage.getItem(storageName); return JSON.parse(retrievedObject); }, clear: function(storageName, allFlag){ if(allFlag){ return localStorage.clear(); } return leStorage.set(storageName,null); }, // deepFlag = true, identical key values will not be overwritten // refer to extendShim if you are using deepFlag push: function(storageName, object, deepFlag){ var returnObject = {} var oldObject = leStorage.get(storageName); if(!oldObject) oldObject = {}; if(deepFlag){ // shim it first leStorage.extendShim(oldObject,object); $.extend(true, returnObject, oldObject, object); } else{ $.extend(returnObject, oldObject, object); } return leStorage.set(storageName,returnObject); }, // append object into array rather than overwriting it // does not shim within an array object. only appends values to the array. within it will be omitted // but you can go as deep as you want with objects extendShim: function(oldObject, newObject){ $.each(newObject,function(i){ // check if value of each newObject is array if(newObject[i].constructor === Array){ // check if the child of this array is an object var objectChild = false; for(n in newObject[i]){ if(typeof(newObject[i][n]) == 'object'){ objectChild = true; break; } } // newObject ready to fill if(objectChild === true){ // check if oldObject is array or not, if not, we do not do anything. let extend overwrite it if(typeof(oldObject[i]) == 'object' && oldObject[i].constructor === Array){ var arrayCount = oldObject[i].length; // fill em up for(var k=0; k < arrayCount; k++){ newObject[i].unshift({}); } } } } // if value is object instead, look deeper else if(typeof(newObject[i]) == 'object'){ // if oldObject has the same level deep if(typeof(oldObject[i]) == 'object'){ // if the old array is an array and the child is object, you wrap the newObject object in an array // this will not go into the array object for recursive, instead it will just append to the first object in the array if(oldObject[i].constructor == Array){ newObject[i] = [newObject[i]]; } leStorage.extendShim(oldObject[i], newObject[i]); } } }); }, // return object[s] in an array that has key and value reduce: function(arrayObject, key, val){ return arrayObject.filter(function (looking) { return looking[key] == val }); }, getAppPath: function(){ return cordova.file.applicationDirectory; }, // return new object array that does not have the one with the key=val removeObjectInArray: function(data,key,val){ return $.grep(data, function(e){ return e[key] != val; }); } } leStorage.session = { set: function(storageName,object){ if(!storageName){ console.error('Please provide storage name'); return false; } if(object !== null && typeof object === 'object'){ object = JSON.stringify(object); } if(object === null || object === 'null'){ return delete sessionStorage[storageName]; } return sessionStorage.setItem(storageName,object); }, get: function(storageName){ var retrievedObject = sessionStorage.getItem(storageName); return JSON.parse(retrievedObject); }, clear: function(storageName, allFlag){ if(allFlag){ return sessionStorage.clear(); } return leStorage.session.set(storageName,null); }, // deepFlag = true, identical key values will not be overwritten // refer to extendShim if you are using deepFlag push: function(storageName, object, deepFlag){ var returnObject = {} var oldObject = leStorage.session.get(storageName); if(!oldObject) oldObject = {}; if(deepFlag){ // shim it first leStorage.extendShim(oldObject,object); $.extend(true, returnObject, oldObject, object); } else{ $.extend(returnObject, oldObject, object); } return leStorage.session.set(storageName,returnObject); } } // uses indexDB // you must first open the datbase if it is not opened yet leStorage.idb = { systemSupport: false, db: false, init: function(){ // check if the system support indexDB if("indexedDB" in window){ // indexDB available leStorage.idb.systemSupport = true; } else{ leStorage.idb.systemSupport = false; console.log('IndexDB not available. Please provide a fallback for storing data'); } }, /* settings = { dbName: "value", version: 1, objectStoreNames: ["value","value",..] } */ open: function(settings){ // open the database // check if settings is complete if(!settings.dbName || !settings.version || settings.objectStoreNames.length < 1){ console.error('IndexedDB: insufficient settings values'); return false; } if(leStorage.idb.systemSupport == true){ var openRequest = indexedDB.open(settings.dbName,settings.version); openRequest.onupgradeneeded = function(e){ // console.log("IndexedDB: upgrading.."); var thisDB = e.target.result; $.each(settings.objectStoreNames, function(key, val){ if(!thisDB.objectStoreNames.contains(val)){ thisDB.createObjectStore(val); } }); }; openRequest.onsuccess = function(e){ // console.log("IndexedDB: success!"); leStorage.idb.db = e.target.result; }; openRequest.onerror = function(e){ // console.log("Error"); console.dir(e); }; } }, set: function(){ }, get: function(){ }, clear: function(){ }, push: function(){ } } // access the file system leStorage.file = { fs: false, // default to root fileEntry: false, dirEntry: false, rootDirEntry: false, request: function(callback){ window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) { // default to root leStorage.file.fs = fs; leStorage.file.rootDirEntry = fs.root; // console.log('file system open: ' + fs.name); if(callback){ callback(fs); } }, leStorage.file.error); }, ls: function(dirEntry, callback){ var directoryReader = dirEntry.createReader(); // Get a list of all the entries in the directory directoryReader.readEntries(function(entries){ if(!callback){ var i; for (i=0; i