javascript - Tree building infinite recursion detection -
i working on jquery mechanism building tree, has fast possible. volume of info quite big master record column used able 'grab' relevant nodes in 1 select websql db. whole mechanism 1 part done, when assembling tree must check there no infinite recursion beingness created. mechanism @ moment if record master , parent of record b, , record b master , parent of record construction a.children[0] = b , b.children[0] = a beingness built. work fine, has knockout.js bound , displayed expandable list users, results in overflow when trying display tree. requirement observe such loops , not create tree relationships.
mechanism check if item in tree came is:
function intree(master, item) { homecoming $.inarray(item, $.map(master, function recurs(n) { homecoming ($.isarray(n) ? $.map(n, recurs) : n); })) != -1; } if(!intree(tree, record)) { //attach } else { // next record } is there faster intree() function me if item in tree?
whole tree building algorithm below (not think relevant rather avoid comments 'show code')
$(document).on('onprequery', onthemove.pagedataroles, function (e, options) { var ischildattachmentqueued = true; var knockoutcontextname = options.knockoutcontextname; if (treeenabled(knockoutcontextname)) { var ismodelreadytoattachchildren = function () { var isready = false; if (pageobj[knockoutcontextname] != undefined) { isready = (pageobj[knockoutcontextname]().length > 0) && ischildattachmentqueued; } homecoming isready; }; var businesscomponent = eval(knockoutcontextname); var treesettings = businesscomponent.tree; treesettings.knockoutcontextname = knockoutcontextname; $(businesscomponent).on('onpreuiupdate', function (e, options) { if (ismodelreadytoattachchildren()) { getchildrenformasterrecordlist({ parenttable: businesscomponent.primarytablename, knockoutcontextname: treesettings.knockoutcontextname, parentidcolumn: treesettings.parentidcolumn, masteridcolumn: treesettings.masteridcolumn }); ischildattachmentqueued = false; } }); } }); function treeenabled(knockoutcontextname) { var istreeenabled = false; seek { eval(knockoutcontextname); } grab (e) { homecoming istreeenabled; } var treesettings = eval(knockoutcontextname).tree; if (treesettings && treesettings.includechildren) { istreeenabled = true; } homecoming istreeenabled; } 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 knockoutcontextname = options.knockoutcontextname; var childrecordidarray = []; if (options.runningonorphans) { if (options.orphans.length > 0) { (var j = 0; j < options.orphans.length; j++) { var rowrecord = options.orphans[j]; var rowrecordparentid = rowrecord[options.parentidcolumn]; var result = establishparentchildconnectiononalreadyprocessednodes(rowrecord, rowrecordparentid, options.parentlayeridlist, knockoutcontextname, childrecordidarray, options); if (result.hasestablishedconnection) { childrecordidarray = result.childrecordidarray; } } options.orphans = $.grep(options.orphans, function (item) { homecoming $.inarray(item['id'], childrecordidarray) == -1; }); } } else { (var = 0; < results.rows.length; i++) { var rowrecord = results.rows.item(i); var rowrecordparentid = rowrecord[options.parentidcolumn]; if (rowrecord[options.parentidcolumn] == '' || rowrecord[options.masteridcolumn] == '' || rowrecord[options.masteridcolumn] == rowrecord['id']) { rowrecord.isinvalid = true; } else if ($.inarray(rowrecord['id'], options.masteridlist) != -1) { masterrecordclone = $.grep(pageobj[knockoutcontextname](), function (item) { homecoming item.fields.id() == rowrecord['id'] })[0]; if (masterrecordclone != undefined && masterrecordclone.children) { rowrecord.children = masterrecordclone.children; } } if (rowrecord.isinvalid == true) { if (rowrecord[options.masteridcolumn] != rowrecord['id']) { var result = establishparentchildconnection(rowrecord, rowrecord[options.masteridcolumn], options.parentlayeridlist, knockoutcontextname, childrecordidarray, options); if (result.hasestablishedconnection) { childrecordidarray = result.childrecordidarray; establishparentchildconnectiononalreadyprocessednodes(rowrecord, rowrecordparentid, options.parentlayeridlist, knockoutcontextname, childrecordidarray, options); } } } else { var result = establishparentchildconnectiononalreadyprocessednodes(rowrecord, rowrecordparentid, options.parentlayeridlist, knockoutcontextname, childrecordidarray, options); if (result.hasestablishedconnection) { childrecordidarray = result.childrecordidarray; } else { var recordobject = addisexpandedproperty(rowrecord); options.orphans.push(recordobject); options.runningonorphans = true; } } } } if (options.orphans.length > 0 && childrecordidarray.length > 0) { options.parentlayeridlist = childrecordidarray; composerecordstotreestructure(results, tablearray, columnarray, options); } } onthemove.seleniumhelper.markpageasloaded(); } function establishparentchildconnectiononalreadyprocessednodes(rowrecord, rowrecordparentid, parentlayeridlist, knockoutcontextname, childrecordidarray, options) { var result = establishparentchildconnection(rowrecord, rowrecordparentid, parentlayeridlist, knockoutcontextname, childrecordidarray); if (result.hasestablishedconnection) { childrecordidarray = result.childrecordidarray; } else { var result = establishparentchildconnection(rowrecord, rowrecordparentid, childrecordidarray, knockoutcontextname, childrecordidarray); if (result.hasestablishedconnection) { childrecordidarray = result.childrecordidarray; } else { var matchingorphans = $.grep(options.orphans, function (item) { homecoming item['id'] == rowrecordparentid; }); if (matchingorphans.length > 0) { attachpassedchildrecord(rowrecord, matchingorphans); var result = { hasestablishedconnection: true }; } } } homecoming { childrecordidarray: childrecordidarray, hasestablishedconnection: result.hasestablishedconnection }; } function establishparentchildconnection(rowrecord, rowrecordparentid, parentlayeridlist, knockoutcontextname, childrecordidarray) { var hasestablishedconnection = false; var parentposition = $.inarray(rowrecordparentid, parentlayeridlist); if (parentposition != -1) { attachchildrecordstoparents(rowrecord, parentlayeridlist[parentposition], knockoutcontextname); childrecordidarray = addchildrecordstonextparentlist(rowrecord, childrecordidarray); childrecordidarray.push(rowrecord['id']); hasestablishedconnection = true; } homecoming { childrecordidarray: childrecordidarray, hasestablishedconnection: hasestablishedconnection }; } function addchildrecordstonextparentlist(childrecord, childrecordidarray) { if (childrecord.children != undefined) { (var = 0; < childrecord.children.length; i++) { childrecordidarray.push(childrecord.children[i]['id']); if (childrecord.children[i].children != undefined) { addchildrecordstonextparentlist(childrecord.children[i], childrecordidarray); } } } homecoming childrecordidarray; } function rowstolistdatastructure(results) { var array = []; (var = 0; < results.rows.length; i++) { array.push(results.rows.item(i)); } homecoming array; } function attachchildrecordstoparents(recordrow, id, knockoutcontextname) { var childtreeoptions = { id: id, knockoutcontextname: knockoutcontextname, results: [] }; findobjectsinchildtreebyid(childtreeoptions); if (childtreeoptions.results.length > 0) { attachpassedchildrecord(recordrow, childtreeoptions.results); } } function attachpassedchildrecord(recordobject, pageobjparentresults) { (var = 0; < pageobjparentresults.length; i++) { if (pageobjparentresults[i].children == undefined) { pageobjparentresults[i].children = []; } if ($.grep(pageobjparentresults[i].children, function (children) { homecoming children['id'] == recordobject['id']; }).length == 0) { recordobject = addisexpandedproperty(recordobject); pageobjparentresults[i].children.push(recordobject); } } } function addisexpandedproperty(recordobject) { recordobject.isexpanded = ko.observable(false); homecoming recordobject; } function findobjectsinchildtreebyid(options) { if (options.item == undefined) { if (typeof pageobj[options.knockoutcontextname] != 'undefined') { (var item in pageobj[options.knockoutcontextname]()) { findobjectsinchildtreebyid({ item: pageobj[options.knockoutcontextname]()[item], id: options.id, results: options.results }); } } } else { if (typeof options.item.fields != 'undefined') { if (options.item.fields['id']() == options.id) options.results.push(options.item); } else { if (options.item['id'] == options.id) options.results.push(options.item); } if (options.item.children != undefined) { (var item in options.item.children) { findobjectsinchildtreebyid({ item: options.item.children[item], id: options.id, results: options.results }); } } } } function getchildrenformasterrecordlist(options) { var parenttable = options.parenttable, masteridcolumn = options.masteridcolumn, parentidcolumn = options.parentidcolumn, knockoutcontextname = options.knockoutcontextname, masterids = getparentidsandmastersofparentsfrompageobj(knockoutcontextname, masteridcolumn); (var item in pageobj[options.knockoutcontextname]()) { addisexpandedproperty(pageobj[knockoutcontextname]()[item]); } 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 + "." + masteridcolumn + " in ('" + masterids.join("','") + "') , record.recordtype ='" + parenttable + "'", selectfields: [{ isaggregate: false, name: "*" }], disablepaging: true, orderclause: "record.id" }, knockoutcontextname: knockoutcontextname, isobservable: false, masteridcolumn: masteridcolumn, masteridlist: masterids, parentidcolumn: parentidcolumn, parenttable: options.parenttable, success: function (results, tablearray, columnarray, options) { composerecordstotreestructure(results, tablearray, columnarray, options); } }); } function getparentidsandmastersofparentsfrompageobj(knockoutcontextname, mastercolumnname) { var list = []; if (typeof pageobj[knockoutcontextname] != 'undefined') { (var item in pageobj[knockoutcontextname]()) { if ($.inarray(pageobj[knockoutcontextname]()[item].fields['id'](), list) == -1) { list.push(pageobj[knockoutcontextname]()[item].fields['id']()); } if (pageobj[knockoutcontextname]()[item].fields[mastercolumnname]() != '' && $.inarray(pageobj[knockoutcontextname]()[item].fields[mastercolumnname](), list) == -1) { list.push(pageobj[knockoutcontextname]()[item].fields[mastercolumnname]()); } } } homecoming list } function intree(master, item) { homecoming $.inarray(item, $.map(master, function recurs(n) { homecoming ($.isarray(n) ? $.map(n, recurs) : n); })) != -1; }
it depends on circumstances. if you're able run code on add/creation of tree may create node id array , check like
if(allnodes[searchkey]) //etc this specific solution of course of study technically it'd fast perchance be.
javascript jquery algorithm recursion tree
No comments:
Post a Comment