Reprinted from: http://www.jianshu.com/p/731488a8a3e6
I. Event Flow
1. Bubble
- What is event bubbles
The official definition is from the most specific event target to the least specific event target.
That is to say, if a user clicks on an element and the element has a click event, the same event will be triggered by its ancestors. This event bubbles from the element to the top of the DOM tree. This process is called event bubbles.
Example:
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Custom right-click menu</title>
</head>
<body>
<ul id='menu'>
<li>menu item 1</li>
<li>menu item 2</li>
</ul>
</body>
</html>
js
document.oncontextmenu =function (){
alert('Triggered);
}
2. Capture
- What is event capture
Event capture is the opposite of an event, that is, when an event is triggered by a user, the event starts at the top of the DOM tree until it is captured to the event source.
Standard ways of listening for events (standard browsers are available, IE9 or more)
element.addEventListener(eventType, fn, false)
Explain:
- The first parameter: eventType: Event type
- Second parameter: callback function triggered by fn
- The third parameter: a Boolean value indicating whether bubbles or captures. false means bubbles, true means capture
Interception Events under IE (IE proprietary)
· attachEvent(eventType,fn). IE is proprietary.
Explain:
Only bubbles are not captured in this way.
Be careful:
-
Standard monitoring method does not need to add on
document.addEventlistener('contextmenu',function (){ alert('I'm the standard. I don't need it. on') },false)
-
IE's way of monitoring events must be added on
document.attachEvent('contextmenu',function(){
alert('I am IE I need on')
})
Generally use the standard, if it is compatible with IE 8 or below, then consider the second, do compatible writing.
oncontextmenu
It belongs to mouse event, triggered by right click of mouse.
Usage:
I bound this event on the document and triggered it through the event bubbling mechanism.
document.oncontextmenu =function (){
alert('Triggered);
}
3. Event object event
Concept:
Event objects represent the state of events, such as the elements in which events occur, the state of keyboard keys, the position of the mouse, and the state of mouse buttons.
Events are usually used in conjunction with functions, which are not executed before events occur.
- First parameter in standard browser as event callback function
document.addEventlistener('contextmenu',function(ev){
alert(ev)
})
- Low version IE as an attribute of window object
document.attachEvent('contextmenu',function(){
alert(window.event)
})
Generally, if it is not compatible with ie 8 or below, use event under the standard.
4. Cancel Default Behavior
event.preventDefault()
5. Preventing bubbles
event.stopPropagation()
Explain:
return false can prevent default behavior as well as bubbles
6. Obtain rolling distance
- chrome:
document.body.scrollTop(scrollLeft)
- Non chrome:
document.documentElement.scrollTop(scrollLeft)
- Compatible Writing:
var scrollTop = document.documentElement.scrollTop||document.body.scrollTop,
var scrollLeft = document.documentElement.scrollLeft||document.body.scrollLeft,
7,clientX(Y)
It provides the horizontal coordinates (different from page coordinates) of the application client area when an event occurs. For example, when you click on the upper left corner of the client area, the clientX value of the mouse event is 0, which is independent of whether the page scrolls horizontally.
That is, the distance to the browser's visual window (excluding the browser's toolbar)
8. Obtain the specific dimensions of elements
- offsetHeight/offsetWidth
Typically, offset Height is a measure of an element, including its borders, vertical (horizontal) inner margins, horizontal (vertical) scrollbars (if present and rendered) and CSS height (width) of the element.
Be careful:
The difference from clientWidth/clientHeight is `clientWidth/clientHeight'. The width (height) of the vertical (horizontal) scrollbar and the border are not included.
9. Getting the Size of Viewport of Browser
var browserHeight = document.documentElement.clientHeight,//Height of Viewport of Browser
browserWidth = document.documentElement.clientWidth;
Be careful:
Initially, window.innerWidth/window.innerHeight was used to obtain the viewport size, and the result was covered partly by the scroll bar in the extreme case. Later, it was found that window.innerWidth/window.innerHeight included the scroll bar as well.
10. Converting Class Array to Array
Array. prototype. slice. call (class array, 0)
11. Implementing Thought of Customizing Right-click Menu
1. Make the custom menu absolutely positioned relative to the browser viewport by changing the left/top value to change the position of each menu.
2. Cancel the default behavior of the original right-click menu
3. Considering the limit case, determine whether the offsetWidth/event.clientY+offsetHeight of event.clientX+menu is greater than or equal to document.documentElement.clientWidth/document.documemtElement.clientHeight. If it is greater than or equal, assign left/top to offsetWidth/event.clientY-menu offsetHeight of event.clientX-menu, otherwise assign event.clientX/event.clientY-menu offsetHeight.
js code:
window.onload = function (){
var oClick = document.getElementById('click_region'),
oMenu = document.getElementById('menu'),
aLi = oMenu.getElementsByTagName('li'),
browserHeight = document.documentElement.clientHeight,//Height of Viewport of Browser
browserWidth = document.documentElement.clientWidth; //Fast reading of browser viewport, excluding the width of vertical scroll days
document.oncontextmenu = function (ev){
oMenu.style.display = 'block';
var ev = ev||window.event,
scrollTop = document.documentElement.scrollTop||document.body.scrollTop,
scrollLeft = document.documentElement.scrollLeft||document.body.scrollLeft,
clientX = ev.clientX,
clientY = ev.clientY,
// Note: Only when the hidden element becomes display:block can its width and height be obtained.
offsetWidth = oMenu.offsetWidth,
offsetHeight = oMenu.offsetHeight,
top,
left;
if(clientY+offsetHeight>=browserHeight){
top = clientY-offsetHeight
}else{
top = clientY
}
if(clientX+offsetWidth>=browserWidth){
left = clientX-offsetWidth
console.log(left);
}else{
left = clientX
}
oMenu.style.left = left+'px';
oMenu.style.top =scrollTop+top+'px';
return false//Prevent default behavior and bubbles
}
// Cancel custom menu
document.onclick = function (){
oMenu.style.display = 'none';
}
var lis = Array.prototype.slice.call(aLi,0); //Converting class arrays to arrays
//foreach
lis.forEach(function (item,index,arr){
aLi[index].onclick = function (event){
alert(this.innerHTML)
event.stopPropagation();
}
})
}