) TreeView parent-child linkage effect to keep the node status consistent

Source: Internet
Author: User
Most of us have used the TreeView control, and the evaluation of this control is also diverse, but I think it is a free open-source control, so I still use it. ASP. NET, remember to create a permission tree for assigning permissions. At that time, I only knew this tree. After a day of research, I found out the basic behavior of the server, however, due to the limited js level at that time, I was very afraid of the client code and had never seen it.
At that time, there was a requirement that if a node is selected, all the child nodes of the node should be selected, if all the sub-nodes of the node are deselected, the node also needs to be deselected (node consistency). The opposite is true.
Another requirement is that it is better to implement a three-state tree (this is a bit difficult and will not be discussed in this article ). This article describes in detail requirements 1.
First of all, we should be glad that Microsoft's TreeView control is open-source. You can easily obtain it from both client code and server code and download it from Microsoft's website. I have also seen some articles on the Internet about this issue. Most of them use js implementations other than TreeView. I personally think that from the object-oriented perspective, this function belongs to TreeView, so there is no reason to separate it, so today I will modify the TreeView. htc to implement the above functions. To get this file (TreeView. htc), you can download it on Microsoft's website.
To be honest, this feature has plagued me for a long time. I have been trying to solve this problem, but I have never had time to study the code in TreeView. htc. Today I finally made up my mind to solve it.
We know that the event handler function needs to be stimulated in oncheck of TreeView. This function is easy to find and can be found in the client script generated by TreeView. The code snippet is as follows:
Oncheck = "javascript: if (this. clickedNodeIndex! = Null) this. queueEvent ('oncheck', this. clickedNodeIndex )"
Therefore, we can go to htc (htc in the future refers to TreeView. htc), find the doCheckboxClick method, and you only need to look at the name to know what it is (the name is too important, otherwise it is really tiring to find a function in line 3000 code ).
This method is the function to be processed when you click CheckBox. The function is as follows:
Function doCheckboxClick (el ){
Var checked = private_getAttribute (el, "checked ")
El. checked =! Checked;
Var evt = createEventObject ();
Evt. treeNodeIndex = getNodeIndex (el );
G_nodeClicked = el;
_ TvevtCheck. fire (evt );
SetNodeState (el, el. checked); // maybe need el only, but I think it's safly
}
The first, second, and last rows are added by me. The first and second rows are modifications made to the failed checked attribute after the page is returned, and el is submitted according to the original method. checked is undefined, so the node cannot be correctly synchronized. If you are interested, try it. The setNodeState function is used to set the node status from the name. It passes the node you selected as a parameter to the function. As mentioned in the comment, you can only pass el in, instead of passing a Boolean value. However, I think the transfer may be safer, but it doesn't matter. If you feel uncomfortable, you can modify it :.
Let's take a look at the setNodeState function body. This function consists of two methods: one is to set the status of all child nodes, and the other is to set the status of the parent node of the node. The Code is as follows:
Function setNodeState (el, state ){
_ SetChildNode (el, state );
_ SetParentNode (el, state );
}
To set whether all the child nodes of the current node are in the same state as the parent node (the current node), we need the function _ setChildNode, similarly, we need the _ setParentNode function to enable the node's parent node and its State to reach the _ setParentNode function. Both functions are recursive functions that traverse all child nodes, all parent nodes, and sibling nodes (why do we need to traverse sibling nodes later ), the code for Traversing child nodes is as follows:
Function _ setChildNode (el, state ){
Var childNodes = el. children;
If (childNodes. length> 0) {// if has childs
For (var I = 0; I <= childNodes. length-1; I ++ ){
Private_setAttribute (childNodes [I], "Checked", state );
_ SaveCheckState (childNodes [I]);
_ SetChildNode (childNodes [I], state );
}
}
}
This function first obtains all the subnodes of the current node. Here, you can directly use the getChildren method provided by TreeView, while I use the original html method. If the node has a subnode, it traverses all the subnodes and sets the subnode status to the same as that of the current node. The function of _ saveCheckState will be described later. The private_setAttribute method is an internal attribute setting method provided by TreeView (js does not have a private keyword, but this is just an illustration). This method sets the Checked attribute of each node to the status of the current node.
The following code sets the status of the parent node:
Function _ setParentNode (el, state ){
Var parentNode = el. parentElement;
If (parentNode ){
If (! _ CheckSiblingdNode (el )){
Private_setAttribute (parentNode, "Checked", state );
_ SaveCheckState (parentNode );
_ SetParentNode (parentNode, state );
}
}
}
This function first obtains the parent node. If the parent node exists, it checks the sibling node of the current node. The purpose of checking the sibling node is as follows: the status of the parent node is not controlled by one node of the current node (this situation only exists when the current node does not have a sibling node). If other siblings are selected, the parent node cannot be canceled, which will lead to inconsistency between the sibling node and the parent and child node. This function also calls the _ saveCheckState function, which will be described later.
The following code describes how to check the status of a sibling node:
Function _ checkSiblingdNode (el ){
Var parentNode = el. parentElement; // you can use getParentTreeNode function in this htc, but I like this usage.
For (var I = 0; I <= parentNode. children. length-1; I ++ ){
If (el! = ParentNode. children [I]) {
If (private_getAttribute (parentNode. children [I], "Checked ")){
Return true;
}
}
}
Return false;
}
As described in the comment, you can use the getParentTreeNode method to obtain the node's parent node, but I prefer the original method :. Exclude yourself (if (el! = ParentNode. children [I]).
With the above code, we can achieve consistent selection of the client without refreshing the New Parent and Child Nodes. Now let's introduce the _ saveCheckState function. If the function page is not submitted, nodes other than manually clicked nodes cannot be saved. Therefore, this function is used to save the status of all nodes (mainly automatically selected nodes) and ensure that the status of the tree still exists after the return. The following code describes the _ saveCheckState function. The Code is as follows:
Function _ saveCheckState (el ){
If (getNodeIndex (el ))
QueueEvent ('oncheck', getNodeIndex (el ));
}
This method first checks whether the index of the current node is valid. If it is valid, it is saved. Here we need to talk about what the queueEvent method has done, and I will not post the code. The actual meaning of this function is to save the client operation in a hidden domain named _ TreeView1_State, in this way, the server will initialize the tree status based on the hidden domain during the return. Here, TreeView1 is the name of my TreeView in the test system.
The final problem is the deployment problem. Because htc is modified, the original htc file needs to be replaced during deployment.
If you need to modify TreeView. htc (formatted), you can leave an email on CSDN. My CSDN account is cuike519.
I hope Microsoft can add this function to the TreeView control as soon as possible, so it is best to implement a multi-state tree structure.

