JavaScript Json row undefined for TreeView - javascript

I have a question. When querying my Json object, although i have my Field as same name and all Json rows available give me an error that is undefined.
//e.g: row.DepParentId
Bellow is my code. Am I missing some tag?
function convert(rows) {
debugger;
function exists(rows, parent) {
for (var i = 0; i < rows.length; i++) {
if (rows[i].DepId === parent) return true;
}
return false;
}
var nodes = [];
// get the top level nodes
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
if (!exists(rows, row.DepParentId)) {
nodes.push({
id: row.DepId,
name: row.Title
});
}
}
var toDo = [];
for (var i = 0; i < nodes.length; i++) {
toDo.push(nodes[i]);
}
while (toDo.length) {
var node = toDo.shift();
// the parent node
// get the children nodes
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
if (row.DepParentId == node.Id) {
var child = {
Id: row.DepId,
Name: row.Title
};
if (node.options) {
node.options.push(child);
} else {
node.options = [child];
}
toDo.push(child);
}
}
}
return nodes;
}
My Json example for one row picked from Firefox
"{"DepId":7,"DepParentId":3,"Title":"OTT"}"
Thanks for helping
Joao

thanks all for helping, it's working now, the problem was the JSON.stringify() was returning only an [Object] so when you use JSON.parse() generates a sintax error.
function onLoaded() {
var itemsCount = items.get_count();
for (var i = 0; i < itemsCount; i++) {
var item = items.itemAt(i);
var dep = JSON.stringify(item.get_fieldValues());
deps.push(dep);
}
So, i had to change the format to be valid to parse like this
var dt = "[" + deps + "]";
var ret = JSON.parse(dt);
Thanks
Joao

Related

How to avoid "maximum call stack size exceeded" exception?

I have the next code for generating sitemap tree by urls list.
C# model:
public class Node
{
public Node(string child, string parent)
{
Child = child;
Parent = parent;
}
public string Parent { get; set; }
public string Child { get; set; }
public bool IsRoot { get; set; }
}
C# method that generates list of nodes.
private static List<Node> ExtractNode(List<string> Urls)
{
List<Node> nodeList = new List<Node>();
foreach (string itm in Urls)
{
string[] arr = itm.Split('/');
int index = -1;
foreach (string node in arr)
{
index += 1;
if (index == 0)
{
Node rootNode = new Node(node, "");
if (!nodeList.Exists(x => x.Child == rootNode.Child & x.Parent == rootNode.Parent))
{
rootNode.IsRoot = true;
nodeList.Add(rootNode);
}
}
else
{
Node childNode = new Node(node, arr[index - 1].ToString());
{
if (!nodeList.Exists(x => x.Child == childNode.Child & x.Parent == childNode.Parent))
{
nodeList.Add(childNode);
}
}
}
}
}
return nodeList;
}
Javascript code. Next function takes list of nodes:
function makeTree(nodes) {
var roots = [];
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].IsRoot) {
roots.push(nodes[i].Child);
}
}
var trees = "";
for (var j = 0; j < roots.length; j++) {
trees += "<div class='sitemapRoot'><ul><li>" + getChildren(roots[j], nodes) + "</li></ul></div>";
}
return trees;
}
And next one called recursively:
function getChildren(root, nodes) {
var result = "";
var index = 0;
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].Parent == root) {
index += 1;
}
}
if (index > 0) {
var RootHeader = "";
for (var j = 0; j < nodes.length; j++) {
if (nodes[j].IsRoot & root == nodes[j].Child) {
RootHeader = nodes[j].Child;
}
}
result += RootHeader + "<ul>\n";
for (var k = 0; k < nodes.length; k++) {
if (nodes[k].IsRoot & root == nodes[k].Child) {
RootHeader = nodes[k].Child;
}
if (nodes[k].Parent == root) {
result += "<ul><li>" + nodes[k].Child + getChildren(nodes[k].Child, nodes) + "</li></ul>\n";
}
}
result += "</ul>\n";
return result;
}
return "";
}
This code works good for a small set of data. But when I try to pass list of 500 nodes I get next error:
Uncaught RangeError: Maximum call stack size exceeded
at getChildren (treeGenerator.js:371)
So, the question is how I can optimize code to avoid this error?
There are two ways that you can fix this issue. You always have to worry about the call stack size when you use recursive functions. If you believe it is an issue, then you need to go asynchronous or refactor to not be recursive. These aren't necessarily the most optimized answers but hopefully they'll get you started.
Non-Recursive function
function makeTree(nodes) {
var roots = [],
limbs = [],
i, j;
//go through all of the nodes and link the parent/children.
for (i = 0; i < nodes.length; i++) {
for (j = i + 1; j < nodes.length; j++) {//only look at the rest of the elements to increase performance
if (nodes[i].Child == nodes[j].Parent) {
nodes[i].children = (nodes[i].children || []);
nodes[i].children.push(nodes[j]);
nodes[j].parentNode = nodes[i];
}
}
for (j = 0; j < limbs.length; j++) {//look through the limbs to see if one of them is my child.
if (nodes[i].Child == limbs[j].Parent) {
nodes[i].children = (nodes[i].children || []);
nodes[i].children.push(limbs[j]);
limbs[j].parentNode = nodes[i];
limbs.splice(j--, 1);//remove from the list since I can only have 1 parent.
}
}
//I have all of my children.
if (nodes[i].IsRoot) {
roots.push(nodes[i]);
}else if(!nodes[i].parentNode){
//I don't know my parent so I'm a limb.
limbs.push(node);
}
}
//now that everyone knows their parent and their children, we'll assemble the html by looking at all of the leafs first and working way up the tree.
i = 0;
while(nodes.length > 0){
if(!nodes[i].children || nodes[i].childHtml){
//I'm either a leaf or I have my child's html.
var node = nodes[i];
node.html = node.Child + (node.childHtml? "<ul>" + node.childHtml + "</ul>" : "");
node.childHtml = null;//don't need this anymore.
if(node.parentNode){
//let's check to see if my siblings are complete
var ready = true,
childHtml = "";
for(var j = 0; j < node.parentNode.children.length; j++){
if(node.parentNode.children[j].html == null){
ready = false;//I don't know this html yet so skip it for now.
break;
}else{
childHtml += "<li>" + node.parentNode.children[j].html + "</li>";//go ahead and try to create the list of children.
}
}
if(ready){
//all of siblings are complete, so update parent.
node.parentNode.childHtml = childHtml;
node.parentNode.children = null;//remove reference for cleanup.
}
}
nodes.splice(i, 1);//remove from the list since I have my html.
}else{
i++;//look at the next node in the list.
}
if(i >= nodes.length){
i = 0;//since we are splicing and going through the list multiple times (possibly), we'll set the index back to 0.
}
}
//every node knows it's html, so build the full tree.
var trees = "";
for (var j = 0; j < roots.length; j++) {
trees += "<div class='sitemapRoot'><ul><li>" + roots[j].html + "</li></ul></div>";
}
return trees;
}
Asynchronous Recursive function
function makeTreeAsync(nodes, callback) {
var roots = [],
numRoots = 0;
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].IsRoot) {
numRoots++;
getChildrenAsync(nodes[i], nodes, create);
}
}
function create(child){
roots.push(child);
if(roots.length === numRoots){
var trees = "";
for (var j = 0; j < roots.length; j++) {
trees += "<div class='sitemapRoot'><ul><li>" + roots[j].html + "</li></ul></div>";
}
callback(trees);
}
}
}
function getChildrenAsync(root, nodes, callback) {
var result = "";
var index = 0;
var children = [];
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].Parent == root.Child) {
index += 1;
getChild(i);
}
}
if (index == 0) {
root.html = root.Child;
callback(root);
}
function getChild(x){
setTimeout(function(){
getChildrenAsync(nodes[x], nodes, createHtml);
});
}
function createHtml(node){
children.push(node);
if(children.length === index){
var result = root.Child;
if(children.length){
result += "<ul>"
for (var j = 0; j < children.length; j++) {
result += "<li>" + children[j].html + "</li>";
}
result += "</ul>";
}
root.html = result;
callback(root);
}
}
}
I used the following to create trees for testing the code:
function makeTestNodes(numRoots, numChildrenPerRoot){
var nodes= [];
for(var i = 0;i < numRoots;i++){
nodes.push({
Parent: "",
Child: i.toString(),
IsRoot: 1
});
var parent = i.toString();
for(var j = 0;j < numChildrenPerRoot;j++){
var child = parent + "." + j.toString();
nodes.push({
Parent: parent,
Child: child,
IsRoot: 0
});
nodes.push({
Parent: parent,
Child: parent + "." + j.toString() + "a",
IsRoot: 0
});
parent = child;
}
}
return nodes;
}
Use the following snippet to call the two functions with the test nodes:
Note: the following uses jquery to get the body node. I called the following snippet when the page was ready.
var body = $("body");
body.append(makeTree(makeTestNodes(20, 50)));
makeTreeAsync(makeTestNodes(20, 50), function(html){
body.append(html);
});

