Moment: avoiding reference - javascript

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.

Related

Javascript indexOf in date array always resulting -1

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));
}

keeping localStorage objects that iterate whilst using clear() within the same function

I'm trying to clear all local storage when the user either completes the game loop or starts a new game, but also keep some values.
I can do this already with my sound values for volume:
// inside a conditional statement that fires when the user chooses to start a new game.
if (newGameBool === '1') {
var tst = myAu;
//myAu is the stored value that the user sets as sound using a range type input
localStorage.clear();
localStorage.setItem("Au", tst);//A newly cleared localStorage just got a new value, and it's the same as it was before.
UI.myLoad();//reload the function that uses LS to do things.
}
How do I do this for key's that have an iterating number attached to them?
Here is how I save them:
var i = +v + +1;
localStorage.setItem("v", i);
var vv = localStorage.getItem("v");
localStorage.setItem("LdrBrd_" + vv, JSON.stringify(LdrBrd));//saves all data with the iterating key name.
Calling them the way i did the sound function:
var gv = v + 1;//v calls the value from LS and adjusted for off-by-one error. gv is a local variable.
if (newGameBool === '1') {
var ldd, vg;
for (var ii = 0; ii < gv; ii++) {
var ld = localStorage.getItem("LdrBrd_" + ii);
if (ld != null) {
//these are the values that i want to pass beyond the clear point
ldd = JSON.parse(ld);//JSON string of data saved
vg = ii;//how many of them.
}
}
localStorage.clear();
for (var xx = 0; xx < vg; xx++) {
var nld = localStorage.getItem("LdrBrd_" + xx);
if (nld != null) {
localStorage.setItem("LdrBrd_" + ii, JSON.stringify(ldd));
}
}
localStorage.setItem("v", vg);
UI.myLoad();
}
I have been using console.log() in various spots to see what is going on. I comment-out the clear function just to see if the values were wrong and they don't save all all. I tried to make a fiddle, but the local storage wasn't working at all there. In visual studio, it works fine but the script to this file is almost 2000 lines long, so i tried to dress it up the best i knew how.
Thanks in advance for any help or guidance.
I was stuck on this for a few days, but i think i found something that will work, so i'll answer my own question in case there is value in posterity.
locatStorage.clear();
/* ^LS clear() function is above all new setItem codes, some variables are declared globally and some are declared at the top of the functional scope or as param^ */
var itemClass = document.querySelectorAll(".itemClass");//the strings are here
if (itemClass) {//make sure some exist
for (var p = 0; p < itemClass.length; p++) {//count them
mdd = JSON.parse(itemClass[p].innerText);//parse the data for saving
localStorage.setItem("v", v);//this is the LS item that saves the amount of items i have, it's declared at the top of the functions timeline.
localStorage.setItem("LdrBrd_" + p, JSON.stringify(mdd));//this setItem function will repeat and increment with 'p' and assign the right string back to the key name it had before.
}
}
The key is to keep the strings physically attached to an element, then call the class name. The i ran a loop counting them. 'mdd' will spit back each item i want. So then all that is left to do is re-set the item back to it's original status.
This has allowed me to create a way for my users to collect trophies and keep them even after clearing the localStorage when the he/she decides to start a new game.
I use CSS to hide the text from the string.
color:transparent;
In my gameLoop, i have a function that will read the saved strings and show them as cards just below the hidden strings.
Since you want to keep some values I recommend one of two things:
Don't call localStorage.clear() and instead only wipe out the values that you want using localStorage.removeItem('itemName'). Since you said the item names have a numeric component, maybe you can do this in a loop to reduce code.
Pull item(s) that you want saved first and restore them after calling clear(). This option is best if there are way more items that you want removed rather than saved (see below)
function mostlyClear() {
var saveMe = {};
saveMe['value1'] = localStorage.getItem('value1');
saveMe['anotherValue'] = localStorage.getItem('anotherValue');
localStorage.clear();
for(var prop in saveMe) {
if(!saveMe.hasOwnProperty(prop)) continue;
localStorage.setItem(prop, saveMe[prop]);
}
}

Get time using cookies javascript

How to get Time with Cookies javascript When I close the tab or Page?
i'm try use window.onunload but time can not be stored in cookies..
in this code i'm push my cookies to be array
setCookie("time",time,1)
window.onunload =function (){
var set = getCookie('time');
var arr = [];
var push = arr.push(set);
console.log (arr);
return arr;
}
In JavaScript, there is a class called "Date" that let's you get the current time.
var d = new Date(); creates a new Date object and assigns it to the variable d
Now, you have the date and time - you can do whatever you like.
For example: document.getElementById('foo').innerHTML = d.toString() finds the element with the ID of "foo" and sets it's contents to the date and time.
Keep in mind that this date and time display will not constantly update itself. You will have to do that with some timed recursion.
There are many more things you can do with dates. Remember, Google is your friend - look up some things about the Date object.

How to put an array into another array?

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

How to reference an array in a function argument

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.

Categories