I want to create a array containing objects, and I'm using Parse to query all the data.
However, the for loop which loops over the results doesn't does that in the correct order but randomly loops over the data. If I log i each iteration, the logs show different results every time.
Here is my code:
for (var i = 0; i < results.length; i++)
{
Parse.Cloud.useMasterKey();
// retrieve params
var objectid = results[i];
var self = request.params.userid;
// start query
var Payment = Parse.Object.extend("Payments");
var query = new Parse.Query(Payment);
query.get(objectid, {
success: function (payment) {
// get all the correct variables
var from_user_id = payment.get("from_user_id");
var to_user_id = payment.get("to_user_id");
var amount = payment.get("amount");
var createdAt = payment.updatedAt;
var note = payment.get("note");
var img = payment.get("photo");
var location = payment.get("location");
var status = payment.get("status");
var fromquery = new Parse.Query(Parse.User);
fromquery.get(from_user_id, {
success: function(userObject) {
var fromusername = userObject.get("name");
var currency = userObject.get("currency");
var toquery = new Parse.Query(Parse.User);
toquery.get(to_user_id, {
success: function(touser)
{
var tousername = touser.get("name");
if(tousername !== null || tousername !== "")
{
sendArray(tousername);
}
},
error: function(touser, error)
{
var tousername = to_user_id;
if(tousername !== null || tousername !== "")
{
sendArray(tousername);
}
}
});
function sendArray(tousername) {
var array = new Array();
// create the time and date
var day = createdAt.getDate();
var year = createdAt.getFullYear();
var month = createdAt.getMonth();
var hour = createdAt.getHours();
var minutes = createdAt.getMinutes();
// create the timestamp
var time = "" + hour + ":" + minutes;
var date = "" + day + " " + month + " " + year;
var associativeArray = {};
if(self == from_user_id)
{
fromusername = "self";
}
if(self == to_user_id)
{
tousername = "self";
}
associativeArray["from"] = fromusername;
associativeArray["to"] = tousername;
associativeArray["amount"] = amount;
associativeArray["currency"] = currency;
associativeArray["date"] = date;
associativeArray["time"] = time;
associativeArray["status"] = status;
if(note == "" || note == null)
{
associativeArray["note"] = null;
}
else
{
associativeArray["note"] = note;
}
if(img == "" || img == null)
{
associativeArray["img"] = null;
}
else
{
associativeArray["img"] = img;
}
if(location == "" || location == null)
{
associativeArray["location"] = null;
}
else
{
associativeArray["location"] = location;
}
array[i] = associativeArray;
if((i + 1) == results.length)
{
response.success(array);
}
},
error: function(userObject, error)
{
response.error(106);
}
});
},
error: function(payment, error) {
response.error(125);
}
});
}
But the i var is always set to seven, so the associative arrays are appended at array[7] instead of the correct i (like 1,2,3,4,5)
The reason that this is so important is because I want to order the payment chronologically (which I have done in the query providing the results).
What can I do to solve this issue?
Success is a callback that happens at a later point in time. So what happens is, the for loop runs 7 times and calls parse 7 times. Then after it has run each of parse success calls will be executed, they look at i which is now at 7.
A simple way to fix this is to wrap the whole thing in an immediate function and create a new closure for i. Something like this
for(var i = 0; i < results.length; i++){
function(iClosure) {
//rest of code goes here, replace i's with iClosure
}(i);
}
Now what will happen is that each success function will have access to it's own iClosure variable and they will be set to the value of i at the point they were created in the loop.
Related
At the moment, I manually create code then manually ask the user to set the trigger for the said function in order for the said user to receive a task and update task.
Heres an example of my coding:
User's Function
function Person1Variables () {
taskedPerson = assignedPerson.filter(x => x == "Person1 (assigned by Somebody)").length
taskReceiver = "Person1 (assigned by Somebody)"
taskReceived = "Person1 (Sent)"
functionCaller = "Person1 "
myTask = "My Tasks"
}
function taskSendPerson1() {
Person1Variables()
if (taskedPerson + 1 > 1){taskSending(taskTitle(myTask)); console.log("Snag")}
}
function updateTaskPerson1() {
Person1Variables()
taskComplete(taskTitle(myTask));
}
Task Creation and Update
function taskTitle(titleTasksList) {
if (typeof titleTasksList === 'undefined') { titleTasksList = 'default'; }
var rezultId = 0;
var response = Tasks.Tasklists.list();
var taskLists = response.items;
if (taskLists && taskLists.length > 0) {
for (var i = 0; i < taskLists.length; i++) {
var taskList = taskLists[i];
if (titleTasksList == 'default') {
rezultId = taskList.id; //return first item
break;
} else {
Logger.log('%s (%s)', taskList.title, taskList.id);
if (titleTasksList == taskList.title) {
rezultId = taskList.id;
break;
}
}
}
} else {
Logger.log('No task lists found.');
}
return rezultId;
}
function taskSending(taskListId) {
// Task details with title and notes for inserting new task
var currentResult = 1
var nextResult = 1
for (var resultsFound = 0; resultsFound < taskedPerson; resultsFound++){
console.log("pong")
var searchEngine = "Assigned Person"
var searchRange = sheet.getRange(nextResult,(lastColumn[0].indexOf(searchEngine) + 1),
sheet.getLastRow(), 1)
var searchRangeValues= searchRange.getValues()
currentResult = searchRangeValues.map(String).indexOf(taskReceiver) + nextResult
var resultTitle = responseNumber[currentResult -1]
var resultNote = typeSupport[currentResult - 1] + " = " + typeRequest[currentResult - 1]
let task = {
title: String(resultTitle),
notes: resultNote,
};
// Call insert method with taskDetails and taskListId to insert Task to specified tasklist.
console.log(task)
console.log(taskListId)
task = Tasks.Tasks.insert(task, taskListId);
// Print the Task ID of created task.
Logger.log('Task with ID "%s" was created.', task.id);
sheet.getRange(currentResult,2).setValue (taskReceived)
nextResult = currentResult + 1
console.log(nextResult + " " + "processed")
}
}
function newTask(taskListId) {
// Task details with title and notes for inserting new task
var allResults = [];
var allTitles = [];
for (var j = 0; j < itemResponses.length + 1; j++) {
var itemResponse = itemResponses[j];
for (var g = 0; g < 30; g++){ try {allResults [g] = String(itemResponses[g].getResponse()); allTitles [g] = itemResponses[g].getItem().getTitle();var lastResponse = g} catch(err) {}}
}
console.log("PING")
var refNumber = new Date().getFullYear().toString().substr(-2) + String(("00000000" + (formResponses.length))).substr(String(("00000000" + (formResponses.length))).length - 8);
let task = {
title: refNumber,
notes: allTitles [3] + " = " + allResults [3],
};
try {
// Call insert method with taskDetails and taskListId to insert Task to specified tasklist.
task = Tasks.Tasks.insert(task, taskListId);
// Print the Task ID of created task.
Logger.log('Task with ID "%s" was created.', task.id);
} catch (err) {
// TODO (developer) - Handle exception from Tasks.insert() of Task API
Logger.log('Failed with an error %s', err.message);
}
}
function taskComplete(taskListId) {
var optionalArgs = {
maxResults: 100,
showHidden: true
};
var tasks = Tasks.Tasks.list(taskListId, optionalArgs);
if (tasks.items) {
for (var i = 0; i < tasks.items.length; i++) {
var task = tasks.items[i];
for (var x = 0; x < responseNumber.length; x++){
if (responseNumber[x] == task.title){sheet.getRange(x + 1,lastColumn[0].indexOf("Status")+1).setValue(task.status); }
}
}
var dataFound = 0
//Tasks.Tasks.remove(taskListId,tasks.items[dataFound].id)
for (var x = 0; x < responseNumber.length; x++)
{try{if (tasks.items[dataFound].status == "completed" && (responseNumber.map(String).indexOf(String(tasks.items[dataFound].title))) > 1){Tasks.Tasks.remove(taskListId,tasks.items[dataFound].id); sheet.getRange(responseNumber.map(String).indexOf(String(tasks.items[dataFound].title)) + 1,lastColumn[0].indexOf("Assigned Person")+1).setValue(functionCaller)}; dataFound++} catch(err){}}
}
}
My plan was to create a button that can detect if that user has or has not created a function. If the user does not have dedicated function, then this button will create a function and assigned the trigger.
You don't need another function. The typical way to handle per user data is to store it in propertiesService and link it to triggerUid of the installed trigger.
Related:
Best way to create and manage someone's triggers (GAS)
Can the function called by ScriptApp.newTrigger identify the triggerID?
Is it possible to create a function on the fly and create triggers though? Maybe as a two step process through google-apps-script-api, but it's unnecessarily complicated for your case.
I'm writing a google docs apps script in making a google docs add-on. When the user clicks a button in the sidebar, an apps script function is called named executeSpellChecking. This apps script function makes a remote POST call after getting the document's text.
total time = time that takes from when user clicks the button, until the .withSuccessHandler(, that means until executeSpellChecking returns = 2000 ms
function time = time that takes for the executeSpellChecking call to complete from its start to its end = 1400 ms
t3 = time that takes for the remote POST call to be completed = 800ms
t4 = time that takes for the same remote POST call to complete in a VB.NET app = 200ms
Problems:
Why total time to complete is bigger than total function time by a staggering 600ms, what else happens there? shouldn't they be equal? How can I improve it?
Why t3 is bigger than t4 ? Shouldn't they be equal? Is there something wrong with POST requests when happening from .gs? How can I improve it ?
the code is (sidebar.html):
function runSpellChecking() {
gb_IsSpellcheckingRunning = true;
//gb_isAutoCorrecting = false;
gi_CorrectionCurrWordIndex = -1;
$("#btnStartCorr").attr("disabled", true);
$("#divMistakes").html("");
this.disabled = true;
//$('#error').remove();
var origin = $('input[name=origin]:checked').val();
var dest = $('input[name=dest]:checked').val();
var savePrefs = $('#save-prefs').is(':checked');
//var t1 = new Date().getTime();
console.time("total time");
google.script.run
.withSuccessHandler(
function(textAndTranslation, element) {
if (gb_IsSpellCheckingEnabled) {
console.timeEnd("total time");
//var t2 = new Date().getTime();
go_TextAndTranslation = JSON.parse(JSON.stringify(textAndTranslation));
var pagewords = textAndTranslation.pagewords;
var spellchecked = textAndTranslation.spellchecked;
//alert("total time to complete:" + (t2-t1) + "###" + go_TextAndTranslation.time);
//irrelevant code follows below...
}
})
.withFailureHandler(
function(msg, element) {
showError(msg, $('#button-bar'));
element.disabled = false;
})
.withUserObject(this)
.executeSpellChecking(origin, dest, savePrefs);
}
and the called function code is (spellcheck.gs):
function executeSpellChecking(origin, dest, savePrefs) {
//var t1 = new Date().getTime();
console.time("function time");
var body = DocumentApp.getActiveDocument().getBody();
var alltext = body.getText();
var lastchar = alltext.slice(-1);
if (lastchar != " " && lastchar != "\n") {
body.editAsText().insertText(alltext.length, "\n");
alltext = body.getText();
}
var arr_alltext = alltext.split(/[\s\n]/);
var pagewords = new Object;
var pagewordsOrig = new Object;
var pagewordsOrigOffset = new Object;
var offset = 0;
var curWord = "";
var cnt = 0;
for (var i = 0; i < arr_alltext.length; i++) {
curWord = arr_alltext[i];
if (StringHasSimeioStiksis(curWord)) {
curWord = replaceSimeiaStiksis(curWord);
var arr3 = curWord.split(" ");
for (var k = 0; k < arr3.length; k++) {
curWord = arr3[k];
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length;
cnt++;
}
offset++;
} else {
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/\n]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length + 1;
cnt++;
}
}
var respTString = "";
var url = 'https://www.example.org/spellchecker.php';
var data = {
"Text" : JSON.stringify(pagewords),
"idOffset" : "0",
"lexID" : "8",
"userEmail" : "test#example.org"
};
var payload = JSON.stringify(data);
var options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
//var t11 = new Date().getTime();
console.time("POST time");
var response = UrlFetchApp.fetch(url, options);
console.timeEnd("POST time");
//var t22 = new Date().getTime();
var resp = response.getContentText();
respTString = resp;
var spellchecked = JSON.parse(respTString);
var style = {};
for (var k in pagewords){
if (pagewords.hasOwnProperty(k)) {
if (spellchecked.hasOwnProperty(k)) {
if (spellchecked[k].substr(0, 1) == "1") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#000000";
}
if (spellchecked[k].substr(0, 1) == "0") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FF0000";
}
if (spellchecked[k].substr(0, 1) == "4") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#0000FF";
}
if (pagewordsOrigOffset[k] < alltext.length) {
body.editAsText().setAttributes(pagewordsOrigOffset[k], pagewordsOrigOffset[k] + pagewordsOrig[k].length, style);
}
}
}
}
//var t2 = new Date().getTime();
console.timeEnd("function time")
return {
"pagewords" : pagewords,
"pagewordsOrig" : pagewordsOrig,
"pagewordsOrigOffset" : pagewordsOrigOffset,
"spellchecked" : spellchecked
}
}
Thank you in advance for any help.
EDIT: I updated the code to use console.time according to the suggestion, the results are:
total time: 2048.001953125 ms
Jun 21, 2021, 3:01:40 PM Debug POST time: 809ms
Jun 21, 2021, 3:01:41 PM Debug function time: 1408ms
So the problem is not how time is measured. function time is 1400ms, while the time it takes to return is 2000ms, a difference of 600ms and the POST time is a staggering 800ms, instead of 200ms it takes in VB.net to make the exact same POST call.
Use console.time() and console.timeEnd():
https://developers.google.com/apps-script/reference/base/console
I modified the code for you. console.timeEnd() outputs the time duration in the console automatically, so I removed the alert for you that showed the time difference.
You might want the strings that I used as the parameter as some sort of constant variable, so there are no magic strings used twice. I hope this is of use to you.
function runSpellChecking() {
gb_IsSpellcheckingRunning = true;
//gb_isAutoCorrecting = false;
gi_CorrectionCurrWordIndex = -1;
$("#btnStartCorr").attr("disabled", true);
$("#divMistakes").html("");
this.disabled = true;
//$('#error').remove();
var origin = $('input[name=origin]:checked').val();
var dest = $('input[name=dest]:checked').val();
var savePrefs = $('#save-prefs').is(':checked');
console.time("total time");
google.script.run
.withSuccessHandler(
function(textAndTranslation, element) {
if (gb_IsSpellCheckingEnabled) {
console.timeEnd("total time");
go_TextAndTranslation = JSON.parse(JSON.stringify(textAndTranslation));
var pagewords = textAndTranslation.pagewords;
var spellchecked = textAndTranslation.spellchecked;
//irrelevant code follows below...
}
})
.withFailureHandler(
function(msg, element) {
showError(msg, $('#button-bar'));
element.disabled = false;
})
.withUserObject(this)
.executeSpellChecking(origin, dest, savePrefs);
}
function executeSpellChecking(origin, dest, savePrefs) {
console.time("function time");
var body = DocumentApp.getActiveDocument().getBody();
var alltext = body.getText();
var lastchar = alltext.slice(-1);
if (lastchar != " " && lastchar != "\n") {
body.editAsText().insertText(alltext.length, "\n");
alltext = body.getText();
}
var arr_alltext = alltext.split(/[\s\n]/);
var pagewords = new Object;
var pagewordsOrig = new Object;
var pagewordsOrigOffset = new Object;
var offset = 0;
var curWord = "";
var cnt = 0;
for (var i = 0; i < arr_alltext.length; i++) {
curWord = arr_alltext[i];
if (StringHasSimeioStiksis(curWord)) {
curWord = replaceSimeiaStiksis(curWord);
var arr3 = curWord.split(" ");
for (var k = 0; k < arr3.length; k++) {
curWord = arr3[k];
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length;
cnt++;
}
offset++;
} else {
pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~##$%^&*()_|+\-="<>\{\}\[\]\\\/\n]/gi, '');
pagewordsOrig["" + (cnt+1).toString()] = curWord;
pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
offset += curWord.length + 1;
cnt++;
}
}
var respTString = "";
var url = 'https://www.example.org/spellchecker.php';
var data = {
"Text" : JSON.stringify(pagewords),
"idOffset" : "0",
"lexID" : "8",
"userEmail" : "test#example.org"
};
var payload = JSON.stringify(data);
var options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : payload
};
console.time("POST time");
var response = UrlFetchApp.fetch(url, options);
console.timeEnd("POST time");
var resp = response.getContentText();
respTString = resp;
var spellchecked = JSON.parse(respTString);
var style = {};
for (var k in pagewords){
if (pagewords.hasOwnProperty(k)) {
if (spellchecked.hasOwnProperty(k)) {
if (spellchecked[k].substr(0, 1) == "1") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#000000";
}
if (spellchecked[k].substr(0, 1) == "0") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FF0000";
}
if (spellchecked[k].substr(0, 1) == "4") {
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#0000FF";
}
if (pagewordsOrigOffset[k] < alltext.length) {
body.editAsText().setAttributes(pagewordsOrigOffset[k], pagewordsOrigOffset[k] + pagewordsOrig[k].length, style);
}
}
}
}
console.timeEnd("function time");
return {
"pagewords" : pagewords,
"pagewordsOrig" : pagewordsOrig,
"pagewordsOrigOffset" : pagewordsOrigOffset,
"spellchecked" : spellchecked
}
}
I have two datasets, one in indexedDB and one in PouchDB (yes I know PouchDB is an implementation of indexedDB).
The one in indexedDB is a list of rooms, stored in indexedDB via a previous page, and displayed on the current page.
The one in PouchDB is the log of room usage recorded by a room auditor. I want to iterate through the first list, and check if each item appears in the list of audited rooms. If it does appear, I want to set a flag to indicate that.
Here's my Javascript. (I have run this in a browser and it does return true at some point in the process, because the console log output shows that, but the flag doesn't get set against the list item.)
I am wondering if it continues to loop through the audit records and overwrites the "true" value?
this is the function that queries indexedDB and calls the function that queries PouchDB:
function getRoomsInRoute() {
var routeNumber = $.jStorage.get('currentRoute', '');
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
openRequest = window.indexedDB.open("rooms", 1);
openRequest.onupgradeneeded = function() {
var db = openRequest.result;
var itemStore = db.createObjectStore("rooms", {keyPath: "room_id"});
var index = itemStore.createIndex("rooms", ["route_number"]);
};
openRequest.onerror = function(event) {
console.error(event);
};
openRequest.onsuccess = function (event) {
var db = openRequest.result;
db.onerror = function(event) {
// Generic error handler for all errors targeted at this database's requests
console.error(event.target);
console.log("Database error: " + event.target.error.name || event.target.error || event.target.errorCode);
};
var transaction = db.transaction(['rooms'], "readwrite");
var itemStore = transaction.objectStore("rooms");
var index = itemStore.index("rooms", ["route_number"]);
console.log('DB opened');
var intRouteNumber = parseInt(routeNumber);
//var range = IDBKeyRange.only(intRouteNumber);
itemStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
var audited;
if(cursor.value.route_number == routeNumber) {
if (checkIfAudited(cursor.value.room_seq)) {
var audited = ' <span class="checked"><i class="fa fa-check"></i></span>';
} else {
var audited = "";
}
$('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '. </small>' + cursor.value.room_name + ''+audited+'</li> ');
}
cursor.continue();
} else {
console.log('Entries all displayed.');
if(!($.jStorage.get('reverseroute', ''))) {
reverseroute = 'asc';
} else {
reverseroute = $.jStorage.get('reverseroute', '');
}
appendHref(reverseroute);
}
};
// Close the db when the transaction is done
transaction.oncomplete = function() {
db.close();
};
};
}
and this is the function that queries PouchDB to see if it has been audited:
function checkIfAudited(roomseq) {
var today = new Date();
if(is_BST(today) == true) {
var currentHour = today.getHours()+1;
} else {
var currentHour = today.getHours();
}
var currentDay = today.getDate();
var currentMonth = today.getMonth();
options = {},
that = this,
pdb = new PouchDB('pouchroomusage');
options.include_docs = true;
var pouchOpts = {
skipSetup: true
};
var opts = {live: true};
pdb.allDocs(options, function (error, response) {
response.rows.some(function(row){
var auditTime = new Date(row.doc.timestamp);
var auditHour = auditTime.getUTCHours();
var auditDay = auditTime.getDate();
var auditMonth = auditTime.getMonth();
if(row.doc.sequence == roomseq && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth) {
var isAudited = true;
console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay);
console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
} else {
var isAudited = false;
console.log('No matches');
}
return isAudited;
});
});
}
I have read a number of other questions and answers about comparing two arrays.
I don't know how to use a for loop with pdb.allDocs though :(
Here is the output from console.log:
49 No matches
RoomSeq: 1; auditHour: 14; currentHour: 14; auditDay: 16
currentDay: 16; auditMonth: 0; currentMonth: 0; isAudited: true
2300 No matches
So how do I get the second function to stop and return true when it hits a matching record in PouchDB?
First, I wouldn't get too fancy with exploiting the short-circuiting behavior of Array.prototype.some. Use the native functionality available to you. indexedDB provides a built in way to stop advancing a cursor, or load only a limited number of objects from a store.
Second, you probably want to avoid loading all objects from a store when you are only interested a in a few of those objects. Use a cursor to walk the store. Since you appear to want to stop iterating when meeting some condition, simply do not call cursor.continue at that point.
Third, is that even if decide to load all objects from the store first, it would be far better to use a for loop than exploit some. By exploit I mean use the function in a way other than it was intended. I bet that if you revert to using a for loop with a break statement, the code will be clearer and therefore it will be simpler to understand why the loop does not break when you expect it to do so.
Fourth, is that I would take the time to append results of an indexedDB query to an intermediate data structure, like an array, rather than immediately interacting with the DOM. It will separate things more, and you will find the code simpler to debug.
Fifth is that you should be very careful when mixing async calls together with indexedDB. indexedDB is known to have problems when you interleave calls to other promises.
It seems to me that the pouchdb method alldocs is asynchronous.
But you test audition in a synchronous way. Therefore whatever the pdb.alldocs callback function returns will be returned after the checkIfAudited is already returned. Therefore checkIfAudited always returns undefined.
In my opinion, you should create the pouchdb instance only once in temStore.openCursor().onsuccess. Then you need to properly return audit state in checkIfAudited function.
For example, you could do something like the following:
itemStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
if (cursor.value.route_number == routeNumber) {
var audited;
options = {},
pdb = new PouchDB('pouchroomusage');
options.include_docs = true;
pdb.allDocs(options, function (error, allDocsResponse) {
if (checkIfAudited(allDocsResponse, cursor.value.room_seq)) audited = ' <span class="checked"><i class="fa fa-check"></i></span>'
else audited = "";
$('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '. </small>' + cursor.value.room_name + ''+audited+'</li> ');
});
};
cursor.continue();
} else {
console.log('Entries all displayed.');
if(!($.jStorage.get('reverseroute', ''))) reverseroute = 'asc'
else reverseroute = $.jStorage.get('reverseroute', '');
appendHref(reverseroute);
};
};
And for checkIfAudited:
function checkIfAudited(allDocs, roomseq) {
var today = new Date();
if(is_BST(today) == true) {
var currentHour = today.getHours()+1;
} else {
var currentHour = today.getHours();
}
var currentDay = today.getDate();
var currentMonth = today.getMonth();
for (i=0; i<allDocs.rows.length; i++) {
var row = allDocs.rows[i];
var auditTime = new Date(row.doc.timestamp);
var auditHour = auditTime.getUTCHours();
var auditDay = auditTime.getDate();
var auditMonth = auditTime.getMonth();
if(row.doc.sequence == roomseq && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth) {
console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay);
console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
return true; ///// <---- return that it is audited
} else {
console.log('No matches');
};
});
return false ///// <---- return false if no iteration has matched
}
This is what I ended up with after much tweaking.
Now it adds <span class="checked"><i class="fa fa-check"></i></span> more than once per <li> but at least it adds to every <li>.
So I did a little hack to the CSS to only display one span.checked:
.checked {
color: #fff;
background-color: #006338;
border-radius: 50%;
padding: 2px 3px;
}
/* only display the first instance of checked */
li > span.checked ~ .checked {
display: none;
}
(I also found and fixed another error in my script, where I wasn't setting route_number or room_id.)
function getRoomsInRoute() {
var routeNumber = $.jStorage.get('currentRoute', '');
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
openRequest = window.indexedDB.open("rooms", 1);
openRequest.onupgradeneeded = function() {
var db = openRequest.result;
var itemStore = db.createObjectStore("rooms", {keyPath: "room_id"});
var index = itemStore.createIndex("rooms", ["route_number"]);
};
openRequest.onerror = function(event) {
console.error(event);
};
openRequest.onsuccess = function (event) {
var db = openRequest.result;
db.onerror = function(event) {
// Generic error handler for all errors targeted at this database's requests
console.error(event.target);
console.log("Database error: " + event.target.error.name || event.target.error || event.target.errorCode);
};
var transaction = db.transaction(['rooms'], "readwrite");
var itemStore = transaction.objectStore("rooms");
var index = itemStore.index("rooms", ["route_number"]);
console.log('DB opened');
var intRouteNumber = parseInt(routeNumber);
//var range = IDBKeyRange.only(intRouteNumber);
itemStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
var audited = "";
if(cursor) {
if(cursor.value.route_number == routeNumber) {
$('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '. </small>' + cursor.value.room_name + '</li> ');
}
cursor.continue();
} else {
console.log('Entries all displayed.');
if(!($.jStorage.get('reverseroute', ''))) {
reverseroute = 'asc';
} else {
reverseroute = $.jStorage.get('reverseroute', '');
}
appendHref(reverseroute);
asyncCallToPouchDb();
}
};
// Close the db when the transaction is done
transaction.oncomplete = function() {
db.close();
};
};
}
function asyncCallToPouchDb() {
$('#mylist li').each(function(){
var audited = "";
var room_id = $(this).attr('id');
var thisLi = $(this);
audited = callPouchDb(room_id, thisLi);
});
}
function callPouchDb(room_id, thisLi) {
options = {},
pdb = new PouchDB('pouchroomusage');
options.include_docs = true;
var audited = "";
//return new Promise(resolve => {
pdb.allDocs(options, function (error, response) {
result = response.rows;
for (i = 0; i < result.length; i++) {
if (checkIfAudited(result[i], room_id)) {
audited = ' <span class="checked"><i class="fa fa-check"></i></span>';
}
thisLi.append(audited);
}
//thisLi.append(audited);
/*end pdb.allDocs*/
}).then(function (result) {
// handle result
console.log(result);
}).catch(function (err) {
console.log(err);
});
// });
}
function checkIfAudited(row, room_id) {
var today = new Date();
if(is_BST(today) == true) {
var currentHour = today.getHours()+1;
} else {
var currentHour = today.getHours();
}
var currentDay = today.getDate();
var currentMonth = today.getMonth();
var currentYear = today.getYear();
var isAudited = false; ///// <---- define isAudited outside of db iteration scope
var auditTime = new Date(row.doc.timestamp);
var auditHour = auditTime.getUTCHours();
var auditDay = auditTime.getDate();
var auditMonth = auditTime.getMonth();
var auditYear = auditTime.getYear();
if(row.doc.room_id == room_id && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth && currentYear == auditYear) {
isAudited = true;
// debug
// console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay);
// console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
} else {
console.log('No matches');
};
return isAudited
}
I'm a beginner in java script a trying a little program that parse data from a text file. In order to create a filter on a particular date i have made a function to get the date from and to that the user have enter. And the date a have to compare if it is in the range is in the text file, this date also i got it. But now i don't want to re-write the function "getAllFilesFromFolder" found in the code below, this function must be executed in all case but if i click on the button filter by by date it must read on the files with the date in range given by the user. Can someone give me an explanation on how to do it. i have tried the code below.
function getdate(){
var dateStart = new Date($('#dateStart').val()).getTime();
var dateEnd = new Date($('#dateEnd').val()).getTime();
//if(!testDate){var testDate = new Date(2014, 05, 02).getTime();}
var testDate = new Date(2014, 05, 02).getTime();
if (dateStart <= testDate && testDate <= dateEnd) {
alert('IN');
//Here filter the files with the date
}else{
alert('OUT');
//Here no new to read and parse the file beacause it is out of range
}
}
//Parse folder and file to get the required files
function getAllFilesFromFolder(folder){
//Parsing the given folder the result which is return is kept in an array
var test = fse.readdirSync(folder);
//Going through the array
for(var n=0; test[n]; n++){
var stats = fs.lstatSync(folder+"\\"+test[n]);
if(stats && stats.isDirectory()){
getAllFilesFromFolder(folder+"\\"+test[n]);
var path = folder+"\\"+test[n]+"<br />";
}else{
var path = folder+"\\"+test[n];
//Regex on the file to be taken
var pattern = /^(PM)[0-9]{5}[_](xam)[_](pmbok5th)[_](pmp)[_](v92)(.txt)$/;
var parent = folder+"\\";
var file = test[n];
var load = pattern.test(file);
//Split on file to get the "id user"
identifiant = file.split('_');
//Test the regex on file name "PM*_xam_pmbok5th_pmp_v92.txt"
if(load == true){
var read = fse.readFileSync(path, 'utf8');
var suspendDate = read.lastIndexOf('xam/');
var wantedDate = read.slice(suspendDate);
info = wantedDate.split('/');
var suspendData = read.lastIndexOf('/DB');
var suspendData = wantedDate.lastIndexOf('/DB');
var wantedData = wantedDate.slice(suspendData);
var db_response = wantedData.split(".");
var all_response = db_response[0].split(":");
if(typeof(info[2]) != "undefined" && all_response != "undefined"){
var response = all_response[1].split("|");
//Parsing the array response to find the "id" here id of the question and the "ans" here answer of the question "R" or "W"
for(var p = 0; p < response.length; p++){
//Test if result exist we increment if not it is generate with the function initResp
if(typeof(response[p]) != "undefined"){
var id = response[p].slice(0,6);
var ans = response[p].slice(-1);
if (question[id]) {
question[id][ans] += 1;
} else {
var results = initResp(ans);
question[id] = results;
};
} else {
}
}
} else {
//$("#results1").append("<strong>La session est vide</strong><br>");
}
i++;
}
}
}
};
I found a solution to my problem. See the code below for more information
function rangeDate(testDate){
var dateStart = new Date($('#dateStart').val()).getTime();
var dateEnd = new Date($('#dateEnd').val()).getTime();
if (dateStart <= testDate && testDate <= dateEnd) {
date = true;
return date;
}else{
date = false;
return date;
}
}
function getAllFilesFromFolder(folder)/*, useDate*/{
//Parsing the given folder the result which is return is kept in an array
var test = fse.readdirSync(folder);
//Going through the array
for(var n=0; test[n]; n++){
var stats = fs.lstatSync(folder+"\\"+test[n]);
if(stats && stats.isDirectory()){
getAllFilesFromFolder(folder+"\\"+test[n]);
var path = folder+"\\"+test[n]+"<br />";
}else{
var path = folder+"\\"+test[n];
//Regex on the file to be taken
var pattern = /^(PM)[0-9]{5}[_](xam)[_](pmbok5th)[_](pmp)[_](v92)(.txt)$/;
var parent = folder+"\\";
var file = test[n];
var load = pattern.test(file);
//Split on file to get the "id user"
identifiant = file.split('_');
//Test the regex on file name "PM*_xam_pmbok5th_pmp_v92.txt"
if(load == true){
var read = fse.readFileSync(path, 'utf8');
var suspendDate = read.lastIndexOf('xam/');
var wantedDate = read.slice(suspendDate);
var info = wantedDate.split('/');
testDate = new Date(info[4]).getTime();
rangeDate(testDate);
if(date == true){
var suspendData = read.lastIndexOf('/DB');
var suspendData = wantedDate.lastIndexOf('/DB');
var wantedData = wantedDate.slice(suspendData);
var db_response = wantedData.split(".");
var all_response = db_response[0].split(":");
if(typeof(info[2]) != "undefined" && all_response != "undefined"){
var response = all_response[1].split("|");
//Parsing the array response to find the "id" here id of the question and the "ans" here answer of the question "R" or "W"
for(var p = 0; p < response.length; p++){
//Test if result exist we increment if not it is generate with the function initResp
if(typeof(response[p]) != "undefined"){
var id = response[p].slice(0,6);
var ans = response[p].slice(-1);
if (question[id]) {
question[id][ans] += 1;
} else {
var results = initResp(ans);
question[id] = results;
};
} else {
}
}
} else {
//$("#results1").append("<strong>La session est vide</strong><br>");
}
i++;
}else{
}
}
}
}
};
I have found similar threads about this but I cant seem to make their solutions work for my specific issue. I currently have a calendar that will highlight the starting date of an Event. I need to change this to highlight the Start Date through the End Date.
Note: I did not write this code. It seems like whoever wrote this left a lot of junk in here. Please don't judge.
attachTocalendar : function(json, m, y) {
var arr = new Array();
if (json == undefined || !json.month || !json.year) {
return;
}
m = json.month;
y = json.year;
if (json.events == null) {
return;
}
if (json.total == 0) {
return;
}
var edvs = {};
var kds = new Array();
var offset = en4.ynevent.getDateOffset(m, y);
var tds = $$('.ynevent-cal-day');
var selected = new Array(), numberOfEvent = new Array();
for (var i = 0; i < json.total; ++i) {
var evt = json.events[i];
var s1 = evt.starttime.toTimestamp();
var s0 = s1;
var s2 = evt.endtime.toTimestamp();
var ds = new Date(s1);
var de = new Date(s2);
var id = ds.getDateCellId();
index = selected.indexOf(id);
if (index < 0)
{
numberOfEvent[selected.length] = 1;
selected.push(id);
}
else
{
numberOfEvent[index] = numberOfEvent[index] + 1;
}
}
for (var i = 0; i < selected.length; i++) {
var td = $(selected[i]);
if (td != null) {
if (!(td.hasClass("otherMonth"))){
td.set('title', numberOfEvent[i] + ' ' + en4.core.language.translate(numberOfEvent[i] > 1 ? 'events' : 'event'));
td.addClass('selected');
}
}
}
},
Instead of trying to select them all, I recommend you iterate over them instead. So something like this:
function highlightDates(startDate, endDate) {
var curDate = startDate;
var element;
$('.selected').removeClass('selected'); // reset selection
while (curDate <= endDate) {
element = getElementForDate(curDate)
element.addClass('selected');
curDate.setDate(curDate.getDate() + 1); // add one day
}
}
function getElementForDate(someDate) {
return $('#day-' + someDate.getYear() + "-" + someDate.getMonth() + "-" + someDate.getDay());
}