Protractor:How to store values in array and then to do sorting

I need to sort list strings under the table ,so for that i have written following lines of code but on console i am not getting any values:
var j = 9;
var rows = element.all(by.repeater('row in renderedRows'));
var column = element.all(by.repeater('col in renderedColumns'));
expect(rows.count()).toEqual(5); //here its printing number of rows
expect(column.count()).toEqual(5); //here its printing number of columns
var arr = [rows.count()];
for (var i = 0; i < rows.count(); i++) {
console.log("aai" + i);
if (i = 0) {
//var columnvalue=column.get(9).getText();
var columnvalue = column.get(9).getText().then(function(ss) {
return ss.trim();
arr[i] = ss.trim(); //here it will save the value first value of column
console.log("value1" + arr[i]);
expect(arr[i]).toEqual('DN');
console.log("aa" + ss.trim());
});
} else {
var j = j + 8;
var columnvalue = column.get(j).getText().then(function(ss) {
return ss.trim();
arr[i] = ss.trim(); //here it will save the other values of column
console.log("value" + arr[i]);
expect(arr[i]).toEqual('DN');
console.log("ab" + ss.trim());
});
}
}
Sorting_Under_Table: function(col){
test = [];
var m;
var dm = 0;
element(by.xpath('//div[#class="ngHeaderScroller"]/div['+col+']')).click();
element.all(by.repeater('row in renderedRows')).then(function(row) {
m = row.length;
for (i = 1; i <= row.length; i++)
{
user_admin_table_name = browser.driver.findElement(by.xpath('//div[#class="ngCanvas"]/div['+i+']/div['+col+']'));
user_admin_table_name.getText().then(function(text) {
var test_var1 = text.toLowerCase().trim();
test.push(test_var1);
var k = test.length
if (k == m){
for (j = 0; j < test.length; j++){
test.sort();
d=j+1;
user_admin_table_name1 = browser.driver.findElement(by.xpath('//div[#class="ngCanvas"]/div['+d+']/div['+col+']'));
user_admin_table_name1.getText().then(function(text1) {
var test_var2 = text1.toLowerCase().trim();
if (test_var2 == test[dm]){
expect(test_var2).toEqual(test[dm]);
dm = dm +1;
}else {
expect(test_var2).toEqual(test[dm]);
log.error("Sorting is not successful");
dm = dm +1;
}
});
}
}
});
}
});
},
You can use this code for sorting and verifying is it sorted or not
I'm not sure how your above example is doing any sorting, but here's a general solution for trimming and then sorting:
var elementsWithTextToSort = element.all(by.xyz...);
elementsWithTextToSort.map(function(elem) {
return elem.getText().then(function(text) {
return text.trim();
});
}).then(function(trimmedTexts) {
return trimmedTexts.sort();
}).then(function(sortedTrimmedTexts) {
//do something with the sorted trimmed texts
});