Note: I remember some discussions on the Internet before: how to ensure that the status of the parent and child nodes is consistent when the TreeView node contains the CheckBox, that is, when the parent node is selected, all the child nodes are automatically selected, otherwise, all are canceled. Select a child node, and select the parent node (including the ancestor node) of this Byte point ).
I also found some methods on the Internet, but I think this is a defect of the TreeView, so it should be implemented inside the control, instead of attaching some external js to control the TreeView (I think ). So I decided to modify the IMPLEMENTATION OF THE TreeView.
I once described how to implement (http://blog.csdn.net/cuike519/archive/2005/02/02/278271.aspx) in the following article, but due to the time relationship at that time, some places are not properly handled, recently work is relatively easy, therefore, I improved it for your reference.
1. Replace TreeView first. htc, I am using TreeView of version 1.0. htc, find this file first (usually under Inetpub \ wwwroot \ webctrl_client \ defaults 0), or specify a proper path for the TreeView.
2. open the file and add the following method to the TreeView control:
// Add by wujian for check
Function _ setChildNode (el, state ){
Var childNodes = el. children;
If (childNodes. length> 0) {// if has childs
For (var I = 0; I <= childNodes. length-1; I ++ ){
Private_setAttribute (childNodes [I], "checked", state );
_ SaveCheckState (childNodes [I]);
_ SetChildNode (childNodes [I], state );
}
}
}

Function _ setParentNode (el, state ){
Var parentNode = el. parentElement;
If (parentNode ){
If (! _ CheckSiblingdNode (el )){
Private_setAttribute (parentNode, "checked", state );
_ SaveCheckState (parentNode );
_ SetParentNode (parentNode, state );
}
}
}

Function setNodeState (el, state ){
_ SetChildNode (el, state );
_ SetParentNode (el, state );
}

Function _ saveCheckState (el ){
If (getNodeIndex (el ))
QueueEvent ('oncheck', getNodeIndex (el ));
}

Function _ checkSiblingdNode (el ){
Var parentNode = el. parentElement; // you can use getParentTreeNode function in this htc, but I like this usage.
For (var I = 0; I <= parentNode. children. length-1; I ++ ){
If (el! = ParentNode. children [I]) {
If (private_getAttribute (parentNode. children [I], "Checked ")){
Return true;
}
}
}
Return false;
}
// ===== End for check
I put it behind the doCheckboxClick function.
3. Find the doCheckboxClick function and modify the function. The modified function is as follows:
Function doCheckboxClick (el ){
If (el. checked! = Event. srcElement. checked)
El. checked = event. srcElement. checked;
Else
El. checked =! El. checked;
Var evt = createEventObject ();
Evt. treeNodeIndex = getNodeIndex (el );
G_nodeClicked = el;
_ TvevtCheck. fire (evt );
SetNodeState (el, el. checked );
}

Blogger note: This is my modified htc file: The treeview after the cascade checkbox is modified.
TIPS: after using the modified htc file, you don't need to use it any more.Solution: use JavaScript in TreeView to select all checkboxesThe method used for the lock. Otherwise, an error will occur (this error has hurt me for 2 hours ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.