Question

Can this tree be constructed faster in JS?

I have WebSQL DB table structure: ID, ParentId, MasterId, [some other fields that are not relevant]

First 20 records are being read and shown to client immediately. then Ids of these records are asynchronously passed to construct object that is global to the page (not my decision, just go along) lets call it PageObj. This object contains 'datasources' that contain tree structure of objects. Example: PageObj.bcAccount[42].Children[0].Children[0]... bcAccount[42] would be holder of MasterId for all the children.

To avoid reading DB layer by layer all records are being selected from WebSQL DB by MasterId like:

SELECT * FROM TableName
WHERE TableName.MasterId IN ([list of ids])

I get records in callback function with structure like this:

     results { rows : { item : function(i), length : 100 } } 

to read value one would do

    results.rows.item(i)[DBColumnName];

rows have length property so I can loop thorough records, but item can be accessed only by calling results.rows.item(i).

Children can belong to more than one parent. At the moment I call ComposeRecordsToTreeStructure concurrently for each layer of children because to bolt them to PageObj parents of child objects have to be present, so one concurrent call per tree layer.

I know I can simply change structure by reiterating all items into list and then simply $.grep children, but lets not do that.

QUESTION: Is there a way of optimising this mechanism to not go layer by layer, (or layer by layer but faster) that would result in faster tree construction? I have no knowledge of position of records in tree just Id, ParentId and MasterId. Expected tree depth can go up to 20 levels, width can be up to 1000 records.

Currently used mechanism is below.

