Google Sites Listitem - javascript

I am working with the google sites list item.
The classes are Here and Here
I have been able to iterate through the columns and put all of the column headers in to one array with the following code.
//Global
var page = getPageByUrl(enter URL here)
var name = page.getName();
function getInfo() {
var columns = page.getColumns();
//Get Column Names
for (var j in columns) {
var cName =columns[j].getName();
columnList.push(cName);
}
}
Now I want to be able to get each row of the listitem and put it in its own array.
I can add the variable
function getInfo() {
var columns = page.getColumns();
var listItems = page.getListItems();//new variable
//Get Column Names
for (var j in columns) {
var cName =columns[j].getName();
columnList.push(cName);
}
}
Now that I have the variable the output is [ListItem, ListItem, ListItem, ListItem]
So I can use a .length and get a return of 4.
So now I know I have 4 rows of data so based on my wants I need 4 arrays.
Small interjection here, Not a coder by trade but code as a precursor to wants becoming needs.
A buddy of mine who is a JS coder by trade showed me this code which does work. With the logger added by me.
for (var i in listItems) {
if (listItems.hasOwnProperty(i)) {
item = listItems[i];
for (var x = 0; x < columnList.length; x++) {
attrib = item.getValueByName(columnList[x]);
Logger.log("Logging value of get list page get value by name = " + columnList[x] + " " + attrib);
}
}
}
Which brings the total code to
var name = page.getName();
var listItems = page.getListItems();
var listCount = listItems.length
var listList = [];
var columns = page.getColumns();
var name = columns[0].getName();
var item, attrib = 0;
var columnList = [];
Logger.log(listItems);
Logger.log(name + " was last updated " + page.getLastUpdated());
Logger.log(name + " was last edited " + page.getLastEdited());
var listCount = 0;
//Get Column Names
for (var j in columns) {
var cName =columns[j].getName();
columnList.push(cName);
}
Logger.log(columnList);
// Get index of Due Date
var dueDateValue = columnList.indexOf("Due Date");
Logger.log("The index of due date is " + dueDateValue);
for (var i in listItems) {
if (listItems.hasOwnProperty(i)) {
item = listItems[i];
for (var x = 0; x < columnList.length; x++) {
attrib = item.getValueByName(columnList[x]);
Logger.log("Logging value of get list page get value by name = " + columnList[x] + " " + attrib);
}
}
}
}`
Forgive the above code as it has been a bit of a sketch pad trying to work this out.
I am a bit behind on understanding what is happening here
for (var i in items) { // This is for each item in the items array
if (items.hasOwnProperty(i)) {
if items is an array, how can we use has own property? Doesn't that belong to an object? Does an array become an object?
My questions are two category fold.
Category # 1
What is happening with the hasOwnProperty?
-Does the array become an object and thus can be passed to .hasOwnProperty value
Category # 2
Is this the only way to take the values from the listitem and populate an array
- If it is, is there some way to delimit so I can pass each row into it's own array
- If it isn't , why does it work with the hasOwnProperty and why doesn't it work without it in the example below
for (var i in listItems) {
for (var y = 0; y < columnList.length; y++) {
item = listItems[i];
listList = item.getValueByName(columnList[x]);
Logger.log("Logging my version of list naming " + listList);
}
In which I get a "Invalid argument: name (line 41" response. Highlighting the
listList = item.getValueByName(columnList[x]);
Not looking for a handout but I am looking to understand the hasOwnPropertyValue further.
My current understanding is that hasOwnValue has to do with prototyping ( vague understanding ) which doesn't seem to be the case in this instance
and it has to depend on a object which I described by confusion earlier.
To clarify my want:
I would like to have each row of listitems in its own array so I can compare an index value and sort by date as my current column headers are
["Project", "Start Date" , "End Date"]
Any and all help is much appreciated for this JS beginner of 2 weeks.

An array can be inside of an object as the value of a member:
{"myFirstArray":"[one,two,blue]"}
The above object has one member, a name/value pair, where the value of the member is an array.
Here is a link to a website that explains JSON.
Link To JSON.org
JSON explained by Mozilla
There are websites that will test the validity of an object:
Link to JSONLint.com
An array has elements, and elements in an array can be other arrays. So, there can be arrays inside of arrays.
.hasOwnProperty returns either true or false.
Documentation hasOwnProperty
Interestingly, I can use the hasOwnProperty method in Apps Script on an array, without an error being produced:
function testHasProp() {
var anArrayTest = [];
anArrayTest = ['one', 'two', 'blue'];
Logger.log(anArrayTest);
var whatIsTheResult = anArrayTest.hasOwnProperty('one');
Logger.log(whatIsTheResult);
Logger.log(anArrayTest);
}
The result will always be false. Using the hasOwnProperty method on an array doesn't change the array to an object, and it's an incorrect way of using Javascript which is returning false.
You could put your list values an object instead of an array. An advantage to an object is being able to reference a value by it's property name regardless of where the property is indexed. With an array, you need to know what the index number is to retrieve a specific element.
Here is a post that deals with adding properties to an object in JavaScript:
StackOverflow Link
You can either use dot notation:
objName.newProperty = 'newvalue';
or brackets
objName["newProperty"] = 'newvalue';
To add a new name/value pair (property) to an object.

Related

Updating the value of an object inside a loop using javascript

I'm currently facing a difficulty in my codes.
First i have an array of objects like this [{Id:1, Name:"AML", allowedToView:"1,2"}, {Id:2, Name:"Res", allowedToView:"1"}...] which came from my service
I assign it in variable $scope.listofResource
Then inside of one of my objects I have that allowedToView key which is a collection of Id's of users that I separate by comma.
Then I have this code...
Javascript
$scope.listofResource = msg.data
for (var i = 0; i < msg.data.length; i++) {
First I run a for loop so I can separate the Id's of every user in allowedToView key
var allowed = msg.data[i].allowedToView.split(",");
var x = [];
Then I create a variable x so I can push a new object to it with a keys of allowedId that basically the Id of the users and resId which is the Id of the resource
for (var a = 0; a < allowed.length; a++) {
x.push({ allowedId: allowed[a], resId: msg.data[i].Id });
}
Then I put it in Promise.all because I have to get the Name of that "allowed users" base on their Id's using a service
Promise.all(x.map(function (prop) {
var d = {
allowedId: parseInt(prop.allowedId)
}
return ResourceService.getAllowedUsers(d).then(function (msg1) {
msg1.data[0].resId = prop.resId;
Here it returns the Id and Name of the allowed user. I have to insert the resId so it can pass to the return object and it will be displayed in .then() below
return msg1.data[0]
});
})).then(function (result) {
I got the result that I want but here is now my problem
angular.forEach(result, function (val) {
angular.forEach($scope.listofResource, function (vv) {
vv.allowedToView1 = [];
if (val.resId === vv.Id) {
vv.allowedToView1.push(val);
I want to update $scope.listofResource.allowedToView1 which should hold an array of objects and it is basically the info of the allowed users. But whenever I push a value here vv.allowedToView1.push(val); It always updates the last object of the array.
}
})
})
});
}
So the result of my code is always like this
[{Id:1, Name:"AML", allowedToView:"1,2", allowedToView:[]}, {Id:2, Name:"Res", allowedToView:"1", allowedToView:[{Id:1, Name:" John Doe"}]}...]
The first result is always blank. Can anyone help me?
Here is the plunker of it... Plunkr
Link to the solution - Plunkr
for (var i = 0; i < msg.length; i++) {
var allowed = msg[i].allowedToView.split(",");
msg[i].allowedToView1 = [];
var x = [];
Like Aleksey Solovey correctly pointed out, the initialization of the allowedToView1 array is happening at the wrong place. It should be shifted to a place where it is called once for the msg. I've shifted it to after allowedToView.split in the first loop as that seemed a appropriate location to initialize it.

Javascript code saving data to 2d array throws undefined

I'm writing a script that takes values from a html table, indexes them in aray and then assign every value to a tag in a form.Codepen https://codepen.io/anon/pen/eVLKyB
My problem is that after taking all specified values from array I get
Code responsible for indexing values from table look like this:
function size_index(){
var table = document.getElementsByClassName("product_table_cus");
var index= [[],[]];
var i_index = 0;
var iter = 0; //index of first dim of array
var len = table[0].rows.length;
console.log("Len:"+len);
while(i_index<len) {
//iterate trough rows
console.log("second for, iter:"+ i_index);
var col_inner = table[0].rows[i_index].cells[0].innerHTML; //size param
var col_param = table[0].rows[i_index].cells[1].innerHTML;//size value
var col_size = col_inner.substr(col_inner.indexOf(' ')+1);
console.log("Rozmiar:"+ col_size+" Wartość:"+col_param);
// index[1][0].push("col_size");
// index[i_index][1].push(col_param);
if(col_inner.search("Rozmiar")!==-1)
{
console.log("Inner wtf:"+col_inner+"Ite:"+iter);
index[iter].push(col_inner,col_param);
console.log("Index+:"+index[iter]);
console.log("Ind:"+col_inner+"Val:"+col_param);
}
else if(col_inner.search("Rozmiar")==-1){
}
iter++;
// col_param=0;
// col_size=0;
//iterate through columns
//columns would be accessed using the "col" variable assigned in the for loop
//rows would be accessed using the "row" variable assigned in the for loop
i_index++;
}
return index;
}
You can see it in the console log:
This line of code
console.log("Inner wtf:"+col_inner+"Ite:"+iter);
Produces this output
Inner wtf:Rozmiar XXLIte:2
Your index variable has exactly two values in it.
So of course, if iter is a value greater than one, this line will cause an error:
index[iter].push(col_inner,col_param);
There are two elements in index, so index[2] will return undefined.
Your underlying problem is that [[][]] is not a two dimensional array. It is an array containing two arrays.
A safer way to do this is:
var index= [];
Then, to add an element:
index[iter] = index[iter] || [];
index[iter].push(...);

How to check if data being added to an array already exists in a different array?

I am looking to create a simple script for a Google sheet in which array 1 will already be populated with a list of names. As a new name gets added to array 2, array 1 is checked for the name. If the name which was entered into array 2 is present in array 1 an action will be performed. This search function must take place each time a new name is added to array 2 to determine if it exists in array 1.
function findPlayer() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var picksRange = ss.getRange("B2:M15");
var poolRange = ss.getRange("B21:G96");
var picksPlayerName = picksRange.getValues();
var poolPlayerName = poolRange.getValues();
for (var i = 0; i < picksRange.length; i++)
for (var j = 0; j < poolRange.lenth; j++)
if (picksPlayerName[i] == poolPlayerName[j]) {
poolPlayerName[i].setBackground("red")}
else {
poolPlayerName[j].setBackground("blue");}
}
This is not a complete answer, nor does it perfectly fit your use-case, but you should be able to take it from here, or perhaps come back with another question when you have a question about a specific part of your code.
const existingNames = ["Carl", "Emma", "Sarah", "Ahmad"];
const newNames = ["Emma", "Sarah", "Isa", "Igor", "Kent"];
// go through the new names and check against existing ones
newNames.forEach(newName => {
if(existingNames.includes(newName)) {
// handle duplicates: do nothing?
} else {
// handle new names: maybe add them to the existing names?
existingNames.push(newName);
}
});
console.log('After going through all new names, the complete list of known names are: ' + existingNames);
Demo where you can play with the code and learn: https://jsfiddle.net/jonahe/11uom4cu/

Iterating over and comparing properties of two arrays of objects

I have set up a HBS helper which takes in two arrays of objects (users privileges). What I want to do is compare them and inject back into the template the privileges the user does and doesn't have.
Presently I can compare the names of the privileges with the following code:
hbs.registerHelper('selected', function(option, value){
var i;
var j;
var privName;
var userPriv;
var privObj = new Object();
var privArray = [];
for(i in option){
console.log('each ' + JSON.stringify(option[i]));
privName = option[i].privname;
for (y in value){
if(privName == value[y].privname){
userPriv = value[y].privname;
console.log('user has the following privileges', value[y].privname);
privObj = new Object();
privObj.name = userpriv;
privObj.id = value[y]._id;
privObj.state = 'selected';
privArray.push(privObj);
} else if (privName != value[y].privname){
console.log('user doesnt have priv ', privName);
privObj = new Object();
privObj.name = option[i].privname;
privObj.id = option[i].id;
privObj.state = '';
privArray.push(privObj);
}
}
}
console.log('privileges array ', privArray);
return privArray;
});
This works OK when the user only has one privilege, however when the user has more than one, for example two privileges, it returns the privileges twice. If the user has 3, thrice and so on. I know this is because the array is looping again because their are 2, 3 etc in the .length. However I can't seem to find an adequate solution.
Any help?
P.S. it would be nice if the Array.includes() method allowed you to search object properties.
The problem creating new objects the way you did is that for each property you add to your privilege-entity you will have to return to that function and set that property as well. You can instead just add/alter the state property of the existing objects:
hbs.registerHelper('selected', function(option, value) {
var names = option.map(function(opt) {
return opt.privname;
});
value.forEach(function(val) {
val.state = names.indexOf(val.privname) >= 0 ? 'selected' : '';
});
return value;
});
Basically:
The variable names is being mapped to be an array only with the privnames. You can check by using console.log(names).
The Array.forEach() function is helpful in this case because you just need to iterate over each object inside value and set its state-property.
To check if the privname exists, you just need to check the index in the previous names-mapped-array. For such a simple thing I used ternary operator (?:).
Finally, you return value, which is the array containing the objects you had updated.

Javascript - clearing duplicates from an array object

Hi
I have a javascript array object rapresenting the amount of items sold in a given country, like this:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item2', 'c3':110}]
I need to avoid duplicates (as you may see, the last two 'records' have the same Country and the same Item) and sum the amounts; if I was getting data from a database I would use the DISTINCT SUM clause, but what about it in this scenario? Is there any good jquery trick?
You could use an object as a map of distinct values, like this:
var distincts, index, sum, entry, key;
distincts = {};
sum = 0;
for (index = 0; index < data.length; ++index) {
entry = data[index];
key = entry.c1 + "--sep--" + entry.c2;
if (!distincts[key]) {
distincts[key] = true;
sum += entry.c3;
}
}
How that works: JavaScript objects are maps, and since access to properties is an extremely common operation, a decent JavaScript implementation tries to make property access quite fast (by using hashing on property keys, that sort of thing). You can access object properties using a string for their name, by using brackets ([]), so obj.foo and obj["foo"] both refer to the foo property of obj.
And so:
We start with an object with no properties.
As we loop through the array, we create unique key from c1 and c2. It's important that the "--sep--" string be something that cannot appear in c1 or c2. If case isn't significant, you might throw a .toLowerCase in there.
If distincts already has a value for that key, we know we've seen it before and we can ignore it; otherwise, we add a value (true in this case, but it can be just about anything other than false, undefined, 0, or "") as a flag indicating we've seen this unique combination before. And we add c3 to the sum.
But as someone pointed out, your last two entries aren't actually the same; I'm guessing that was just a typo in the question...
jQuery may have an array function for this, but because your two Italy objects are not distinctly unique, your asking for a custom solution. You want to populate a array and check it for duplicates as you go:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item1', 'c3':110}]
var newArray = [];
var dupeCheck = {}; // hash map
for(var i=0; i < data.length; i++){
if(!dupeCheck[data[i].c1]){
newArray.push(data[i]);
dupeCheck[data[i].c1] = true;
}
}
test
HTML:
<div id="test"></div>
JS:
var data = [{'c1':'USA', 'c2':'Item1', 'c3':100},
{'c1':'Canada', 'c2':'Item1', 'c3':120},
{'c1':'Italy', 'c2':'Item2', 'c3':140},
{'c1':'Italy', 'c2':'Item1', 'c3':110}];
var
l = data.length, // length
f = "", // find
ix = "", // index
d = []; // delete
for (var i = 0; i < l; i++) {
ix = data[i].c1 + "_" + data[i].c2 + "__";
//var re = new RegExp(ix);
//if (re.test(f))
if (f.indexOf(ix) != -1)
d.push(i);
else
f += ix;
}
for (var i1 = 0; i1 < d.length; i1++){
$("#test").append("<div>for delete: "+d[i1]+"</div>");
}
EDIT
Although chrome works much faster, works only in chrome faster the example with indexOf, then in IE/Opera/Firefox/Safary works faster with an object.
The code created by "# TJ Crowder" is much more efficient.

Categories

Resources