Populate form from JSON.parse

I am trying to re-populate a form from some values in localStorage. I can't quite manage the last part to get the loop to populate my name and values.
function loadFromLocalStorage() {
PROCESS_SAVE = true;
var store = localStorage.getItem(STORE_KEY);
var jsn = JSON.parse(store);
console.log(jsn);
if(store.length === 0) {
return false;
}
var s = jsn.length-1;
console.log(s);
for (var i = 0; i < s.length; i++) {
var formInput = s[i];
console.log(s[i]);
$("form input[name='" + formInput.name +"']").val(formInput.value);
}
}
Could I get some pointers please.
Your issue is in this section of code.
var s = jsn.length-1;
console.log(s);
for (var i = 0; i < s.length; i++) {
You are setting s to the length of the jsn array minus 1, then using it as if it were jsn. I think you intended something like this.
function loadFromLocalStorage() {
PROCESS_SAVE = true;
var store = localStorage.getItem(STORE_KEY);
var jsn = JSON.parse(store);
console.log(jsn);
if(store.length === 0) {
return false;
}
for (var i = 0; i < jsn.length; i++) {
var formInput = jsn[i];
console.log(jsn[i]);
$("form input[name='" + formInput.name +"']").val(formInput.value);
}
}

How to filter elements in array in JavaScript object

If I have a JavaScript object like this:
{"products":
[
{
"id":"6066157707315577",
"reference_prefix":"BB",
"name":"BeanieBaby",
"product_line":false,
"has_ideas":true
},
{
"id":"6066197229601550",
"reference_prefix":"BBAGS",
"name":"BlackBags",
"product_line":false,
"has_ideas":false
}
],
"pagination": {
"total_records":4,
"total_pages":1,
"current_page":1
}
}
How do I write a function in js to loop over each pair and only return the elements of the array where has_ideas === true?
I have started with this but I'm stuck. Clearly I am new to this. Any help appreciated.
product: function(mybundle) {
var json = JSON.parse(mybundle.response.content);
for(var i = 0; i < json.length; i++) {
var obj = json[i];
if (json[i].id === "has_ideas" && json[i].value === true) {
return json;
}
return [];
}
}
You can filter out each pair by simply checking that property:
var json = {"products":[{"id":"6066157707315577","reference_prefix":"BB","name":"BeanieBaby","product_line":false,"has_ideas":true},{"id":"6066197229601550","reference_prefix":"BBAGS","name":"BlackBags","product_line":false,"has_ideas":false}],"pagination":{"total_records":4,"total_pages":1,"current_page":1}}
var stuff = json.products.filter(function(obj) {
return obj.has_ideas === true
});
console.log(stuff);
Demo:http://jsfiddle.net/bsyk18cb/
try this
product: function(mybundle) {
var json = JSON.parse(mybundle.response.content);
for(var i = 0; i < json.length; i++) {
if(json[i].has_ideas === true){
return json;
}
return [];
}
}
You want to check the "has_ideas" attribute and if true, return the id.
product: function(mybundle) {
var json = JSON.parse(mybundle.response.content);
for(var i = 0; i < json.length; i++) {
if (json[i].has_ideas === true) {
return json[i].id;
}
return [];
}
}
Use code below.
this will return array of elements having has_ideas=true
var json = "{'products':"+
"["+
"{"+
"'id':'6066157707315577',"+
"'reference_prefix':'BB',"+
"'name':'BeanieBaby',"+
"'product_line':false,"+
"'has_ideas':true"+
"},"+
"{"+
"'id':'6066197229601550',"+
"'reference_prefix':'BBAGS',"+
"'name':'BlackBags',"+
"'product_line':false,"+
"'has_ideas':false"+
"}"+
"],"+
"'pagination': {"+
"'total_records':4,"+
"'total_pages':1,"+
"'current_page':1"+
"}"+
"}";
function filter(){
var jsonArr = [];
var gList = eval( "(" + json + ")");
alert(gList.products.length);
for(var i=0;i<gList.products.length;i++){
if(gList.products[i].has_ideas){
jsonArr.push(gList.products[i]);
}
}
return jsonArr;
}
Demo

trying to create an array of arrays for return JSON

Im currently working on this script that is written in javascript that returns data from the netsuite ERP platform.
Right now we have the code returning in an array, whilst this is good, it is a result of a dataset of product information.
The script is querying for 3 products, and as a result it returns an array of 21 keys.
this should be returning 3 arrays of arrays so we can handle the content easily externally to Netsuite.
I for the life of me cant figure out which loop I am required to create a new array to manage the content.
function loadRecord(request, response)
{
var recType = request.getParameter('recType');
var savedSearchId = request.getParameter('savedSearchId');
var internalid = request.getParameter('internalid');
//perform the required search.
var filter = [];
if(recType == 'customer' || recType == 'contact' )
{
filter[0] = new nlobjSearchFilter('internalid', null, 'is', internalid); // just get the 1 item by the internal id of the record
}
if( recType == 'item')
{
var internal_ids = new Array();
internal_ids[0] = 25880;
internal_ids[1] = 25980;
internal_ids[2] = 333 ;
filter[0] = new nlobjSearchFilter('internalid', null, 'anyOf', internal_ids); // just get the 1 item by the internal id of the record
}
if(recType == 'transaction')
{
filter[0] = new nlobjSearchFilter('type',null,'anyOf','SalesOrd');
filter[1] = new nlobjSearchFilter('internalid','customer','is', internalid );
}
var rsResults = nlapiSearchRecord(recType, savedSearchId, filter);
var rsObj = [];
// not sure how to make each row a new array of arrays so it is structured more elegantly...
for (x = 0; x < rsResults.length; x++)
{
var flds = rsResults[x].getAllColumns();
for (i = 0; i < flds.length; i++)
{
var rowObj = {};
rowObj.name = flds[i].getName();
rowObj.label = flds[i].getLabel();
rowObj.val = rsResults[x].getValue(flds[i].getName(), flds[i].getJoin(), flds[i].getSummary());
rowObj.txtval = rsResults[x].getText(flds[i].getName(), flds[i].getJoin(), flds[i].getSummary())
rsObj.push(rowObj);
}
}
response.write(JSON.stringify(rsObj));
}
Any help greatly appreciated
Is this what you're looking for?
var rsObj = [];
var rowArr, fields, x, i;
for (x = 0; x < rsResults.length; x++)
{
flds = rsResults[x].getAllColumns();
for (i = 0; i < flds.length; i++)
{
rowArr = rsObj[x] = [];
rowArr.push(flds[i].getName());
rowArr.push(flds[i].getLabel());
rowArr.push(rsResults[x].getValue(flds[i].getName(), flds[i].getJoin(), flds[i].getSummary()));
rowArr.push(rsResults[x].getText(flds[i].getName(), flds[i].getJoin(), flds[i].getSummary()));
}
}
console.log(rsObj[0][0]); // row0.name
console.log(rsObj[2][1]); // row2.label
Maybe something like this:
for (var x = 0; x < rsResults.length; x++)
{
var flds = rsResults[x].getAllColumns();
for (var i = 0; i < flds.length; i++)
{
rsObj.push({
name: flds[i].getName(),
label: flds[i].getLabel(),
val: rsResults[x].getValue(flds[i].getName(), flds[i].getJoin(), flds[i].getSummary()),
txtval: rsResults[x].getText(flds[i].getName(), flds[i].getJoin(), flds[i].getSummary())
});
}
}
If you are using ECMAScript5, you cold simplify the loop with forEach, like this:
rsResults.forEach(function(result) {
result.getAllColumns().forEach(function(fields) {
rsObj.push({
name: fields.getName(),
label: fields.getLabel(),
val: result.getValue(fields.getName(), fields.getJoin(), fields.getSummary()),
txtval: result.getText(fields.getName(), fields.getJoin(), fields.getSummary())
});
});
});
This must solve you problem. Some declaration problem might be there.
var rsObj = [];
for (int x = 0; x < rsResults.length; x++)
{
var flds = rsResults[x].getAllColumns();
for (int i = 0; i < flds.length; i++)
{
var rowObj = [];
rowObj.push(flds[i].getName());
rowObj.push(flds[i].getLabel());
rowObj.push(rsResults[x].getValue(flds[i].getName(), flds[i].getJoin(), flds[i].getSummary()));
rowObj.push(rsResults[x].getText(flds[i].getName(), flds[i].getJoin(), flds[i].getSummary()));
rsObj.push(rowObj);
}
}

Categories

Resources