After writing JavaScript applications for so long, I did not know the two events, so I went to Google to search for them. these two events are so good and easy to use... however, many people seem to be unaware of the real difference and purpose between these two events and Mouseover mouseout during the search process .. in addition, we can see the cross-browser solutions implemented by some friends who have searched in Google. it seems complicated... so there was an impulse to write a blog to thoroughly understand this stuff... okay. let's go to the topic.
The biggest difference between Mouseover and mouseenter is that mouseenter is a non-bubble event. How can this problem be solved?
<Div id = "parent">
<Div id = "child"> </div>
</Div>
For the Mouseover time, when the mouse moves from other elements to the child node, but this event will bubble up, so the parent will also start Mouseover.
If we have registered a Mouseover listener for the parent, what is the problem? Moving from parent to child also sets out parent Mouseover. Sometimes we don't want this to happen. at this time, if the registered listener is mouseenter, no matter whether the mouse moves from any element to the child, only the child element has a mouseenter event, and its parent node will not trigger this event because of bubbling... this allows us to completely discard the previously troublesome solution that we used to disable Mouseover bubbling on subnodes to achieve the same logic or to determine the event source object or srcelement/relatedtarget.
This is also true for mouseout and mouseleave. When the mouse is removed from the child, the mouseout will also bubble to the parent, thus triggering the parent's mouseout II mouseleave.
Knowing the difference makes it easier to deal with the rest of the things. In this case, we should always use mouseenter mouseleave. The problem is that this is only supported by IE. What should we do?
We can only use Mouseover and mouseout for simulation, but if our simulation solution is too complicated, it doesn't make much sense... at this time, we can use the XML method comparedocumentposition to completely solve this problem.
I encapsulated a method in my class library to determine whether the location of a node is in the subnode of another node...
Ie can use parentnode. Contains (childnode) to determine whether the existence of childnode in the parentnode DOM tree is true.
The contains method is exclusive to IE, so we use it !! (Node. comparedocumentposition (node2) & 16) to achieve the same effect.
Next, let's talk about the comparedocumentposition method. Otherwise, you will be very confused when you see & 16 above...
The comparedocumentposition method is implemented in non-ie browsers to the Node object.
Node. comparedocumentposition (node2) is used to compare the positional relationship between nodes and node2 ..
The returned value is a number value...
Generally, the following values are useful to us:
1. 20 (decimal: 010100)
001010 (decimal)
3. 4 (decimal: 000100)
000010 (decimal)
5. 0 (decimal: 000000)
100 to *** number...
So how did these 20 10 4 2 0 come from? Let's take a look...
Try this binary system.AlgorithmIt is used to explain the relationship between two nodes.
This 6-digit binary number is the root
The 6th bits indicate whether two nodes are in the DOM tree or not. This is for the whole DOM tree. That is to say, if both nodes are not in the DOM tree or both are in the DOM tree, the value is 0. Otherwise, the value is 1.
The value 5th indicates whether the node is the parent node of node2. If the value is 1, the value 0.
The value 4th indicates whether the node is a subnode of node2. If the value is 1, the value 0.
The first digit indicates whether the node is in front of node2. If it is in front of node2, it is 1; otherwise, it is 0 (Note: if the node is the parent node of node2, the node is also considered in front of node2)
The 2nd bits indicate whether the node is behind node2. If it is followed by 1, it is 0. (Note: if the node is a subnode of node2, the node is also considered behind node2)
If 2, 3, 4, 5, and 6 bits are both 0, that is, 000000 indicates that the two nodes are either in the DOM tree or not at the same time. there is no relationship between the two nodes, so there is only one possibility that the two nodes are the same node... that is, node = node2
So what is the result of node. comparedocumentposition (node2) & 16 bit operation? Only 010100 & 010000 and 110 *** & 16 of the above combinations have 010000 results, that is, 16 is returned. In other cases, 0 is returned and then 0 is used !! If number is implicitly converted to the boolean type, we can determine whether the node is the parent node of node2...
Therefore, we can also use node2.comparedocumentposition (node) & 8 to determine whether node2 is a node subnode.
Alternatively, you can directly use node. comparedocumentposition (node2) = 20 to determine whether this can be omitted !! Transformation is also possible.
Smart here, you must find out what this is? It is clearly the usage of flag ID enumeration in C...
In C #, the file. Attributes enumeration may have n attributes at the same time. For example, a file can be read-only, hidden, or shared.
So how can I use an enumerated value to determine which attributes a file has without conflict? The answer is the same as comparedocumentposition...
I used js to implement a class similar logic to manage the flag ID to illustrate this problem.CodeAs follows:
// Flag class
Function flag (sflags ){
This. _ flags = {};
This. _ Status = 0;
Sflags & this. initflags (sflags );
}
Flag. Prototype = {
Constructor: flag,
Initflags: function (sflags) {// sflags "status 1, status 2, status 3... initialize the original collection of identifiers...
Sflags = sflags. Split (',');
For (VAR I = 0, Len = sflags. length; I <Len; I ++) This. _ flags [sflags [I] = 1 <I;
// Here, the value of the initialization identifier. If n States exist at the same time, the value of each state must be 000001 000010 000100 001000 010000 100000
},
Setstatus: function (sflags) {// sflags "status 1, status 3... set the current status
Sflags = sflags. Split (',');
This. _ Status = 0;
for (VAR I = 0, Len = sflags. length; I This. _ Check [sflags [I];
This. _ Status | = This. _ flags [sflags [I];
}< BR >},
addstatus: function (sflags) {// sflags "status 1, status 3 ...... check whether status 1 and 3 are available. If not, add
sflags = sflags. split (',');
for (VAR I = 0, Len = sflags. length; I This. _ Check (sflags [I]);
If (this. hasstatus (sflags [I]) continue; // checks whether the status exists.
This. _ Status | = This. _ flags [sflags [I];
// The current status value and the allowed id value are used. | the operation adds the status.
}
},
Removestatus: function (sflags ){
Sflags = sflags. Split (',');
For (VAR I = 0, Len = sflags. length; I <Len; I ++ ){
This. _ Check (sflags [I]);
If (! This. hasstatus (sflags [I]) continue;
This. _ Status ^ = This. _ flags [sflags [I];
// Perform the ^ operation on the current status value and the status value to be removed to delete the status.
}
},
Clear: function (){
This. _ Status = 0;
},
Hasstatus: function (sflags) {// sflags "status 1, status 3... status N. Check whether the current status ID has both status 1, status 3, and status n.
Sflags = sflags. Split (',');
For (VAR I = 0, Len = sflags. length; I <Len; I ++ ){
This. _ Check (sflags [I]);
If (this. _ Status & this. _ flags [sflags [I])! = This. _ flags [sflags [I]) return false;
// Compare the current status value with the input status. If the returned value is not the same as the id value of the changed status, return false.
// For example, if 010101 and 010000 are returned, the current ID value is 010000.
}
Return true;
},
_ Check: function (sflag ){
If (! Sflag in this. _ flags) throw new error ("the current flag does not exist" + sflag + "identifier ");
// Check whether the input string is valid.
}
}
Usage:
VaR filestatus = new flag ('readonly, hidden, otherstatus ');
Filestatus. setstatus ('readonly, den ');
Alert (filestatus. hasstatus ('readonly') // true;
Alert (filestatus. hasstatus ('den den ') // true;
Alert (filestatus. hasstatus ('otherstatus') // false;
Finally, let's go back to the topic. We use comparedocumentposition to simulate mouseenter mouseleave.
Dom structure:
<Div id = "DD" style = "background-color: #369; width: 50%; Height: 50%; position: absolute; left: 25%; top: 25%;">
<Div style = "background-color: # ff0; width: 50%; Height: 50%; position: relative; left: 25%; top: 25%">
<Div style = "background-color: #789; width: 50%; Height: 50%; position: relative; left: 25%; top: 25%">
<Div style = "background-color: #123; width: 50%; Height: 50%; position: relative; left: 25%; top: 25%">
<Div style = "background-color: #456; width: 50%; Height: 50%; position: relative; left: 25%; top: 25%">
</Div>
</Div>
</Div>
</Div>
</Div>
JS script:
VaR dd = Document. getelementbyid ('dd ')
If (! + '\ V1') {// IE
Dd. onmouseenter = function () {alert (1 );};
Dd. onmouseleave = function () {alert (2 );};
}
Else {// others
Dd. onmouseover = function (e ){
VaR T = E. relatedtarget;
VaR t2 = e.tar get;
This = t2 & T &&! (T. comparedocumentposition (this) & 8) & alert (1 );
};
Dd. onmouseout = function (e ){
VaR T = E. relatedtarget;
VaR t2 = e.tar get;
This = t2 & T &&! (T. comparedocumentposition (this) & 8) & alert (2 );
};
}
Success !!!!!