function ComposeRecordsToTreeStructure(results, tableArray, columnArray, options)
{
     if (results.rows.length > 0) {
     if (options.parentLayerIdList == undefined){
            options.parentLayerIdList = options.masterIdList;
        }

         var childRecordIdArray = [];
         var isThereNextLayer = false;
         for(var i = 0; i < options.parentLayerIdList.length; i++)
            {
                for(var ii = 0; ii < results.rows.length; ii++)
                {
                    if(options.parentLayerIdList[i] == results.rows.item(ii)[options.parentIdColumn]) 
                    {
                        var childRecord = AttachChildRecordsToParents(results.rows.item(ii), options.parentLayerIdList[i], options.knockoutContextName)
                        childRecordIdArray.push(childRecord.Fields['Id']);
                        if (isThereNextLayer == false){
                            for(var iii = 0; iii < results.rows.length; iii++){
                                if (childRecord.Fields['Id'] == results.rows.item(iii)[options.parentIdColumn])
                                {
                                    isThereNextLayer = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

    if (isThereNextLayer)
    {
        options.parentLayerIdList = childRecordIdArray;
        ComposeRecordsToTreeStructure(results, tableArray, columnArray, options);
    }
}

function AttachChildRecordsToParents(recordRow, id, knockoutContextName)
{
    var childTreeOptions = {id : id, knockoutContextName : knockoutContextName, results: []};
            findObjectsInChildTreeById(childTreeOptions);
            if (childTreeOptions.results.length > 0) {
                       var childRecord = AttachChildRecord(recordRow, childTreeOptions.results);
                }

    return childRecord;
}

function ComposeChildObject(recordRow)
{
        var recordObject = { Fields: {}, SetFields: [], Insert: false };
        for (var field in recordRow) {
                recordObject.Fields[field] = field === "Id" && recordRow.PrimaryRowId ? recordRow.PrimaryRowId : recordRow[field];
            }

        return recordObject;
}

function AttachChildRecord(recordRow, pageObjParentResults)
{
     var recordObject = ComposeChildObject(recordRow);
        for(var i = 0; i < pageObjParentResults.length; i++){
            if(pageObjParentResults[i].Children == undefined)
                {
                    pageObjParentResults[i].Children = ko.observableArray([]);
                }
            if ($.grep(pageObjParentResults[i].Children, function(children){ return children['Id'] == recordObject['Id'];}).length == 0)
                pageObjParentResults[i].Children.push(recordObject);
            }

    return recordObject;
}

function findObjectsInChildTreeById(options)
{
    if (options.item == undefined)
    {
        for(var item in PageObj[options.knockoutContextName]())
        {
            findObjectsInChildTreeById({item : PageObj[options.knockoutContextName]()[item], id : options.id, results: options.results});
        }
    }
    else
    {
        if (typeof options.item.Fields['Id'] == 'function')
        {
            if (options.item.Fields['Id']() == options.id)
                options.results.push(options.item);
        }
        else
        {
            if (options.item.Fields['Id'] == options.id)
                options.results.push(options.item);
        }

        if (options.item.Children!=undefined)
        {
            for(var item in options.item.Children())
            {
                findObjectsInChildTreeById({item : options.item.Children()[item], id : options.id, results: options.results});
            }
        }
    }
}
Was it helpful?

Solution

Since no one cares.
Depth - how deep record chain goes in one branch,
Record count - how many records are in total
Time is in milliseconds. There's obviously a lot of noise in these results.

Example: Depth 5 record count 500 means 100 branches of 5 records each

[Element] --> [Child] --> [Child] --> [Child] --> [Child] --> [Child]
[Element] --> [Child] --> [Child] --> [Child] --> [Child] --> [Child]
...
[97 more]
...
[Element] --> [Child] --> [Child] --> [Child] --> [Child] --> [Child]

Performance:

    +-------+--------------+------------------------------------------+------------------------------------------------+---------------------------------------+----------------------------+----------------------------+-----------------------+
    | Depth | Record count | Chrome (Parent-child-orphan) shuffled ms | Chrome (Bulk read grep with clean) shuffled ms | Chrome (Bulk read grep with clean) ms | Chrome (Bulk read grep) ms | Chrome (Layer by layer) ms | Chrome (Bulk read) ms |
    +-------+--------------+------------------------------------------+------------------------------------------------+---------------------------------------+----------------------------+----------------------------+-----------------------+
    |     1 |           25 |                                      650 |                                            659 |                                   464 |                          0 |                          0 |                     0 |
    |     1 |           50 |                                      614 |                                            707 |                                   417 |                          0 |                          0 |                     0 |
    |     1 |           75 |                                      577 |                                            683 |                                   448 |                          0 |                          0 |                     0 |
    |     1 |          100 |                                      659 |                                            679 |                                   442 |                          0 |                          0 |                     0 |
    |     1 |          200 |                                      604 |                                            819 |                                   514 |                          0 |                          0 |                     0 |
    |     1 |          500 |                                      759 |                                           1217 |                                   766 |                          0 |                          0 |                     0 |
    |     1 |         1000 |                                     1696 |                                           2310 |                                  1421 |                          0 |                          0 |                     0 |
    |     5 |           25 |                                      373 |                                            669 |                                   502 |                        651 |                        806 |                   865 |
    |     5 |           50 |                                      464 |                                            661 |                                   534 |                        893 |                        932 |                  1097 |
    |     5 |           75 |                                      462 |                                            676 |                                   588 |                        641 |                        939 |                  1348 |
    |     5 |          100 |                                      581 |                                            679 |                                   599 |                        677 |                       1025 |                  1764 |
    |     5 |          200 |                                      562 |                                            772 |                                   629 |                        761 |                       1234 |                  2942 |
    |     5 |          500 |                                      712 |                                           1359 |                                  1007 |                       1339 |                       1908 |                 13299 |
    |     5 |         1000 |                                     1274 |                                           2792 |                                  2072 |                       2900 |                       3733 |                 32602 |
    |    10 |           20 |                                      428 |                                            647 |                                   429 |                        601 |                        948 |                   790 |
    |    10 |           50 |                                      386 |                                            670 |                                   435 |                        576 |                        975 |                   930 |
    |    10 |           70 |                                      597 |                                            710 |                                   440 |                        631 |                       1023 |                  1284 |
    |    10 |          100 |                                      432 |                                            695 |                                   463 |                        653 |                       1001 |                  1321 |
    |    10 |          200 |                                      654 |                                            809 |                                   501 |                        684 |                       1357 |                  3130 |
    |    10 |          500 |                                      758 |                                           1356 |                                   826 |                       1208 |                       2116 |                 11246 |
    |    10 |         1000 |                                     1243 |                                           2765 |                                  1661 |                       2524 |                       3687 |                 33714 |
    |    20 |           20 |                                      531 |                                            634 |                                   435 |                        612 |                       1198 |                   848 |
    |    20 |           40 |                                      574 |                                            668 |                                   425 |                        687 |                       1176 |                  1003 |
    |    20 |           60 |                                      545 |                                            690 |                                   478 |                        620 |                       1245 |                  1093 |
    |    20 |          100 |                                      552 |                                            735 |                                   448 |                        671 |                       1343 |                  1693 |
    |    20 |          200 |                                      711 |                                            837 |                                   486 |                        785 |                       1584 |                  3134 |
    |    20 |          500 |                                      965 |                                           1417 |                                   914 |                       1125 |                       2478 |                 12825 |
    |    20 |         1000 |                                     1510 |                                           2985 |                                  1763 |                       2621 |                       3956 |                 35619 |
    |    50 |           50 |                                      513 |                                            679 |                                   411 |                        571 |                       1854 |                  1129 |
    |    50 |          100 |                                      529 |                                            747 |                                   435 |                        684 |                       1984 |                  1523 |
    |    50 |          200 |                                      677 |                                            860 |                                   458 |                        704 |                       1928 |                  3107 |
    |    50 |          500 |                                     1065 |                                           1254 |                                   781 |                       1428 |                       3081 |                 12592 |
    |    50 |         1000 |                                     1868 |                                           2768 |                                  1595 |                       2765 |                       4908 |                 35515 |
    |   100 |          100 |                                      468 |                                            676 |                                   467 |                        729 |                       3071 |                  1835 |
    |   100 |          200 |                                      477 |                                            812 |                                   556 |                        776 |                       3232 |                  3894 |
    |   100 |          500 |                                      848 |                                           1379 |                                   855 |                       1330 |                       4215 |                 13687 |
    |   100 |         1000 |                                     2054 |                                           2670 |                                  1998 |                       2577 |                       6415 |                 37376 |
    |   200 |          200 |                                        0 |                                              0 |                                     0 |                        823 |                       5336 |                  3771 |
    |   200 |          400 |                                        0 |                                              0 |                                     0 |                       1197 |                       6243 |                 10169 |
    |   200 |         1000 |                                        0 |                                              0 |                                     0 |                       3080 |                       9392 |                 36198 |
    +-------+--------------+------------------------------------------+------------------------------------------------+---------------------------------------+----------------------------+----------------------------+-----------------------+

'Parent-child-orphan'™ by myself wins
Could someone please beat this algorithm.
I am shuffling data before processing.

Here's the code.

function ComposeRecordsToTreeStructure(results, tableArray, columnArray, options)
{
     if (results.rows.length > 0) {
     if (options.parentLayerIdList == undefined){
            options.parentLayerIdList = options.masterIdList;
        }

     if (options.orphans == undefined){
            options.orphans = [];
        }

         var childRecordIdArray = [];             
         if (options.runningOnOrphans)
         {
            if (options.orphans.length > 0)
            {
                for (var j = 0; j < options.orphans.length; j++)
                {
                    var rowRecord = options.orphans[j];
                    var parentPosition = $.inArray(rowRecord.Fields[options.parentIdColumn], options.parentLayerIdList);
                    if (parentPosition != -1)
                    {
                        AttachPassedChildRecordsToParents(rowRecord, options.parentLayerIdList[parentPosition], options.knockoutContextName);
                        childRecordIdArray.push(rowRecord.Fields['Id']);
                        childRecordIdArray = AddChildRecordsToNextParentList(rowRecord, childRecordIdArray);
                    }
                    else
                    {
                        var recentParentPosition = $.inArray(rowRecord.Fields[options.parentIdColumn], childRecordIdArray);
                        if (recentParentPosition != -1)
                        {
                            AttachPassedChildRecordsToParents(rowRecord, childRecordIdArray[recentParentPosition], options.knockoutContextName);
                            childRecordIdArray.push(rowRecord.Fields['Id']);
                            childRecordIdArray = AddChildRecordsToNextParentList(rowRecord, childRecordIdArray);
                        }
                        else
                        {
                            var matchingOrphans = $.grep(options.orphans, function(item){ return item.Fields['Id'] == rowRecord.Fields[options.parentIdColumn]; });
                            if (matchingOrphans.length > 0)
                            {
                                AttachToOrphans(rowRecord, matchingOrphans);
                            }
                        }
                    }
                }

                options.orphans = $.grep(options.orphans, function(item){
                    return $.inArray(item.Fields['Id'], childRecordIdArray) == -1;
                });
            }
         }
         else
         { 
             for(var i = 0; i < results.rows.length; i++)
                {
                    var rowRecord = results.rows.item(i);
                    if (rowRecord[options.parentIdColumn] == '' || rowRecord[options.masterIdColumn] == '' ||  rowRecord[options.masterIdColumn] ==  rowRecord['Id'])
                    {
                        rowRecord.isInvalid = true;
                    }

                    if (rowRecord.isInvalid == true)
                    {
                            var parentPosition = $.inArray(rowRecord[options.masterIdColumn], options.parentLayerIdList);
                            if (parentPosition != -1)
                            {
                                var childRecord = AttachChildRecordsToParents(rowRecord, options.parentLayerIdList[parentPosition], options.knockoutContextName);
                                childRecordIdArray.push(childRecord.Fields['Id']);
                            }
                    }
                    else
                    {
                        var parentPosition = $.inArray(rowRecord[options.parentIdColumn], options.parentLayerIdList);
                        if (parentPosition != -1)
                        {
                            var childRecord = AttachChildRecordsToParents(rowRecord, options.parentLayerIdList[parentPosition], options.knockoutContextName);
                            childRecordIdArray.push(childRecord.Fields['Id']);
                        }
                        else
                        {
                            var recentParentPosition = $.inArray(rowRecord[options.parentIdColumn], childRecordIdArray);
                            if (recentParentPosition != -1)
                            {
                                var childRecord = AttachChildRecordsToParents(rowRecord, childRecordIdArray[recentParentPosition], options.knockoutContextName);
                                childRecordIdArray.push(childRecord.Fields['Id']);
                            }
                            else
                            {
                                var matchingOrphans = $.grep(options.orphans,function(item){ return item.Fields['Id'] == rowRecord[options.parentIdColumn]; });
                                var composedObject = ComposeChildObject(rowRecord);
                                if (matchingOrphans.length > 0)
                                {
                                    AttachToOrphans(composedObject, matchingOrphans);
                                }
                                else
                                {
                                    options.orphans.push(composedObject);
                                    options.runningOnOrphans = true;
                                }
                            }
                        }
                    }
                }
            }         

        if (options.orphans.length > 0)
        {
            options.parentLayerIdList = childRecordIdArray;
            ComposeRecordsToTreeStructure(results, tableArray, columnArray, options);
        }
    }
}

function AddChildRecordsToNextParentList(childRecord, childRecordIdArray)
{
    if (childRecord.Children != undefined)
        {
            for(var i = 0; i < childRecord.Children().length; i++)
            {
            childRecordIdArray.push(childRecord.Children()[i].Fields['Id']);
                if (childRecord.Children()[i].Children != undefined)
                {
                    AddChildRecordsToNextParentList(childRecord.Children()[i], childRecordIdArray);
                }
            }
        }

    return childRecordIdArray;
}

function RowsToListDataStructure(results)
{
    var array = [];
    for(var i = 0; i < results.rows.length; i++)
    {
        array.push(results.rows.item(i));
    }

    return array;
}

function AttachLayerOfChildRecords(results, tableArray, columnArray, options)
{
    var childRecordArray = [];
    if (results.rows.length > 0) {
        for(i = 0; i < results.rows.length; i++){
               var childRecord = AttachChildRecordsToParents(results.rows.item(i), results.rows.item(i)[options.parentIdColumn], options.knockoutContextName);
               childRecordArray.push(childRecord);
            }
        }

    return childRecordArray;
}

function AttachChildRecordsToParents(recordRow, id, knockoutContextName)
{
    var childTreeOptions = {id : id, knockoutContextName : knockoutContextName, results: []};
            findObjectsInChildTreeById(childTreeOptions);
            if (childTreeOptions.results.length > 0) {
                       var childRecord = AttachChildRecord(recordRow, childTreeOptions.results);
                }

    return childRecord;
}

function ComposeChildObject(recordRow)
{
        var recordObject = { Fields: {}, SetFields: [], Insert: false };
        for (var field in recordRow) {
                recordObject.Fields[field] = field === "Id" && recordRow.PrimaryRowId ? recordRow.PrimaryRowId : recordRow[field];
            }

        return recordObject;
}

function AttachChildRecord(recordRow, pageObjParentResults)
{
     var recordObject = ComposeChildObject(recordRow);
        for(var i = 0; i < pageObjParentResults.length; i++){
            if(pageObjParentResults[i].Children == undefined)
                {
                    pageObjParentResults[i].Children = ko.observableArray([]);
                }
            if ($.grep(pageObjParentResults[i].Children, function(children){ return children['Id'] == recordObject['Id'];}).length == 0)
                pageObjParentResults[i].Children.push(recordObject);
            }

    return recordObject;
}

function AttachPassedChildRecordsToParents(recordObject, id, knockoutContextName)
{
    var childTreeOptions = {id : id, knockoutContextName : knockoutContextName, results: []};
            findObjectsInChildTreeById(childTreeOptions);
            if (childTreeOptions.results.length > 0) {
                       var childRecord = AttachPassedChildRecord(recordObject, childTreeOptions.results);
                }

    return childRecord;
}

function AttachPassedChildRecord(recordObject, pageObjParentResults)
{
        for(var i = 0; i < pageObjParentResults.length; i++){
            if(pageObjParentResults[i].Children == undefined)
                {
                    pageObjParentResults[i].Children = ko.observableArray([]);
                }
            if ($.grep(pageObjParentResults[i].Children, function(children){ return children['Id'] == recordObject['Id'];}).length == 0)
                pageObjParentResults[i].Children.push(recordObject);
            }

    return recordObject;
}

function AttachToOrphans(recordObject, orphanParents)
{
    for(var i = 0; i < orphanParents.length; i++){
        if (orphanParents[i].Children == undefined)
        {
            orphanParents[i].Children = ko.observableArray([]);
            orphanParents[i].Children.push(recordObject);
        }
    }
}

function findObjectsInChildTreeById(options)
{
    if (options.item == undefined)
    {
        for(var item in PageObj[options.knockoutContextName]())
        {
            findObjectsInChildTreeById({item : PageObj[options.knockoutContextName]()[item], id : options.id, results: options.results});
        }
    }
    else
    {
        if (typeof options.item.Fields['Id'] == 'function')
        {
            if (options.item.Fields['Id']() == options.id)
                options.results.push(options.item);
        }
        else
        {
            if (options.item.Fields['Id'] == options.id)
                options.results.push(options.item);
        }

        if (options.item.Children!=undefined)
        {
            for(var item in options.item.Children())
            {
                findObjectsInChildTreeById({item : options.item.Children()[item], id : options.id, results: options.results});
            }
        }
    }
}

The next best thing is changing that rows.item(i) structure to list, that then can be JQuery 'grepped' and then processing layer by layer:

Bulk read grep with clean:

  function ComposeRecordsToTreeStructure(results, tableArray, columnArray, options)
{
     if (results.rows.length > 0) {
     if (options.parentLayerIdList == undefined){
            options.parentLayerIdList = options.masterIdList;
        }

         var childRecordIdArray = [];
         var isThereNextLayer = false;
         if (options.listResult == undefined){
            options.listResult = RowsToListDataStructure(results);
         }

         for(var i = 0; i < options.parentLayerIdList.length; i++)
            {
                var children = $.grep(options.listResult, function(item){ return item[options.parentIdColumn] == options.parentLayerIdList[i]});
                for(var ii = 0; ii < children.length; ii++)
                {
                   AttachChildRecordsToParents(children[ii], options.parentLayerIdList[i], options.knockoutContextName)
                   childRecordIdArray.push(children[ii]['Id']);
                      if (isThereNextLayer == false){
                            isThereNextLayer = ($.grep(options.listResult, function(item){ return children[ii]['Id'] == item[options.parentIdColumn];}).length > 0)
                          }  
                }
            }

        if (isThereNextLayer)
        {
            options.parentLayerIdList = childRecordIdArray;
            ComposeRecordsToTreeStructure(results, tableArray, columnArray, options);
        }
    }
}

function RowsToListDataStructure(results)
{
    var array = [];
    for(var i = 0; i < results.rows.length; i++)
    {
        array.push(results.rows.item(i));
    }

    return array;
}

function AttachLayerOfChildRecords(results, tableArray, columnArray, options)
{
    var childRecordArray = [];
    if (results.rows.length > 0) {
        for(i = 0; i < results.rows.length; i++){
               var childRecord = AttachChildRecordsToParents(results.rows.item(i), results.rows.item(i)[options.parentIdColumn], options.knockoutContextName);
               childRecordArray.push(childRecord);
            }
        }

    return childRecordArray;
}

function AttachChildRecordsToParents(recordRow, id, knockoutContextName)
{
    var childTreeOptions = {id : id, knockoutContextName : knockoutContextName, results: []};
            findObjectsInChildTreeById(childTreeOptions);
            if (childTreeOptions.results.length > 0) {
                       var childRecord = AttachChildRecord(recordRow, childTreeOptions.results);
                }

    return childRecord;
}

function ComposeChildObject(recordRow)
{
        var recordObject = { Fields: {}, SetFields: [], Insert: false };
        for (var field in recordRow) {
                recordObject.Fields[field] = field === "Id" && recordRow.PrimaryRowId ? recordRow.PrimaryRowId : recordRow[field];
            }

        return recordObject;
}

function AttachChildRecord(recordRow, pageObjParentResults)
{
     var recordObject = ComposeChildObject(recordRow);
        for(var i = 0; i < pageObjParentResults.length; i++){
            if(pageObjParentResults[i].Children == undefined)
                {
                    pageObjParentResults[i].Children = ko.observableArray([]);
                }
            if ($.grep(pageObjParentResults[i].Children, function(children){ return children['Id'] == recordObject['Id'];}).length == 0)
                pageObjParentResults[i].Children.push(recordObject);
            }

    return recordObject;
}

function findObjectsInChildTreeById(options)
{
    if (options.item == undefined)
    {
        for(var item in PageObj[options.knockoutContextName]())
        {
            findObjectsInChildTreeById({item : PageObj[options.knockoutContextName]()[item], id : options.id, results: options.results});
        }
    }
    else
    {
        if (typeof options.item.Fields['Id'] == 'function')
        {
            if (options.item.Fields['Id']() == options.id)
                options.results.push(options.item);
        }
        else
        {
            if (options.item.Fields['Id'] == options.id)
                options.results.push(options.item);
        }

        if (options.item.Children!=undefined)
        {
            for(var item in options.item.Children())
            {
                findObjectsInChildTreeById({item : options.item.Children()[item], id : options.id, results: options.results});
            }
        }
    }
}

OTHER TIPS

Version that does not use MasterId, and reads ParentIds in bulk Layer by layer (Chrome (Layer by layer) ms)

function getBulkChildrenForParentRecordList(options)
{
    var listArray = options.listArray;
    var parentTable = options.parentTable;
    var parentIdColumn = options.parentIdColumn;
    var knockoutContextName = options.knockoutContextName;

    if (listArray == undefined || listArray.length == 0) {
        return;
    }

    var parentIds = getParentIds(listArray);     
    var dbManager = new OnTheMoveDatabaseManager();
    dbManager.queryDatabase({
        statement: {
            Tables: [
                        { Alias: parentTable,   JoinSpec: null,                              JoinType: "",       Name: parentTable },
                        { Alias: "Record",      JoinSpec : "Record.Id = "+parentTable+".Id", JoinType: "INNER",  Name: "Record"}
                    ],
            WhereClause: parentTable + "."+parentIdColumn+" IN ('" +  parentIds.join("','") + "') AND Record.RecordType ='"+parentTable+"'",
            SelectFields: [{ IsAggregate: false, Name: "*"}],
            DisablePaging: true
                    },
        knockoutContextName: knockoutContextName,
        isObservable: false,
        parentIdColumn : parentIdColumn,
        parentTable : options.parentTable,
        success: function (results, tableArray, columnArray, options) {
            var childListArray = AttachChildRecords(results, tableArray, columnArray, options);
                if (childListArray.length > 0){
                    getBulkChildrenForParentRecordList({listArray : childListArray, parentTable : options.parentTable, parentIdColumn : options.parentIdColumn, knockoutContextName : options.knockoutContextName});
            }
        }
    });
}

function AttachChildRecords(results, tableArray, columnArray, options)
{
    var childRecordArray = [];
    if (results.rows.length > 0) {
        for(i = 0; i < results.rows.length; i++){
        var childTreeOptions = {id : results.rows.item(i)[options.parentIdColumn], knockoutContextName : options.knockoutContextName, results: []};
            findObjectsInChildTreeById(childTreeOptions);
            if (childTreeOptions.results.length > 0) {
                    for(var ii = 0; ii < childTreeOptions.results.length; ii++)
                    {
                        if(childTreeOptions.results[ii].Children == undefined)
                        {
                            childTreeOptions.results[ii].Children = ko.observableArray([]);
                        }

                        var recordObject = { Fields: {}, SetFields: [], Insert: false };
                        for (var field in results.rows.item(i)) {
                            recordObject.Fields[field] = field === "Id" && results.rows.item(i).PrimaryRowId ? results.rows.item(i).PrimaryRowId : results.rows.item(i)[field];
                        }

                        childTreeOptions.results[ii].Children.push(recordObject);
                        childRecordArray.push(recordObject);
                    }
                }
            }
        }

    return childRecordArray;
}

function findObjectsInChildTreeById(options)
{
    if (options.item == undefined)
    {
        for(var item in PageObj[options.knockoutContextName]())
        {
            findObjectsInChildTreeById({item : PageObj[options.knockoutContextName]()[item], id : options.id, results: options.results});
        }
    }
    else
    {
        if (typeof options.item.Fields['Id'] == 'function')
        {
            if (options.item.Fields['Id']() == options.id)
                options.results.push(options.item);
        }
        else
        {
            if (options.item.Fields['Id'] == options.id)
                options.results.push(options.item);
        }

        if (options.item.Children!=undefined)
        {
            for(var item in options.item.Children())
            {
                findObjectsInChildTreeById({item : options.item.Children()[item], id : options.id, results: options.results});
            }
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top