I have a chart that updates with the current bitcoin prices, however, the date and time on the x-axis is incorrect. It always starts at Dec. 31, 19:00 hours. In my console I am recieving the correct date and time, but I can't seem to get it to appear correctly on the chart. I'm pretty sure I need to stick one array into another. Any help is appreciated, thanks.
$.ajax({
url: "/chart/ajax_get_chart", // the URL of the controller action method
dataType: "json",
type: "GET",
success: function (result) {
var result = JSON.parse(result);
series = [];
for (var i = 0; i < result.length; i++) {
tempDate = Date.parse(result[i]['date']);
tempArray = [parseFloat(result[i]['price'])];
var date = new Date();
tempDate = date.toString();
series.push(tempArray);
var tempDate = tempDate.concat(tempArray);
}
If I understood correctly, for every i:
result[i]['date'] gives the date at position i
result[i]['price'] gives the price at position i
Now first of all, let's take a look at your loop:
for (var i = 0; i < result.length; i++) {
//Here you grab the date from the result array
tempDate = Date.parse(result[i]['date']);
//Here you grab the price from the result array and parse it to a float
tempArray = [parseFloat(result[i]['price'])];
//Here you grab the current date (of today)
var date = new Date();
//Here you overwrite the 'grabbed date' with the current date (of today)
tempDate = date.toString();
//Here you add the price at position i to the 'result array' called series
series.push(tempArray);
//Here you join tempArray with the tempDate
var tempDate = tempDate.concat(tempArray);
}
So what exactly goes wrong?
Well I have prepared a JsFiddle for you: http://jsfiddle.net/KzLFr/1/
Look closely at the code and what exactly 'shows up' in the alert box. You see that the value of tempDate is overwritten by the current date. Applying this info to your loop: you will see that for each iteration, you overwrite the date that you grab from the result array with the current date.
This means that the 'actual' dates (from result[i]['date']) are always overwritten, hence, if you would add all the tempDates to an array at each iteration, you will end up with an array consisting of result.length times the current date.
Another interesting point is your statement: var tempDate = tempDate.concat(tempArray);
As you can see in the second alert box in the JsFiddle, this will create an array which has two arrays after each other. But why in the world would you do this in every iteration?
Also, you never do something with your dates. You don't add them to an array or anything: you just create them and then leave them alone.
This begs the question: what exactly do you want to do?
Therefore:
NOTE: It could be that I am mistaken, but if I'm right you want to end up with an array that contains the x-axis information and the y-axis information. Because it is not clear from your question and your code how you want to accomplish this, I can only guess.
So by guessing what you want to end up with, I would rewrite your loop as follows:
var dateData = [];
var priceData = [];
for( var i = 0; i < result.length; i++ ){
dateData.push( result[i][0] );
priceData.push( result[i][1] );
}
You can see how this works here: http://jsfiddle.net/WT58s/1/
If that doesn't solve your problem, please explain with what you want to end up with (a two dimensional array or two different arrays?), so we can assist you better.
Also, often when you download information from the internet, the information is stored backwards; so starting with the current date and then going backwards in time.
Try and see if that is also the case with your data. If this is indeed the case, you can read about reversing here:
Reverse order of elements in 2-dimensional array
Related
Goal
Write a script that does the following:
get data from sheet
modify column to flip names from [Last, First] to [First Last]
modify 2 columns to abbreviate company names & statuses
write resulting data to another spreadsheet without changing the format
add timestamp for when data copied
Problem
I can get the data BUT it writes everything back as plain text. Thus instead of dates writing out as "yyyy-MM-dd", they write out as something like this: Mon Oct 19 2020 01:00:00 GMT-0400 (Eastern Daylight Time)
Expectation:
screenshot of dates as "yyyy-MM-dd"
Result:
screenshot of dates as whatever this garble is
I have googled extensively and can't seem to find a solution. I believe my problem is with using toString() in the Array.map. I'm not sure how to restrict the map method to only the columns that need modifying. Right now it affects the whole array.
(I used the code from Google Apps Script for Multiple Find and Replace in Google Sheets to write this part)
//-----FIND AND REPLACE FOR COMPANY & STATUS ABBREVIATIONS
function replaceInSheet(initArray, to_replace, replace_with){
//Loop over rows in array
for(var row in initArray ){
//Use Array.map to execute a replace call on each of the cells in the row.
var replaced_values = initArray[row].map(function(originalValue){
return originalValue.toString().replace(to_replace,replace_with);
});
//Replace the original row values with the replaced values
initArray[row] = replaced_values;
}
}
Question--> How do I get the output of my script to format dates in two of my columns, correctly?
Attempted Solutions that didn't work
I tried swapping the name flip code to happen after the abbreviation code so I could add a setNumberFormat('yyyy-MM-dd') within the name flip for loop. I couldn't figure out how to apply this to columns within my array. Something like initarray[x][5].setNumberFormat("yyyy-MM-dd") gave me an error saying "TypeError: initArrayx.setNumberFormat is not a function"
I tried adding code before (and then even after) .setValues() at the end to change the format. Some resources I referenced:
setNumberFormat('yyyy-MM-dd') from stackoverflow: Set cell format with google apps script
Utilities.formatDate(new Date(), "CST", "yyyy-MM-dd") from stackoverflow: Get today date in google appScript
website post by BLACKCJ: "Cell Number Formatting with Google Apps Script"
google's developer documentation
and all sorts of other articles, blogs, forums, etc.
I tried writing a completely separate function to change the format after my script runs. Nope. I can't get those 2 columns to format as dates
Code & Sample Spreadsheet
Here's the whole code I'm using, modified to work with a sample google sheet I created just for the purposes of this question.
Sample Google Sheet:
https://docs.google.com/spreadsheets/d/1Ys77hQHHajIo-Xaxyom0SVnyVMZ6bKOT8Smpadd2jv4/edit?usp=sharing
Script:
// ==================================================
// FUNCTION TO RUN
// ==================================================
function syncData(){
//Ger Source Data
var ss = SpreadsheetApp.getActiveSpreadsheet();
var thisSheet = ss.getSheetByName("source");
var thisData = thisSheet.getRange("A4:M11");
var initArray = thisData.getValues();
//Get Target Location
var toSheet = ss.getSheetByName("target");
var toRange = toSheet.getRange("A4:M11"); //Range starts at A4
//CHANGE [LAST, FIRST] TO [FIRST LAST]
for (var x = 0; x < initArray.length; x++){
var indexOfFirstComma = initArray[x][0].indexOf(", ");
if(indexOfFirstComma >= 0){
//If comma found, split and update values in the values array
var lastAndFirst = initArray[x][0];
//Update name value in array
initArray[x][0] = lastAndFirst.slice(indexOfFirstComma + 2).trim() + " " + lastAndFirst.slice(0, indexOfFirstComma).trim();
}
}
//ABBREVIATE COMPANY
replaceInSheet(initArray, 'Bluffington School','BLF HS');
replaceInSheet(initArray, 'Honker Burger','HBGR');
replaceInSheet(initArray, 'Funky Town','FT');
//ABBRIVIATE STATUS
replaceInSheet(initArray, 'Regular','Staff');
replaceInSheet(initArray, 'Contractual','Part');
replaceInSheet(initArray, 'Temporary','Temp');
//Clear Target Location
var toClear = toSheet.getRange("A4:M11")
toClear.clearContent();
//Write updated array to target location
toRange.setValues(initArray);
//Write timestamp of when code was last run
setTimeStamp(toSheet);
}
//-----FIND AND REPLACE FOR COMPANY & STATUS ABBREVIATIONS
function replaceInSheet(initArray, to_replace, replace_with){
//Loop over rows in array
for(var row in initArray ){
//Use Array.map to execute a replace call on each of the cells in the row.
var replaced_values = initArray[row].map(function(originalValue){
return originalValue.toString().replace(to_replace,replace_with);
});
//Replace the original row values with the replaced values
initArray[row] = replaced_values;
}
}
//-----ADD TIMESTAMP FOR WHEN THE SCRIPT LAST RAN
function setTimeStamp(toSheet) {
var timestamp = Utilities.formatDate(new Date(), "CST", "yyyy-MM-dd # h:mm a");
toSheet.getRange('F1').setValue(timestamp);
}
setNumberFormat('yyyy-MM-dd') is a good solution but it's a method of a Range of the sheet. Not an array.
To apply the format you need to get a range first. Something like this:
toSheet.getRange('G4:G').setNumberFormat('yyyy-MM-dd');
And there is one more thing ) Try to change this line:
var initArray = thisData.getValues();
to:
var initArray = thisData.getDisplayValues();
I'm facing a problem checking whether a date is in my array or not.
I refer to this article How to correctly use JavaScript indexOf in a date array
But when I use it in my project, it always results in -1.
Here's my code
for (var current = dateStart; current <= dateEnd; current.setDate(current.getDate() + 1)) {
console.log(this.leaveState.currentHoliday.map(Number).indexOf(+current));
}
I need to check whether current date is in currentHoliday array or not.
I think mapping doesn't require to loop into your array.
and -1 is somehow mean that the date does not exist in your array.
Maybe because in every loop you add a day to it before you see the actual day.
I think you could try:
var alldays = [...];
//you should eliminate these two codes
// datestart = something;
// dateend = something;
var holiday;
for(var i in alldays){
console.log(alldays.map(Number).indexOf(this.leaveState.currentHoliday));
}
I want to receive an array of moment objects, based on start / and date.
I wrote the following code in which the first start date is 27/12/2014:
_calculateDateInterval: function(date_start, date_end){
var current = date_start.startOf("day");
var arr_dates = [];
var i = 1;
while(date_end.startOf("day").diff(current, "days") > 0){
var copy_current = $.extend({}, current); //Clone the object without reference
console.log(copy_current);
arr_dates.push(copy_current);
current.add(1, "days");
//Break the loop for testing purposes
i++;
if(i == 2){
return false;
};
};
return arr_dates;
},
There is a problem though. Even when checking only on the first loop, the console gives me the following log:
This is confusing; when opening the dropdown, _d shows another day than when it is collapsed.
In order to store the right moment object, I need to remove the reference to the original (current) Moment object of which the day is increased on each loop. (In this case I need 27/12/2014, not the value including the day increase).
Any (better) suggestions?
Found it already in the docs:
All moments are mutable. If you want a clone of a moment, you can do
so explicitly or implicitly.
Calling moment() on a moment will clone it.
Okay, I've been working on this for about a month. I've tried numerous different ways of doing this, and I think I'm close. I'm not an expert, but here is what I'm trying to do. I've created a form that allows me to capture behavior data for my son. (He's autistic, which is why this is important.) I can get the data from the form into a results spreadsheet and I can transfer the data to a new report style pre formatted spreadsheet. What I can't do is filter the dates effectively. My script is below.
function onOpen() {
var rawdata=SpreadsheetApp.openById("0AtkuL_H_DshvdFU5U1dBLVI1NWhlWXdSNjBXOHdIaUE");
var sheet1=rawdata.getSheetByName("FormResponses");
var maxrows=sheet1.getMaxRows();
var lastcol = sheet.getLastColumn();
var vals=sheet1.getRange(1,1,maxrows,1).getValues();
var date = new Date();
var newDate = date.setDate(date.getDate()+1);
var Sdate=Utilities.formatDate(date,"GMT-0400","yyyy:MM:dd");
var newerDate=Utilities.formatDate(newDate,"GMT-0400","yyyy:MM:dd");
var filter=ArrayLib.filterByDate(vals,1,Sdate,newerDate);
var range1 = sheet1.getRange(1,1,filter,lastcol);
var values = range1.getValues();
var target = SpreadsheetApp.openById("0AtkuL_H_DshvdGxWNGJ0ZjA2VU5zV01iaVNacDZQYWc")
var sheet2 = target.getSheetByName("Sheet1");
var range2 = sheet2.getRange(4,1,i,7);
SpreadsheetApp.setActiveSpreadsheet(rawdata);
values
SpreadsheetApp.setActiveSpreadsheet(target);
range2.setValues(values);
}
//for (var i = 0; i < maxrows; i++) if (Date.parse(vals[i]).valueOf() >= todaydt.valueOf() );
The last line is a prior way I tried to filter the dates. That's the part I can't quite get to work. Part of my challenge is that I don't quite understand the "for" command yet. I'm doing the CodeAcademy java course, but since I work, have a family, and don't do this for a living its slow going. I've searched about a thousand websites and tried numerous ways to filter the dates, but I can't get any of them to work. Any help is appreciated.
I assume arraylib.filterbydate takes dates but you are passing strings. Try passing dates.
Or just filter by string if that lib allows it. Since you are formatting the date strings as yyyymmdd your string comparisons could work.
I have a series of arrays that contain words I want to use as text in various HTML divs (there are about 35 of these, I included only a few for brevity).
var bodyplan = ['Anguilliform', 'Compressiform', 'Depressiform', 'Filiform', 'Fusiform', 'Globiform', 'Sagittiform', 'Taeniform'];
var mouthposition = ["Inferior", "Jawless", "Subterminal", "Superior", "Terminal"];
var barbels = ['1', '2', '4 or more'];
var caudalshape = ['Continuous', 'Emarginate', 'Forked', 'Lunate', 'Rounded', 'Truncate'];
I have a switch function that is supposed to change the text based on user selections:
switch(n){
case 1:
changelabels(bodyplan, 8);
break;
case 2:
changelabels(mouthposition, 5);
break;
case 3:
changelabels(barbels, 3);
break;
case 4:
changelabels(caudalshape, 6);
break;
case 5:
changelabels(dorsalspines, 8);
break;
default:
alert("handquestsel error")}};
Finally, I have the function which I would like to make the changes (except it doesn't):
function changelabels(opt1,opt2){
var i = opt2;
var im = opt2 - 1;
var c = 1;
var index = 0;
while (i>=c){
var oldlbl = document.getElementById("rb" + c + "lbl");
var newlbla = opt1.slice(im,i);
var newlblb = opt1.toString();
oldlbl.innerHTML = newlblb;
c = c + 1
index = index + 1
}};
I know the code for my function is just plain wrong at this point, but I have altered it so many times that I'm not sure what's going on anymore. At one point I did have the function able to change the text, but it did so incorrectly (it parsed the name of the array, not extracted a value from the array as I wished). Please help. I know I am overlooking some fundamental concepts here, but am not sure which ones. I've lost count of the hours I've spent trying to figure this out. It's seems like it should be so simple, yet in all my chaotic attempts to make it work, I have yet to stumble on an answer.
EDIT: I want my switch statement to call the function and pass to the function, the appropriate array from which to pull the labels from. The purpose of the app is to help a user learn to identify fish. When the user makes selections on the page, a series of pictures will be shown for various character states with an accompanying label describing the state. For example, when the user selects Mouth Position a series of divs will show the different mouth positions that fish have and have a label below the picture to tell the user what that certain character state is called. I can get the pictures to change just fine, but I am having a hell of a time with the labels.
Why not just something along the lines of:
document.getElementById("bodyplan_label").innerHTML = bodyplan[bodyplan_index];
You seem trying to put everything in really abstract data structures, I see no reason to. Just keep it simple.
Also bodyplan has only 8 elements, so bodyplan[8] will give you an out of bounds exception because arrays start at 0 as is common in all modern programming languages.
If I'm reading your requirement and code correctly, in your switch statement you are passing both a reference to the appropriate array and that array's expected length - you don't need the second parameter because all JavaScript arrays have a .length property.
You don't want to use .slice() to get the individual values out of the array, because that returns a new array copied out of the original - just use arrayVariable[index] to get the individual item at index.
So, putting that together try something like this (with your existing array definitions):
switch(n){
case 1:
changelabels(bodyplan);
break;
case 2:
changelabels(mouthposition);
// etc.
}
function changelabels(data) {
var i,
lbl;
for (i = 0; i < data.length; i++) {
lbl = document.getElementById("rb" + (i+1) + "lbl");
lbl.innerHTML = data[i];
}
}
Notice how much simpler that is than your code? I'm assuming here the elements you are updating have an id in the format "rb1lbl", "rb2lbl", etc, with numbering starting at 1: I'm getting those ids using (i+1) because JavaScript array indexes start at zero. Note also that you don't even need the lbl variable: you could just say document.getElementById("rb" + (i+1) + "lbl").innerHTML = data[i] - however I've left it in so that we have something to expand on below...
Within your function you seem to be changing the labels on a set of elements (radio button labels?), one per value in the array, but you stop when you run out of array items which means any leftover elements will still hold the values from the previous selection (e.g., if the previous selection was "bodyplan" with 8 options and you change to "mouthposition" with only 5 - you probably should hide the 3 leftover elements that would otherwise continue to display the last few "bodyplan" items. One way to do that is instead of setting your loop up based on the array length you could loop over the elements, and if the current element has an index beyond the end of the array hide it, something like this:
function changelabels(data) {
var i,
lbl,
elementCount = 20; // or whatever your element count is
for (i = 0; i < elementCount; i++) {
lbl = document.getElementById("rb" + (i+1) + "lbl");
if (i < data.length) {
lbl.innerHTML = data[i];
lbl.style.display = "";
} else {
lbl.innerHTML = "";
lbl.style.display = "none";
}
}
}
If these elements are labels for radio buttons (just a guess based on the ids) then you'd also want to hide or show the corresponding radio buttons, but I hope you can figure out how to add a couple of lines to the above to do that.
(As mentioned above, be careful about having element ids count up from 1 when the array indexes start at 0.)
If the above doesn't work please post (at least some of) the relevant HTML - obviously I've just had to guess at what it might be like.
SOLUTION: Changed the scope of the array variables to local by moving them into the function where they are used, instead of having them as global variables at the top of the page. I don't understand as I was following every rule of variable declaration. But for some unknown reason, global variables in javascript are abhorrent.
Solution Edit: Found an error in declaring my global variables. This may have been the source of my problem of why I could not access them. But it is a non-issue at this point since I corrected my code.
I don't understand what your trying to achieve exactly with your code. But to pass a variable (in this case an array) by reference you just have to add "&" before the variable.
function the_name(&$var_by_ref, $var_by_value) {
// Here if you modify $var_by_ref this will change the variable passed to the function.
}
More: http://php.net/manual/en/language.references.pass.php
Hope that helps.