In chrome "Application" -> IndexedDB I see the property value of an object with value "inactive",
on retrieving that record, the property shows with value "active".
This is the function that does the retrieving:
function retrievesClientsFrom(databaseWithThisName, thisVersion, thisObjectStoreName) {
var requestToOpenDatabase = indexedDB.open(databaseWithThisName, thisVersion);
requestToOpenDatabase.onsuccess = function(event) {
var theDatabaseObject = requestToOpenDatabase.result;
//gets a transaction object
var theTransactionObject = theDatabaseObject.transaction(thisObjectStoreName, "readonly");
//gets the object store with that name
var theObjectStore = theTransactionObject.objectStore(thisObjectStoreName);
//gets all objects inside the objectStore sent to the function
var requestToGetContentOfAnObjectStore = theObjectStore.getAll();
requestToGetContentOfAnObjectStore.onsuccess = function(event) {
arrayOfRetrievedClients = requestToGetContentOfAnObjectStore.result;
//here I get the wrong value (I see it in chrome console).
console.log("arrayOfRetrievedClients: o%",arrayOfRetrievedClients);
};
};
requestToOpenDatabase.onerror = function(event) {
window.alert("There was a problem reading the database:
"+requestToOpenDatabase.error);
};
}
I have absolutely no idea what to do. Any ideas?
Related
I've separated the variables for scoping purposes, I'm able to fill out all the variables with the respective DOM elements from url1 but when I try to pass them to url2 fields, they get set to undefined as if the variable was never set. Yet the console.log works... I've passed also a function to .setValue('#address-serviceability-form', '', '', function(e){ // set the value here}) but still I get undefined... Is this variable scoping issue?
describe('Ecosia.org Demo', function() {
var address ='';
var streetNumber = '';
var city = '';
var stateAndZip = '';
var state = ''
var zip = '';
before(browser => browser.url('url1.com'));
test('Extract random address', function (browser) {
browser
.getText('.rand_large li:first-child', function(result) {
address = result.value.split("\n");
streetNumber = address[0];
console.log('streetNumber', streetNumber) //this works and logs correctly
city = address[1].split(",")[0];
stateAndZip = address[1].split(",")[1];
state = stateAndZip.split(" ")[1];
zip = stateAndZip.split(" ")[2];
})
.url('url2.com')
.waitForElementVisible('form')
.setValue('#address-serviceability-form', streetNumber) // this is set to undefined
.pause(5000)
});
after(browser => browser.end());
});
This looks to me to be a problem with your understanding of NodeJS callbacks.
You should be able to fix this using async/await. Your code is not waiting for the callback to be resolved and the value is not assigned before being used in set value function. you could try something like below.
test('Extract random address', async function(browser) {
await browser
.getText('.rand_large li:first-child', function(result) {
address = result.value.split("\n");
streetNumber = address[0];
console.log('streetNumber', streetNumber) //this works and logs correctly
city = address[1].split(",")[0];
stateAndZip = address[1].split(",")[1];
state = stateAndZip.split(" ")[1];
zip = stateAndZip.split(" ")[2];
})
browser.url('url2.com')
.waitForElementVisible('form')
.setValue('#address-serviceability-form', streetNumber) // this is set to undefined
.pause(5000)
});
I want to execute this query
select * from properties where propertyCode IN ("field1", "field2", "field3")
How can I achieve this in IndexedDB
I tried this thing
getData : function (indexName, params, objectStoreName) {
var defer = $q.defer(),
db, transaction, index, cursorRequest, request, objectStore, resultSet, dataList = [];
request = indexedDB.open('test');
request.onsuccess = function (event) {
db = request.result;
transaction = db.transaction(objectStoreName);
objectStore = transaction.objectStore(objectStoreName);
index = objectStore.index(indexName);
cursorRequest = index.openCursor(IDBKeyRange.only(params));
cursorRequest.onsuccess = function () {
resultSet = cursorRequest.result;
if(resultSet){
dataList.push(resultSet.value);
resultSet.continue();
}
else{
console.log(dataList);
defer.resolve(dataList);
}
};
cursorRequest.onerror = function (event) {
console.log('Error while opening cursor');
}
}
request.onerror = function (event) {
console.log('Not able to get access to DB in executeQuery');
}
return defer.promise;
But didn't worked. I tried google but couldn't find exact answer.
If you consider that IN is essentially equivalent to field1 == propertyCode OR field2 == propertyCode, then you could say that IN is just another way of using OR.
IndexedDB cannot do OR (unions) from a single request.
Generally, your only recourse is to do separate requests, then merge them in memory. Generally, this will not have great performance. If you are dealing with a lot of objects, you might want to consider giving up altogether on this approach and thinking of how to avoid such an approach.
Another approach is to iterate over all objects in memory, and then filter those that don't meet your conditions. Again, terrible performance.
Here is a gimmicky hack that might give you decent performance, but it requires some extra work and a tiny bit of storage overhead:
Store an extra field in your objects. For example, plan to use a property named hasPropertyCodeX.
Whenever any of the 3 properties are true (has the right code), set the field (as in, just make it a property of the object, its value is irrelevant).
When none of the 3 properties are true, delete the property from the object.
Whenever the object is modified, update the derived property (set or unset it as appropriate).
Create an index on this derived property in indexedDB.
Open a cursor over the index. Only objects with a property present will appear in the cursor results.
Example for 3rd approach
var request = indexedDB.open(...);
request.onupgradeneeded = upgrade;
function upgrade(event) {
var db = event.target.result;
var store = db.createObjectStore('store', ...);
// Create another index for the special property
var index = store.createIndex('hasPropCodeX', 'hasPropCodeX');
}
function putThing(db, thing) {
// Before storing the thing, secretly update the hasPropCodeX value
// which is derived from the thing's other properties
if(thing.field1 === 'propCode' || thing.field2 === 'propCode' ||
thing.field3 === 'propCode') {
thing.hasPropCodeX = 1;
} else {
delete thing.hasPropCodeX;
}
var tx = db.transaction('store', 'readwrite');
var store = tx.objectStore('store');
store.put(thing);
}
function getThingsWherePropCodeXInAnyof3Fields(db, callback) {
var things = [];
var tx = db.transaction('store');
var store = tx.objectStore('store');
var index = store.index('hasPropCodeX');
var request = index.openCursor();
request.onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
var thing = cursor.value;
things.push(thing);
cursor.continue();
} else {
callback(things);
}
};
request.onerror = function(event) {
console.error(event.target.error);
callback(things);
};
}
// Now that you have an api, here is some example calling code
// Not bothering to promisify it
function getData() {
var request = indexedDB.open(...);
request.onsuccess = function(event) {
var db = event.target.result;
getThingsWherePropCodeXInAnyof3Fields(db, function(things) {
console.log('Got %s things', things.length);
for(let thing of things) {
console.log('Thing', thing);
}
});
};
}
I am trying to enter a number of shifts under their date. This is working fine for the 19-01 but then when I try to enter the 20-01 that saves and deletes the entry of the 19-01.
Anyone know what the problem is and why it can't allow me to have more that one tree?
//ROSTERS SAVING
//ROSTERS FOR MONDAYS
$(function Monday(){
// CREATE A REFERENCE TO FIREBASE
var dateMondayRef = new Firebase('https://shiftsapp.firebaseio.com/roster');
// REGISTER DOM ELEMENTS
var date1Field = $('#date1Input');
var emp1put1Field = $('#emp1Input1');
var enter1Field = $('#enter1');
// LISTEN FOR KEYPRESS EVENT
enter1Field.keypress(function (e) {
if (e.keyCode == 13) {
//FIELD VALUES
var dateMonday = date1Field.val();
var emp1put1 = emp1put1Field.val();
var enter1 = enter1Field.val();
//SAVE DATA TO FIREBASE AND EMPTY FIELD
var obj1 = {};
obj1[dateMonday] = {
emp1:emp1put1,
}
dateMondayRef.set(obj1);
enter1Field.val('');
}
});
});
$(function Tuesday(){
// CREATE A REFERENCE TO FIREBASE
var dateTuesdayRef = new Firebase('https://shiftsapp.firebaseio.com/roster');
// REGISTER DOM ELEMENTS
var date2Field = $('#date2Input');
var emp1put2Field = $('#emp1Input2');
var enter2Field = $('#enter2');
// LISTEN FOR KEYPRESS EVENT
enter2Field.keypress(function (e) {
if (e.keyCode == 13) {
//FIELD VALUES
var dateTuesday = date2Field.val();
var emp1put2 = emp1put2Field.val();
var enter2 = enter2Field.val();
//SAVE DATA TO FIREBASE AND EMPTY FIELD
var obj = {};
obj[dateTuesday] = {
emp1:emp1put2
}
dateTuesdayRef.set(obj);
enter2Field.val('');
}
});
});
This happens because you use Firebase's set method instead of update on the same ref (your dateMondayRef and dateTuesdayRef both point to the same Firebase node).
As described in the docs, set will
write or replace data
In other words, when you call set on your ref, you instruct firebase to write at this location (or replace any data that might be stored there with) the object you pass as an argument.
You can either use update on this ref (but that would preserve any child key that was present at roster/$dateMonday but that is not included in your new object) or grab a reference to your dateMonday node, and call set on that.
dateMondayRef.update(obj1)
dateTuesdayRef.update(obj2)
// or
dateMondayRef.child(dateMonday).set({emp1: ...})
dateTuesdayRef.child(dateTuesday).set({emp1: ...})
I have a bug in my code that only saves the last object in an array upon reload. I have a feeling that my addAccount() function is not saving or inserting data correctly. Everything else works correctly. In my console, it shows that the data is being inserted into the array, but when I refresh I only get the last object saved.
I'm not sure what to do.
// The list of accounts array.
var accountsArray = [];
function addAccount() {
// Take fields and put user data into varables.
var accountName = document.getElementById('accountName').value;
var accountBalance = document.getElementById('accountBalance').value;
var accountType = document.getElementById("accountType");
var accountTypeSelected = accountType.options[accountType.selectedIndex].text;
var accountCurrency = document.getElementById("accountCurrency");
var accountCurrencySelected = accountCurrency.options[accountCurrency.selectedIndex].text;
var temporaryObject = {
'accountName': accountName,
'accountBalance': accountBalance,
'accountTypeSelected': accountTypeSelected,
'accountCurrencySelected': accountCurrencySelected
};
accountsArray.push(temporaryObject);
console.log(accountsArray);
saveAccountData();
showAccountsArray();
}
function saveAccountData() {
localStorage.setItem('accountsArray', JSON.stringify(accountsArray));
}
function showAccountsArray() {
//var accountsLocalStorage = JSON.parse(localStorage['accountsArray']);
if (localStorage.getItem("accountsArray") === null) {
document.getElementById("getStarted").style.visibility="visible";
document.getElementById("balanceToolbarName").style.visibility="hidden";
document.getElementById("accountsMainList").style.visibility="hidden";
} else {
var accountsLocalStorage = JSON.parse(localStorage['accountsArray']);
console.log(accountsLocalStorage);
var accountInfo = '';
var i = 0;
while (i < accountsLocalStorage.length) {
accountInfo += '<li class="swipeout"><div class="swipeout-content item-content"><div class="item-inner"><div class="item-title">' + accountsLocalStorage[i].accountName + '</div><div class="item-after">$' + accountsLocalStorage[i].accountBalance + '</div></div></div><div class="swipeout-actions-left"><a href="#" class="action1">Clear</div><div class="swipeout-actions-right">Delete</div></a></li>';
document.getElementById("accountsList").innerHTML = accountInfo;
i++;
}
document.getElementById("getStarted").style.visibility="hidden";
document.getElementById("balanceToolbarName").style.visibility="visible";
document.getElementById("accountsMainList").style.visibility="visible";
}
}
*
all of your functions work correctly as tested by the link you've provided. When the page loads it successfully retrieves the data (if any) from the local storage and displays on the page. However, the global array variable accountsArray is populated with data retrieved from the local storage.
You need to repopulate the global array otherwise when you call saveAccountData it will save whatever the array holds which indeed overrides whatever you had in the local storage. To fix it, simply add add this code block...
$(function(){
var data = localStorage.getItem("accountsArray");
if(data != null)
accountsArray = JSON.parse(localStorage.getItem("accountsArray"));
});
I'm trying to create an application for Firefox OS which basically needs to store some data using IndexedDB.
The store() function is called when the user clicks on a submit button which results in the creation of the name and description variables an user submitted form.
However, I keep getting a Reference Error saying my db object is not defined. Any ideas why this is happening?
Here's my current code:-
function store () {
// create the transaction with 1st parameter is the list of stores and the second specifies
// a flag for the readwrite option
var transaction = db.transaction([ 'Apps' ], 'readwrite');
//Create the Object to be saved i.e. our App details
var value = {};
value.name = name;
value.desc = description;
// add the details to the store
var store = transaction.objectStore('Apps');
var request = store.add(value);
request.onsuccess = function (e) {
alert("Your App data has been saved");
};
request.onerror = function (e) {
alert("Error in saving the App data. Reason : " + e.value);
}
}
$(document).ready(function(){
// variable which will hold the database connection
var db;
if (window.indexedDB) {
console.log("IndexedDB is supported");
}
else {
alert("Indexed DB is not supported!");
}
// open the database
// 1st parameter : Database name. We are using the name 'Appsdb'
// 2nd parameter is the version of the database.
var request = indexedDB.open('Appsdb', 1);
request.onsuccess = function (e) {
// e.target.result has the connection to the database
db = e.target.result;
console.log(db);
console.log("DB Opened!");
}
request.onerror = function (e) {
console.log(e);
};
// this will fire when the version of the database changes
// We can only create Object stores in a versionchange transaction.
request.onupgradeneeded = function (e) {
// e.target.result holds the connection to database
db = e.target.result;
if (db.objectStoreNames.contains("Apps")) {
db.deleteObjectStore("Apps");
}
// create a store named 'Apps'
// 1st parameter is the store name
// 2nd parameter is the key field that we can specify here. Here we have opted for autoIncrement but it could be your
// own provided value also.
var objectStore = db.createObjectStore('Apps', { keyPath: 'id', autoIncrement: true });
console.log("Object Store has been created");
};
});
The problem is with the scope of the db variable. Currently you have the following line var db; declared inside of the $(document).ready function. Move its declaration to a more global scope i.e. outside of this function and the variable will be visible in the store() function too.
Hope this helps.
var value = {};
value.name = name;
value.desc = description;
assign value to the name and description.
name=formname.name.value
description=formname.description.value