Kendo tree view adding child nodes dynamically is not working - model-view-controller

Here, there are two Kendo tree views,First One here (named- #credentialsTreeView") contains nodes with check boxes with parent node, it's child nodes and inner children etc,
there is another kendo tree view (named-#CurriculumcustomCredTreeView ),what i want to do is,all the nodes i checked in the first tree view should be added into the second tree view by maintaining the exact parent child relation,for example if there is a hierarchy like parent1==>child1==>child2 (which is child of child1),if child2 is checked all it's parent nodes including child2 should be added to second tree view, but here the problem is , 1st: parent node can be added, as it can be added to the treeview in user i/f and also in datasource,so it is working fine but again on appending it's child node to this added node it is not added with the datasource,so on adding the next child node to it, it is impossible to get the details of the node from datasource to which i need to add the next node,
Kendo version--2013.3.1119.440
please see the code i have used.and please let me know the details as soon as possible.
function onAddToRequirement()
{
var treeViewCraftData = $("#credentialsTreeView").data("kendoTreeView").dataSource.data();//1st tree view which contains initially loaded list of nodes with different levels(with multiple childs and innerchilds with check boxes)
var treeViewSelectedTextList = [];
var requirementTreeView = $("#CurriculumcustomCredTreeView").data("kendoTreeView");//2nd tree view to which the selected nodes from 1st tree view to be added dynamically
$("#credentialsTreeView input[type=checkbox]:checked").closest(".k-item").each(function () {
treeViewSelectedTextList.push(
$(this).closest('.k-item').text()
);
});
var treeViewSelectedList = [];
var currentCraftNode = null;//currently three levels are there as craft==>its levels(can be multiple)==>it's Modules(can be multiple)
var currentLevelNode = null;
var currentModuleNode = null;
for (var j = 0; j < treeViewCraftData.length; j++) //treeViewCraftData contains the entire data in the datsource of 1st tree view and looping through it
{
if (treeViewCraftData[j].hasChildren)//checking craft has children
{
var treeViewLevelData = treeViewCraftData[j].children.data();//if so taking all its, levels (craft,s children)
currentCraftNode = treeViewCraftData[j];
for (var k = 0; k < treeViewLevelData.length; k++) //looping through levels
{
if (treeViewLevelData[k].hasChildren) //checking levels has children(named modules here)
{
currentLevelNode = treeViewLevelData[k];
var treeViewModuleData = treeViewLevelData[k].children.data();
for (var l = 0; l < treeViewModuleData.length; l++) //looping through modules(inner children) and checking if it is checked
{
if (treeViewModuleData[k].checked || $.inArray(treeViewModuleData[k].text, treeViewSelectedTextList) > -1)
{
currentModuleNode = treeViewModuleData[k];
if (requirementTreeView.dataSource._data.length > 0)//added condition to prevent it from adding duplicate nodes to 2nd tree view,in first case directly it goes to else part
{
var dataItemcraft1 = null;
var dataItemlevel1 = null;
$(requirementTreeView.dataSource.data()).each(function()
{
if (this.id !== currentCraftNode.id)
{
requirementTreeView.append({//appending 1st node
Name: currentCraftNode.Name,
id: currentCraftNode.id,
hasChildren:currentCraftNode.hasChildren,
//items: treeViewSelectedList.length != 0 ? treeViewSelectedList : null
}, null);
}
});
dataItemcraft1 = requirementTreeView.dataSource.get(currentCraftNode.id);
$(requirementTreeView.dataSource.data()).each(function() {
if (this.id !== currentLevelNode.id) {//appending 2nd node to first node
requirementTreeView.append({
Name: currentLevelNode.Name,
id: currentLevelNode.id,
hasChildren: currentLevelNode.hasChildren,
}, requirementTreeView.dataSource.get(dataItemcraft1.uid));
}
});
dataItemlevel1 = requirementTreeView.dataSource.get(currentCraftNode.id);//here it throws exception as above node is not added to the datsource
$(requirementTreeView.dataSource.data()).each(function() {//code to append 3rd node to above added node
//ebugger;
if (this.id !== currentModuleNode.id) {
requirementTreeView.append({
Name: currentModuleNode.Name,
id: currentModuleNode.id,
hasChildren: currentModuleNode.hasChildren,
//items: treeViewSelectedList.length != 0 ? treeViewSelectedList : null
}, requirementTreeView.dataSource.get(dataItemlevel1.uid));
}
});
dataItemcraft1 = null;
dataItemlevel1 = null;
} else
{
requirementTreeView.append//appending 1st node
({
Name: currentCraftNode.Name,
id: currentCraftNode.id,
hasChildren: currentCraftNode.hasChildren,
Value: currentCraftNode.id
});
var dataItemcraft = requirementTreeView.dataSource.get(currentCraftNode.id);//working fine
requirementTreeView.append//appending 2nd node to first node
({
Name: currentLevelNode.Name,
id: currentLevelNode.id,
hasChildren: currentLevelNode.hasChildren,
}, requirementTreeView.findByUid(dataItemcraft.uid));
requirementTreeView.expand(requirementTreeView.findByUid(dataItemcraft.uid));
var dataItemlevel = requirementTreeView.dataSource.get(currentLevelNode.id);//here it throws exception as above node is not added to the datsource
requirementTreeView.append({
Name: currentModuleNode.Name,
id: currentModuleNode.id,
hasChildren: currentModuleNode.hasChildren,
//items: treeViewSelectedList.length != 0 ? treeViewSelectedList : null
}, requirementTreeView.findByUid(dataItemlevel.uid));
requirementTreeView.expand(requirementTreeView.findByUid(dataItemlevel.uid));
dataItemcraft = null;
dataItemlevel = null;
}
}
}
} else {
}
}
}
}

Related

Filter on Tree or Nested Data

I have seen in one of the issues "Filter on Tree or Nested Data #1562" Oli has mentioned that
Hey #fr0z3nfyr
Filtering is supported on tree child nodes since version 4,2
Cheers
Oli :)
I am unable to find any example or the code to search nested data.
My code works perfectly fine for flat tables, but with nested tables it only works for the root node.
//data - the data for the row being filtered
//filterParams - params object passed to the filter
var match = false;
for (var key in data) {
if (data[key] != null) {
if ((data[key]).indexOf(filterParams.value) != -1) {
match = true;
}
}
}
return match;
}
function updateFilter(){
if ($("#filter-field").val() == "All Columns") {
table.setFilter(matchAny,{ value: $("#filter-value").val()});
} else {
table.setFilter($("#filter-field").val(), "like", $("#filter-value").val());
}
//var filter = $("#filter-field").val() == "All Columns" ? matchAny : $("#filter-field").val() ;
}```
Oli could you please point me to an example where Nested data filtering is supported
I was able to solve this, but by re-setting table data with filtered value and also the tree structure is not maintained in the filtered list. I can maintain the tree structure with some changes in code, but this flat looks more like what I needed once filtering is done.
// This method iterates through the dataRows and its tree children and call a recursive function which creates the filtered table data.
function updateFilter() {
var filtertableData = [];
table.getRows().filter(function (row) {
var rootData = row.getData();
rootData._children = [];
matchData(rootData, filtertableData);
var childRows = row.getTreeChildren();
searchForChildRows(rootData,childRows,filtertableData);
while (childRows.length != 0) {
for (var i = 0; i < childRows.length; i++) {
var childrow = childRows[i];
var childData = childrow.getData();
childData._children = [];
childRows = childrow.getTreeChildren();
searchForChildRows(childData,childRows,filtertableData);
}
}
});
table.setData(filtertableData);
}
function matchData(rootData, filtertableData, childdata) {
if (typeof childdata === "undefined") {
for (var key in rootData) {
console.log(key);
console.log(allVisibleCBSCols);
if (rootData[key] != null && typeof rootData[key] == 'string' && allVisibleCBSCols.includes(key)) {
if ((rootData[key]).indexOf($("#filter-value-Project").val()) != -1) {
filtertableData.push(rootData);
break;
}
}
}
} else {
for (var key in childdata) {
if (childdata[key] != null && typeof childdata[key] == 'string' && allVisibleCBSCols.includes(key)) {
if ((childdata[key]).indexOf($("#filter-value-Project").val()) != -1) {
//rootData._children.push(childdata);
filtertableData.push(childdata);
break;
}
}
}
}
}
function searchForChildRows(rootData,childRows,filtertableData) {
for (var i = 0; i < childRows.length; i++) {
var childrow = childRows[i];
var childData = childrow.getData();
childData._children = [];
matchData(rootData,filtertableData,childData);
}
}

Optimizations for a recursive formula finding a path between two random nodes

I have written a recursive formula that finds a path between two nodes arranged in a grid pattern. My code works with two problems. The first is that sometimes the start node's position is changed from one to another number, but I fixed this by reassigning it after the recursion so it's not that big of a deal. The second issue is that it runs unbearably slow. It takes about 30 seconds to generate a 5x5 and I haven't been able to generate a 7x7 which is my ultimate goal. I am hoping that someone will see if there are any optimizations that can be made.
The Node class, shown below, has a Key property and a Value property. The Key is the position in the grid starting at 0. So, for a 5x5, the top left node will have a Key of 0 and the bottom right node will have a Key of 24. Each node has Up, Down, Left and Right properties that are the other nodes it is connected to. When there are no nodes in that direction, the value is null. For example, in a 5x5, a node with Key = 0 will have an Up of null, a Down of the node with Key = 5, a Left of null, and a Right of the node with Key = 1. As another example, still in a 5x5, a node with Key = 6 will have an Up of the node with Key = 1, a Down of the node with Key = 11, a Left of the node with Key = 5, and a Right of the node with Key = 7. The Position property is the path. The path starts with the node with Position = 1, then goes to the node with Position = 2 etc. until it reaches the end node, which would be position N*N on a NxN board (e.g. a 5x5 board would have an end node with position 25). These nodes are added to a list called nodeList-(a global variable). One of these nodes gets randomly marked as Start-(boolean) and a different node gets randomly assigned as End-(boolean).
The next part is the path. We want to find a random path (starting at 1) between the Start and End nodes that touches every other node without touching the same node twice. This is for a game, so it is important that it is random so the user doesn't play the same board twice. If this is not possible given the Start and End Positions, new Start and End positions are chosen and the algorithm is run again.
class Node
{
public int Key { get; set; }
public int? Position { get; set; } = null;
public Node Up { get; set; } = null;
public Node Down { get; set; } = null;
public Node Left { get; set; } = null;
public Node Right { get; set; } = null;
public bool Start = false;
public bool End = false;
public Node(int key)
{
Key = key;
}
}
public bool GeneratePath()
{
var current = nodeList.Where(w => w.Start).FirstOrDefault();
var start = current;
int position = 1;
bool Recurse(Node caller)
{
if (current.Position == null)
{
current.Position = position;
}
if (current.End)
{
return true;
}
var directions = GetDirections();
for (var i = 0; i < 4; i++)
{
var done = false;
if (directions[i] == 0 && current.Up != null && current.Up.Position == null
&& (!current.Up.End || position == n * n - 1))
{
var temp = current;
current = current.Up;
position++;
done = Recurse(temp);
}
else if (directions[i] == 1 && current.Down != null && current.Down.Position == null
&& (!current.Down.End || position == n * n - 1))
{
var temp = current;
current = current.Down;
position++;
done = Recurse(temp);
}
else if (directions[i] == 2 && current.Left != null && current.Left.Position == null
&& (!current.Left.End || position == n * n - 1))
{
var temp = current;
current = current.Left;
position++;
done = Recurse(temp);
}
else if (directions[i] == 3 && current.Right != null && current.Right.Position == null
&& (!current.Right.End || position == n*n - 1))
{
var temp = current;
current = current.Right;
position++;
done = Recurse(temp);
}
if(done)
{
return true;
}
}
current.Position = null;
position--;
if(caller == null)
{
return false;
}
current = caller;
return false;
}
var success = Recurse(null);
if (success)
{
start.Position = 1;
}
return success;
}
private int[] GetDirections()
{
List<int> toPerm = new List<int>();
for (var i = 0; i < 4; i++)
{
toPerm.Add(i);
}
Random random = new Random();
var perms = HelperMethods.GetPermutations(toPerm, toPerm.Count);
var randomNumber = random.Next(0, perms.Count());
var directions = perms.ElementAt(randomNumber).ToArray();
return directions;
}
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
{
if (length == 1) return list.Select(t => new T[] { t });
return GetPermutations(list, length - 1)
.SelectMany(t => list.Where(o => !t.Contains(o)),
(t1, t2) => t1.Concat(new T[] { t2 }));
}
To reiterate, I am wondering if there are optimizations I can make as it runs too slow for my purposes.
So I found an implementation of an amazing algorithm that can produce 10,000 7x7's in 12 seconds. You can find the implementation here. The author is Nathan Clisby and it is based off of a paper “Secondary structures in long compact polymers”. The idea is to produce a non-random path between the two points, then randomly mutate the path as many times as the user wishes. Supposedly, with enough iterations, this algorithm can produce paths that are nearly as random as the algorithm I posted in the question.
Way to go computer scientists!

how to use lockf with xerces-c

I am new to programming and I am trying to use lockf to lock a XML file. I using xerces-c to parse the XML file and I need to lock the file. The function is similar the the example below:
void GetConfig::readConfigFile(string& configFile)
throw( std::runtime_error )
{
// Configure DOM parser.
m_ConfigFileParser->setValidationScheme( XercesDOMParser::Val_Never );
m_ConfigFileParser->setDoNamespaces( false );
m_ConfigFileParser->setDoSchema( false );
m_ConfigFileParser->setLoadExternalDTD( false );
try
{
m_ConfigFileParser->parse( configFile.c_str() );
// no need to free this pointer - owned by the parent parser object
DOMDocument* xmlDoc = m_ConfigFileParser->getDocument();
// Get the top-level element: NAme is "root". No attributes for "root"
DOMElement* elementRoot = xmlDoc->getDocumentElement();
if( !elementRoot ) throw(std::runtime_error( "empty XML document" ));
// Parse XML file for tags of interest: "ApplicationSettings"
// Look one level nested within "root". (child of root)
DOMNodeList* children = elementRoot->getChildNodes();
const XMLSize_t nodeCount = children->getLength();
// For all nodes, children of "root" in the XML tree.
for( XMLSize_t xx = 0; xx < nodeCount; ++xx )
{
DOMNode* currentNode = children->item(xx);
if( currentNode->getNodeType() && // true is not NULL
currentNode->getNodeType() == DOMNode::ELEMENT_NODE ) // is element
{
// Found node which is an Element. Re-cast node as element
DOMElement* currentElement
= dynamic_cast< xercesc::DOMElement* >( currentNode );
if( XMLString::equals(currentElement->getTagName(), TAG_ApplicationSettings))
{
// Already tested node as type element and of name "ApplicationSettings".
// Read attributes of element "ApplicationSettings".
const XMLCh* xmlch_OptionA
= currentElement->getAttribute(ATTR_OptionA);
m_OptionA = XMLString::transcode(xmlch_OptionA);
const XMLCh* xmlch_OptionB
= currentElement->getAttribute(ATTR_OptionB);
m_OptionB = XMLString::transcode(xmlch_OptionB);
break; // Data found. No need to look at other elements in tree.
}
}
}
}
}
So, can anyone help me to implement lockf in this function?

Kendo UI: TreeView - How to tell if a given node has parents

I am trying to use the dragend event on a TreeView in order to send a command to the server in order to make the appropriate change, however, to do this I need parent information on both the target and destination nodes. Currently I have the following:
function dragEndEvent(e) {
var treeViewData = $(".hierarchy-tree").data('kendoTreeView');
var quotaSetID = $("#quotaset-id").val();
var columnID = $("#treeViewColumnID").val();
var targetNode = treeViewData.dataItem(e.sourceNode);
var targetParentNode = targetNode.parent();
var destinationNode = treeViewData.dataItem(e.destinationNode);
var destinationParentNode = null;
if(destinationNode!=null )
destinationParentNode = destinationNode.parent();
var targetName = targetNode.text;
var targetID = targetNode.id;
var targetsParentID = null;
if (targetParentNode != null && targetParentNode.length == 1)
targetsParentID = targetParentNode[0].id;
var destinationName = null;
var destinationID = null;
var destinationsParentID = null;
if (destinationNode != null) {
destinationName = destinationNode.text;
destinationID = destinationNode.id;
if (destinationParentNode != null && destinationParentNode.length == 1)
destinationsParentID = destinationParentNode[0].id;
}
// Followed by ajax query
}
What I have noticed is that the parent() call returns a list and it doesn't seem to me to have any indication of the actual parent. Perhaps I am catching the wrong event, but here, the parent() function seems to return the siblings of the target node. I would also like to be able to tell if the node doesn't have a parent (ie it is at the root level)
Use parentNode(), because parent() returns the array which holds this dataItem as you noticed.
I don't see the parentNode() method either. To tell if a node is a top level node in the dragend event you can just use jquery. You can use jquery to grab the UID as well, which then you can use to get the data node.
var targetNode = e.destinationNode;
if ($(targetNode).parent("ul").parent(".k-treeview").length === 1) {
//top level node
} else {
//not top level node
var htmlNode = $(targetNode).parent("ul").parent(".k-item");
//if you need the telerik version of the node
var treeViewData = $(".hierarchy-tree").data('kendoTreeView');
var parentUid = $(htmlNode).data("uid");
var parentNode = treeViewData.findByUid(parentUid);
var parentDataNode = treeViewData.dataItem(parentNode);
var parentid = parentDataNode.id;
}

Need get all A tags in selection in editable iframe and add them attribute "class"

I have an editable <iframe> with the some HTML code in it. I need get all <a> tags in my range. I tried this code but it doesn't work:
var select = document.getElementById(iframe_id).contentWindow.getSelection();
var range = select.getRangeAt(0);
//HERE I WANT TO FIND ALL TAGS IN THIS RANGE AND IF IT "A" - ADD NEW ATTRIBUTE "CLASS". SOMETHING LIKE THIS
var parent = rng.commonAncestorContainer;
for(var i=0; i<parent.childNodes.length; i++)
{
if(parent.childNodes[i].tagName.toLowerCase() == "a")
parent.childNodes[i].setAttribute("class", "href_class");
}
You can use getElementsByTagName() to get all <a> tags of the range container and then check for each of them whether it actually belongs to the range using range.compareBoundaryPoints() (only parts of the container might be selected). Something like this:
var links = rng.commonAncestorContainer.getElementsByTagName("a");
for (var i = 0; i < links.length; i++)
{
var linkRange = document.createRange();
linkRange.selectNode(links[i]);
if (rng.compareBoundaryPoints(Range.START_TO_START, linkRange) <= 0 && rng.compareBoundaryPoints(Range.END_TO_END, linkRange) >= 0)
{
links[i].className = "href_class";
}
}
This should get you started in the right direction. This code does not do any null reference checks on the iframe, selection, range or list.
function addAnchorClass(targetFrameId) {
var targetIframe = document.getElementById(targetFrameId).contentWindow;
var selection = targetIframe.getSelection();
var range = selection.getRangeAt(0);
var alist = range.commonAncestorContainer.getElementsByTagName("a");
for (var i=0, item; item = alist[i]; i++) {
if (selection.containsNode(item, true) ) {
item.className += "PUT YOUR CSS CLASS NAME HERE";
}
}
}

Resources