I want to build up on an existing solution to find out when all elements in an array have been inserted successfully.
Web SQL Database + Javascript loop
insert: function(configurationVOs) {
var self = this;
this.database.transaction(function(transaction){
var total = 0;
for(var i=0; i<configurationVOs.length; i++) {
(function(configurationVO) {
var params = [configurationVO.id, configurationVO.key, configurationVO.value, configurationVO.type];
transaction.executeSql(self.configurationInsertSQL, params, self.insertComplete, self.insertError);
})(configurationVOs[i]);
}
});
},
if someone can provide an elegant self-contained solution within this for loop/function that can do a single callback upon success.
My attempt, please edit/suggest for any improvements.
insert: function(configurationVOs) {
var self = this;
this.database.transaction(function(transaction){
var total = 0;
for(var i=0; i<configurationVOs.length; i++) {
(function() {
var params = [configurationVOs[i].id, configurationVOs[i].key, configurationVOs[i].value, configurationVOs[i].type];
transaction.executeSql(self.configurationInsertSQL, params, function(transaction, resultSet){
if(++total == configurationVOs.length) {
self.insertComplete();
}
}, self.insertError);
})();
}
});
},
Related
I have an empty javascript array(matrix) that I created to achieve refresh of divs. I created a function to dynamically put data in it. Then I created a function to update the Array (which I have issues).
The Data populated in the Array are data attributes that I put in a JSON file.
To better undertand, here are my data attributes which i put in json file:
var currentAge = $(this).data("age");
var currentDate = $(this).data("date");
var currentFullName = $(this).data("fullname");
var currentIDPerson = $(this).data("idPerson");
var currentGender = $(this).data("gender");
Creation of the array:
var arrayData = [];
Here is the function a created to initiate and addind element to the Array :
function initMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
var isFound = false;
// search if the unique index match the ID of the HTML one
for (var i = 0; i < arrayData.length; i++) {
if(arrayData[i].idPerson== p_currentIDPerson) {
isFound = true;
}
}
// If it doesn't exist we add elements
if(isFound == false) {
var tempArray = [
{
currentIDPerson: p_currentIDPerson,
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate, currentAge: p_currentAge
}
];
arrayData.push(tempArray);
}
}
The update function here is what I tried, but it doesn't work, maybe I'm not coding it the right way. If you can help please.
function updateMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
for (var i = 0; i < arguments.length; i++) {
for (var key in arguments[i]) {
arrayData[i] = arguments[i][key];
}
}
}
To understand the '$this' and elm: elm is the clickableDivs where I put click event:
(function( $ ) {
// Plugin to manage clickable divs
$.fn.infoClickable = function() {
this.each(function() {
var elm = $( this );
//Call init function
initMatrixRefresh(elm.attr("idPerson"), elm.data("gender"), elm.data("fullname"), elm.data("date"), elm.data("age"));
//call function update
updateMatrix("idTest", "Alarme", "none", "10-02-17 08:20", 10);
// Définition de l'evenement click
elm.on("click", function(){});
});
}
$('.clickableDiv').infoClickable();
}( jQuery ));
Thank you in advance
Well... I would recommend you to use an object in which each key is a person id for keeping this list, instead of an array. This way you can write cleaner code that achieves the same results but with improved performance. For example:
var myDataCollection = {};
function initMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
if (!myDataCollection[p_currentIDPerson]) {
myDataCollection[p_currentIDPerson] = {
currentIDPerson: p_currentIDPerson,
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate,
currentAge: p_currentAge
};
}
}
function updateMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
if (myDataCollection[p_currentIDPerson]) {
myDataCollection[p_currentIDPerson] = {
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate,
currentAge: p_currentAge
};
}
}
Depending on your business logic, you can remove the if statements and keep only one function that adds the object when there is no object with the specified id and updates the object when there is one.
I think the shape of the resulting matrix is different than you think. Specifically, the matrix after init looks like [ [ {id, ...} ] ]. Your update function isn't looping enough. It seems like you are trying to create a data structure for storing and updating a list of users. I would recommend a flat list or an object indexed by userID since thats your lookup.
var userStorage = {}
// add/update users
userStorage[id] = {id:u_id};
// list of users
var users = Object.keys(users);
I really try my damndest not to ask, but i have to at this point before I tear my hair out.
By the time the js interpreter gets to this particular method, I can print it to the console no problem, it is an array of "event" objects. From FireBug I can see it, but when I try to set a loop to do anything with this array its as if it doesn't exist. I am absolutely baffled......
A few things:
I am a newbie, I have tried a for(var index in list) loop, to no avail, I have also tried a regular old for(var i = 0; i < listIn.length; i++), and I also tried to get the size of the local variable by setting var size = listIn.length.
As soon as I try to loop through it I get nothing, but I can access all the objects inside it from the FireBug console no problem. Please help, even just giving me a little hint on where I should be looking would be great.
As for the array itself, I have no problems with getting an array back from PHP in the form of: [{"Event_Id":"9", "Title":"none"}, etc etc ]
Here is my code from my main launcher JavaScript file. I will also post a sample of the JSON data that is returned. I fear that I may be overextending myself by creating a massive object in the first place called content, which is meant to hold properties such as DOM strings, settings, and common methods, but so far everything else is working.
The init() function is called when the body onload is called on the corresponding html page, and during the call to setAllEvents and setEventNavigation I am lost.
And just to add, I am trying to learn JavaScript fundamentals before I ever touch jQuery.
Thanks
var dom, S, M, currentArray, buttonArray, typesArray, topicsArray;
content = {
domElements: {},
settings: {
allContent: {},
urlList: {
allURL: "../PHP/getEventsListView.php",
typesURL: "../PHP/getTypes.php",
topicsURL: "../PHP/getTopics.php"
},
eventObjArray: [],
buttonObjArray: [],
eventTypesArray: [],
eventTopicsArray: []
},
methods: {
allCallBack: function (j) {
S.allContent = JSON.parse(j);
var list = S.allContent;
for (var index in list) {
var event = new Event(list[index]);
S.eventObjArray.push(event);
}
},
topicsCallBack: function(j) {
S.eventTopicsArray = j;
var list = JSON.parse(S.eventTopicsArray);
topicsArray = list;
M.populateTopicsDropDown(list);
},
typesCallBack: function(j) {
S.eventTypesArray = j;
var list = JSON.parse(S.eventTypesArray);
typesArray = list;
M.populateTypesDropDown(list);
},
ajax: function (url, callback) {
getAjax(url, callback);
},
testList: function (listIn) {
// test method
},
setAllEvents: function (listIn) {
// HERE IS THE PROBLEM WITH THIS ARRAY
console.log("shall we?");
for(var index in listIn) {
console.log(listIn[index]);
}
},
getAllEvents: function () {
return currentArray;
},
setAllButtons: function (listIn) {
buttonArray = listIn;
},
getAllButtons: function () {
return buttonArray;
},
setEventNavigation: function(current) {
// SAME ISSUE AS ABOVE
var l = current.length;
//console.log("length " + l);
var counter = 0;
var endIndex = l - 1;
if (current.length < 4) {
switch (l) {
case 2:
var first = current[0];
var second = current[1];
first.setNextEvent(second);
second.setPreviousEvent(first);
break;
case 3:
var first = current[0];
var second = current[1];
var third = current[2];
first.setNextEvent(second);
second.setPreviousEvent(first);
second.setNextEvent(third);
third.setPreviousEvent(second);
break;
default:
break;
}
} else {
// do something
}
},
populateTopicsDropDown: function(listTopics) {
//console.log("inside topics drop");
//console.log(listTopics);
var topicsDropDown = document.getElementById("eventTopicListBox");
for(var index in listTopics) {
var op = document.createElement("option");
op.setAttribute("id", "dd" + index);
op.innerHTML = listTopics[index].Main_Topic;
topicsDropDown.appendChild(op);
}
},
populateTypesDropDown: function(listTypes) {
//console.log("inside types drodown");
//console.log(listTypes);
var typesDropDown = document.getElementById("eventTypeListBox");
for(var index2 in listTypes) {
var op2 = document.createElement("option");
op2.setAttribute("id", "dd2" + index2);
op2.innerHTML = listTypes[index2].Main_Type;
typesDropDown.appendChild(op2);
}
}
},
init: function() {
dom = this.domElements;
S = this.settings;
M = this.methods;
currentArray = S.eventObjArray;
buttonArray = S.buttonObjArray;
topicsArray = S.eventTopicsArray;
typesArray = S.eventTypesArray;
M.ajax(S.urlList.allURL, M.allCallBack);
//var tempList = currentArray;
//console.log("temp array length: " + tempList.length);
M.setAllEvents(currentArray);
M.testList(currentArray);
M.setEventNavigation(currentArray);
//M.setEventNavigation();
M.ajax(S.urlList.topicsURL, M.topicsCallBack);
M.ajax(S.urlList.typesURL, M.typesCallBack);
}
};
The problem you have is that currentArray gets its value asynchronously, which means you are calling setAllEvents too soon. At that moment the allCallBack function has not yet been executed. That happens only after the current running code has completed (until call stack becomes emtpy), and the ajax request triggers the callback.
So you should call setAllEvents and any other code that depends on currentArray only when the Ajax call has completed.
NB: The reason that it works in the console is that by the time you request the value from the console, the ajax call has already returned the response.
Without having looked at the rest of your code, and any other problems that it might have, this solves the issue you have:
init: function() {
dom = this.domElements;
S = this.settings;
M = this.methods;
currentArray = S.eventObjArray;
buttonArray = S.buttonObjArray;
topicsArray = S.eventTopicsArray;
typesArray = S.eventTypesArray;
M.ajax(S.urlList.allURL, function (j) {
// Note that all the rest of the code is moved in this call back
// function, so that it only executes when the Ajax response is
// available:
M.allCallBack(j);
//var tempList = currentArray;
//console.log("temp array length: " + tempList.length);
M.setAllEvents(currentArray);
M.testList(currentArray);
M.setEventNavigation(currentArray);
//M.setEventNavigation();
// Note that you will need to take care with the following asynchronous
// calls as well: their effect is only available when the Ajax
// callback is triggered:
M.ajax(S.urlList.topicsURL, M.topicsCallBack); //
M.ajax(S.urlList.typesURL, M.typesCallBack);
});
}
How would I access the values of 'timestamp' and 'usage' in the following example,
function executeReadingsQuery(query, postQueryProcessing) {
var d = new $.Deferred();
var processing = function(tx, results) {
var result = [];
var len = results.rows.length;
for ( var i = 0; i < len; i++) {
result.push({
"timestamp" : moment(results.rows.item(i).timeStamp),
"usage" : results.rows.item(i).usage
});
}
if (postQueryProcessing) {
result = postQueryProcessing(result);
}
d.resolve(result);
};
executeQuery(query, processing);
return d;
}
A function that builds a query string will subsequently call the above function,
function getReadingsInternal(noOfReadings, postQueryProcessing) {
var query = "SELECT * from usage ORDER BY timestamp DESC limit " + noOfReadings.toString();
return executeReadingsQuery(query, postQueryProcessing);
}
And then there is another function that exposes the entire functionality globally,
getReadings : function(noOfReadings) {
return getReadingsInternal(noOfReadings);
}
The original function (the first one listed) is within a Variable called WNDatabase
So I can access the function with a call that looks like this
WNDatabase.getReadings(30)
But I would like to be able to also globally access the values of timestamp and usage which populate the result[] array of the deferred object.
It seems that it is not possible to do something like this
$.when(WNDatabase.getReadings(30)).done(function() {
for(var i=0; i<7; i++){
console.log(this[i].usage);
}
});
So what would one do in this event?
I have the following code in one of my function. I have an array 'arr' which is working correctly when used inside if{}. But its now working when using outside it. Can anyone point me what I am missing.
function runQueries()
{
var arr = new Array;
db.transaction (function (transaction)
{
var sql = "SELECT * FROM incomecategory";
transaction.executeSql (sql, undefined,
function (transaction, result)
{
if (result.rows.length)
{
for (var i = 0; i < result.rows.length; i++)
{
var row = result.rows.item (i);
var categoryname = row.categoryname;
arr[i] = categoryname;
}
//alert(arr[0]); // It works
}
else
{
}
}, error);
});
//alert (arr[0]); // It doesn't work.
}
It's asynchronous behavior. Your alert at the bottom of the code is probably executed before the database query.
I am developing an application,In that application i have many functions that return us server data.. I have 40 function that needs to be executed 1 by 1 for synchronization to take place.SO i have taken a single function and placed my 40 functions in it... Now the problem is that some of these function skip performing database operations
My one out of 40 function to perform this is
function sync_down_client_info(){
try {
parent.parent.parent.stmt_select.text = "select query";
parent.parent.parent.stmt_select.execute();
parent.parent.parent.result = parent.parent.parent.stmt_select.getResult();
if (parent.parent.parent.result.data != null) {
for (var i = 0; i < parent.parent.parent.result.data.length; i++) {
var admin_id = parent.parent.parent.admin_id;
var sync_client_date = parent.parent.parent.result.data[i].last_sync_client;
// alert(admin_id+"======="+ sync_client_date);
GATEWAY = 'http://projects/one_acc/flashservices/gateway.php';
conn = new parent.parent.parent.air.NetConnection();
conn.connect(GATEWAY);
response = new parent.parent.parent.air.Responder(clientresult, clientFault);
conn.call('down_client_info', response,admin_id,sync_client_date);
response = new parent.parent.parent.air.Responder(clientserverdatetimeResult, clientserverdatetimeFault);
conn.call('check_datetime', response);
}
};
and clientresult function is
function clientresult(e)
{
for (var i=0; i<e.length; i++) {
//alert(e.length);
parent.parent.parent.stmt_select.text="select query ;
parent.parent.parent.stmt_select.execute();
parent.parent.parent.result = parent.parent.parent.stmt_select.getResult();
if(parent.parent.parent.result.data!=null){
parent.parent.parent.stmt_insert.text= "update client_info ;
parent.parent.parent.stmt_insert.execute();
}
can anyone tell me how to do this syncing?
jQuery has constructs like the AjaxQueue to avoid these race conditions you are seeing. I'd advise using these plugins.
Refer http://plugins.jquery.com/project/ajaxqueue