I have a form that can submit a number of rows of data associated with a given date. One of those fields is a percentage (i.e.: 0-100). I could have three rows of a given date with percentages that add up to 100 (or not, but that's a different validation issue) or two rows with different dates and associated percentages, etc.
I need to keep track of everything and sort all the percentages into the right date buckets on submission so I can do my validation.
To that end, I created an array, PctArray. Each element of PctArray is a two field Object - date, pct. As I loop through submitted data, I check each row's date to see if it's in the PctArray already, and, if so, increment the associated pct field of that date and move on. If not, I create a new element in PctArray and insert the information.
This all works fine and dandy if there's only one row submitted, or even several rows for one date. But the minute I submit information for a second date, it chokes. At this point, I give you the code:
// If this is our first row to process
if(PctArray.length == 0){
PctArray[0] = new Object();
PctArray[0].effdt = datefield.options[datefield.selectedIndex].value;
PctArray[0].pct = parseInt(pctfield.value);
}
else{
// We loop through the array to see if this EffDt exists yet. Not very efficient, but the array will always be small
var found = "no";
for(p=0;p<PctArray.length;p++){
if(PctArray[p].effdt == datefield.options[datefield.selectedIndex].value){
PctArray[p].pct = PctArray[p].pct + parseInt(pctfield.value);
found = "yes";
}
}
if(found == "no"){
PctArray[PctArray.length] = new Object();
PctArray[PctArray.length].effdt = datefield.options[datefield.selectedIndex].value;
PctArray[PctArray.length].pct = pctfield.value;
}
}
The initital take, when it's the first row, everything creates and inserts just fine. But, when I need to go into the block of if(found == "no") it creates the new element, but then dies on the first assignment statement saying Unable to set value of the property 'effdt': object is null or undefined.
I don't get it. I'm declaring the new element the SAME EXACT WAY in both places, but there's something I'm missing that it's not liking about the second time.
I've also tried replacing new Object() with {"effdt":'', "pct":''} with identical results. It works on the top one, not the bottom one.
I'm lost. Does anyone see what I'm missing here?
Thanks.
PctArray[PctArray.length] = new Object();
PctArray[PctArray.length].effdt = datefield.options[datefield.selectedIndex].value;
After the first assignment PctArray.length has increased so you are trying to address non-existing element. You may improve the code by combining your assignments without expllicit new Object():
PctArray.push(
{ effdt: datefield.options[datefield.selectedIndex].value
, pct: pctfield.value
})
Related
I try to compare the current line item index with the line number and see if they are the same with a new sales order. If the two numbers are the same then skip the validation otherwise check if they are the same item. However, it doesn't always return the line number which I wonder why.
Here are the two variables that I want to compare:
var linenum= nlapiGetCurrentLineItemValue('item','line');
var currentIndex = nlapiGetCurrentLineItemIndex('item');
linenum does return a number sometimes but most of the time it returns null; when that happened the comparison doesn't work. When I logged the variables, index always shows up correct. Is there any other parameter I can use to grab information from creating sales order page?
Any idea/suggestion would be appreciated!
var linenum= nlapiGetCurrentLineItemValue('item','line');
linenum will only have a value if the line was saved previously. If linenum is null it means the user is trying to add a new Line item and not edit.
I'm trying to run the following code on a spreadsheet. The column of names is the 4th column. I'm attempting to run through that list of names, pushing each new unique name to an array (listOfNames), and then add a new worksheet (NamesList), and finally add the array to cell A1 of the new worksheet. When I run the code below, all I get is a blank popup with an OK and Cancel button. When I view the log, it is blank as well. I'm quite new at this, and I feel like I'm missing something obvious... just not sure what it is. Am I misunderstanding something specific to GAS rather than JS?
var sheet = SpreadsheetApp.getActiveSheet();
var listOfNames = new Array ();
function copyNames() {
var data = sheet.getDataRange().getValues();
for (i=0; i<=sheet.getLastRow(); i++){
var tempName = sheet.getDataRange(i,4).getValue();
for (i=0; i<=listOfNames.length; i++){
if (tempName != listOfNames[i]){
listOfNames.push(tempName);
logger.log(listOfNames);
}
}
}
sheet.insertSheet(ListOfEDs);
sheet.getRange('a1').setValue(listOfEDs);
}
Edit: I'm starting to see that this will push values multiple times to the list... so maybe it's just back to the drawing board all together. I have found other code that would create a list of unique elements, but wasn't really sure how that code worked. I thought I'd try to figure it out myself so I'd at least understand it.
EDIT 2: Ok... I tried some new code, but I'm still getting a blank message box, and nothing on the log. I wasn't sure if having i be the iterator for a for loop within a for loop was a bad thing, so I switched it to j. Also, I know there's the remove duplicates example, and have been looking at that, but am unsure why one needs to use join.
function copyNames() {
var sheet = SpreadsheetApp.getActiveSheet();
var listOfNames = new Array ();
var data = sheet.getDataRange().getValues();
for (i=2; i<=data.length; i++){ //starting at 2 because first row is a header
var tempName = data[i][4];
for (j=0; j<=listOfNames.length+1; j++){
if (tempName != listOfNames[j]){
listOfNames.push(tempName);
logger.log(listOfNames);
}
}
}
sheet.insertSheet("ListOfNames");
sheet.getRange('a1').setValue(listOfNames);
}
As far as I understand you went help instead of a ready solution, so here you go.
First:
Try to avoid using global variables. Keep all your variables inside of your functions. Otherwise you will have issues when you add more functions to your spreadsheet. Your Code should start like this:
function copyNames() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var listOfNames = new Array ();
Second:
Try to decrease the amount of service calls to spreadsheet. it takes several seconds for your script to go to your sheet and take the values. Instead of doing it each time, take these values once and push them in to a variable.
In your case, you already did that, however did not use that variable and kept using service calls. Check this line:
var data = sheet.getDataRange().getValues();
Now all of the data on that sheet is in a variable called data.
sheet.getDataRange(i,4).getValue();
is the same as
data[i][4];
The only difference is that in the first case it will take approximately 2 seconds to get that value, while in the second case only a few milliseconds.
Same goes for
sheet.getLastRow();
Either call it once and push it into a variable and use that, or in your case just use
data.length;
Third:
listOfNames is an empty array, so it's length is 0.
This line
for (i=0; i<=listOfNames.length; i++)
will not even run, as both i and listOfNames.length is 0.
That is why you logger does not give any output. Your script never get's to that line.
Fourth:
You do not have a variable called ListOfEDs, therefore your last two rows of code just give an error. Your script does not know what is ListOfEDs as it doesn't exist.
Hope this helps.
I have some script that is calling AJAX information from a server and then displaying the information into blocks on the page. And every 8 seconds those blocks will fade to a new set of information.
The information from the server is stored in a fixed queue that pushes new items to it every 8 seconds.
And for each block I have it grab a random item from that array to show. The only thing is my blocks are getting a lot of duplicates.
Is there a way to check and see if that array item has been called from another block, and if so it will move on to find another item not in use.
var queue = FixedQueue( 50 );
$(document).ready(function() {
$('.submit').click(function(){
setInterval(function(){
queue.push(fulltweet);
},8000);
});
});
setInterval(function(){
randotime = intervals[Math.floor(Math.random()*intervals.length)];
$('.block1', '.photo1:nth-child(1)').queue(function(){
$(this).hide();
$(this).html(queue[0]);
$(this).fadeIn(2000);
$(this).delay(randotime);
$(this).dequeue();
});
$('.block1', '.photo1:nth-child(1)').fadeOut(2000);
},randotime);
I was creating a random number based on the length of the queue and using that to call queue[rando] but again, I keep getting duplicates in the blocks.
First, if you don't want duplicate items in your array, don't let them to be duplicate. Before inserting new items to your array, control whether it exists in your array or not. Using equality operation may not work if you use objects instead of primitive types(string, integer, etc..). Therefore you need a function checks if a given element exists in the array before insertion, and this function must use a equals function which compares two given objects.
Secondly, javascript allows you to add fields to objects in runtime. So when a block reaches and displays an object, you can put a field over this object. Let's say its name is 'inuse'.
When block A reaches the object:
object.inuse = true;
When block B reaches the same object randomly:
var object = pickRandomly();
while (object.inuse) {
object = pickRandomly();
}
// here's the unique object which is not used by another block.
I hope that helps.
If you can provide a sample code, I can provide a better answer.
I've been given two arrays, each of which has several objects within them. I'm trying to make it so that when a certain dropdown selection is made, it pushes that "flight information" into a "flight summary" div, but I'm having a hard time figuring out how to do it.
var possibleDepartureFlights=[{year:2012,month:11,day:13,hour:17,minute:37,price:137.38} and so on];
var possibleReturnFlights=[{year:2012,month:11,day:18,hour:21,minute:45,price:189.46} and so on];
Each var has 10 objects within the array, each of which has all those properties.
And as a bonus question, I've figured out how to hide a "submit" button when the return flight selected is earlier than the departure, but I can't figure out how to make the submit button come back when a different selection is made!
function displayDivs() {
var departureValue = $('#departureFlightsControl').val();
var returnValue = $('#returnFlightsControl').val();
if (departureValue != "default") {
$('.CumulativeSummary').addClass('totalAvailable');
$('.DepartureSummary').addClass('flightChosen');
}
if (returnValue != "default") {
$('.CumulativeSummary').addClass('totalAvailable');
$('.ReturnSummary').addClass('flightChosen');
}
if ($('#returnFlightsControl').val() < $('#departureFlightsControl').val()) {
$('.SubmitArea').hide();
}
Sorry if this question is vague! I'm new to jQuery and JavaScript, so I'm not really sure what I'm doing (and I'm not even really sure what to Google for to find the answer to my problem(s)). Please use small words, as if you're speaking to a child. Thanks!
Your question is really too broad, anyways... Suppose you have following
var possibleDepartureFlights=[
{year:2012,month:10,day:13,hour:10,minute:37,price:137.38},
{year:2012,month:11,day:15,hour:17,minute:47,price:150.50}
];
The possibleDepartureFlights is an array of two objects and the first element of the array is the first object and it's {year:2012,month:10,day:13,hour:10,minute:37,price:137.38} and it's index is 0 and the second element in your possibleDepartureFlights array is the second object and it's {year:2012,month:11,day:15,hour:17,minute:47,price:150.50} and it's index is 1. Now, if you want to access the month property of the first item of the array then you can write like
alert(possibleDepartureFlights[0].month); // this will alert 10
For the month of the second item/object in the array you can write
alert(possibleDepartureFlights[1].month); // this will alert 11
To loop through the array and print out the each property of every objects, you can try this
for(i=0;i<possibleDepartureFlights.length;i++)
{
console.log(possibleDepartureFlights[i].year);
console.log(possibleDepartureFlights[i].month);
console.log(possibleDepartureFlights[i].hour);
console.log(possibleDepartureFlights[i].minute);
console.log(possibleDepartureFlights[i].price);
}
An Example Here.
Remember, this is only a short example and there are more about arrays and objects in JavaScript. Also remember that you can loop an object with for in like for loop. Also this one could be helpful too.
OK, I'm missing something here and I just can't seem to find it because the logic seems correct to me, but I'm certain I'm not seeing the error.
var VisibleMarkers = function() {
var filtered = _.reject(Gmaps.map.markers, function(marker) {
return marker.grade != $('.mapDataGrade').val() && !_.contains(marker.subjects,$('.mapDataSubjects').val())
});
return filtered
}
I'm using underscore.js and jQuery to simplify my javascript work.
So right now, I'm checking by means of selects which data gets to be rejected and then I display the filtered markers on the (google) map (if it helps at all, this is using gmaps4rails which is working perfectly fine, its this bit of javascript that's making me lose the last of the hairs on my head).
Currently, the code functions 100% correctly for the ".mapDataGrade" select, but the ".mapDataSubjects" isn't. Now the markers object has a json array of the subjects (this is for students) and each item in the array has its ID. Its this ID that I am supposed to be checking.
Can someone see what I'm doing wrong?
If there's more info that needs to be included, please let me know.
This is on plain javascript on a RoR application using gmaps4rails
Now the markers object has a json array of the subjects (this is for students) and each item in the array has its ID. Its this ID that I am supposed to be checking.
_.contains compares a values, but it sounds like you want your iterator to compare a value to an object's "id" property. For that, _.some would work; it's like contains, except that, instead of comparing values, you can write the comparison as a function:
Returns true if any of the values in the list pass the iterator truth test.
Here's how you'd use it:
!_.some(marker.subjects, function(subject) {
return subject.id == $('.mapDataSubjects').val();
})
If I'm right, the whole line should be like this:
return marker.grade != $('.mapDataGrade').val() &&
// check that none of the subjects is a match
!_.some(marker.subjects, function(subject) {
// the current subject is a match if its ID matches the selected value
return subject.id == $('.mapDataSubjects').val();
});